An agentic coding CLI · voice-first · open source

Speak.
It builds.

Spruce Grove OS is a coding agent that streams its thinking, takes dictation, survives its own process dying, and lets you steer mid-run — in a desktop shell machined around the machine. Every trail inspired by Code Puppy. Every value our own.

$ uv tool install spruce-grove
test files, CI-gated
packages on install
k
token context, vision tier
model tiers, one keychain
build-log entries
s
install to PATH
01

The session, streamed

No spinner-and-pray. The agent speaks the ACP protocol — message deltas, thinking blocks, tool cards with live status chips, per-turn token counts — and the desktop renders every event the instant it lands. Press run. It's the real dialect.

spruce-grove --acp · session 8f3a… idle

Structured, not scraped

Legacy shells scrape terminal lines and guess. Grove speaks JSON-RPC over stdio: every token, every tool call, every permission is a typed event with a home in the UI.

Thinking streams in italics. Tools get cards. Usage lands at turn-end.

dialect pinned by fixtures/acp/session.jsonl
replayed through the real router in CI
9 Rust unit tests · protocol drift fails loudly
02

Voice, gated by hands

Dictation is on-device. Whisper runs locally, the transcript lands editable in the prompt, and nothing sends until you send it. The mic is a gate, not a wiretap.

dictation · whisper local ready
press the mic — say a feature
transcript lands here — edit it before it ever sends

Whisper never leaves the machine

The voice plugin records, transcribes with local whisper, and drops text in your prompt. Review is a first-class step, not a compromise.

And because it fills the same prompt box, dictation doubles as mid-run steering — speak a redirect while the agent works.

verb: spruce-grove --transcribe file
plugin: mockingbird · user-plugins tier
zero core edits · zero cloud calls
03

Steer it like it's moving

Because it is. ACP turns are strict request/response, so Grove makes steering clean: sending while busy cancels the turn and redirects within the same session — context intact, nothing re-explained. Type below mid-sweep.

long-running turn idle

Cancel, then redirect — same brain

Naive shells lose the thread on cancel. Grove's client races on purpose: turnActive tracking plus a fallback timer, so a steer can never wedge on a missed turn-end.

Two real bugs — found by the UI test, fixed before they shipped.

flow: session/cancel → turn-end → re-prompt
same sessionId · context preserved
voice steer rides the same path
04

Watch the browser work

When the agent drives a browser, screenshots stream into a Live Look-in panel as they're taken — paths detected in tool payloads, ferried to the panel, rendered while the cursor still moves.

agent browser · checkout flow idle

Cedar Lane Supply — checkout

An ordinary form. The agent fills it; you watch it happen.

place order
live look-in · panel
waiting for take_screenshot…
panel armed — tool payload watch on

Not a screenshot folder — a window

Browser tools save PNGs to tempdirs and report the path. The desktop scans tool payloads, whitelisted-reads the image, and slides it into the panel with a rolling action log.

Auto-opens on capture. Toggle it any time.

command: grove_read_image_base64
extension-whitelisted · 20 MB cap
Playwright-verified end to end
05

It survives its own death

Sessions persist across process relaunches. Plant a marker, kill the agent, relaunch — the fresh process loads the same session and recalls the marker verbatim. Proven at the protocol level before a single line of UI.

lifecycle test · acp_probe --lifecycle session live
session A · process 1 8f3a21c4-… marker: GROVE-DURABILITY-082318 context warm
session A · process 2 (fresh) 8f3a21c4-… (loaded) not launched

Durability is a protocol fact

The desktop stores your session per working directory. Relaunch the app and the pill reads ACP · resumed — same conversation, same context, new process.

A dead session never bricks the shell: load failures fall back to a fresh session, gracefully.

flow: session/load across process death
probe: marker recalled verbatim
UI: resume wired, fallback wired
06

The ladder it was built on

Nineteen beads tracked across the build. Sixteen closed with evidence. One needs your mic.

L0Rebrand & Junto boot bannerthe grove in grove clothesclosed
L1Plugin tier + trust gateevery feature, zero core editsclosed
L2Cohort bricks · NWA plugin suitereal people, real problems5 shipped
L3Voice-first pillarmic → local whisper → review → sendclosed
L4Namespace ratchetCI-audited i18n catalogclosed
L5Desktop shell · Tauri 2ACP streaming · look-in · steering · resumeone smoke click
L6Bootable OS spin — the name made literalparked, on purpose, until users asknorth star
07

The model rig

Rotation-safe aliases pin behavior while the vendor rotates models behind them. Keys resolve from the macOS Keychain — never a plaintext config.

aliasbacks ontocontextcost weightrole
syn:large:textGLM-5.3-Flash524k1.0×the builder
syn:small:textGLM-4.7-Flash196k0.1×the workhorse
syn:small:visionQwen3.8-27B262k0.1×the eyes (look-in)
syn:large:visionQwen3.8-27B524k1.0×the deep read
08

Proven, not promised

The full what/why/how lives in TEST-MAP. The short version:

layer 1 · the engine

363 test files

Every tool, hook, plugin tier and i18n catalog — CI-gated on macOS before any release.

uv run pytest · publish workflow
layer 2 · the chassis

9 Rust tests + UI suite

ANSI stripping, ACP routing, permission selection, session parsing — plus Playwright driving the real UI: streaming, steering, look-in, dictation.

cargo test · 9/9 · ui green
layer 3 · the contract

The pinned dialect

The recorded ACP session replays through the real router. Protocol drift fails loudly — and the lifecycle probe proves session/load recalls across process death.

marker: GROVE-DURABILITY-082318
09

In the wild

The grove doesn't demo with mockups — it works for the town. Every link below is live today, built by the agent and shipped to a real door.

forwhat was builtsee it live
tylergranlund.comThe flagship: TanStack Start · React 19 SSR · TypeScript strict · Tailwind v4 · Vitest gates — resale desk, ventures, career, writing, and a colophon that declares its own stacktylergranlund.com
Benton DronesLead intake: form → geocode → Jira → dashboard — Python stdlib + SQLite core, Render, Playwright-verified (the full build story)leads.bentondrones.com
Bentonville BarbershopStatic, accessibility-audited, owner-servable shopfront with a booking flow (the full build story)candmbarbershop.net
The grove itselfThis page, the CLI, the desktop shell — all shipped from the same treesprucegrove.io

Four seconds to a grove on your PATH

One command from the public index. No tokens, no config ceremony — the keychain asks when it's needed.

$ uv tool install spruce-grove
installs grove + spruce-grove 111 packages resolved macOS arm64 today try first: uvx spruce-grove --version