Skip to content

Latest commit

 

History

History
47 lines (37 loc) · 2.38 KB

File metadata and controls

47 lines (37 loc) · 2.38 KB

Architecture

Runtime boundaries

The desktop app uses a React/Vite renderer and a Tauri/Rust host. Frontend code talks to Tauri commands only through the typed desktop-api.ts adapter. Backend commands delegate business rules to services, which use storage repositories and the Codex process adapter.

React components
      ↓
Zustand + useDesktop
      ↓
typed desktop API
      ↓ Tauri IPC
commands
      ↓
services ─────→ Codex App Server / gh / Git adapters
      ↓
SQLite storage

Ownership

  • React owns transient presentation state and a Task-keyed event projection.
  • Rust owns validation, process execution, configuration, and persistent state.
  • SQLite is the source of truth for projects, tasks, and their Codex thread ids; it does not duplicate conversation content.
  • Codex is the source of truth for thread/turn/item history. Tasks may belong to a project or use HOME as an unowned temporary workspace.
  • One lazy App Server actor owns stdio and response correlation. Task services independently monitor events for their active thread/turn, so unrelated Tasks can run concurrently.
one codex app-server process
    ├── Task A → thread A → active turn A → event/approval stream A
    ├── Task B → thread B → active turn B → event/approval stream B
    └── Task C → thread C → resumed history

Extension points

  • App Server JSONL notifications and requests are normalized into CodexEvent and emitted through a Tauri channel.
  • Stable command, file-change, and permission approvals are routed back over the bidirectional transport.
  • A PTY can be added as a separate terminal surface without changing thread ownership.
  • packages/shared can host renderer-neutral schemas when a web client is introduced.
  • GitHub and Git integrations live in dedicated services and never place business logic in main.rs or command handlers.
  • Editor, terminal, and MCP features should follow the same service boundary.

Failure handling

Rust uses AppResult<T> and serializes AppError as a stable IPC error string. The frontend normalizes unknown failures through getErrorMessage and exposes them in a dismissible notification. Failed or interrupted turns remain available from Codex history and update only their owning Task. PR checkout is rejected for dirty worktrees, and destructive Git discard operations require UI confirmation.