Claude Code Worktrees: Run Parallel Sessions Without Collisions
Run parallel Claude Code sessions with git worktrees: what claude --worktree creates, what it isolates, what stays shared, cleanup, and subagent isolation.
By Matthews WongReviewed on Checked against Claude Code v2.1.301
Key takeaway
A git worktree is a second working directory with its own files and branch, sharing one repository history. Running claude --worktree gives each Claude Code session its own checkout, so two sessions can edit the same project without overwriting each other. Isolation covers files only: history, approvals and everything outside the repository stay shared.
You will be able to
- Start isolated parallel sessions with claude --worktree and know where they live.
- Name what a worktree isolates and what it still shares with the main checkout.
- Choose between a worktree session, a plain subagent and a subagent with isolation.
Step through the diagram
Press Play, or step with the arrows. Every step is written out below the diagram.
Two sessions, two checkouts, one repository
claude --worktree creates a checkout under .claude/worktrees on its own branch for each session; edits stay in that directory while the .git history is shared, and exiting asks whether to keep a worktree that holds changes.
Reviewed on 17 October 2026 · Claude Code v2.1.301
Keys: ← → step · Home / End · K play or pause
A git worktree is a second working directory with its own files and branch, sharing the repository's one history. So far there is only the main checkout and its .git.
claude --worktree feature-auth creates a checkout under .claude/worktrees on a new branch, worktree-feature-auth, and starts the session inside it.
claude --worktree feature-authA second terminal and a different name give session B its own checkout and branch. Each session now holds a separate copy of every tracked file.
claude --worktree bugfixPredict the next step Both sessions edit the same file at the same moment. Do they overwrite each other? (Yes, there is one file on disk · No, each has its own copy)Session A's edit lands only in its own directory. The main checkout and session B's copy are untouched until you bring the branches together with git.
git worktree listA worktree holds tracked files only. Untracked files such as .env are missing and dependencies are not installed, unless a .worktreeinclude file copies the ignored ones.
.env .env.localPredict the next step You exit session A, which left uncommitted changes. What happens to its worktree? (It is removed silently · Claude asks: keep or remove · It is always kept)On exit Claude checks for work. A clean unnamed worktree is removed with its branch; one holding changes prompts you, and keeping it preserves the directory and branch.
claude --worktree feature-auth --resume
What does claude --worktree create, and where does it put it?
A git worktree is a separate working directory with its own files and its own branch, sharing the repository's history and remote with your main checkout. Pass --worktree, or -w, with a name and Claude Code creates one and starts the session inside it. By default it lands under .claude/worktrees/ at the repository root, on a new branch named worktree- followed by your name. Run the same command with another name in a second terminal and you have two isolated sessions. Leave the name out and Claude generates one.
Read more (2)Show less
Three preconditions trip people up. The repository needs at least one commit, because a worktree is created from an existing commit. An interactive run needs workspace trust, so run claude once in the directory first. And the docs suggest adding .claude/worktrees/ to .gitignore so the contents do not show up as untracked files in your main checkout.
By default a new worktree branches from the repository's default branch on the remote, usually main, not from whatever you have checked out. Set worktree.baseRef to "head" in settings to branch from your current local HEAD, which carries unpushed commits. To start from a pull request, quote the number with a hash: claude --worktree "#1234". Passing a name whose directory already exists opens that worktree instead of creating a new one.
What do parallel worktrees isolate, and what do they still share?
A worktree isolates files. While a session is isolated, Claude Code blocks edits that target a path in the main checkout, blocks shell commands whose working directory resolves there, and blocks git commands redirected into it. The same checks cover every subagent that session spawns. They read paths and command text only, so a cp or a shell redirect that writes into the main checkout without running git is not refused by them. It is an ordinary command under your permissions and sandbox settings.
Read more (2)Show less
A worktree still shares a lot. Every worktree writes to the repository's one .git directory, which is why git commit works inside each. Plugins installed at project scope load in every worktree of the repository. And when you choose Yes, and don't ask again on a Bash command, the rule is saved to the main checkout's .claude/settings.local.json, so it applies in your other worktrees too and survives the worktree's removal. Anything outside the repository, such as a temporary folder, a port or a database, was never part of the checkout, so it is shared by definition.
Two setup gaps follow from a worktree being a fresh checkout. Untracked files such as .env are absent, so list them in a .worktreeinclude file at the project root. It uses .gitignore syntax and copies only files that match and are also gitignored. Dependencies are not installed either, so ask Claude to run your project's setup in the worktree. One hook detail matters too: after Claude enters a worktree, CLAUDE_PROJECT_DIR in a hook command still points at the main checkout, while the cwd field in the hook's JSON input follows Claude.
Worktree session, subagent, or both?
The docs list worktrees as one way to run Claude in parallel. Worktrees isolate file edits, subagents split work up inside one session, and cross-session messaging lets sessions in different worktrees pass findings to each other. They also combine: ask Claude to use worktrees for its agents, or set isolation: worktree in a custom subagent's frontmatter, and each run gets a temporary worktree. Claude Code removes it when the subagent finishes without changes. A worktree holding changes stays until a periodic sweep can remove it without losing work.
Read more (2)Show less
This repository uses none of that, and it is worth saying plainly. Its one custom agent, blog-post-author, runs in the main checkout with no isolation field. Collisions are avoided by convention. Each agent stages into its own folder under /tmp/blog-staging, writes its own article component, and is told not to touch the six shared files that only the merge script writes. The main session is the single writer. That suits agents producing independent drafts, and a validator, not the filesystem, enforces the boundary.
My rule of thumb: choose a worktree session when two sessions would edit the same tracked files for different goals, such as a feature in one terminal and a bug fix in another. Choose a plain subagent for research or an independent draft that one writer merges. Add isolation: worktree to a subagent when it edits tracked files and you cannot guarantee it stays in its own lane.
The real config behind this lesson
Excerpts from the repository that builds and deploys this website, quoted as they are.
2. `/tmp/blog-staging/agent-<slug>/registry.json` — an array holding **exactly
one** descriptor with complete `meta`. Your own folder, never shared: the
per-post validator rejects a folder containing more than one entry.The collision rule for parallel agents, written as a convention. Each agent stages into a folder named for its own slug, never shared, and the validator rejects a folder holding more than one post. This is isolation by naming, not by worktree: /tmp sits outside any checkout.
- **Do not** run `merge-blog-staging.mjs`, `merge-blog-faqs.mjs`, or any git
command. The main session merges, generates covers, builds and commits.
- **Do not** edit `messages/en.json`, `messages/id.json`, `lib/blog-*.ts` or
`[slug]/page.tsx` — the merge script owns those six files.The single-writer rule. The shared files, including both message files, are off limits to every agent, so five agents running at once never write the same file. A worktree would isolate the repository's files; this boundary does it for the few files that every post must change.
- **One folder per post**, named for the slug: `agent-epson-escpos`,
`agent-flutter-permissions`, … The merge reads every `agent-*` folder, so five
folders is still one merge — and each post keeps its per-post validation.How the batch scales. One folder per post means a batch of five is five folders and still one merge, because the merge script reads every agent-* folder. The fan-out is wide on drafting and serial on the one step that writes shared files.
Mistakes that cost real time
A worktree in a repository with no commits
A worktree is created from an existing commit. In a brand-new repository the command fails with Failed to resolve base branch "HEAD". Make one commit first.
Your unpushed commits are missing
The default base is the repository's default branch on the remote, not your current branch. A worktree started to continue local work therefore does not contain it. Set worktree.baseRef to "head", or create the worktree yourself with git worktree add on the branch you want.
A fresh checkout with no .env and no dependencies
The dev server fails in the new worktree because only tracked files were checked out. Install dependencies there, and list .env files in .worktreeinclude so new worktrees get them automatically.
Hooks that assume the project root never moves
Claude Code keeps CLAUDE_PROJECT_DIR at the main checkout after Claude enters a worktree. A hook command written like this repo's, which starts from that variable, runs the main checkout's copy of the script. If the script needs the worktree path, read cwd from the hook's JSON input. I have not tested this repo's hook inside a worktree.
What I'd change here: nothing ignores the worktree folder
This repository's .gitignore has no entry for .claude/worktrees/, and the folder is not in use today. Before anyone starts a worktree here, add that line, or every worktree shows up as untracked files in the main checkout.
| Approach | What it isolates | In this repo |
|---|---|---|
| Worktree session | Files and branch, per session | Not used yet |
| Plain subagent | Context window, not files | blog-post-author, with folders |
| Subagent with isolation: worktree | Both context and files | Not set on any agent |
Do it on your own machine
You need Claude Code and a scratch git repository with at least one commit. You will run two sessions on the same file, watch them stay apart, then see cleanup.
Keep worktree folders out of git status, and commit that change so the repository has a commit to branch from.
echo ".claude/worktrees/" >> .gitignore git add .gitignore && git commit -m "ignore worktrees"In one terminal, start a session in a worktree named try-a. In a second terminal, start try-b.
claude --worktree try-a # second terminal claude --worktree try-bAsk each session to add a different line to the same file, such as README.md. Then compare from a third terminal.
git worktree list git -C .claude/worktrees/try-a diff --stat git -C .claude/worktrees/try-b diff --stat git status --shortExit session try-b without changing anything, and exit try-a after leaving its edit uncommitted. Note which one Claude offers to keep.
Reopen the kept worktree with the command Claude printed on exit, then remove it yourself when you are done.
claude --worktree try-a --resume git worktree remove --force .claude/worktrees/try-a
Three questions before you move on
Pick an answer to see why it is right or wrong. Nothing is saved or graded, so guess freely.
Answer in your head, then check
1.Do worktrees stop two sessions from overwriting each other's work?Show the answer
Answer:For files in the repository, yes: each session edits its own copy on its own branch. The work still has to meet in git, so two branches that change the same lines conflict at merge time. Anything outside the repository is shared.
2.Why does this repo's blog-post-author not use a worktree?Show the answer
Answer:The files show a different design. Each agent writes its own component and its own staging folder, and the six shared files are written only by the merge script in the main session. That is isolation by convention plus a validator. The files give no stated reason beyond that.
3.Can you start a worktree after the session has already begun?Show the answer
Answer:Yes. Ask Claude to work in a worktree and it creates one with its EnterWorktree tool. Entering a worktree outside .claude/worktrees asks for your approval first, because the session's working directory and write access move there.
Related deep dives on this site
Sources
Primary sources checked on the research date. Follow them for the current version.
- Claude Code docs: Run parallel sessions with worktrees
- Claude Code docs: clean up worktrees
- Claude Code docs: what worktrees share with the main checkout
- Claude Code docs: isolate subagents with worktrees
- Claude Code docs: common workflows, parallel sessions
- Claude Code docs: subagents and the isolation field
- Git documentation: git-worktree