Skip to content

Claude Code Worktrees: Run Parallel Sessions Without Collisions

Core Concept LearningAugust 18, 202613 min readUpdated October 17, 2026

Two Claude Code sessions in the same checkout edit the same files, and sooner or later one overwrites the other's work or runs the tests in the middle of the other's change. A git worktree fixes that: a separate working directory with its own files and branch that shares the repository's history and remote with your main checkout. Claude Code builds this in: claude --worktree <name> creates a worktree and starts the session inside it.

This guide follows Anthropic's worktrees documentation. It covers starting sessions in worktrees, setting up each one (including copying .env with .worktreeinclude), what happens on exit, resuming, how Claude Code enforces isolation and where that stops, worktrees for subagents, choosing the base branch, manual git worktree use, and the errors you may hit. It replaces two older posts on this site that covered the same topic.

For the desktop app's worktree option, see Claude Code Desktop App. For sparse worktrees in a monorepo, see Claude Code in Monorepos.

Each parallel Claude Code session gets its own git worktree: separate files and branch, shared repository history
Each parallel Claude Code session gets its own git worktree: separate files and branch, shared repository history

Start sessions in worktrees

Pass --worktree (or -w) with a name:

1# terminal 12claude --worktree feature-auth3 4# terminal 25claude --worktree fix-login

Each command creates .claude/worktrees/<name>/ at the repository root, on a new branch named worktree-<name>, and starts Claude there. Omit the name and Claude generates one, such as bright-running-fox. Passing a name whose directory already exists reopens that worktree instead of creating a new one.

You can also ask Claude mid-session to "work in a worktree", and it creates one with the EnterWorktree tool. Entering a path outside .claude/worktrees/ always asks for your approval first, because it moves the session's working directory, write access, and project configuration there.

Two setup steps matter. Add .claude/worktrees/ to .gitignore so worktree contents never show as untracked files in the main checkout. And remember that interactive --worktree runs need workspace trust: run plain claude once in a new directory to accept the trust dialog, or --worktree exits with an error. claude -p --worktree skips the trust check.

Quick reference

  • claude --worktree "#1234" (quoted, so the shell does not treat # as a comment) fetches pull request or merge request 1234 from origin and creates .claude/worktrees/pr-1234.
  • Worktrees require git. For SVN, Perforce, or Mercurial, WorktreeCreate and WorktreeRemove hooks replace the git logic.
  • Worktrees isolate file edits only. Subagents split work inside one session; cross-session messaging lets worktree sessions share findings.

Remember this

One claude -w <name> per task gives each session its own directory and branch; ignore .claude/worktrees/ in git.

Set up each worktree: dependencies and .worktreeinclude

A worktree is a fresh checkout of tracked files. It has no node_modules, no virtual environment, no build output, and none of your gitignored local files. Ask Claude to install dependencies first, or run your setup command in the worktree.

For gitignored files you need everywhere, such as .env, add a .worktreeinclude file at the project root. It uses .gitignore syntax, and only files that match a pattern and are gitignored are copied into each new worktree, so tracked files are never duplicated:

1.env2.env.local3config/secrets.json

It applies to every worktree Claude Code creates with git: --worktree sessions, subagent worktrees, and desktop-app parallel sessions. With a WorktreeCreate hook, it is not processed; copy the files in your hook script.

Two practical consequences of separate checkouts: each worktree needs its own dependency install (time and disk), and if two worktrees start dev servers they need different ports. Tell Claude which port to use in each session, or configure your dev server to pick a free one.

Quick reference

  • Copying .env into every worktree also copies its secrets. Consider a Read(./.env) deny rule if Claude should never see them.
  • Patterns starting with **/ reach into a wholly ignored directory only in specific cases; name the directory in the pattern, such as vendor/**/config.json, to be sure.
  • Plugins installed at project scope in the main checkout also load in its worktrees, so you do not reinstall them.

Remember this

Install dependencies per worktree, copy gitignored local files with .worktreeinclude, and give each dev server its own port.

Exit, clean up, and resume

When you exit an interactive worktree session, Claude checks the worktree for work removal would delete: changed or untracked files, uncommitted work in submodules, and new commits.

  • Clean: for an unnamed session, Claude removes the worktree and its branch automatically. A named session asks first, so you can keep it.
  • Has work: Claude asks whether to keep or remove it. Keeping preserves the directory and branch, and Claude prints the claude --worktree <name> --resume command to return. Removing deletes the directory, the branch, and everything in them.
  • Cannot verify: Claude asks rather than deleting anything, and names what it could not check.

Non-interactive claude -p runs have no exit prompt, so their worktrees are never cleaned up automatically. Remove them with git worktree remove, after git worktree unlock if git says the worktree is locked.

Resuming a session that ended inside a worktree returns it to that worktree, for interactive resumes, --continue and --resume with -p, and the Agent SDK. If the worktree was deleted, the session resumes in your launch directory and tells you. Resume from the main checkout when in doubt; some worktrees are only re-entered from there.

On exit Claude checks the worktree: clean unnamed worktrees are removed, anything with work prompts you to keep or remove it
On exit Claude checks the worktree: clean unnamed worktrees are removed, anything with work prompts you to keep or remove it

Quick reference

  • Merging is still your job. Push the worktree branch, open a pull request, and review it like any other.
  • git worktree list shows every worktree; git worktree remove ../path --force removes one with uncommitted changes.
  • Reusing a name reopens the old worktree, and with the default base it resets to the default branch only if it is clean and unchanged or its PR was merged.

Remember this

Interactive exits clean up or ask; -p runs leave worktrees behind for git worktree remove.

What isolation Claude Code enforces, and where it stops

While a session is isolated in a worktree, Claude Code applies four checks, including to every subagent the session spawns:

1. File edits: Edit, Write, and NotebookEdit calls that target the main checkout are blocked. 2. Command working directory: a Bash, PowerShell, or Monitor command whose working directory resolves to the main checkout, or cannot be verified to stay out of it, is blocked. 3. Git redirects: commands that point git at the main checkout through git -C, --git-dir, GIT_DIR or GIT_WORK_TREE, or a cd first, are blocked. 4. Command shape: commands whose git usage cannot be verified from the text, such as computed command names or unparseable syntax, are blocked, and Claude is told how to rewrite them. This check cannot be turned off.

The limit is stated plainly in the docs: these checks read paths, directories, and command text, and none tracks which files a shell command writes. A cp into the main checkout or a shell redirect such as echo x > ../main/file is not refused by them; it falls under your normal permission rules and sandbox settings.

Hooks also need care. ${CLAUDE_PROJECT_DIR} stays pointed at the project root where the session started, while the cwd field in the hook's JSON input follows Claude into the worktree. A hook that should act on the files Claude is editing must read cwd.

While isolated in a worktree, Claude Code blocks edits, commands, and git redirects that target the main checkout, but not every shell write
While isolated in a worktree, Claude Code blocks edits, commands, and git redirects that target the main checkout, but not every shell write

Quick reference

  • Worktrees share the repository's .git directory, so git commit from a worktree works even with the sandbox on.
  • "Yes, and don't ask again" approvals in a worktree are saved to the main checkout's .claude/settings.local.json and apply to every worktree.
  • Claude Code refuses to create a worktree when .claude, .claude/worktrees, or the worktree directory is a symlink.

Remember this

Edits, command directories, and git redirects into the main checkout are blocked; arbitrary shell writes are not, so keep permission rules and the sandbox on.

Worktrees for subagents

Subagents can each run in their own worktree so parallel edits inside one session do not collide. Ask Claude to "use worktrees for your agents", or make it permanent for a custom subagent with isolation: worktree in its frontmatter:

1---2name: refactorer3description: Applies mechanical refactors across many files4isolation: worktree5---6 7Apply the requested refactor across every affected file, then run the tests8and report the results.

Each subagent gets a temporary worktree. Claude Code removes it automatically when the subagent finishes without changes; one with changes stays until a periodic sweep can remove it without losing work, based on your cleanupPeriodDays setting. While an agent runs, Claude Code holds a git worktree lock on its worktree so cleanup cannot remove it mid-task.

A subagent in its own worktree takes its instruction files from your main conversation. When the worktree is in the default location, it does not load the worktree branch's own CLAUDE.md or .claude/rules/, even if they differ.

Quick reference

  • The sweep never removes worktrees you created yourself with git worktree add, or ones that still hold uncommitted work or unpushed commits.
  • /batch <instruction> splits a large change across subagents, each in its own worktree.
  • Subagent worktrees branch from the same base as --worktree; set worktree.baseRef to "head" if they need your in-progress work.

Remember this

isolation: worktree gives each subagent its own checkout; changed worktrees survive until you merge or the sweep can safely remove them.

Choose the base branch, or manage worktrees yourself

By default, new worktrees branch from the repository's default branch on the remote (worktree.baseRef: "fresh"), so each starts clean and matching origin. If the repository has not been fetched in 24 hours, Claude Code fetches the default branch first (capped at five seconds) and falls back to the cached ref. To branch from your current local HEAD instead, including unpushed commits, set:

1{2  "worktree": {3    "baseRef": "head"4  }5}

baseRef cannot name a branch. To start from a specific existing branch, or to put the worktree outside the repository, use git directly:

1git worktree add ../project-feature-a -b feature-a   # new branch2git worktree add ../project-bugfix fix-issue-456     # existing branch3cd ../project-feature-a && claude4git worktree list5git worktree remove ../project-feature-a

Worktrees you create this way get the same sharing (plugins, approvals, untracked skills read-through), but Claude Code's automatic cleanup never removes them.

Quick reference

  • In a large monorepo, worktree.sparsePaths checks out only the listed directories in each Claude-created worktree; see the monorepo guide.
  • If you set up Git LFS with git lfs install --local, Claude-created worktrees contain LFS pointer files; run git lfs pull inside the worktree.
  • A WorktreeCreate hook can also place worktrees outside .claude/worktrees/ entirely.

Remember this

Fresh base by default; baseRef: head for in-progress work; plain git worktree add for a specific branch or location.

Errors you may hit

Most worktree problems are about git identity. Claude Code checks that a worktree really is a separate checkout before using it, because a directory whose git metadata points back into the main checkout would let an ordinary git reset --hard destroy work there. When it refuses, it leaves the directory in place, since it may hold work, and the end of the message names the recovery.

When something looks wrong, run git worktree list from the main checkout first. It shows each worktree's path, branch, and lock state, which explains most surprises.

Worktree errors from Anthropic's troubleshooting section
Message or symptomCauseFix
--worktree exits asking for trustNo workspace trust in this directoryRun plain claude once and accept the trust dialog
Worktree creation fails on a symlinked path.claude or the worktree path is a symlinkRemove the symlink and retry
LFS files are pointers in the worktreeLFS filter set with --local in .git/configRun git lfs pull in the worktree
Refusing to use <path> as an isolation worktreeIts git metadata resolves into the main checkoutFollow the message: launch from the main checkout or recreate
Session resumes outside its worktreeWorktree deleted or could not be verifiedRead the message; resume from the main checkout
git worktree remove refuses: lockedLock left from a -p run or running agentgit worktree unlock, then remove

Quick reference

  • Never delete a refused directory before reading why it was refused; some messages point at the main checkout's metadata, not the worktree's.
  • Claude Code skips the repository's own filter drivers when creating worktrees, because a filter driver is a shell command anything could have written.
  • Worktrees at network paths are never resumed into; recreate them on a local path.

Remember this

Start with git worktree list; refusals protect the main checkout, and the message's ending tells you the fix.

Hands-on: two parallel sessions and a subagent

Use a repository with a test command.

1. Add .claude/worktrees/ to .gitignore and create .worktreeinclude containing .env. 2. In two terminals, run claude -w add-validation and claude -w update-docs, and give each a small task. 3. In each, run git status and git branch --show-current. Confirm separate files and branches. 4. In the first session, ask Claude to run echo test > ../../../scratch.txt (a new file in the main checkout) and see whether it is blocked or falls to a permission prompt. 5. Create .claude/agents/refactorer.md with isolation: worktree and ask Claude to use it for a rename across three files. 6. Exit both sessions; keep one worktree and remove the other. Run git worktree list.

Pass criterion: the sessions never saw each other's changes, the subagent worked in its own worktree, and git worktree list shows exactly the worktrees you chose to keep.

Quick reference

  • Step 4 shows the boundary in practice: shell writes are governed by permissions and the sandbox, not by the worktree checks.
  • If .env did not appear in a new worktree, check that it is gitignored; .worktreeinclude copies only ignored files.
  • Remove the kept worktree with git worktree remove when you have merged its branch.

Remember this

Prove separation, the shell-write boundary, and cleanup once before relying on parallel sessions.

Key takeaway

Git worktrees are how Claude Code runs several sessions on one repository without collisions: claude --worktree <name> creates .claude/worktrees/<name> on its own branch, .worktreeinclude copies gitignored local files, and interactive exits either clean up or ask before deleting work. Subagents can get their own worktrees with isolation: worktree, and worktree.baseRef chooses between a fresh default-branch base and your current HEAD.

Inside a worktree, Claude Code blocks edits, command directories, and git redirects that target the main checkout, but not every shell write, so permission rules and the sandbox still matter. And each worktree is a full checkout: install dependencies and use separate ports. For the permission rules involved, see Claude Code Permissions; for running sessions in the background, see Agent View.

Practice (30 min): complete the six steps above, then decide which of your tasks are independent enough to run in parallel worktrees.

Share:

References

  1. Claude Code docs: Run parallel sessions with worktrees — checked Oct 17, 2026
  2. Git documentation: git-worktree — checked Oct 17, 2026
  3. Claude Code docs: Subagents — checked Oct 17, 2026
SH

Shoaib Hossain

Lead Author & Systems Architect

Software engineer and distributed systems architect specializing in backend scalability, cloud-native infrastructure, databases, and AI engineering workflows. Author and maintainer of Core Concept Learning.

Human-Engineered & Fact-CheckedOriginal Visual DiagramsEditorial Standards →Send Feedback

Related Articles

Running several Claude Code sessions in separate terminals works until you lose track of which one is waiting for you. A…

Read

Claude Code is an agent that works in your project: it reads files, edits them, and runs commands such as your test suit…

Read

There are two ways to use Claude Code in VS Code. The extension gives you a graphical chat panel with side-by-side diffs…

Read

Explore this topic

Keep learning

Follow a structured path or browse all courses to go deeper.