Run a swarm of coding agents. Keep one calm surface.
Grove runs Claude Code, Codex, Cursor — any CLI agent — in parallel, each pinned to its own git worktree so they never collide. This roster is live: the elapsed timers below are a real wall-clock, ticking. Nothing else moves until you do.
| Status | Agent | Worktree | Δ | Elapsed |
|---|---|---|---|---|
| Running | Claude Code | fix/auth-flow | +64 -12 | 2:14 |
| Needs attention | Codex | feat/ports | +28 -4 | 0:41 |
| Done | Cursor | perf/diff | +211 -96 | 12:22 |
| Error | Gemini | feat/sync | +9 -31 | 5:18 |
| Idle | Aider | docs/hotkeys | +0 -0 | — |
| Running | Claude Code | fix/pty-backpressure | +47 -18 | 1:36 |
| Running | Codex | chore/migrate | +132 -40 | 3:42 |
| Done | Cursor | feat/qr-pair | +88 -14 | 15:05 |
| Running | opencode | feat/adapter-codex | +56 -9 | 2:38 |
| Running | Claude Code | fix/toast-throttle | +22 -6 | 1:13 |
| Needs attention | Gemini | feat/bearer | +38 -21 | 1:04 |
| Running | Aider | chore/prune | +14 -52 | 3:09 |
| Running | Codex | feat/ansi-map | +71 -11 | 1:52 |
| Running | Cursor | a11y/reduced-motion | +33 -7 | 3:25 |
Click a row to pin its worktree in the rail · hover a worktree for its path
The swarm dial
Crank the agent count by hand — drag, or use the arrow keys. Every agent is pinned to its own .grove/wt/agent-N worktree. Watch what does not happen: the geometry, the order, the colour, the cadence hold steady from one agent to a hundred. The calm surface is the whole product.
12 agents · 12 worktrees · one trunk · order steady · 0 reflows
Every agent on its own worktree
The trunk forks into one working tree per agent. They share history, never a checkout — so two agents editing the same file is a non-event, not a merge conflict. Flip to a shared checkout to see the failure mode Grove removes.
5 worktrees, one trunk
Each shoot ends in its own checkout node — no two agents touch the same tree.
.git/worktrees layout
.git/worktrees/
├── auth-flow/ → fix/auth-flow (Claude Code)
├── port-scanner/ → feat/ports (Codex)
├── diff-virtualize/ → perf/diff (Cursor)
├── sync-resume/ → feat/sync (Gemini)
└── adapter-codex/ → feat/adapter-codex (opencode)
# one repo · one trunk · N working trees
# each agent edits only its own checkout const claims = decode(token); if (claims.exp < now()) {- throw new Expired();+ // Rotate instead of failing the open session.+ const next = rotate(claims);+ audit.record(next.id, claims.sub);+ return next;+ }+ return token; }Grove: each diff applies to its own tree — no shared-file contention.
The terminal, streamed
Each agent gets a real shell — full PTY, ANSI mapped to the Grove palette. Each tab is a different agent's recorded session: switch tabs and you see that agent's own output. It holds still until you replay it, then plays once and stops. The only thing moving at rest is the cursor.
Replay the active tab with the ▶ control, or run up from the command palette (⌘K).
Review the diff, harvest the work
When an agent finishes, you review its diff like a commit and stage exactly that one worktree onto main. Harvest is deliberate and scoped: it stages one reviewed tree, retires it, and leaves every other agent — including the ones that need attention — untouched.
return ( <div className={cn(- "overflow-auto",+ "overflow-auto grove-grid-contain",+ // content-visibility: skip offscreen hunks+ // so a 4k-line diff scrolls at 60fps. )}>+ {/* virtualized below */} {rows}- {/* render every row up front */}Run summary
- agent
- Claude Code
- branch
- fix/auth-flow
- worktree
- .grove/wt/auth-flow
- changes
- +5 -2 · 1 file
- status
- Running
perf/diff: skip offscreen hunks with content-visibility so a 4k-line diff scrolls at 60fps.
Harvest flips this agent's row in the left rail to done-green and prints the result on the status strip — one reviewed worktree, never a fleet auto-merging.
Monitoring & attention
One board for the whole swarm. State is triple-encoded — colour, word, and shape — so it never relies on colour alone. The board reads from the same source of truth as the rest of the cockpit; a notification is a pull, fired on request, never pushed at you.
14
agents
8
running
2
attention
1
idle
2
done
1
error
Pair the phone, keep watching
The desktop hosts a small PWA you pair over loopback with a bearer token — the QR is generated by the running app, on your machine. Once paired, the phone is the same cockpit bound to the same state: tap an agent here and the desktop rail updates. No account, no cloud, no network leaving the box.
grove://loopback:7433/pair
bearer-gated · token rotates per session
Labeled sample — not a scannable code. The real QR is rendered by the desktop app from your loopback host and bearer token.
Locked
Pair from the desktop QR to bind this phone to the running cockpit.
grove://loopback:7433/pair
to-scale · 300px
Install Grove
One command to a running cockpit. Self-hosted, open source, loopback by default — nothing leaves your machine. The phone PWA pairs from the running desktop over the in-app QR.
brew install grove
grove upGrove-1.0.0-arm64.dmg
signed installer · ~ — sample, set at release
git clone github.com/GhostlyGawd/grove
build from source · cd grove && grove up
grove up — loopback, bearer-gated, embedded Postgres. Nothing leaves your machine.
Install URLs and package managers are launch markers, named here ahead of the release channels going live.