Skip to content

Git Worktrees at Scale

Boris Cherny, creator of Claude Code, runs dozens of Claude instances simultaneously — and git worktrees are how he does it.

The problem they solve is simple: multiple Claude sessions writing to the same working directory step on each other. One session modifies auth.ts while another is reading it to generate tests. File conflicts, inconsistent state, blocked sessions. Git worktrees eliminate the problem entirely by giving each Claude instance its own isolated branch and working directory — no cloning, no coordination overhead.


What Git Worktrees Are

A git worktree is an additional working tree linked to the same repository. Each worktree:

  • Has its own working directory on disk
  • Has its own checked-out branch
  • Shares the same object store (commits, blobs) as the main repository
  • Has no awareness of what other worktrees are doing

You get full branch isolation without the overhead of cloning the repository. A 2GB repo doesn’t become 20GB when you create 10 worktrees — the objects are shared, only the working files are duplicated.

Terminal window
# Manual worktree creation (Claude manages this automatically with -w)
git worktree add ../myrepo-feat-auth feat/auth
git worktree list
/home/user/myrepo abc1234 [main]
/home/user/myrepo-feat-auth def5678 [feat/auth]

Claude Worktree Mode

Terminal window
claude -w
claude -w --label "feat-auth"

The -w flag tells Claude to automatically create and manage a worktree for this session. What happens:

  1. Claude creates a new branch named after the task label (or a generated name)
  2. A new working directory is created at ../reponame-label/
  3. Claude’s session operates entirely within that worktree
  4. The main repository is untouched until you merge

Each Claude instance gets its own branch state. Multiple instances write files without knowing about each other — because they’re literally working in different directories on different branches.

The Desktop app exposes this as a “New Worktree” checkbox when starting a session.


Why Worktrees Enable Parallel AI Development

flowchart TD subgraph Sequential["Without Worktrees (Sequential)"] M1[main branch] --> W1[Work on auth] W1 --> P1[PR: auth] P1 --> M2[merge] M2 --> W2[Work on payments] W2 --> P2[PR: payments] P2 --> M3[merge] M3 --> W3[Work on notifications] end subgraph Parallel["With Worktrees (Parallel)"] BASE[main branch] --> B1[branch: auth] BASE --> B2[branch: payments] BASE --> B3[branch: notifications] B1 --> PR1[PR: auth] B2 --> PR2[PR: payments] B3 --> PR3[PR: notifications] PR1 --> MERGE[squash merge] PR2 --> MERGE PR3 --> MERGE end style M1 fill:#1e293b,color:#7dd3fc,stroke:#334155 style M2 fill:#1e293b,color:#7dd3fc,stroke:#334155 style M3 fill:#1e293b,color:#7dd3fc,stroke:#334155 style W1 fill:#1e293b,color:#7dd3fc,stroke:#334155 style W2 fill:#1e293b,color:#7dd3fc,stroke:#334155 style W3 fill:#1e293b,color:#7dd3fc,stroke:#334155 style P1 fill:#1e293b,color:#86efac,stroke:#334155 style P2 fill:#1e293b,color:#86efac,stroke:#334155 style P3 fill:#1e293b,color:#86efac,stroke:#334155 style BASE fill:#1e293b,color:#7dd3fc,stroke:#334155 style B1 fill:#1e293b,color:#7dd3fc,stroke:#334155 style B2 fill:#1e293b,color:#7dd3fc,stroke:#334155 style B3 fill:#1e293b,color:#7dd3fc,stroke:#334155 style PR1 fill:#1e293b,color:#86efac,stroke:#334155 style PR2 fill:#1e293b,color:#86efac,stroke:#334155 style PR3 fill:#1e293b,color:#86efac,stroke:#334155 style MERGE fill:#1e293b,color:#86efac,stroke:#334155

The sequential model means you’re always waiting. The parallel model means you’re reviewing while Claude is still working on the next thing.


The Dozens-of-Claudes Workflow

This is the approach Boris Cherny described for maximum parallelism:

Step 1: Decompose the work

Break the task into 5-10 independent units. The key question: do these units touch the same files? If yes, they’re dependent and must run sequentially. If no, they’re independent and can run in parallel.

Step 2: Launch one session per unit

Terminal window
claude -w --label "task-auth-login"
claude -w --label "task-auth-oauth"
claude -w --label "task-auth-2fa"
claude -w --label "task-payments-stripe"
claude -w --label "task-payments-invoices"

Each session gets its own worktree automatically. Launch them all, then let them run.

Step 3: Let them work

You don’t monitor. You move on to the next thing — reviewing the plan, writing specs, or taking a break. The sessions run independently.

Step 4: Review the PRs

As each session completes, it creates a PR. You review each independently. If a session got blocked, you’ll see a notification — attach, provide guidance, it continues.

Step 5: Merge

Squash merge each PR to main. Because the tasks were independent (different files), there are no merge conflicts.

Step 6: Clean up

Terminal window
git worktree remove ../myrepo-task-auth-login
git worktree prune # cleans stale references

Identifying Independent Tasks

This is the critical skill. Get it wrong and you’ll have merge conflicts. Get it right and parallel execution is seamless.

Independent (safe to parallelize):

  • Different directories: src/auth/ vs src/payments/
  • Different feature areas that don’t share utilities
  • Read-only analysis tasks (any number can run in parallel)
  • Tasks that each create new files rather than modifying existing ones

Dependent (must run sequentially):

  • Both tasks modify the same file
  • Task B depends on output from Task A (e.g., B imports a module A is creating)
  • Both tasks modify shared configuration (e.g., package.json, tsconfig.json)
  • Database schema changes that affect multiple areas

When in doubt: check the file overlap. If two task descriptions would list any of the same files, run them sequentially.


Example: Migrating 50 API Endpoints

You need to migrate 50 API endpoints from session-based auth to JWT. The endpoints are in 5 directories of 10 each. The migration pattern is identical for each endpoint.

Terminal window
# Group 1: user endpoints (1-10)
claude -w --label "auth-migration-users" \
"Migrate the endpoints in src/api/users/ from session auth to JWT.
Pattern: replace req.session.userId with verifyJWT(req).userId.
Run tests after. Create PR when done."
# Group 2: product endpoints (11-20)
claude -w --label "auth-migration-products" \
"Migrate the endpoints in src/api/products/ from session auth to JWT.
Pattern: replace req.session.userId with verifyJWT(req).userId.
Run tests after. Create PR when done."
# Groups 3-5 follow the same pattern
claude -w --label "auth-migration-orders"
claude -w --label "auth-migration-payments"
claude -w --label "auth-migration-admin"

All 5 run simultaneously. A migration that would take 2-3 hours sequentially takes 25-30 minutes — bounded by the slowest group, not the sum of all groups.


Sparse Checkout for Large Monorepos

In a large monorepo, each worktree checking out the full repository wastes disk space and slows down the initial setup. Sparse checkout limits each worktree to only the files it needs:

Terminal window
git worktree add ../myrepo-feat-auth feat/auth
cd ../myrepo-feat-auth
git sparse-checkout init --cone
git sparse-checkout set src/auth/ shared/utils/ package.json

Now the worktree only contains src/auth/, shared/utils/, and package.json. The agent working on auth has no access to (and won’t accidentally modify) src/payments/.

Sparse checkout is especially valuable when:

  • The monorepo is > 5GB
  • Each agent only touches a well-defined subset of directories
  • You’re running 10+ agents and disk space is a concern

Integration with /batch

/batch is the structured version of this workflow. Where manual worktree management requires you to decompose the work, launch sessions, and track progress yourself, /batch automates all three steps:

  1. You describe the task and specify agent count
  2. /batch decomposes the work into chunks
  3. Creates worktrees automatically for each agent
  4. Dispatches agents with their specific chunks
  5. Monitors and merges when complete

Manual worktrees give you more control. /batch gives you less friction. Use manual worktrees when the decomposition requires human judgment; use /batch when the task has a clear mechanical split.


Practical Limits and the Human Bottleneck

Each Claude instance is a separate context window with a separate token budget. Running 10 instances in parallel means 10x the API cost compared to running 1.

But the real bottleneck at scale isn’t cost — it’s your review capacity. Each agent produces a PR. Each PR needs review. At 15+ parallel sessions, PRs pile up faster than you can review them.

Sweet spot for individual developers: 3-7 parallel sessions. This keeps the review queue manageable while delivering meaningful parallelism.

For teams with dedicated reviewers, the bottleneck shifts to the reviewers’ capacity. With 2-3 reviewers, 10-15 parallel sessions can be sustainable.

The right number is: how many PRs can you review per hour, times how long each session runs.


Worktree Cleanup

After merging, clean up to avoid stale worktrees accumulating:

Terminal window
# List all worktrees
git worktree list
# Remove a specific worktree (after merging the branch)
git worktree remove ../myrepo-feat-auth
# Clean up stale references (worktrees deleted without git worktree remove)
git worktree prune
# Verify
git worktree list

Stale worktrees don’t cause problems, but they clutter git worktree list and waste disk space.