Running two Claude Code sessions on the same repository is a race condition waiting to happen. Both sessions read the same files, write to the same paths, and frequently blow up each other’s in-progress assumptions mid-task. The result: merge conflicts, lost work, and confusion about which session produced which output.
Git worktrees solve this structurally. Each session gets its own directory, its own branch, and complete file isolation — while sharing the same repository history and remote. Claude Code has first-class worktree support baked in, and the 2026 release expanded that support to cover subagents, background agents, and desktop parallel sessions.
This guide covers every layer of the worktree system: the --worktree flag, isolation: worktree for subagents, the .worktreeinclude file for syncing gitignored configs, tmux-based split-pane monitoring, and practical merge strategies once parallel work converges.
What Git Worktrees Actually Are
A standard git checkout gives you one working tree: one directory, one branch checked out at a time. Switching branches means stashing or committing, then checking out the new branch — losing your place in the process.
Git worktrees give you multiple working directories backed by a single .git folder:
# Main checkout: ~/project (branch: main)
# Worktree 1: ~/project-feature-auth (branch: feature/auth)
# Worktree 2: ~/project-fix-login (branch: fix/login-bug)
All three directories point at the same repository. Commits made in any worktree are immediately visible to the others. There is no sync step, no extra clone, and no wasted disk space for the .git data.
The constraint: each branch can only be checked out in one worktree at a time. Git enforces this to prevent split-brain scenarios.
The —worktree Flag: Single-Command Parallel Sessions
The simplest way to use worktrees with Claude Code:
# Create a worktree and start Claude in it
claude --worktree feature-auth
Short form -w works identically:
claude -w bugfix-123
What this does internally:
- Creates a new branch named
worktree-feature-authfromorigin/HEAD(remote default branch) - Creates a new working directory at
.claude/worktrees/feature-auth/inside your repo root - Starts a Claude Code session in that directory
The worktree is created under .claude/worktrees/<name>/ by default. Add that path to .gitignore so worktree contents don’t appear as untracked files in your main checkout:
# .gitignore
.claude/worktrees/
Omitting the Name
If you omit the name, Claude generates one automatically:
claude --worktree
# Creates: .claude/worktrees/bright-running-fox/
Branching from a Pull Request
Pass a PR number prefixed with # or a full GitHub PR URL to branch from that pull request:
claude --worktree "#1234"
# Fetches pull/1234/head from origin
# Creates: .claude/worktrees/pr-1234/
Base Branch Configuration
By default, worktrees branch from origin/HEAD. To always branch from your current local HEAD instead (useful when working on in-progress feature branches):
{
"worktree": {
"baseRef": "head"
}
}
Setting baseRef to "head" means new worktrees carry your unpushed commits — useful when isolating subagents that need to build on work that isn’t merged yet.
Pattern 1: Manual Parallel Terminal Sessions
The most straightforward pattern: open multiple terminals, one per task.
Terminal 1 — Feature development:
cd ~/project
claude -w feature/new-dashboard
# Claude works in .claude/worktrees/feature-new-dashboard/
# Branch: worktree-feature-new-dashboard
Terminal 2 — Bug fix:
cd ~/project
claude -w fix/broken-api
# Claude works in .claude/worktrees/fix-broken-api/
# Branch: worktree-fix-broken-api
Terminal 3 — Refactor:
cd ~/project
claude -w refactor/auth-module
Three Claude sessions, three branches, zero file conflicts. Your main ~/project directory on main remains untouched throughout.
Pattern 2: Subagent Isolation with isolation: worktree
When Claude Code spawns subagents for parallel work within a single session, those subagents write to files. Without isolation, two subagents editing the same directory will produce conflicts or overwrite each other’s changes.
isolation: worktree in a subagent definition fixes this:
---
name: feature-builder
description: Implements new features on isolated branches. Writes code, runs tests, commits changes.
tools: read, write, bash, edit
isolation: worktree
model: claude-sonnet-4-6
---
You implement new features in isolated git worktrees.
Always run tests before committing. Write a clear commit message describing what changed.
With isolation: worktree, each time this subagent is invoked, it gets its own temporary worktree automatically. Two feature-builder subagents running simultaneously get separate directories — no conflicts.
Requesting Worktree Isolation Inline
You can also request worktree isolation without a predefined subagent:
Task: Refactor the authentication module.
Spawn three parallel subagents using worktree isolation:
1. Analyze current auth code dependencies
2. Research JWT best practices for Node.js
3. Check the current implementation for security issues
Claude creates the subagents with isolated worktrees for each.
Base Branch for Subagent Worktrees
Subagent worktrees use the same base branch setting as --worktree. Set worktree.baseRef to "head" in settings when subagents need to work from your current in-progress state:
{
"worktree": {
"baseRef": "head"
}
}
Pattern 3: Agent Teams with Worktrees
Agent teams (experimental, requires CLAUDE_CODE_EXPERIMENTAL_AGENT_TEAMS=1) coordinate multiple Claude Code instances that communicate with each other directly. Combine agent teams with worktrees for maximum parallelism:
{
"env": {
"CLAUDE_CODE_EXPERIMENTAL_AGENT_TEAMS": "1"
}
}
Then instruct the lead to create a team with worktree-isolated teammates:
Create an agent team with 4 teammates. Each teammate should work in a worktree:
- Frontend teammate: update the dashboard components
- Backend teammate: update the API endpoints
- Test teammate: write integration tests
- Documentation teammate: update the API docs
All teammates should use worktree isolation and commit their work to their own branches.
The shared task list coordinates who works on what. Teammates claim tasks, work in their worktrees, and report back. The lead synthesizes results.
.worktreeinclude: Syncing Gitignored Files
Worktrees are fresh checkouts. Gitignored files — .env, .env.local, config/secrets.json — are not present in a new worktree by default. Without them, your app often fails to start.
The .worktreeinclude file solves this. Place it in your project root using .gitignore syntax:
# .worktreeinclude
.env
.env.local
.env.development
config/secrets.json
.credentials
When Claude creates a worktree (via --worktree, subagent isolation: worktree, or the desktop app), it copies any files matching these patterns — but only if those files are also gitignored. Tracked files are never duplicated.
What .worktreeinclude Does Not Cover
- Files that are tracked by git (they’re already present via the checkout)
- Directories with dynamic content (node_modules, build artifacts) — install those fresh in each worktree
- Files outside the repository root
Per-Worktree Environment Setup
After Claude creates the worktree and copies your env files, you may still need to install dependencies. Put setup instructions in your CLAUDE.md:
## Worktree Setup
After creating a worktree, run:
1. `npm install` (or `pnpm install`)
2. `npm run db:migrate` if working on database-touching features
Cleanup Behavior
When you exit a worktree session, Claude’s cleanup depends on what happened during the session:
| Session State | Cleanup Behavior |
|---|---|
| No changes, no commits | Worktree and branch deleted automatically |
| Named session, no changes | Claude prompts before deleting (preserves named sessions) |
| Uncommitted changes | Claude prompts: keep or remove |
| New commits | Claude prompts: keep or remove |
Non-interactive (-p flag) | No automatic cleanup — remove manually |
For subagent worktrees that Claude created automatically: they’re removed once older than cleanupPeriodDays (default: 7 days) if they have no uncommitted changes, untracked files, or unpushed commits.
Manual cleanup when needed:
# List all active worktrees
git worktree list
# Remove a specific worktree
git worktree remove .claude/worktrees/feature-auth
# Force remove (when worktree has changes you want to discard)
git worktree remove --force .claude/worktrees/feature-auth
# Clean up stale worktree metadata
git worktree prune
tmux Setup for Parallel Monitoring
Claude Code’s agent teams support split-pane mode with tmux or iTerm2. For manual parallel sessions, tmux lets you see all sessions at once.
Basic tmux Layout for 3 Parallel Sessions
#!/bin/bash
# parallel-claude.sh — Launch 3 worktree sessions in tmux
SESSION="claude-parallel"
PROJECT_DIR="$HOME/project"
# Create tmux session
tmux new-session -d -s "$SESSION" -n "main"
# Window 1: Lead session
tmux send-keys -t "$SESSION:0" "cd $PROJECT_DIR && claude" C-m
# Window 2: Feature work
tmux new-window -t "$SESSION" -n "feature"
tmux send-keys -t "$SESSION:1" "cd $PROJECT_DIR && claude -w feature-auth" C-m
# Window 3: Bugfix
tmux new-window -t "$SESSION" -n "bugfix"
tmux send-keys -t "$SESSION:2" "cd $PROJECT_DIR && claude -w fix-api" C-m
# Split view: show all three in one window
tmux new-window -t "$SESSION" -n "overview"
tmux split-window -h -t "$SESSION:3"
tmux split-window -v -t "$SESSION:3.0"
tmux send-keys -t "$SESSION:3.0" "cd $PROJECT_DIR/.claude/worktrees/feature-auth && git log --oneline -10" C-m
tmux send-keys -t "$SESSION:3.1" "cd $PROJECT_DIR/.claude/worktrees/fix-api && git log --oneline -10" C-m
# Attach
tmux attach-session -t "$SESSION"
Monitoring Worktree Status
Check progress across all active worktrees from your main session:
# See all worktrees and their current branch
git worktree list
# Check what each worktree has committed
for wt in .claude/worktrees/*/; do
echo "=== $wt ==="
git -C "$wt" log --oneline -3 2>/dev/null || echo "empty"
done
# See uncommitted changes across worktrees
for wt in .claude/worktrees/*/; do
echo "=== $wt ==="
git -C "$wt" status --short
done
Agent Teams in tmux Split-Pane Mode
For Claude Code’s native agent teams, configure split-pane mode:
{
"teammateMode": "tmux"
}
Or force it for a single session:
claude --teammate-mode tmux
Claude Code auto-detects whether to use tmux or iTerm2 based on your terminal. Install tmux via Homebrew on macOS:
brew install tmux
The Four Patterns: When to Use What
Not every parallel scenario calls for the same approach. Here’s the taxonomy:
| Pattern | When to Use | Token Cost | Coordination |
|---|---|---|---|
Manual --worktree | You want direct control over each session | 1× per session | Manual |
isolation: worktree subagents | Quick parallel workers that report back to main session | Medium | Automatic |
| Agent teams + worktrees | Complex parallel work where agents need to communicate | High (each teammate = separate instance) | Self-coordinating |
| Desktop parallel sessions | GUI users, automatic worktree per session | Medium | Manual |
Pattern Taxonomy by Task Type
Independent parallel tasks (no inter-agent communication needed):
Use subagents with isolation: worktree. Each subagent does its work, returns results to the orchestrator, done.
Tasks requiring agents to share findings and debate: Use agent teams. The shared task list and mailbox let teammates challenge each other’s approaches.
Long-running sessions you want to monitor interactively:
Use manual --worktree sessions in separate terminals or tmux panes.
PR-based review workflows:
Use claude --worktree "#1234" to branch directly from a pull request.
Merge Strategies After Parallel Work
Parallel sessions produce parallel branches. Merging them back requires a strategy.
Strategy 1: Sequential Merge into Main
The safest approach when changes touch overlapping files:
# Review each worktree's changes
git log main..worktree-feature-auth --oneline
git diff main...worktree-feature-auth
# Merge one at a time
git merge worktree-feature-auth --no-ff -m "feat: auth module"
# Review conflicts, resolve, then merge the next
git merge worktree-fix-api --no-ff -m "fix: API endpoint"
Strategy 2: Integrate via Pull Requests
The most reviewable approach for team repos:
# Push each worktree branch
cd .claude/worktrees/feature-auth
git push -u origin worktree-feature-auth
# Create PRs for each branch via GitHub CLI
gh pr create --base main --head worktree-feature-auth --title "feat: auth module"
Review PRs individually, merge in dependency order.
Strategy 3: Octopus Merge (Independent Changes Only)
When branches are genuinely independent (no shared files, no shared history), merge all at once:
git merge worktree-feature-auth worktree-fix-api worktree-refactor-ui \
--no-ff -m "merge: parallel feature work"
Only use octopus merge when you’re confident branches don’t overlap. If any merge fails, git aborts the whole operation.
Strategy 4: Rebase onto Main
Produces linear history, useful before merging into a protected main branch:
cd .claude/worktrees/feature-auth
git rebase main
# Then merge from main
cd ~/project
git merge worktree-feature-auth --ff-only
CLAUDE.md Behavior Across Worktrees
CLAUDE.md files follow the same directory-hierarchy rules in worktrees as in normal checkouts:
- Repository root CLAUDE.md: present in every worktree (same repo, same root files)
- Subdirectory CLAUDE.md: present if the subdirectory exists in that worktree’s checkout
~/.claude/CLAUDE.md(user scope): always present in every session
This means project-level instructions apply to all parallel sessions automatically. No special configuration required.
For subagent-specific instructions, use the subagent’s frontmatter description and system prompt body, or put them in an AGENTS.md that the subagent definition references.
What Worktrees Do Not Provide
File isolation, not environment isolation. All sessions on the same machine share:
- Environment variables (unless each terminal sets its own)
- Local databases (PostgreSQL, SQLite files outside the repo)
- Network resources (both sessions can hit the same dev server)
- Running processes (a dev server started in one worktree is visible to all)
For true environment isolation, combine worktrees with Docker containers or devcontainers. Worktrees solve the file conflict problem — containers solve the environment conflict problem.
Common Mistakes and How to Avoid Them
Checking out the same branch in two worktrees. Git prevents this. Use unique branch names or create new branches with git worktree add -b new-branch-name.
Forgetting to add .claude/worktrees/ to .gitignore. All those worktree directories show as untracked files. Add the path immediately.
Running file-writing subagents without isolation: worktree. The most common conflict source. Any subagent that edits files needs worktree isolation.
Not running npm install in new worktrees. The .worktreeinclude copies env files, but node_modules/ is not copied (it’s gitignored but not in .worktreeinclude — and you wouldn’t want a 300MB copy for every worktree). Always run your project setup in each new worktree.
Letting dead worktrees accumulate. Run git worktree list and git worktree prune periodically. Old worktrees waste disk space and make the worktree list confusing.
Hooks for Custom Worktree Behavior
Two hook events fire around worktree lifecycle:
WorktreeCreate: fires when Claude creates a worktree. The command hook can print a custom path to stdout, overriding Claude’s default location:
{
"hooks": {
"WorktreeCreate": [
{
"hooks": [
{
"type": "command",
"command": "bash -c 'NAME=$(jq -r .name); DIR=\"$HOME/worktrees/$NAME\"; git worktree add \"$DIR\" -b \"$NAME\" >&2 && echo \"$DIR\"'"
}
]
}
]
}
}
WorktreeRemove: fires when Claude removes a worktree. Use it for cleanup tasks (archiving logs, sending notifications):
{
"hooks": {
"WorktreeRemove": [
{
"hooks": [
{
"type": "command",
"command": "bash -c 'NAME=$(jq -r .name); echo \"Worktree $NAME removed at $(date)\" >> ~/worktree-audit.log'"
}
]
}
]
}
}
For non-git VCS (SVN, Perforce, Mercurial), implement custom checkout logic entirely inside WorktreeCreate. The hook replaces Claude’s default git behavior when present.
Subagent Worktree Lifecycle in Detail
What happens internally when a subagent with isolation: worktree runs:
- Claude receives a task that matches the subagent’s
description - Claude calls the
EnterWorktreetool with a generated name - A new worktree is created at
.claude/worktrees/<generated-name>/ .worktreeincludepatterns are processed — matching gitignored files are copied- The subagent session starts inside the new worktree directory
- Subagent does its work, commits if needed, reports results back to the orchestrator
- If no uncommitted changes/untracked files/unpushed commits: worktree is removed automatically
- If changes exist: worktree persists until
cleanupPeriodDaysor manual removal
The orchestrator receives the subagent’s result summary regardless of whether the worktree was cleaned up.
Practical Workflow: Large Feature Across 5 Parallel Agents
A complete example of using all the pieces together for a non-trivial task:
Objective: Add OAuth2 authentication to a Node.js API
Step 1: Spawn research subagents in worktrees
Task: I'm adding OAuth2 authentication to this Node.js API.
Spawn 3 parallel subagents with worktree isolation:
1. Research the OAuth2 libraries available for Node.js (compare passport, oauth2-server, openid-client)
2. Audit our current session management code for compatibility issues
3. Check if our database schema needs changes for token storage
Each subagent should return a concise summary. Use isolation: worktree.
Step 2: Plan based on research
Main session receives summaries. No worktrees needed for planning — just thinking.
Step 3: Execute in parallel
Based on the research:
Spawn 2 implementation subagents with worktree isolation:
1. Implement the OAuth2 token endpoint (use openid-client, modify src/auth/)
2. Update the database schema and migration files
Use isolation: worktree. Both should commit their changes.
Step 4: Merge and validate
# Review what each worktree produced
git diff main...$(git -C .claude/worktrees/worktree-abc123 rev-parse HEAD)
git diff main...$(git -C .claude/worktrees/worktree-def456 rev-parse HEAD)
# Merge implementation branches
git merge worktree-abc123 --no-ff
git merge worktree-def456 --no-ff
# Run full test suite
npm test
Related Articles
- Claude Code Subagents Best Practices 2026 — Subagent definitions, scoping, and cost optimization
- Claude Code Agent Teams Architecture 2026 — Inter-agent communication, task lists, and coordination patterns
- Claude Code Hooks: Complete Reference 2026 — Lifecycle events, exit codes, WorktreeCreate/Remove hooks
- AGENTS.md Best Practices 2026 — Writing effective subagent definitions
Frequently Asked Questions
Q: Can I use git worktrees without Claude Code’s --worktree flag?
Yes. Create worktrees manually with git worktree add ../project-feature -b feature-name, then start Claude Code in that directory with cd ../project-feature && claude. The --worktree flag just automates this process and places worktrees inside .claude/worktrees/ for organization.
Q: How many parallel sessions can I run?
No hard limit. Practical constraints: your machine’s RAM (each Claude Code session uses memory), API rate limits on your Anthropic account, and coordination overhead. Anthropic recommends 3–5 agents for most workflows, with diminishing returns beyond that.
Q: Does isolation: worktree work with user-scoped subagents?
Yes. Subagent definitions at user scope (~/.claude/agents/), project scope (.claude/agents/), and plugin scope all support the isolation: worktree frontmatter field.
Q: What happens if two subagents try to create worktrees with the same name?
Claude Code generates unique names automatically for subagent worktrees. Naming conflicts only arise when you use --worktree with an explicit name that already exists.
Q: Can worktrees work with non-git VCS?
Yes, via WorktreeCreate and WorktreeRemove hooks. Implement custom checkout logic in the hook command — it replaces Claude’s default git behavior entirely. Works for SVN, Perforce, Mercurial, or any VCS. Note that .worktreeinclude is not processed when using custom WorktreeCreate hooks.