Running Claude Code in Parallel with Git Worktrees
The moment you run two Claude Code sessions against the same checkout, they start stepping
on each other: mixed git status, builds picking up half-finished edits from the
other task, commits that bundle unrelated changes. git worktree fixes this with one clone and one working
directory per session. This guide is the worktree setup we actually use — including the
parts that only bite after a week of daily use.
Why worktrees beat the alternatives
There are three ways to give parallel sessions their own files, and two of them have real costs:
- Same checkout, "be careful" — fails immediately. Both sessions see each other's
uncommitted edits, and a
git checkoutin one silently rewrites the files the other is reading. - Multiple clones — works, but each clone duplicates the entire object store, re-fetches independently, and drifts out of sync with your remotes and local branches.
- Worktrees — one repository, one shared object store and remote config, any number of working directories, each pinned to its own branch. Creating one takes about a second.
The basic setup
# From your main checkout
git worktree add ../myapp-fix-auth -b fix-auth
git worktree add ../myapp-new-onboarding -b new-onboarding
# One Claude Code session per worktree
cd ../myapp-fix-auth && claude # terminal tab 1
cd ../myapp-new-onboarding && claude # terminal tab 2
git worktree add <path> -b <branch> creates the directory, creates the
branch, and checks it out in one step. Each session now has a clean tree and its own build
artifacts, and commits made in one worktree are instantly visible to the others — same
repository, so no pushing or pulling between them.
Name the directory after the task, not the repo: myapp-fix-auth beats
myapp-2. Every session list you look at — terminal tabs, git worktree
list, a status board — shows the directory name, so this one habit keeps every list readable.
Keeping worktrees as siblings of the main checkout (../myapp-*) makes them easy
to find and easy to exclude from backup and file-watcher configs.
What worktrees share — and what they don't
Worktrees share the object store, branches, remotes, stashes, and repository config. They do not share anything git doesn't track — and that's the list that catches people:
.envand local secrets — untracked by design, so a fresh worktree starts without them. Copy what the task needs:cp ../myapp/.env .- Installed dependencies —
node_modules/, virtualenvs, and friends are per-directory. Run your install step once per worktree, or the first build fails confusingly. - Build caches — each worktree builds from scratch the first time. That's the price of isolation; incremental builds are fast after that.
Tracked files need no such care, which is exactly why a per-repo
CLAUDE.md works so well with worktrees: every new worktree, and therefore every
new Claude Code session, starts with the same build commands, test commands, and conventions
without re-explaining. A branch can only be checked out in one worktree at a time — git
refuses the second checkout. That's a feature: it makes "which session owns this branch"
unambiguous.
The lifecycle: merge, remove, prune
Worktrees are cheap enough to be disposable. When the branch merges:
git worktree remove ../myapp-fix-auth # deletes the directory
git branch -d fix-auth # deletes the merged branch
git worktree prune # cleans up records for manually deleted dirs
Treat a worktree like a session, not a home: create it when the task starts, remove it when the branch merges. Long-lived worktrees drift behind the default branch and greet you with conflicts; if one must live for weeks, rebase or merge regularly like any long-lived branch. Ending the Claude Code session when its worktree goes away keeps every session list truthful.
The part worktrees don't solve: who needs you now
Worktrees isolate the files. They do nothing about attention. Each parallel session still blocks at unpredictable moments — a permission prompt for an edit or shell command, a plan waiting for approval, a clarifying question, or plain completion — and with three or four worktree sessions running, one of them is usually stalled behind the others' output while you watch the wrong tab.
Claude Code's hooks
can push each of those moments to you as a
macOS notification. For the aggregate view —
"which of my worktrees is blocked right now?" — we built
AgentManager: a macOS menu bar app that lists every Claude Code session as a row
with a status lamp —
waiting for input,
running,
done,
idle.
Rows are labeled with the working directory's name — which is why task-named worktrees like
myapp-fix-auth pay off twice — and clicking a row jumps to the terminal pane
running that session in iTerm2, Terminal.app, Ghostty, and VS Code-family editors
(tmux sessions are tracked on the board too, but pane jumping isn't supported for tmux yet).
The window surfaces on its own when a session starts waiting, and hides when everything is clear.
A worktree session checklist
- One worktree, one branch, one session. The 1:1:1 mapping is what makes parallel work reviewable.
- Name worktree directories after tasks. Every list you'll ever scan shows that name.
- Script the setup. A five-line
new-task.shthat runsgit worktree add, copies.env, and installs dependencies removes the friction that tempts you back into a shared checkout. - Match worktree count to review bandwidth. Each session produces diffs you must read; two to four parallel tasks is the sweet spot for most people.
- Remove worktrees when branches merge. Stale worktrees turn every list into archaeology.
One status lamp per worktree
AgentManager shows every Claude Code session — across all your worktrees — in one floating window, and surfaces the one that needs you. Free to use, no account required.