Recipe · Intermediate · 15 min
Claude Code worktree: run agents in parallel without clashes
Run several Claude Code sessions in parallel with claude --worktree, copy your .env with .worktreeinclude and clean up worktrees without losing work.
Tested with Claude Code 2.1.316 · reviewed
See the files on GitHub Free · MIT license
The problem
You want one Claude Code session to build a feature while another fixes a bug, but if both work in the same folder they step on each other's files and the changes get mixed up. Making another copy of the repository by hand is slow, and the new copy is missing the .env.
The solution
A git worktree is another working folder with its own branch that shares the repository's history. If each session lives in its own worktree, they don't clash. Claude Code does it with a single flag: claude --worktree <name> (or -w).
1. Your first parallel session in 2 minutes
Requirement: be in a git repository. At the project root, open a terminal and run claude --worktree fix-login. Claude Code creates the folder .claude/worktrees/fix-login/ on a new branch called worktree-fix-login and starts the session inside it. Open another terminal and run claude --worktree new-api: you now have two isolated sessions. If you give no name, Claude generates one like bright-running-fox.
cd ~/my-project
echo '.claude/worktrees/' >> .gitignore
# terminal 1
claude --worktree fix-login
# terminal 2
claude --worktree new-api
# review a PR in its own worktree (quotes required)
claude --worktree "#1234"
# with tmux
claude --worktree docs --tmux
Interactive sessions need you to have accepted trust for the folder: if it is your first time in that repository, run claude there once; with -p that check is skipped.
Recommended first change: add .claude/worktrees/ to your .gitignore so the worktrees' contents don't show up as untracked files in your main checkout.
If you use tmux, --tmux creates a tmux session for the worktree (requires --worktree; with iTerm2 it uses native panes, and --tmux=classic forces traditional tmux). You can also ask for it in the middle of a conversation: "work in a worktree", and Claude uses the EnterWorktree tool.
2. The missing .env: .worktreeinclude
A worktree is a fresh checkout: it only brings versioned files. Your .env, .env.local or a config/secrets.json ignored by git won't be there, and neither will node_modules or the Python virtual environment.
For the first group, create a .worktreeinclude file at the project root with .gitignore syntax:
.env
.env.local
config/secrets.json
Only files that match a pattern and are also ignored by git are copied, so it never duplicates versioned files. It applies to every worktree Claude Code creates with git: those from --worktree, subagent worktrees and parallel sessions in the desktop app. It does not apply if you create the worktree by hand with git worktree add, nor if a WorktreeCreate hook replaces creation (there you copy the files in the script).
Be careful with patterns starting with **/ when the files are inside a whole ignored folder: write vendor/**/config.json instead of **/config.json (behavior fixed in 2.1.239).
For dependencies, ask Claude to install them at the start or run npm install, pip install or whatever your project uses yourself inside the worktree folder.
3. Where does it start from? worktree.baseRef and PRs
By default, new worktrees start from the remote's default branch (usually origin/main), not from your HEAD: that way they start clean. If it hasn't fetched in 24 hours, Claude Code fetches that branch (five seconds at most) and, if that fails, uses the local ref; with no remote configured, it uses your local HEAD.
If you want the worktree to carry your unpushed commits or the state of your working branch, set worktree.baseRef to "head" in your settings:
{
"worktree": {
"baseRef": "head"
}
}
It doesn't accept a branch name: to start from a specific branch, create the worktree with git worktree add and run claude inside it.
To review or continue a pull request, pass the number with # or the URL: claude --worktree "#1234". The quotes are needed so the shell doesn't take # as a comment. Claude Code fetches the PR commit from origin and creates .claude/worktrees/pr-1234. Since 2.1.233 it also accepts GitLab merge request URLs. If git or ssh need a password or to confirm a new host, it fails with "Failed to fetch PR/MR": load your key into ssh-agent and run a git fetch by hand once.
4. Exit and clean up without losing work
When you exit an interactive session in a worktree, Claude Code checks whether deleting it would remove work: changed or untracked files, submodule changes and new commits.
- If it is clean and the session has no name, it deletes the worktree and its branch automatically; if the session has a name, it asks you.
- If there is work, it asks whether to keep or remove it. Keeping leaves the folder and the branch, and to come back you use the command it prints on exit:
claude --worktree <name> --resume. Removing deletes the folder and the branch with everything in them: commit or push first if you want to keep it.
With -p there is no question on exit: the worktree stays and is also locked (git worktree list shows it as locked). To remove it:
git worktree list # shows 'locked' if it was left locked
git worktree unlock .claude/worktrees/demo
git worktree remove .claude/worktrees/demo # --force if it has uncommitted changes (they are lost!)
git branch -D worktree-demo # only if you no longer need the branch
Subagent and background-session worktrees are cleaned up by a periodic sweep once they exceed cleanupPeriodDays, unless they have pending work.
5. Isolated subagents, /batch and what is shared
Not just sessions: subagents can also each work in their own worktree. Ask for it ("use worktrees for your agents") or make it permanent with isolation: worktree in the frontmatter of a subagent in .claude/agents/. Each one gets a temporary worktree that is deleted automatically only if it finishes with no changes.
.claude/agents/refactorer.md, a subagent that is always isolated:
---
name: refactorer
description: Applies mechanical refactors across many files
isolation: worktree
---
Apply the requested refactor in every affected file, run the tests and report the result.
The /batch <instruction> command takes this to the extreme: it researches the code, splits the work into 5 to 30 independent units, presents a plan and, once you approve it, launches one background subagent per unit, each in its own isolated worktree.
What worktrees share with the main checkout:
- the
.gitdirectory (commits work, even with sandbox); - plugins installed at project level;
- permission approvals: "Yes, and don't ask again" is saved in the main checkout's
.claude/settings.local.jsonand applies to every worktree (see permissions); - the main checkout's skills, agents and commands when the worktree has no
.claude/skillsof its own.
While a session is isolated, Claude Code blocks edits and commands that target the main checkout.
6. When to parallelize and when not to
Yes:
- independent tasks that touch different areas of the code (a backend bug and a new screen);
- trying two approaches to the same task and keeping the best;
- reviewing a PR while you carry on with your own work;
- long tasks you can leave running.
No:
- tasks that touch the same files (you will end up resolving merge conflicts);
- when you won't have time to review what all of them do (the bottleneck becomes your review);
- when you are short on limit: each session makes its own requests, so three sessions spend roughly like three sessions (check
/usage; see usage limits).
A reasonable flow to start with: one main session where you plan (plan mode) and one or two in worktrees for bounded tasks with a clear "done" criterion (tests that must pass). When each finishes, review the diff, commit on its branch and open the PR or merge. If you need sessions to pass information to each other, the documentation describes messages between sessions; if you only want to split work within one session, use subagents.
Check it
Reproducible test on Linux, in a throwaway repository:
mkdir -p /tmp/wt-demo && cd /tmp/wt-demo && git init -q
printf '.env\n.claude/worktrees/\n' > .gitignore
echo 'SECRET=demo' > .env
echo '.env' > .worktreeinclude
echo hello > a.txt && git add . && git commit -qm init
claude -p -w demo --model haiku "Reply only: OK"
ls -a .claude/worktrees/demo # a.txt and the copied .env
git worktree list # [worktree-demo] locked
We ran it on 1 Nov 2026 with Claude Code 2.1.316: it created .claude/worktrees/demo on the worktree-demo branch, copied .env thanks to .worktreeinclude and left the worktree marked as locked; we cleaned it up with git worktree unlock, remove and branch -D. With no remote, it started from the local HEAD, as the documentation says. We have not recorded the interactive part yet: two terminals at once, the keep-or-remove question on exit, --tmux and --worktree "#<PR>" against a repository with a GitHub remote.
Why it works
git worktree lets you have several working folders of the same repository, each on its own branch, sharing a single .git. Claude Code creates and deletes those folders for you, copies what you list in .worktreeinclude and confines each session to its own, so two sessions never write to the same files. Sources: worktrees, CLI reference, commands, worktree settings, subagents and the CHANGELOG.
Common mistakes
- The worktree has no
.env→ it is a fresh checkout with only versioned files → add.envto.worktreeinclude(and it must be ignored by git). .worktreeincludecopies nothing → you created the worktree withgit worktree add, or aWorktreeCreatehook replaces creation → useclaude --worktreeor copy the files in the hook script.- A
**/config.jsonpattern finds no files inside an ignored folder → write the path from the folder:vendor/**/config.json. - The worktree doesn't have your latest commits → it starts from the remote's default branch → set
worktree.baseRefto"head". claude --worktree #1234doesn't open the PR → the shell took#as a comment → quote it:"#1234".- "Failed to fetch PR/MR" → git or ssh ask for a password or to confirm a host → load your key into
ssh-agentand run agit fetchby hand once. git worktree removesays it is locked → a-prun or a running agent left it that way → if nothing is running any more,git worktree unlock <path>and thenremove.
FAQ
Where does Claude Code create worktrees?
In .claude/worktrees/<name>/ at the repository root, on the worktree-<name> branch. For a PR, .claude/worktrees/pr-<number>.
Why doesn't my worktree have the .env?
Because it is a fresh checkout with only versioned files. Add .env to .worktreeinclude (and it must be ignored by git).
Why doesn't the worktree have my latest commits?
By default it starts from the remote's default branch. Set worktree.baseRef to "head" to start from your HEAD.
Is my work deleted when I exit?
Only if you choose to remove it. If there are changes, Claude Code asks; if it is clean and the session has no name, it deletes it because there is nothing to lose.
git worktree remove says it is locked
-p runs and running agents lock it. If nothing is running any more, git worktree unlock <path> and then remove.
Does it work without git?
For SVN, Perforce or Mercurial you need to configure the WorktreeCreate and WorktreeRemove hooks; in that case .worktreeinclude is not processed.
Do several worktrees use more limit?
Yes: each session makes its own requests. Keep an eye on it with /usage.