Native desktop shell for the iii chat surface. Tauri 2 in Rust, React renderer
on iii-browser-sdk, runs against the canonical
iii harness graph.
Two halves:
src-tauri/— Rust shell. Owns the window, native menu, deep links, file dialogs. Registers a smalldesktop::*worker on the engine (ws://127.0.0.1:49134by default).web/— Vite + React renderer. Connects to the browser RBAC port (ws://127.0.0.1:49135) viaiii-browser-sdkand drives the chat graph throughharness::call.
The renderer never speaks REST. Every action is iii.trigger(...) against
either the harness or the desktop worker.
0.x. Stays sub-1.0 until the shell is in real production use against a
running engine + harness.
-
Rust stable (
rustup toolchain install stable) -
Node 20 + pnpm 9 (
corepack enable && corepack prepare pnpm@9 --activate) -
A running iii engine with the
harnessworker installed:curl -fsSL https://install.iii.dev/iii/main/install.sh | sh iii worker add harness iii # runs the engine in the foreground
Engine subcommands:
iii trigger,iii worker,iii console,iii sandbox,iii cloud. Bareiiiis the long-running engine process.Provider API keys:
auth-credentialsreads them from the environment of the process that spawns the workers, so exportANTHROPIC_API_KEY/OPENAI_API_KEYetc before runningiii.
# install renderer deps
pnpm --dir web install
# start Tauri + Vite together
cargo tauri devcargo tauri dev is the canonical entry. It runs pnpm --dir web dev in the
background, watches src-tauri/, and rebuilds the shell on change.
If cargo tauri is missing, install it once:
cargo install tauri-cli --version "^2"pnpm --dir web build
cargo tauri buildOutput bundles land in src-tauri/target/release/bundle/.
Environment variables read at launch:
| Var | Default | Meaning |
|---|---|---|
III_URL |
ws://127.0.0.1:49134 |
Backend engine port (for the desktop worker). |
VITE_III_BROWSER_URL |
unset | Override the browser worker WS. Skips harness::info round-trip. |
III_HARNESS_HTTP |
http://127.0.0.1:39134 |
HTTP base for the harness::call proxy used by Vite in dev. |
The renderer is itself an iii worker. On boot it:
- Fetches
harness::infoover HTTP to discover the browser WS endpoint (skipped ifVITE_III_BROWSER_URLis set). - Connects via
iii-browser-sdk::registerWorker. - Mints a stable
browser_idfor the page and registersui::session::event::<browser_id>for liveagent::events. - Calls
ui::subscribe { browser_id, session_id }so the harness fanout knows which sessions to forward. - Sends turns via
harness::call { function_id: "run::start", payload }.
The desktop worker registers two functions on the backend port:
desktop::status— version + name liveness probedesktop::window::focus— bring the desktop window to the front (useful for cross-app deep links and approval prompts)
.
├── src-tauri/ Rust shell
│ ├── src/
│ │ ├── main.rs thin bin entry
│ │ ├── lib.rs tauri::Builder + plugin wiring
│ │ ├── worker.rs iii-sdk worker registration
│ │ ├── menu.rs native menu
│ │ └── functions/ Tauri IPC commands
│ ├── capabilities/ Tauri 2 capability scopes
│ └── tauri.conf.json
├── web/ Vite + React renderer
│ └── src/
│ ├── App.tsx
│ ├── components/
│ ├── lib/
│ │ ├── iii-client.ts iii-browser-sdk wrapper
│ │ ├── useAgentStream.ts agent::events subscription
│ │ ├── tauri.ts Tauri IPC + menu event helpers
│ │ └── types.ts
│ └── styles/ vendored iii console design tokens
└── .github/workflows/ ci + release
Apache-2.0