01. The problem with one checkout
When components are independent, the obvious move is to port them in parallel. While porting a design system to Angular (the full story), one wave ran up to nine implementer agents at once, all in the same working tree. Each agent's last step is a verification run: type-check, tests, lint, a production build. Each run saw every other agent's half-written files.
The result, in the wave's own run report: the shared build was red most of the time.
- False failures. Agent A's verification fails on agent B's unfinished component. A either wastes tokens investigating, or learns to ignore red, which is worse.
- Races on shared state. Two agents committing at once fight over git's index lock. Two production builds write to the same output folder.
- Commits that carry the wrong files. A bare
git commit -apicks up a neighbour's edits. We forced pathspec commits (git commit --only -- <paths>), which helps with the commit but not with the build. - One agent's git surgery is everyone's. An implementer that "tidied" history with low-level ref commands rewrote the branch under eight colleagues.
- Ports. Every agent's end-to-end run wants the same dev-server port.
It is not only agents. The main checkout was also shared with other Claude sessions switching
branches in it, and one git reset --hard moved the wrong branch. A checkout is shared
mutable state, and parallel writers on shared mutable state is a bug whoever the writers are.
02. What a worktree gives you
git worktree add creates a second working directory attached to the same repository:
its own checked-out branch, its own index, its own files, but the same object store and the same
refs. Creating one is cheap: no clone, no network, seconds.
one task, one worktreegit worktree add .claude/worktrees/wave2-task-7 -b wave2/task-7 feature/ui-kit
ln -s ../../../node_modules .claude/worktrees/wave2-task-7/node_modules
# the agent works, verifies and commits only in here
# the dispatcher lands it:
git -C .claude/worktrees/wave2-task-7 rebase feature/ui-kit
git switch feature/ui-kit && git merge --ff-only wave2/task-7
git worktree remove .claude/worktrees/wave2-task-7
From the next wave on, every implementer got its own worktree under
.claude/worktrees/. An agent's verification now sees exactly the code it wrote on top of
the last landed state, and nothing else. A red build means that agent broke something.
03. How we run it
- Symlink
node_modules. A fresh install per worktree costs minutes and gigabytes. Claude Code has a setting for exactly this (worktree.symlinkDirectories: ["node_modules"]), and subagents can be declared withisolation: worktreeso the platform creates and cleans up the tree itself. - A port per agent. Agent N runs its e2e server on 4400 + N. Wave gates run on their own fixed port, after another project's dev server took the default one in the middle of a gate.
- Only the dispatcher lands. Finished tasks are rebased onto the integration branch and fast-forwarded, one at a time, never while a gate is running. Agents never touch the integration branch.
- Gates run on the integration branch, not in a task tree. A task proves itself; the wave gate proves the combination.
- A long-lived worktree for a long-lived branch. The whole UI kit lived on one branch in one worktree for weeks, so the main checkout stayed free for reviews, hotfixes and other tickets.
- Remove when landed. A finished task's worktree is removed the moment it lands.
git worktree removeis allowed for agents;rm -rfis not.
| Shared checkout | Worktree per agent | |
|---|---|---|
| Verification | sees every agent's half-edits | sees one agent's work on landed code |
| Commits | pathspec discipline, index-lock races | own index, plain commits |
| Builds and dev servers | one output folder, one port | per tree, port 4400 + N |
| Git mistakes | hit everyone | hit one branch |
| Integration | implicit and continuous | explicit: rebase, fast-forward, gate |
04. What still goes wrong
A symlinked node_modules belongs to whichever branch installed it. One worktree was
cut from a branch on the next framework major while the shared modules were still the old one:
every first verification failed until someone ran a clean install. When the branch's lockfile
differs from the one that installed the modules, the tree needs its own install.
Nx starts a daemon per workspace. Removing a worktree whose daemon is still alive leaves its cache folder behind, and a daemon whose graph went stale after a library rename silently skips the new library. Our verification script runs with the daemon off.
Worktrees are cheap to create and easy to forget. Six weeks in, 46 were registered and about 20 belonged to merged or abandoned work, plus hundreds of megabytes of build copies. One cleanup took it to 7. Now a worktree is removed when its task lands, and a worktree for a human branch is created only when someone asks for isolation.
05. The takeaway
Parallel agents are parallel writers. Give each one its own working tree, its own port and its own branch; let exactly one actor integrate, in order, with a gate on the result. Git has had the primitive since 2015. The agents are what made it necessary.
A red build should mean one thing: the agent that ran it broke something.