Repository navigation
Architecture
Layered, local-first desktop app. Stack: Tauri v2, React 19 + TypeScript
(strict) frontend in src/, Rust backend in src-tauri/src/, SQLite via
rusqlite (bundled, FTS5).
-
React UI (
src/) — presentational only; no business logic. Data access goes through typed wrappers insrc/lib/around Tauriinvoke. -
Commands layer (
src-tauri/src/commands/) — thin IPC translation only. Validates args, maps errors to secret-free classifiedCommandError, clones managed state (Database,AgentRunRegistry,TaskRegistry,TerminalRegistry,ConfirmationRegistry) into worker threads, streamsagent-run-event/ task-event frames. No business logic, no repository/SQL access. -
Application layer (
src-tauri/src/application/) — use cases and the agent subsystem: deterministic ReAct runner, run bridge, bounded plan → act → verify → report task loop, three-tier approval gate, autonomy modes, permission evaluation, spend/budget enforcement, governance checkpoints and audit log, context assembly/compaction, snapshots, injection hardening, self-audit, read-only inspector. Also owns the provider-independent execution boundary (application/execution.rs). -
Domain layer (
src-tauri/src/domain/) — entities and business rules, UI-independent. -
Infrastructure layer (
src-tauri/src/infrastructure/) — SQLite (database.rs, migrations v1–v14, WAL + FK + busy-timeout), per-table repositories, provider executors (providers/), filesystem, OS integration, logging.
AI providers are external services reached only through backend executors behind the execution boundary. Nothing above infrastructure touches SQLite or the network directly; nothing below commands handles Tauri IPC.
User action (React) → Tauri invoke with typed args → commands (validate, map
errors, acquire state) → application logic (use case / runner, approvals,
budgets) → persistence or AI request (repositories / provider executors) →
result plus streamed event frames for long-running work → UI update.
-
invokeargs are camelCase ({ conversationId }) mapping to snake_case Rust params (conversation_id); returned structs and event payloads stay snake_case. - New Tauri commands must be registered in the
generate_handler![...]list insrc-tauri/src/lib.rs; a missed registration compiles but fails at invoke time. - Errors are classified, logged without secrets, and shown to users in clear form; unexpected failures must not corrupt user data.
-
unsafe_code = "forbid"; clippy pedantic warnings deny CI.
See also: Database, Providers-and-Models, Agent-Runs, Security-and-Credentials.