Architecture
Runtime Boundaries
What crosses each boundary, and what each layer is allowed to do.
CoreLayer separates the UI, the desktop shell, the daemon, and external processes so that a failure in one cannot silently escalate into another.
Boundary Model
Webview UI (React)
║ Tauri IPC — typed, registered commands only
╚═► Tauri shell (Rust)
║ HTTP — loopback only
╚═► Node.js daemon (Hono)
║ in-process module calls (public-api modules)
╠═► shared packages
║ subprocess / network
╠═► ACP executor process (Claude Code, Codex, OpenCode)
╠═► MCP servers (stdio child processes or HTTP/SSE)
╚═► database (SQLite file, Supabase, PostgreSQL)Cross-boundary rules
| Boundary | Rule |
|---|---|
| UI → Tauri | Only registered commands; no direct filesystem or network |
| Tauri → daemon | HTTP on loopback; daemon port is chosen at spawn and reported by /api/runtime/status |
| Daemon → packages | Import through each runtime's public-api.ts, never into internal modules |
| Daemon → executor | Child process in a git worktree, with a pinned model/executor and a narrowed bounds envelope |
| Daemon → MCP server | stdio child process or remote HTTP/SSE; every reported tool is registered and risk-tagged |
| Daemon → database | Through the repository layer only; no route queries the database directly |
The daemon enforces one of these mechanically: an import-boundary test fails the build if an HTTP route reaches into a runtime's internals instead of its public-api.ts.
UI ↔ Tauri
- Commands are typed on both sides (TypeScript ↔ Rust structs)
- Payloads are JSON
- Calls are async; the UI never blocks on daemon startup
Tauri ↔ daemon
- HTTP, loopback only.
/api/runtime/shutdownadditionally refuses non-loopback peers. - SSE for streaming chat and run progress
- The shell owns the daemon lifecycle: spawn, health check, restart on crash, terminate on exit
Daemon ↔ executors
Coding work is not run in the daemon process. The coding runtime spawns an external agent through an adapter (see Coding Executor Adapters) inside an isolated git worktree, and reads back only structured events, artifacts, and a diff. What the child may do is fixed at dispatch time by the delegation bounds and cannot be widened by the child.
Why this matters
- Containment — a misbehaving executor can only damage its own worktree
- Attribution — every state change has a run id, an actor, and an audit entry
- Replaceability — a provider, an executor, or a storage backend can be swapped without touching the others
- Testability — boundaries are enforced by tests, not by convention alone
Next Steps
- Security Model — the enforcement layers in detail
- Executor Governance — containment for coding agents
- System Overview — the full topology