Run Claude Code sessions in parallel with git worktrees
Start isolated parallel sessions with claude --worktree, carry .env files in with .worktreeinclude, and know which tool calls the isolation checks block.
Contents
Claude Code works on one task per session. Ask it to build feature A and fix bug B at once and the edits land in the same working directory, where separating the diffs becomes your problem.
A git worktree solves this: a separate working directory with its own files and branch, sharing the same repository history and remote as your main checkout. Claude Code has a flag that creates one and starts the session inside it, so you rarely need the raw git commands.
KEY POINT
What you will learn
- Starting an isolated session with
--worktree, and how to carry gitignored files in - The isolation checks that stop a worktree session from touching the main checkout
- How cleanup works on exit, and when a worktree is left behind
Start a session in a worktree
Pass --worktree or -w with a name:
claude --worktree feature-auth
By default the worktree is created under .claude/worktrees/<name>/ at your repository root, on a new branch named worktree-<name>. Run the same command with a different name in a second terminal to start a second isolated session. Omit the name and Claude Code generates one, such as bright-running-fox.
Two preconditions are worth knowing. The worktree is created from an existing commit, so the repository needs at least one commit; in a repository with none, the command fails with Failed to resolve base branch "HEAD": git rev-parse failed. And an interactive run requires workspace trust — if you have never run Claude in the directory, run claude once there to accept the trust dialog. A non-interactive claude -p --worktree skips the trust check.
# Keep worktree contents out of your main checkout's untracked files
echo '.claude/worktrees/' >> .gitignore
You can also ask Claude to "work in a worktree" mid-session, and it creates one with the EnterWorktree tool. Entering a path outside .claude/worktrees/ always asks for your approval first, because the move takes the session's working directory, write access and project configuration with it — a permission rule or "don't ask again" does not suppress that prompt.
Set up the environment in each worktree
A worktree is a fresh checkout, so your development environment is not there. Install dependencies in it, either by asking Claude or by running your project's setup in the directory under .claude/worktrees/.
For gitignored files such as .env, add a .worktreeinclude file at your project root. It uses .gitignore syntax, and only files that match a pattern and are gitignored get copied, so tracked files are never duplicated:
.env
.env.local
config/secrets.json
This applies to every worktree Claude Code creates with git, including subagent worktrees and the desktop app's parallel sessions.
Two sessions still collide outside the file system
Worktrees isolate files, not ports or databases. Give each session its own dev-server port (PORT=3001 npm run dev), and separate the database by name or keep one of the two tasks off it entirely. Rewrite those values in the copied .env after the worktree is created.
What isolation actually enforces
While a session is in a worktree, Claude Code blocks four classes of tool call, whether you started with --worktree, Claude entered with EnterWorktree, or you resumed a worktree session. The same checks cover every subagent it spawns.
| Check | What it blocks |
|---|---|
| File edits | An Edit, Write or NotebookEdit targeting a path in the main checkout |
| Command working directory | A Bash, PowerShell or Monitor command whose working directory resolves to the main checkout, or can't be verified to stay outside it |
| Git redirects | A command that redirects git into the main checkout via git -C, --git-dir, GIT_DIR, GIT_WORK_TREE, or a cd first |
| Command shape | A command where Claude Code can't verify from the text that any git it runs stays inside the worktree — a computed command name, unparseable syntax, or an expansion such as ${!name}. This check can't be turned off |
These checks read the path an edit targets, the directory a command runs in and the command text. None of them tracks which files a shell command writes, so a cp or a shell redirect into the main checkout is not refused by them — it falls under your ordinary permissions and sandboxing settings.
What a worktree shares with the main checkout
| Shared | Detail |
|---|---|
The .git directory | Git commands in a worktree write to the main repository's shared .git, and sandboxing allows those writes, so git commit works from inside a worktree with the sandbox on |
| Project-scope plugins | Plugins installed from the main checkout load in worktrees of the same repository (v2.1.200 or later) |
| Permission approvals | "Yes, and don't ask again" for a Bash command saves to the main checkout's .claude/settings.local.json, so it applies everywhere and survives the worktree's removal (v2.1.211 or later) |
| Untracked skills, agents, commands | When the worktree has no .claude/skills of its own — for example because yours is gitignored — the main checkout's project skills load. The same read-through covers .claude/agents and .claude/commands |
New worktrees branch from the repository's default branch on the remote. Set worktree.baseRef to "head" in settings to branch from your current local HEAD instead, so the worktree carries your unpushed commits. You can't set it to a branch name — to start from a specific existing branch, create the worktree with git directly.
Clean up
When you exit an interactive worktree session, Claude checks it for work that removal would delete — changed or untracked files, uncommitted work in checked-out submodules, and new commits:
- Clean: an unnamed session's worktree and branch are removed automatically. A named session prompts you first, so you can keep it.
- Holds work: Claude prompts you to keep or remove it. Keeping preserves the directory and branch, and Claude Code prints the
claude --worktree <name> --resumecommand to return later. Removing deletes the directory, the branch and the work in them. - State can't be verified: Claude prompts rather than removing, and names what it couldn't check.
A -p run has no exit prompt, so its worktree is left in place along with the lock Claude Code took at creation. Remove one with git worktree remove, adding --force for uncommitted changes; if git refuses because the worktree is locked, run git worktree unlock on it first.
Designing parallel work
- Keep the tasks independent. Two tasks editing the same files will conflict at merge time. Work out the blast radius in plan mode before splitting them.
- Two or three at a time. There is a limit to what you can review. Raising the parallelism past your review capacity lowers quality rather than raising throughput.
- Subagents are for inside one task. Investigating something from several angles at once suits subagents better than worktrees. To make a subagent's edits isolated too, add
isolation: worktreeto its frontmatter.
Summary
claude --worktree <name>creates a worktree under.claude/worktrees/on aworktree-<name>branch and starts the session there- A worktree is a fresh checkout: install dependencies in it, and use
.worktreeincludeto carry gitignored files like.env - Isolation blocks edits, command working directories and git redirects that reach the main checkout, but not a plain
cpinto it - The
.gitdirectory, project plugins and permission approvals are shared with the main checkout - Exiting an interactive session prompts you about a worktree that holds work; a
-prun leaves its worktree behind
FAQ
- Do I have to run git worktree add myself?
- No. Pass --worktree (or -w) with a name and Claude Code creates the worktree under .claude/worktrees/<name>/ on a new branch named worktree-<name>, then starts the session in it.
- Do I need to install dependencies in every worktree?
- Yes. A worktree is a fresh checkout, so node_modules and similar are not there. Ask Claude to install them, or run your project's setup in the worktree directory yourself.
- How do I get my .env into a new worktree?
- Add a .worktreeinclude file at your project root, using .gitignore syntax. Only files that match a pattern and are also gitignored are copied, so tracked files are never duplicated.
- What happens to the worktree when I exit?
- If it is clean, an unnamed session's worktree and branch are removed automatically and a named session prompts you first. If it holds work, Claude prompts you to keep or remove it. A -p run has no exit prompt, so its worktree stays.
Primary sources
This article was drafted by AI from official documentation and reviewed by the site operator before publishing. Found a mistake? Let us know via the contact page.