grovev1.0.0
00

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.

self-hosted · loopback · embedded Postgres
agent rostersort
StatusAgentWorktreeΔElapsed
RunningClaude Codefix/auth-flow+64 -122:14
Needs attentionCodexfeat/ports+28 -40:41
DoneCursorperf/diff+211 -9612:22
ErrorGeminifeat/sync+9 -315:18
IdleAiderdocs/hotkeys+0 -0
RunningClaude Codefix/pty-backpressure+47 -181:36
RunningCodexchore/migrate+132 -403:42
DoneCursorfeat/qr-pair+88 -1415:05
Runningopencodefeat/adapter-codex+56 -92:38
RunningClaude Codefix/toast-throttle+22 -61:13
Needs attentionGeminifeat/bearer+38 -211:04
RunningAiderchore/prune+14 -523:09
RunningCodexfeat/ansi-map+71 -111:52
RunningCursora11y/reduced-motion+33 -73:25

Click a row to pin its worktree in the rail · hover a worktree for its path

01

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.

agents
12
8 running2 attention1 done1 idle

12 agents · 12 worktrees · one trunk · order steady · 0 reflows

02

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.

Checkout strategy
isolated

5 worktrees, one trunk

per-worktree fork

Each shoot ends in its own checkout node — no two agents touch the same tree.

.git/worktrees layout

.git/worktrees
.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
.grove/wt/auth-flow/src/session.ts
+6-1modifiedclean apply
@@ -18,7 +18,12 @@ export function refreshSession(token: Token) {
1818 const claims = decode(token);
1919 if (claims.exp < now()) {
20- throw new Expired();
20+ // Rotate instead of failing the open session.
21+ const next = rotate(claims);
22+ audit.record(next.id, claims.sub);
23+ return next;
24+ }
25+ return token;
2126 }

Grove: each diff applies to its own tree — no shared-file contention.

03

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.

recorded session
grove › auth-flow · pwsh 7.4 · .grove/wt/auth-flow$ bun test auth/bun test v1.3.14 ok auth/login.test.ts 8 pass 142ms ok auth/session.test.ts 5 pass 61ms fail auth/refresh.test.ts 1 fail expected 200 — received 401 (token expired) 13 pass · 1 fail · 19 expect() calls› agent paused — waiting on your input to continue
pwsh 7.4 · .grove/wt/auth-flow120×32live

Replay the active tab with the ▶ control, or run up from the command palette (⌘K).

04

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.

Diff layout
inline · amend one line before staging
.grove/wt/diff-virtualize/packages/ui/src/react/DiffView.tsx
+5-2modified
@@ -91,9 +91,12 @@ export function DiffView(props: DiffViewProps) {
9191 return (
9292 <div className={cn(
93- "overflow-auto",
93+ "overflow-auto grove-grid-contain",
94+ // content-visibility: skip offscreen hunks
95+ // so a 4k-line diff scrolls at 60fps.
9496 )}>
97+ {/* virtualized below */}
9598 {rows}
96- {/* render every row up front */}
amend+ 94// content-visibility: skip offscreen hunks

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.

reviewed · ready

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.

05

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.

RunningNeeds attentionIdleDoneError

14

agents

8

running

2

attention

1

idle

2

done

1

error

attention queue
boardgroup by
running8
fix/auth-flowfix/pty-backpressurechore/migratefeat/adapter-codexfix/toast-throttlechore/prunefeat/ansi-mapa11y/reduced-motion
needs attention2
feat/portsfeat/bearer
done2
perf/difffeat/qr-pair
error1
feat/sync
idle1
docs/hotkeys
06

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.

pair over loopback

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.

grovenot paired

Locked

Pair from the desktop QR to bind this phone to the running cockpit.

grove://loopback:7433/pair

to-scale · 300px

07

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.

self-hostedOSS · MITembedded Postgres (PGlite) · no service to run
macOS · shell
brew install grove
grove up

Grove-1.0.0-arm64.dmg

signed installer · ~ — sample, set at release

download

git clone github.com/GhostlyGawd/grove

build from source · cd grove && grove up

source

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.

grove · @swarm/ui · IBM Plex Sans + Mono (OFL) · Lucide (ISC) · self-hosted · OSS (MIT)

Mission control for a swarm of CLI coding agents — calm surface, swarming depth.

grove · loopback:7433 · bearer · embedded postgres · 0 outbound--:--:--