← All posts

Git Worktrees + Claude Code: Parallel Agents Without Merge Hell

Three agents in one checkout will overwrite each other. Git worktrees give every agent its own directory and branch. Here is the exact workflow I run.

The first time I ran three Claude Code sessions at once, I did the obvious thing. Three tabs, one repo, three tasks. Twenty minutes later one agent had rewritten a function another agent was mid-way through refactoring, a database migration was half applied, and git status looked like a crime scene.

The agents were not the problem. The problem was that a git checkout is a single mutable directory, and I had pointed three writers at it.

Git worktrees fix this. Not partially. Completely.

What actually goes wrong in a shared checkout

Three failure modes, in the order they bit me.

The silent overwrite. Agent A reads auth.ts, thinks for forty seconds, writes its version. Agent B read the same file thirty seconds ago and writes its version on top. No conflict marker, no warning. Git sees one file with one final state. You find out during review, if you are lucky.

The branch rug-pull. Agent A runs git checkout -b feature/x. Every other session in that directory is now on feature/x too, because the branch is a property of the checkout, not of the shell. Agent B commits its unrelated work onto A's branch.

The test collision. Both agents run the suite. Both spin a dev server on port 3000. Both write to the same SQLite test file. One of them gets a failure that has nothing to do with its code, then spends ten minutes and a lot of tokens debugging a ghost.

None of these are fixable with discipline or a better prompt. They are structural.

Worktrees in ninety seconds

A worktree is a second working directory backed by the same .git. Same object database, same remotes, same history. Separate files on disk, separate branch, separate index, separate stash state.

# from inside your repo
git worktree add ../myapp-auth -b agent/auth

That creates ../myapp-auth as a full checkout on a new branch agent/auth. It is fast, because git does not re-download anything. It shares objects with the original clone.

The three commands you actually need:

git worktree list                    # what exists and what branch each is on
git worktree remove ../myapp-auth    # delete it (refuses if dirty)
git worktree prune                   # clean up records for dirs you rm -rf'd

Two rules git enforces for you. You cannot check out the same branch in two worktrees, which is exactly the guardrail you want. And git worktree remove refuses if there are uncommitted changes, so you will not delete an agent's unmerged work by accident.

The one-agent-per-worktree workflow

Here is the script I keep in my path. It creates the worktree, copies the things git will not copy, and prints the path.

#!/usr/bin/env bash
# wt <name>: create an agent worktree
set -euo pipefail

name="$1"
root="$(git rev-parse --show-toplevel)"
dir="$(dirname "$root")/$(basename "$root")-$name"

git worktree add "$dir" -b "agent/$name"

# gitignored files do NOT come along. Copy what the app needs to boot.
[ -f "$root/.env" ] && cp "$root/.env" "$dir/.env"
[ -f "$root/.env.local" ] && cp "$root/.env.local" "$dir/.env.local"

echo "$dir"

The dependency question comes up immediately. A fresh worktree has no node_modules, no .venv, no target/. You have three options.

Install fresh in each worktree. Slowest, most correct. This is what I do when the agent might touch package.json.

Symlink from the main checkout. ln -s "$root/node_modules" "$dir/node_modules". Fast, and fine for read-only use. It breaks the moment one agent runs an install, because now every worktree gets that agent's dependency change. Use it only when you are confident nobody is touching deps.

Use a content-addressed store. pnpm and uv both make this a non-issue, because installs are hard links into a shared store. If you are already on pnpm, just run the install in each worktree and stop thinking about it.

Ports are the other thing to handle up front. Give each worktree a fixed offset and write it into the copied .env, so the agent never has to guess:

echo "PORT=$((3000 + RANDOM % 100))" >> "$dir/.env"

Or better, assign deliberately: auth gets 3001, billing gets 3002. Predictable beats random when you are the one opening the browser.

Naming and cleanup

Naming matters more than it sounds like it should, because in a week you will have six directories and no memory of what myapp-2 was.

I use agent/<topic> for the branch and <repo>-<topic> for the directory. The prefix makes cleanup trivial:

git branch --list 'agent/*'          # what am I running
git worktree list                    # where does it live

When work merges, tear it down in this order:

git worktree remove ../myapp-auth
git branch -d agent/auth

If you deleted the directory manually first, git worktree prune clears the stale record. If the worktree has junk you genuinely want to throw away, git worktree remove --force will do it, and the --force is the point: it should take a deliberate keystroke.

Merging is the boring part now, which is the whole goal. Each worktree is a real branch, so it is a normal pull request. Conflicts happen at merge time, where git has fifteen years of good tooling, rather than at write time, where nothing helps you. One tip: merge the smallest branch first. Rebasing three big branches onto each other in a random order costs more than sequencing them by size.

Watching four agents at once

The workflow has one weakness. Agents finish and ask questions at unpredictable times, and a worktree in another directory does not shout. I used to cycle tabs every couple of minutes just to check, which is a bad use of a human.

This is the problem MOLTamp 3.2 was built around. Each worktree gets a tab. Tabs adopt whatever title the agent sets, so Claude Code's /rename puts "auth refactor" on the tab instead of a directory path. When an agent is waiting on input and the tab is not focused, the badge glows amber. When it finishes, the badge goes green. Cmd+P opens a session manager with search, so at fourteen tabs you type "auth" instead of hunting.

The practical effect is that I stop polling. I work in one tab and respond to the color changes. If you want the shell to also look like your project, the skinning docs cover per-session themes, and the community marketplace has skins other people already built.

What I would skip

Do not spin a worktree for a one-file change. The setup cost is thirty seconds and the review cost is real. Just do it in the main checkout.

Do not run eight agents. I have tried. The bottleneck is not the machine, it is me reading eight diffs. Three or four is where the throughput actually peaks.

Do not let agents merge their own branches into main. The isolation you just built exists so that a human sees each diff once. Spend the ten minutes.

For more on running several sessions at once, see running multiple Claude Code sessions and multiple AI agents in one terminal.

Quick reference
git worktree add ../repo-topic -b agent/topic   # create
git worktree list                               # inspect
git worktree remove ../repo-topic               # delete
git worktree prune                              # clean stale records
git branch --list 'agent/*'                     # what is in flight

Five commands. It replaced every merge disaster I used to have.