One task, one branch, one worktree. That is the clean way to run multiple agents in parallel. The git commands are the same on every OS — the path conventions and the gotchas are not.
The four-line recipe to give one agent its own isolated branch. Click through the tabs for your shell.
$cd ~/code/myrepo$git worktree add ../myrepo-add-auth -b add-auth # create branch + checkout at path$cd ../myrepo-add-auth$claude # agent runs in its own dirgit worktree add <path> -b <branch> — create a new branch and check it out at <path>.
git worktree add <path> <branch> — check out an existing branch at a new path. The branch can only live in one worktree at a time.
git worktree list — show every worktree attached to the repo, including the main one.
git worktree remove <path> — clean removal. Refuses if there are uncommitted changes; pass --force to override.
git worktree prune — drop bookkeeping for worktree directories that were deleted by hand. Run this after a rm -rf.
git worktree lock <path> --reason "agent mid-task" — protect a worktree from accidental remove or prune. Useful when an agent is in the middle of a long edit and you do not want a bulk-cleanup script to take it out.
git worktree move <path> <new-path> — rename a worktree directory without confusing git. Renaming with mv alone leaves git pointing at the old path.
git worktree repair — fix the internal links after you have moved the main repo or a worktree by hand. Saves you from re-cloning.
If you only run Claude Code, the official CLI now has a --worktree flag (short: -w) that does add + cd + launch in one step:
claude --worktree feature-auth
# creates .claude/worktrees/feature-auth/ on a new branch worktree-feature-auth
# cds in, starts Claude thereTwo things to do before you rely on it. Add .claude/worktrees/ to your .gitignore so the in-repo worktrees do not show as untracked files. And if your default branch on the remote was renamed after you cloned, run git remote set-head origin -a once — otherwise new worktrees branch from a stale base.
This is great if Claude Code is your only agent. The moment you also run Codex or Aider, you are back to managing the worktrees yourself — which is the rest of this page.
Every worktree is a real, separate directory. Your shell, your editor, and the agent only see the one they were started in. After you run git worktree add, nothing automatically moves you there — you have to cd in yourself, and remember to start the agent from inside that directory. Forget once and you will run Claude Code in the main checkout and wonder why the diff lands on the wrong branch.
Three habits help:
put the branch in your prompt. Every shell can show the current git branch. With four worktrees open, this is the only thing that tells you which window is which without running a command.
use git worktree list. One command, one line per worktree, with the path and branch. Run it whenever you lose track.
name worktree directories after the branch. ../myrepo-add-auth is self-documenting. ../wt-2 is not.
Worktrees do not clean themselves up. Once a PR merges, the branch still exists locally and so does the worktree. Multiply by ten agents a week and your repo accumulates dead branches and dead directories.
The full teardown:
# from inside the main checkout, not the worktree
git worktree remove ../myrepo-add-auth # drop the worktree directory
git branch -d add-auth # delete the local branch
git fetch --prune # drop the remote-tracking refTwo things go wrong here. First, git worktree remove refuses if you are currently cded into the worktree you are deleting — the shell is holding the directory open. Move out first. Second, if you delete the directory by hand with rm -rf instead, git keeps the bookkeeping forever until you run git worktree prune.
For bulk cleanup of merged branches and their worktrees:
git fetch --prune
for b in $(git branch --merged main | grep -v 'main\|master'); do
wt=$(git worktree list --porcelain | awk -v b="$b" '/^worktree/{p=$2} $0=="branch refs/heads/"b{print p}')
[ -n "$wt" ] && git worktree remove "$wt"
git branch -d "$b"
done.env files are missing. A fresh worktree is a fresh checkout. Anything in .gitignore — your .env, your .env.local, your local config — is not there. The agent will run, the dev server will boot, then crash on the first secret. Fix: copy them into every new worktree, or use Claude Code's .worktreeinclude at the repo root (gitignore syntax; only gitignored files get copied).
node_modules eats your disk. Each worktree needs its own npm install before the agent can build. People have reported 10+ GB consumed in an afternoon across auto-created worktrees. Switch to pnpm: its content-addressable store symlinks packages so repeated installs across worktrees cost negligible disk.
Ports collide. Worktrees isolate files, not runtime. Two worktrees both running npm run dev will fight over localhost:3000. Pick a per-worktree port — PORT=3001 npm run dev in the second one, or define it in that worktree's .env.local. Same problem applies to Postgres ports, Redis ports, anything bound to a fixed address.
Stashes are shared across all worktrees. The stash list lives in .git, which is shared. A stash created in one session shows up in every other session and can be applied from the wrong place. Name your stashes (git stash push -m "wt: add-auth") or just avoid stashing while parallel agents are running.
macOS / Linux: the most common mistake is putting worktrees inside the repo (./worktrees/foo). Git will complain and your .gitignore gets weird. Use a sibling directory.
Windows (PowerShell): Windows still has a 260-character path limit unless long paths are enabled (git config --global core.longpaths true). Pick short worktree directory names. Set core.autocrlf=true globally so worktrees do not disagree about line endings. Antivirus scanning every file in a fresh worktree can make the first add take 30+ seconds — exclude your dev folder.
WSL: keep the repo and all worktrees inside the WSL filesystem (/home/...), not /mnt/c. Crossing the boundary is 10–100× slower for git operations. And do not open the same worktree from PowerShell at the same time — line-ending mode collides.
Submodules: each worktree gets its own submodule state. Run git submodule update --init after the first add if your project uses them.
The error you will see most:
fatal: 'add-auth' is already used by worktree at '/Users/you/code/myrepo-add-auth'A branch can only be checked out in one worktree. Either cd into the existing worktree, or git worktree remove it first, or pass --force to the new add.
The unlock is real — agents stop stepping on each other's files, and you can review four diffs in parallel instead of one. The cost is also real, and it does not live in any of the commands above. It lives in your head.
You can wrap git worktree add, cd, agent launch, and teardown in npm scripts, justfiles, or shell aliases. People do. It helps. But the scripts still need a human in the right terminal at the right time — knowing which window points at which branch, which agent is mid-edit, which worktree was already merged and is safe to remove. Add a fourth agent and your working memory is now a bookkeeping job.
Create a session. Pane gives the agent its own worktree, opens a terminal there, shows the diff, and keeps commit / push / rebase / merge a keystroke away. The lifecycle above — add, cd, run, review, remove, prune — collapses into one window per agent with a label, a status dot, and a teardown button.
Raw worktrees are a great Git primitive and a miserable interface. Pane makes the primitive feel invisible while keeping the review loop explicit.
- run Claude Code and Codex on Windows
- compare Pane with Claude Squad