Generated: 2026-04-09 | Commit: 93661da | Branch: dev
Tauri 2 desktop app for managing code projects with integrated PTY terminals. React 19 + TS frontend, Rust workspace backend, SQLite via Diesel.
2code/
├── src/ # React 19 + Vite frontend
│ ├── features/ # Feature-first: debug git home profiles projects settings terminal topbar watcher
│ ├── shared/ # lib/ providers/ components/ hooks/
│ ├── layout/ # AppSidebar + sidebar/ sub-components
│ ├── generated/ # AUTO-GENERATED Tauri IPC bindings (DO NOT EDIT, gitignored)
│ └── paraglide/ # AUTO-GENERATED i18n messages (DO NOT EDIT, gitignored)
├── src-tauri/
│ ├── src/handler/ # #[tauri::command] entry points (8 files)
│ ├── crates/infra/src/ # DB, PTY, git, shell init, watcher, logger, slug
│ ├── crates/service/src/ # Business logic: project, profile, pty, watcher
│ ├── crates/repo/src/ # Diesel CRUD: project, profile, pty
│ ├── crates/model/src/ # DTOs, Diesel models, error types
│ └── migrations/ # Diesel SQL migrations (embedded at compile time)
├── messages/ # i18n source: en.json zh.json
└── justfile # Build helpers: coverage, fmt
| Task | Location |
|---|---|
| Add Tauri command | src-tauri/src/handler/*.rs → register in lib.rs → run cargo tauri-typegen generate |
| Consume IPC in frontend | Import from @/generated → wrap in TanStack Query hook |
| Query keys | src/shared/lib/queryKeys.ts — always use this, never inline strings |
| Terminal tabs/state | src/features/terminal/store.ts (Zustand + Immer) |
| PTY session lifecycle | src-tauri/crates/infra/src/pty.rs + crates/service/src/pty.rs |
| DB migrations | src-tauri/migrations/ (Diesel; auto-applied on startup) |
| Git operations | src-tauri/crates/infra/src/git.rs + src-tauri/src/handler/debug.rs |
| Context ID resolution | crates/repo/src/project.rs::resolve_context_folder (polymorphic project/profile) |
| Worktree profiles | crates/service/src/profile.rs — creates ~/.2code/workspace/{id} |
| Agent status detection | src/features/terminal/detector/ → Terminal.tsx → terminalStore |
| i18n messages | messages/en.json + messages/zh.json → import * as m from "@/paraglide/messages.js" |
| Shell init injection | infra/shell_init.rs (ZDOTDIR-based) |
bun tauri dev # full dev (frontend + Rust hot reload)
bun run dev # frontend only
bun tauri build # production build
cd src-tauri && cargo test # Rust tests
cargo tauri-typegen generate # regenerate src/generated/ after Rust command changes
just fmt # format TS + Rust
just coverage # llvm-cov HTML report- Server state: TanStack Query — always invalidate on mutations
- Client state: Zustand with Immer — terminal store uses
Set(requiresenableMapSet()) - Persist:
terminalSettingsStore,notificationStore,themeStoreuse localStorage viapersistmiddleware - Outside React:
useTerminalStore.getState().addTab(...)(direct access, no hook)
- IPC flow: Rust
#[tauri::command]→tauri-typegen→src/generated/→ TanStack Query hook - Terminal persistence: CSS
display: noneon tab switch — NEVER unmount or conditionally render terminals - Context ID: git handlers accept project ID or profile ID — backend resolves via
resolve_context_folder - Rust test setup: in-memory SQLite +
conn.run_pending_migrations(MIGRATIONS)insetup_db() - DB lock: single
Arc<Mutex<SqliteConnection>>— acquire/release quickly, never hold across awaits
src/api/— forbidden; all IPC viasrc/generated/auto-gensrc/generated/orsrc/paraglide/— DO NOT EDIT (gitignored, regenerated)src-tauri/src/schema.rs— DO NOT EDIT (Diesel generated)- Conditional rendering of
<Terminal>— breaks xterm.js state - Legacy UI-library APIs/components — removed; use shadcn/ui primitives from
src/components/ui - Long-held DB mutex locks — causes deadlocks
- Font listing / sound APIs without macOS platform guard (macOS-only)
src-tauri/src/main.rs:1—#![cfg_attr(…, windows_subsystem = "windows")]hasDO NOT REMOVE!!topbarfeature is NOT part ofgitfeature despite CLAUDE.md proximity — it's a separate customizable control bar system- Immer
MapSetplugin must be enabled before any store usingSet/Map(already done instore.ts) noUnusedLocals+noUnusedParametersenforced in tsconfig — TS will error on unused vars- CI:
.github/workflows/tauri-smoke.yml— smoke test onubuntu-24.04usingxvfb-run(virtual display) +webkit2gtk-driver+ Tauri driver. Not a full test suite. - E2E:
e2e-tests/uses Mocha + Selenium WebDriver via Tauri driver (not Playwright/Cypress) - Frontend uses Vitest (
npm test=vitest run); test files colocated as*.test.ts— Zustand store tests useresetStore()helper pattern - ESLint uses
@antfu/eslint-configwith React flat config — configuration lives ineslint.config.jsat the repo root openspec/dir at root is OpenSpec workflow tooling — not application codesrc-tauri/src/bridge.rs— trait impls (TauriPtyEmitter,TauriWatchSender) that decouple service layer from Tauri