One coding agent is an assistant. Three coding agents in the same checkout are a demolition crew: they edit the same files, fight over the same branch, and trip over each other's dev servers on the same port. The naive fixes — locks, turn-taking, "please coordinate" in the system prompt — all try to make sharing safe. The right fix is older and simpler than any of them: stop sharing.

Worktrees are the isolation primitive

Git has had the answer since 2015: git worktree add gives you a second working directory backed by the same repository — same object store, same history, different checkout, different branch. It's the cheapest isolation you can buy: no clone, no duplicated history, near-instant to create and destroy.

repo/
├─ .git/                     one object store, shared
└─ .claude/worktrees/
   ├─ feature-login/         branch wt/feature-login ← agent 1
   ├─ bugfix-nav/            branch wt/bugfix-nav    ← agent 2
   └─ refactor-api/          branch wt/refactor-api  ← agent 3

Every agent gets exactly one worktree, on its own wt/ branch. Now the concurrency proof is trivial: two agents can't conflict on files because they don't share files; they can't conflict on commits because they don't share branches. The merge point moves to where it belongs — a human reviewing a diff — instead of being scattered through a hundred racing file writes. Conventions do the rest: worktrees live under .claude/worktrees/ and get added to .git/info/exclude, so the agents' scratch space never pollutes anyone's git status.

Sessions that survive

Claude Work Manager sits on top of this as a self-hosted dashboard: it spawns each agent as a claude -p --output-format stream-json process in its worktree, parses the event stream into a chat UI with tool-use cards and per-turn cost, and — the feature I'd defend in a fight — resumes sessions automatically via --resume when a process dies. A fleet where any crash loses context isn't a fleet, it's a gamble. Resumability changed how I use the thing more than any other property: agents became fire-and-forget, checkable from a phone on the couch, because the worst case stopped being "lost an afternoon of context" and became "picked up where it left off."

It runs through the claude CLI you're already logged into — your account, no API keys stored — and the whole personal layer (registered repos, chat history, settings) lives in gitignored directories, so the open-source core and the personal instance never mix.

The second problem: seeing what they built

Isolation creates a new problem. Three agents means three dev servers, and port juggling (5173, 5174, was it 5175?) is exactly the kind of coordination we just abolished for files. Worktree Optimiser abolishes it for servers: every worktree runs in its own Docker container, and Traefik routes by hostname —

http://main.localhost               →  worktree: main
http://feature-login.localhost      →  worktree: feature/login
http://bugfix-nav.localhost         →  worktree: bugfix/nav

The name of the thing you want to look at is its address. Review a PR and your own branch side by side in two tabs; nothing was stopped to look at anything else. Traefik reads container labels and rebuilds its routing when a container starts, so "add a worktree" and "get a URL" are the same action. There's an MCP server on top, which closes a pleasing loop: the agents can drive the machinery that hosts them — spawn a worktree, boot its container, report the preview URL — without a human in the middle.

What transfers beyond agents

  • Isolation beats coordination. Every concurrency bug in this system was designed out by giving workers disjoint state, not by making shared state safer. This is the same insight as share-nothing architectures and actor models — worktrees just happen to be the filesystem's native version of it.
  • Resumability is the real feature. Parallelism gets the demo applause; recovery is what makes the system usable daily. Design the crash story before the happy path.
  • Name things after what they are. Branch wt/feature-login, container wt-app-feature-login, host feature-login.localhost — one name, three layers, zero lookup tables. Boring naming is load-bearing at fleet scale.
  • The bottleneck moves to review. Once agents run in parallel safely, the scarce resource is your attention on their diffs. That's the honest ceiling on fleet size — not compute, not tokens: how many diffs you can genuinely read in a day.

Both tools are open source, and the Agents page maps how they fit into the studio's wider structure. The fleet built a decent chunk of what's on this site — including, in a turn I enjoy, parts of the tools that run the fleet.