Claude Code Worktree Setup for Parallel Agents
A git worktree is a second working directory attached to the same repository, with its own checked-out branch, living in its own folder on disk. That is what makes parallel Claude Code agents possible: each agent gets a real directory to run in and a real branch to commit to, so two agents can edit two different branches of the same repo at the same time without either one running git checkout on top of the other.
git worktree add ../myrepo-feature-x -b feature-x
git worktree list
git worktree remove ../myrepo-feature-x
add creates the new directory and branch in one step, list shows every worktree attached to the repo and which branch each one has checked out, and remove deletes a worktree once you are done with it. Nothing here is Claude Code specific: worktrees are a plain git feature. What is specific to running agents is what breaks when you skip this and let two agents share one checkout.
Why agents need their own working tree, not just their own branch
A single checkout has one file tree on disk and one HEAD. If an agent runs git checkout -b some-branch in that checkout, it just repointed the one file tree every other process in that directory is using. That is fine for a human switching tasks serially. It is not fine for two agents running at the same time, because the second agent’s checkout happens underneath the first agent’s uncommitted work: the first agent’s edits are still sitting in the working directory, unstaged, and the second agent’s branch switch silently rewrites the files out from under it. Nothing errors. The first agent keeps editing files that now belong to a different branch, and the corruption surfaces later, if it surfaces at all, as changes that mysteriously vanished or landed on the wrong branch.
The rule that avoids this is simple and has no exceptions: one working tree per repository per agent, always. A worktree gives each agent its own directory and its own HEAD, so a branch switch in one worktree cannot touch another worktree’s files. Git itself helps enforce this in one direction: it refuses to check the same branch out in two places at once, so you cannot accidentally double-assign a branch even if you try.
That still leaves the shared-checkout failure mode open for everything else. Every prompt you hand to a delegated agent working in a shared repo should explicitly forbid four commands: git checkout --, git stash, git reset, and git clean. Each one mutates the working directory or the index in a way that can silently discard or hide another process’s changes, and none of them announce that another agent’s work was sitting there. A worktree keeps agents out of each other’s way structurally; the forbidden-command list is what keeps a single agent from doing the same damage to itself, or to files a supervising process assumed were safe.
Multiple repos: branches drift, and merges are not transactional
Real work rarely stays inside one repo. The moment you are coordinating agents across a backend repo and a frontend repo, two things stop being obvious and both cause real breakage if assumed away.
First, never assume sibling repos share a branch. They drift independently: one repo can sit three commits ahead of main while another is still exactly on it, and an agent that assumes both are on the same branch will operate on the wrong base without any error telling it so. Check each repo’s git status before acting on it, every time, rather than trusting the last time you looked.
Second, pull requests across repos are not transactional. There is no mechanism that merges a backend PR and a frontend PR together, or rolls one back if the other fails. If the frontend PR merges first and expects an API the backend PR hasn’t shipped yet, you get a broken window between the two merges with no automatic protection. The fix is procedural, not technical: merge the backend PR first, and write the intended order directly into each sibling PR’s description so whoever merges second knows a first exists and has already landed.
The RAM leak: what happens when every worktree bootstraps at once
This is the failure that does not show up until you actually run several worktrees in parallel, and it is worth naming precisely because the obvious safeguard does not catch it. Each worktree here maps to one ticket, shiploop’s term for a single piece of dispatched work, the one you’ll find under a ## #N heading in queue/tickets.md.
Every new worktree that gets used for real work needs its dependencies installed, and running several ticket-driven agents in parallel means several worktrees bootstrapping their installs at close to the same moment. The natural instinct is to throttle that inside the bootstrap script itself, something like backgrounding the install and wait-ing on it. That throttle works, but only within one worktree’s own bootstrap. It has no visibility into any other worktree’s bootstrap running at the same time in a different process. So the real ceiling on concurrent installs was never one number: it was tickets in flight multiplied by repos per ticket multiplied by roughly a gigabyte of resident memory per install, with nothing capping the product.
Measured on a twenty-four gigabyte laptop running a governor fleet in parallel: thirteen concurrent dependency installs pushed resident memory to about ~14GB shiploop CHANGELOG.md with 3.7GB shiploop CHANGELOG.md swapped, and the machine was unusable for minutes. Neither layer involved was individually wrong. A concurrency knob at the governor level reasons about API spend and how many agents should run at once. A wait at the end of one worktree’s bootstrap script reasons about that one worktree’s own install finishing before the script continues. Nothing in between either layer was denominated in machine memory, so nothing caught the case where every worktree’s install landed in the same few seconds.
The actual fix is a cross-process semaphore: a shared slot count that every worktree bootstrap, regardless of which process or which worktree it belongs to, has to acquire before it is allowed to start installing, and release when it finishes. That caps concurrent installs globally instead of per-worktree. The default cap is four concurrent installs (WORKTREE_INSTALL_PARALLEL, default 4), enforced through atomic slot acquisition so it works safely even across independent processes that share no memory.
Cleanup: a worktree you never remove is a leak
A worktree that finishes its job and never gets removed is not harmless. It is a leaked checkout on disk plus a leaked node_modules (or equivalent dependency tree) sitting inside it, and if you accumulate enough of them the same RAM and disk pressure from the section above comes back through a different door: stale worktrees left mid-install, or just left holding gigabytes of installed dependencies nobody is using anymore.
git worktree remove ../myrepo-feature-x
git worktree prune
remove deletes a specific worktree; prune cleans up git’s own bookkeeping for worktrees whose directories were already deleted by hand instead of through remove. The right moment to run cleanup is right after the PR from that worktree merges, not “later.” Later is where leaked worktrees actually come from.
One more cleanup step that is easy to skip: tear the local dev stack down the moment a PR opens, not after it merges. A dev server left running against a worktree that is about to be removed holds a port open and keeps serving stale code from a branch that no longer reflects what is under review, which produces confusing results for anyone checking the PR against a running instance.
Never do this
- Never point two agents at the same checkout in one worktree. Give each its own worktree.
- Never let a delegated agent run
git checkout --,git stash,git reset, orgit cleanin a shared repo. Forbid all four explicitly in the prompt. - Never assume sibling repos are on the same branch. Check
git statusin each one. - Never merge cross-repo PRs without stating the merge order in each PR description.
- Never let worktree bootstraps install dependencies with no shared concurrency cap. Uncapped parallel installs are how a laptop runs out of RAM.
- Never leave a worktree around after its PR merges, and never leave a dev server running once the PR is open.
For the underlying mechanics of how Claude Code runs work in the background at all, see Anthropic’s headless mode documentation and the sub-agents documentation, which describe how a session can hand work to another process in the first place.
The shiploop angle
shiploop wraps this whole flow into two commands: npm run worktree:new -- <slug> creates a fresh worktree per ticket across every sub-repo in the workspace, and npm run worktree:rm -- <slug> tears it down once the PR merges. The convention is one worktree per ticket, never shared, and reaping runs automatically so finished worktrees don’t sit around leaking disk and dependencies after the work is done. The cross-process install semaphore described above is exactly the mechanism that keeps a fleet of these worktrees bootstrapping in parallel without taking a machine down.
See our guides on subagents, running Claude Code headlessly, and managing token usage for the rest of what makes parallel agent work practical rather than a novelty.
Last updated 2026-09-04.