A native T3 Code-style desktop client for coding agents, built with GPUI and GPUI Kit. It drives Claude Code and Pi.
Every thread runs its own agent process in the background. Claude Code threads talk to the
claude CLI over the stream-json protocol the Claude Agent SDKs use
(--input-format/--output-format stream-json plus the stdio control channel). Pi threads
talk to pi --mode rpc over its JSONL RPC protocol.
The layout and workflow follow T3 Code. The look follows MetalUI, the "soft hardware" design system vectrum.cc is built on: the conversation sits on a raised sheet, buttons are caps that sink when pressed, code and tool output sit in inset wells, and labels are engraved in mono caps. It comes in MetalUI's two colorways, Bone and Graphite, or Auto to follow the desktop.


claude CLI, logged in (claude once interactively)npm install -g @earendil-works/pi-coding-agent, then log in to a provider with pi)vulkan-icd-loader plus your GPU's Vulkan driver, wayland,
libxkbcommon-x11, libxcb, fontconfig, freetype2)cargo run --release -- /path/to/project # defaults to the current directory
| Shortcut | Action |
|---|---|
| Enter / Shift+Enter | Send / new line |
| Esc | Interrupt Claude |
| Ctrl+N | New thread in the current project |
| Ctrl+O | Add a project folder |
| Ctrl+K | Search threads |
| Ctrl+, | Open or close settings |
| Ctrl+B | Show or hide the sidebar |
| Ctrl+Shift+B | Show or hide the project panel |
| Ctrl+Q | Quit |
VECTRUM_CODE_CLAUDE_BIN: path to the claude binary. Otherwise it's looked up on PATH,
then ~/.local/bin and ~/.claude/local.VECTRUM_CODE_PI_BIN: path to the pi binary. Otherwise it's looked up on PATH, then in
~/.local/bin, ~/.npm-global/bin, ~/.bun/bin, ~/.volta/bin and nvm's Node versions.Favorite models and everything in the settings view are saved in
~/.config/vectrum-code/settings.json. The environment variables above win over the binary
paths set there.
Threads started without a project run in ~/.local/share/vectrum-code/scratch.
src/claude.rs: spawns and owns the agent process, claude or pi (stdin writer and
stdout/stderr reader threads).src/session.rs: per-thread state. Folds Claude's stream-json and Pi's RPC events into
chat items, handles permission requests, control requests and extension dialogs, and
snapshots each turn's changes.src/models.rs: the model catalog across providers, and favorites.src/git.rs: branch and change stats, working-tree snapshots, and diffs.src/settings.rs: the saved settings file, cached in memory.src/ui/chat.rs: start screen, transcript (with turn folding), tool cards, permission bar
and composer.src/ui/pickers.rs: the model, reasoning and access pickers.src/ui/settings.rs: the settings view and its pages.src/ui/changes.rs: the per-turn change overview and the diff view.src/ui/workspace.rs: window root: thread sidebar, top bar and project panel, plus the
git and editor helpers behind it.src/ui/icons.rs: the extra Lucide icons the app embeds.src/ui/metal.rs: the MetalUI layer. Colorway tokens and shadow recipes copied from
MetalUI's CSS, the theme mapping for the stock widgets, and the primitives (caps, wells,
keycaps, status LEDs, segmented switch).assets/fonts/: Geist, Geist Mono and Geist Pixel, embedded in the binary
(SIL Open Font License, see assets/fonts/OFL.txt).Threads, settled or not, aren't persisted across app restarts. There is no UI for Claude's
AskUserQuestion (the tool is disabled, so Claude asks in plain text) or for Pi extensions
that ask for free text, code blocks have no syntax highlighting, and T3 Code's project
scripts and terminal drawer aren't here yet.