# CLAUDE.md

This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.

## Project Overview

**Sprout Launcher (萌芽桌面启动器)** is a Windows desktop application launcher built with **Tauri 2 + React 18 + TypeScript**. Users add apps to a categorized grid, launch them from a single window, and manage shortcuts/icons.

## Commands

```bash
npm install                 # Install JS dependencies
npm run tauri dev           # Start Vite dev server + Tauri (hot reload)
npm run lint                # ESLint — must pass with zero warnings
npm run tauri build         # tsc && vite build && Tauri bundler → src-tauri/target/release/bundle/
```

No automated test framework is configured. Manual smoke testing: add/edit/delete apps, category CRUD, config persistence across restart, icon extraction, window controls.

## Architecture

The app uses Tauri 2's two-process model:

```
Renderer (React UI in src/)
    ↕ invoke() / listen() via @tauri-apps/api
Rust backend (src-tauri/src/lib.rs)
    ↕ Native APIs
Windows OS (filesystem, registry, shell, PowerShell)
```

**Key source files:**

| File | Role |
|------|------|
| `src/App.tsx` | Master state container — config, drag-drop, dialog orchestration |
| `src/types.ts` | Shared TypeScript interfaces (`App`, `Config`, `Category`) |
| `src/components/AppCard.tsx` | Memoized app tile |
| `src/components/AddAppDialog.tsx` | Add/edit app modal — calls `invoke()` for file pickers |
| `src/components/GridWithFill.tsx` | Responsive grid using ResizeObserver |
| `src-tauri/src/lib.rs` | All Tauri commands + tray + protocol + setup |
| `src-tauri/tauri.conf.json` | Window config, bundle targets, CSP |
| `src-tauri/capabilities/default.json` | Plugin permission grants |

## IPC Communication

The frontend calls Rust via `invoke(command_name, args)` from `@tauri-apps/api/core`. Events from Rust to frontend use `listen()` from `@tauri-apps/api/event`.

Key commands in `src-tauri/src/lib.rs`:

| Command | Purpose |
|---------|---------|
| `launch_app` | Execute app via `cmd /C start` |
| `select_target` / `select_folder` / `select_single_executable` | Native file/folder dialogs |
| `select_executables` | Multi-select executables |
| `create_shortcut` | Create Windows `.lnk` via PowerShell COM |
| `ensure_icon` | Extract icon from EXE/folder via PowerShell + .NET, cache as PNG |
| `delete_app_artifacts` | Clean up shortcut + cached icon |
| `show_app_context_menu` | Show native right-click menu; emits `app-context-action` event |
| `load_config` / `save_config` | Read/write `%APPDATA%/com.smyhub.sprout-launcher/launcher-config.json` |
| `export_config` / `import_config` | File dialog + JSON backup/restore |
| `get_auto_launch` / `set_auto_launch` | Windows boot startup via `tauri-plugin-autostart` |
| `minimize_window` / `maximize_window` / `close_window` | Window controls (close → hide to tray) |
| `refresh_icons` | Re-extract all icons to disk; returns `sprout-icon://` URLs |

## Data & File Locations

- **Config:** `%APPDATA%/com.smyhub.sprout-launcher/launcher-config.json`
- **Cached icons:** `%APPDATA%/com.smyhub.sprout-launcher/data/icons/` (PNG files)
- **Shortcuts:** `%APPDATA%/com.smyhub.sprout-launcher/data/shortcuts/` (`.lnk` files)
- Icons are served via a custom `sprout-icon://` URI scheme registered in `lib.rs`

If you change the config schema, add a migration path in `src/App.tsx` inside `migrateAndMaybeSaveConfig()` (existing `exePath → targetPath` migration is the pattern to follow).

## Tauri Plugins Used

| Plugin | Purpose |
|--------|---------|
| `tauri-plugin-dialog` | File open/save dialogs (Rust side) |
| `tauri-plugin-autostart` | Windows login-item / startup registry |
| `tauri-plugin-single-instance` | Prevent duplicate instances; focus existing window |
| `tauri-plugin-log` | Structured logging |

## Coding Conventions

- TypeScript strict mode; all changes must be type-safe
- ESM (`"type": "module"`) throughout
- 2-space indentation
- React components: `PascalCase.tsx` in `src/components/`; shared types in `src/types.ts`
- Rust: standard `snake_case`, all commands registered in `invoke_handler!` at bottom of `lib.rs`
- Commits: Conventional Commits (`feat:`, `fix:`, `chore:`, etc.)
- `dist/`, `src-tauri/target/` are build artifacts — do not edit
