The first time I ran two Claude Code agents in the same repo without worktrees, one of them checked out a different branch mid-session and wiped out the other agent's uncommitted edits. The other agent kept working against a phantom file state, writing code that referenced files that no longer existed. The whole run collapsed.
This is the pattern I use now. Git worktrees plus file-ownership claims. Three instances of the pattern in production.
The pattern
Git worktrees are a built-in feature of git (available since 2.5, stable since 2015) that let you have multiple working trees checked out from the same repo at the same time. Each worktree has its own directory, its own working tree, its own branch. They share the underlying .git so pushes and pulls are unified, but the file state is independent.
For parallel Claude Code agents, this maps perfectly. Each agent lives in its own worktree. Branch switches in one worktree do not affect the others. File edits in one worktree do not touch the others. Two agents can work simultaneously on different features without stepping on each other.
The killer detail: you still share one .git, so commits from either worktree show up in the same local repo history. Branches are cheap. Pushes are unified. You do not pay the storage cost of a full clone per worktree.
Instance 1: the two-agent feature split
A shop I was working with had two features to ship in parallel. Feature A was a Shopify theme section. Feature B was a copy refresh across marketing pages. Totally independent work.
Running them in the same worktree would have been fine if both agents behaved. They did not. Agent A kept switching branches to verify context from main. Agent B's uncommitted edits disappeared on each switch. Five minutes of lost work per collision.
What the shape tells us: even when agents are working on unrelated features, they can collide through branch switches, file state, and shell state. Isolation is the cheapest fix.
How it resolved: spawned two worktrees, one per agent. Agent A in repo.feature-a/ on branch feature/a. Agent B in repo.feature-b/ on branch feature/b. Zero collisions for the rest of the run.
Instance 2: the build-and-review pair
Not every parallel pattern is two feature streams. Sometimes it is one active developer and one review agent.
I run a workflow where I edit code in one worktree while a review agent runs continuously against the last commit in a second worktree. The review agent watches for new commits, runs the review pipeline, writes findings to a shared notes file. My editing worktree does not affect it; its review worktree does not affect me.
What the shape tells us: worktrees are not just for parallel features. They are an isolation primitive. Any time you want two processes on the same repo with different file states, worktrees are the answer.
How it resolved: main/ is my editing worktree. main.reviewer/ is the review agent's worktree, always checked out to the latest commit on main. When I commit, the reviewer notices, fetches, and runs. We never block each other.
Instance 3: the hotfix + feature overlap
A brand I was working with needed a hotfix on production while a feature branch was mid-flight. Without worktrees, I would have stashed the feature work, checked out main, done the hotfix, checked back to the feature branch, popped the stash. Ten minutes minimum, assuming no merge conflicts on the pop.
What the shape tells us: worktrees let you handle branch context switches without touching your working tree.
How it resolved: created a third worktree, repo.hotfix/, checked out to main, made the fix, pushed, deleted the worktree. Feature work never interrupted. Hotfix shipped in about 90 seconds of branch setup.
The setup script
Worktrees have a few gotchas around node_modules, IDE configs, and symlinks. I wrote a short bash helper that handles the common setup.
#!/usr/bin/env bash
# scripts/agent-worktree.sh
# Usage: ./scripts/agent-worktree.sh feature/some-branch
set -euo pipefail
BRANCH="${1:?branch name required}"
SAFE="${BRANCH//\//-}"
REPO_NAME="$(basename "$PWD")"
TARGET="../${REPO_NAME}.${SAFE}"
# Create the branch if it doesn't exist yet, branching off main.
if ! git rev-parse --verify "$BRANCH" >/dev/null 2>&1; then
git branch "$BRANCH" main
fi
# Create the worktree.
git worktree add "$TARGET" "$BRANCH"
# Symlink node_modules so we don't pay the install cost per worktree.
if [[ -d "node_modules" ]]; then
ln -s "$(pwd)/node_modules" "${TARGET}/node_modules"
fi
# Copy .env.local if present (it isn't in git).
if [[ -f ".env.local" ]]; then
cp .env.local "${TARGET}/.env.local"
fi
echo "Worktree ready: $TARGET"
The script does three things worth calling out:
- Creates the branch if missing. First-time workflows often forget this step.
- Symlinks node_modules. Worktrees share
.gitbut notnode_modules. Symlinking saves the install cost and keeps versions aligned. - Copies
.env.local. Environment files that are not in git need to be copied manually. Easy to forget.
The file-ownership rule
Worktrees isolate file state. They do not isolate intent. If two agents decide they both need to edit the same file, they can still write conflicting changes (on different branches, merged later as a merge conflict).
What I do to reduce the merge-conflict tax: a file-ownership table. Each agent claims a region of the codebase before starting. Written down in a shared CLAUDE.md or a notes file.
Agent A: src/lib/checkout.ts, src/components/Checkout/**
Agent B: src/lib/cart.ts, src/components/Cart/**
The rule: agents can read any file, but modify only files in their owned regions. If an agent needs to modify outside its region, it stops and asks. This turns most merge conflicts from "surprise at merge time" into "coordination at dispatch time."
This pattern generalizes beyond agents. I use the same file-ownership table on projects where multiple developers share the repo, too. The parallel dispatch post covers the broader coordination cost.
Cleaning up
Worktrees stay around after you stop using them. Clean up when you are done:
git worktree remove ../repo.feature-a
Or, if the directory is already gone (IDE cleaned it up, you deleted it manually), tell git:
git worktree prune
Stale worktrees do not cause bugs, but they accumulate and clutter git worktree list. I clean up weekly.
What the pattern tells us
Three things I keep coming back to:
- Parallel agents in the same repo need isolation at the filesystem level. Not just at the branch level. Branch switches affect the working tree; worktrees decouple them.
- File-ownership claims prevent most merge conflicts. A cheap coordination step at dispatch time saves expensive reconciliation later.
- Worktrees compose with background agents. A long-running build in one worktree, an active edit session in another, with the build backgrounded via run_in_background, is the shape that unlocks serious multi-thread work.
How to spot when worktrees are overkill
Two signals:
- You are running one agent at a time. Worktrees add setup overhead for no benefit if only one agent is active.
- Your parallel agents are genuinely working on disjoint files and never switch branches. Without branch switches, the collision risk is low.
On the other side, two signals that you definitely want worktrees:
- You have ever said "wait, what did that other agent just do to my working tree?"
- You have ever lost uncommitted work because another agent checked out a different branch.
For operators running multi-agent workflows in production, the Operator's Stack curriculum includes the full worktree + file-ownership pattern applied to a real DTC engineering shop. The agent engineering handbook indexes the broader concurrency discipline.
FAQ
Do worktrees need a lot of disk space?
Each worktree is a full working tree of files, so yes. But .git is shared, which is usually the largest part of a repo. On a 500MB repo with a 400MB .git, each worktree adds 100MB, not 500MB.
Can I work on the same branch in two worktrees?
No. Git enforces that each branch is checked out in at most one worktree. If you try, git refuses with an error. Use different branches (one per worktree) or use a detached HEAD.
Does Claude Code know about worktrees automatically?
Yes. If you point Claude Code at a worktree directory, it treats it as a normal repo. You can have multiple Claude Code sessions open, each in a different worktree, with no special configuration.
What happens if I delete a worktree directory without using git worktree remove?
Git thinks the worktree still exists. Run git worktree prune to clean up the stale references.
Can worktrees replace parallel branches in a single worktree?
Not always. For one developer, branch switching in a single worktree is fine for most work. Worktrees pay off when you need two checkouts live at the same time, which is the parallel-agent scenario.
