The standard Claude Code workflow is one session, one branch, one task at a time. That works fine for a focused bug fix. But when you have a feature to build, a module to refactor, and tests to write — all of which Claude Code could handle — you're leaving a lot of speed on the table by doing them serially.
Git worktrees change that. They let you check out multiple branches from the same repository into separate directories. Each directory is independent. Each can run its own Claude Code session. Multiple AI agents working in parallel, zero interference.
What Git Worktrees Actually Are
A git worktree is a linked working directory attached to the same repository. You get a separate folder with its own branch, its own staging area, and its own HEAD — but sharing the same .git history and object store.
# Normal repo: one branch at a time
my-app/
.git/
src/
# active branch: main
# With worktrees: multiple branches simultaneously
my-app/ # main branch
my-app-dash/ # feature/dashboard
my-app-refactor/ # refactor/auth-module
Each extra directory is a full checkout. You can git status, git add, git commit in any of them independently. Changes in one don't touch the others.
Why This Pairs Well with Claude Code
Claude Code operates inside a directory — it reads files there, edits them, runs shell commands in that context. If two tasks touch different parts of your codebase, running them in the same directory creates friction:
- Context bleed: Claude sees half-done work from task A while doing task B
- File conflicts: both tasks might edit a shared file for unrelated reasons
- Serial bottleneck: you wait for task one before starting task two
With worktrees, each Claude Code session gets a clean working copy on its own branch. They run in true parallel, completely isolated.
Setting Up Worktrees
# Inside your main repo
cd my-app
# Create a worktree for a new feature (creates the branch too)
git worktree add ../my-app-dashboard -b feature/dashboard
# Create one for a refactor
git worktree add ../my-app-auth -b refactor/auth-cleanup
Now you have three separate directories, each on its own branch, all pointing at the same git repository.
Starting Claude Code in each
# Terminal 1
cd ../my-app-dashboard
claude
# Terminal 2
cd ../my-app-auth
claude
Two Claude Code sessions running in parallel, on different branches, no overlap.
A Real Parallel Workflow
Say today's backlog has three independent tasks:
- Build a
/dashboardpage with charts and a stats row - Refactor the auth module from better-auth v1 to v2
- Add missing Vitest coverage for
src/lib/payments.ts
None of them share files. All three can run simultaneously.
# Create the worktrees
git worktree add ../my-app-dashboard -b feature/dashboard
git worktree add ../my-app-auth -b refactor/auth-v2
git worktree add ../my-app-tests -b tests/payments-coverage
# Install dependencies in each
for dir in ../my-app-dashboard ../my-app-auth ../my-app-tests; do
(cd "$dir" && npm install --silent) &
done
wait
Then kick off all three with focused prompts:
# Terminal 1 — cd ../my-app-dashboard, then claude:
"Build a /dashboard page with a revenue chart using Recharts, a recent orders
table using shadcn DataTable, and a stats summary row. Use the existing layout.tsx."
# Terminal 2 — cd ../my-app-auth, then claude:
"Read src/lib/auth.ts first, then migrate it to better-auth v2.
session.create() replaces createSession(). user.findById() replaces getUserById().
Keep the same exports."
# Terminal 3 — cd ../my-app-tests, then claude:
"Write Vitest unit tests for src/lib/payments.ts.
Cover createSubscription, cancelSubscription, applyPromoCode.
Mock the Stripe client at the module level."
Per-Task CLAUDE.md
Your project's CLAUDE.md is shared across all worktrees since they point to the same repo. But you can add a task-specific CLAUDE.md at the worktree root for focused context:
# CLAUDE.md — refactor/auth-v2 worktree
## Current goal
Migrate src/lib/auth.ts from better-auth v1 to v2.
## Do not touch
- src/lib/auth-adapters/ — already migrated
- src/middleware.ts — separate PR
## better-auth v2 breaking changes
- `createSession()` → `session.create()`
- `getUserById()` → `user.findById()`
- All methods return `{ data, error }` now
Worktrees vs Subagents
Claude Code subagents also run tasks in parallel. The difference matters:
| Worktrees + parallel sessions | Subagents | |
|---|---|---|
| Isolation | Separate directories + branches | Same working directory |
| File conflicts | Impossible | Possible |
| Context | Each session is independent | Shared parent context |
| Best for | Long independent tasks (hours) | Short parallel lookups (minutes) |
Use worktrees when tasks are genuinely independent and involve many file changes. Use subagents when tasks are quick and need to share results within one session.
Headless Batch Execution
Combine worktrees with Claude Code's -p flag for fully automated parallel execution:
#!/bin/bash
declare -A TASKS
TASKS["dashboard"]="feature/dashboard|Build the /dashboard page with revenue charts and a stats summary row"
TASKS["auth"]="refactor/auth-v2|Migrate src/lib/auth.ts to better-auth v2. Read the file first."
TASKS["tests"]="tests/payments|Write Vitest tests for src/lib/payments.ts"
mkdir -p logs
for name in "${!TASKS[@]}"; do
IFS='|' read -r branch prompt <<< "${TASKS[$name]}"
git worktree add "../$(basename "$PWD")-$name" -b "$branch" 2>/dev/null || true
(
cd "../$(basename "$PWD")-$name"
npm install --silent
claude -p "$prompt" --output-format text > "../logs/$name.log" 2>&1
echo "done: $name"
) &
done
wait
echo "All tasks finished. Logs in ./logs/"
Managing Worktrees
# See all worktrees
git worktree list
# Remove after merging
git worktree remove ../my-app-dashboard
# Prune if manually deleted
git worktree prune
Common Issues
"fatal: 'feature/dashboard' is already checked out"
A branch can only be active in one worktree. Use a new branch name:
git worktree add ../my-app-dashboard -b feature/dashboard-v2
.env not found
Worktrees don't copy .env files. Symlink it:
ln -s "$(pwd)/.env" ../my-app-dashboard/.env
node_modules not found
Worktrees share the git index but not node_modules. Run npm install in each new worktree.
Shell Alias
function cw() {
local name=$1
local branch=${2:-feature/$1}
local dir="../$(basename "$PWD")-$name"
git worktree add "$dir" -b "$branch"
cd "$dir"
npm install --silent
claude
}
# Usage
cw dashboard feature/dashboard
The setup takes about two minutes. Any Claude Code task that runs longer than two minutes — which is most real tasks — pays off immediately.
Full article with more patterns at stacknotice.com/blog/claude-code-worktrees-2026












