The layers
apps/desktop
The desktop frontend: Next.js plus assistant-ui.
The Rust host owns the Rust-side concerns: the window and custom title bar, the system
keychain, spawning and reaping the sidecar subprocess, and exposing business-table reads
and writes to the sidecar as host RPC.
The sidecar does not write files or open SQLite connections for business data — that
work is handed to the host over host RPC on stdout. This is exactly why the sidecar
falls back to local SQLite storage when there is no Rust host, as in
bun run smoke.apps/sidecar/pi-agent
The agent runtime, Bun + TypeScript. Entry pointsrc/index.ts, exposing an NDJSON
protocol on stdin/stdout, organised by domain:
apps/mobile
Expo SDK 57 + React Native 0.86. No backend — it connects to the sidecar through the desktop gateway’s/ws, exchanging a pairing code for a token stored in the
Keychain/Keystore. See Remote & mobile.
packages
- pi-protocol — the cross-surface contract shared by frontend, sidecar, and mobile. All three take their types from here, so nobody writes a fourth copy.
- shared — utilities and components shared on the desktop side.
plugins
See Plugins & workspaces.Data flow: one tool call
1
The frontend sends
While rendering the thread, the frontend sends a message to the sidecar over NDJSON.
2
The sidecar decides
The agent loop hands the message to the model, which returns tool calls. The sidecar
checks each call against the current session mode and approval level.
3
It may stop and ask
If approval is required, the sidecar pushes an approval event to the frontend, which
shows the card. Your choice goes back to the sidecar.
4
Execute and persist
The tool runs inside the sidecar. Writes that touch business tables go to the Rust
host over host RPC on stdout, where the keychain and SQLite live.
5
Push events back
Results and streaming deltas return to the frontend as events, render as a tool-call
record in the thread, and land in a checkpoint.
Why the agent is a separate process
- The UI stays responsive — long jobs and heavy tool output never block the render process;
- Crash isolation — a sidecar failure does not take the window down with it;
- Reuse across surfaces — mobile and web connect to the same WS endpoint and the same runtime, so there is no second implementation;
- Testable in isolation —
bun run smokeruns the full protocol handshake with no GUI at all.
Standing on other people’s work
Session transcripts, context compaction, and the subagent model are ported from or modelled on Earendil Works’ pi-agent. The manyPI-Desktop 同设计 comments in the code point at those sources.
Next
Build your own thing on top of these layers.
