Loading homepage
Claude Code installed (claude --version ≥ 1.0)
Git 2.40+ with worktree support (git worktree list)
Yarn 4 / npm / pnpm
A repo with at least 1 commit
A working .claude/ setup that dispatches 25 concurrent agents into isolated worktrees, with skill-driven file-ownership matrices preventing merge conflicts.
The naive approach to multi-agent Claude Code work is to dispatch agents on the same branch, watch them clobber each other's staged changes, and then spend longer debugging the collisions than the parallel work saved. I've been through that. Once is enough.
Git worktrees are the correct isolation primitive. Each agent gets its own working tree on disk — a separate checkout of the repository at a separate path, on a separate branch. Reads and writes in one worktree don't affect another. The agents run in parallel; git handles the tree-level isolation.
This tutorial walks through the full setup: the directory convention, the file-ownership skill, dispatching agents, what breaks at scale, how to merge, and how to clean up. By the end you have a pattern you can apply to any repo.
A branch is a pointer. Two agents on different branches of the same working tree still share the same files on disk — they'd need to stash or commit before switching, and Claude Code agents generally don't do that automatically.
A worktree is a separate directory on disk, checked out to a specific branch. Two agents in two worktrees can write to their respective branches simultaneously, with no locking, because they're operating on different paths.
# Single working tree — one checkout, one branch at a time
git branch --list
# * main
# feat/agent-a
# feat/agent-b
# Worktrees — each branch has its own path
git worktree list
# /repo HEAD [main]
# /repo/.claude/worktrees/agent-a abc1234 [feat/agent-a]
# /repo/.claude/worktrees/agent-b def5678 [feat/agent-b]With worktrees, agent-a writes to /repo/.claude/worktrees/agent-a/src/foo.ts and agent-b writes to /repo/.claude/worktrees/agent-b/src/bar.ts. No conflict, no coordination needed during the work phase.
.claude/worktrees/ conventionCreate the directory that will hold worktree checkouts:
mkdir -p .claude/worktrees
echo ".claude/worktrees/" >> .gitignoreThe .gitignore entry prevents git from tracking the worktree directories as untracked content in the parent checkout. Each worktree has its own .git file (a plain file, not a directory) pointing back to the shared object store.
When you add a worktree:
git worktree add .claude/worktrees/agent-a -b feat/agent-aThis creates .claude/worktrees/agent-a/ as a full working tree on a new branch feat/agent-a. The branch starts from the current HEAD of main.
List all worktrees at any time:
git worktree listThe worktree isolation prevents runtime conflicts — two agents writing the same byte at the same time. But it doesn't prevent logical conflicts: two agents editing different lines of the same file, producing a merge conflict that requires manual resolution.
The way to prevent logical conflicts is to assign each agent exclusive ownership of specific files before dispatch. No two agents touch the same file.
Create a skill file at .claude/skills/file-ownership.md:
# File-ownership matrix
When dispatched as a subagent, your allowed files are listed in your brief.
You may only write to files in your ownership list.
If you need to modify a file that is not in your list, STOP and report the
conflict to the parent agent. Do not attempt to edit files outside your list.
## Common ownership groups
| Concern | Owner files |
|--------------------|--------------------------------------------------|
| API route | app/api/<route>/route.ts |
| Component | components/<name>.tsx |
| Library module | lib/<name>.ts |
| DB migration | supabase/migrations/<dtg>_<name>.sql |
| Test file | <name>.test.ts (co-located with the source file) |
If two agents need the same file, the parent must sequence them, not parallelize.In your dispatch brief for each agent, include the ownership list explicitly:
You are agent-a. Your branch: feat/agent-a. Your worktree: .claude/worktrees/agent-a.
Your files: lib/email-delivery.ts, lib/email-templates/welcome.ts
Do not touch any file outside this list.This is the single most effective conflict-prevention measure. Worktrees handle runtime isolation; the ownership matrix handles content isolation.
With worktrees created and ownership assigned, dispatch is straightforward. Each agent receives a brief containing:
Example dispatch brief for agent 3 of 5:
You are agent-3, working on feat/add-mailgun-welcome-email.
Worktree: /repo/.claude/worktrees/agent-3 (absolute path).
Your files: lib/mailgun.ts, lib/email-templates/welcome.ts
Task: Add a welcome email function to lib/mailgun.ts that sends a plain text
+ HTML welcome message. Template source lives in lib/email-templates/welcome.ts.
Create that file with the template content.
Commit with: feat(email): add welcome email template and send function
Use batch_commit with workspaceRoot set to your worktree path.
Do NOT push.The absolute worktree path in the brief prevents the most common subagent mistake: writing to the parent checkout instead of the worktree. Brief agents to pass their worktree path explicitly to every tool call that accepts a root or workspace parameter.
Create the worktrees before dispatching:
for i in 1 2 3 4 5; do
git worktree add .claude/worktrees/agent-$i -b feat/batch-$i
doneThen dispatch all 5 agents in one dispatch call (or via your orchestration tool of choice). They run concurrently.
The worktree model scales linearly from 5 to 25 agents with one caveat per resource:
Disk I/O. Each worktree is a full working tree checkout. 25 worktrees of a large repo can be significant disk usage. On an NVMe drive this is fast. On a network-attached volume it can be a bottleneck. Check with du -sh .claude/worktrees/ after the first batch.
npm/yarn cache contention. If agents run yarn install or npm install concurrently in their worktrees, they may hit cache lock contention. The fix is to run a single install in the parent checkout first (cache is warm), then create worktrees after — most package managers share the cache across worktrees in the same repo, so agents that don't modify package.json don't need to install at all.
Claude Code rate limits. Claude API calls from agents count against your rate limit. 25 concurrent agents making tool calls simultaneously can hit the per-minute token ceiling. The practical mitigation is to stagger dispatch in batches of 5–10 and not wait for all 25 to complete in one synchronous wave.
Context window per agent. Each agent runs in its own context. Briefing 25 agents means 25 separate context windows. Keep briefs tight — under 500 words each. Long briefs consume context that should go to the actual work.
Mental overhead of 25 branches. The ownership matrix is not just for git — it's for you. With 25 agents and no matrix, you won't know which agent is responsible for which file when a problem surfaces. Keep the matrix in a file, not in your head.
When an agent finishes and its commits land on its branch, bring them to main via cherry-pick, not merge. Cherry-picks produce a linear history, make bisect reliable, and let you apply commits one at a time with review in between.
# Inspect what the agent committed
git log feat/agent-3 --oneline --not main
# Cherry-pick each commit onto main
git cherry-pick <commit-sha>After cherry-picking, run your verification gate:
yarn verify:dev # lint + typecheck, safe while dev is runningFix any issues before picking the next agent's commits. Do not batch all 25 agents' commits onto main at once — you'll lose the ability to isolate which agent introduced a problem.
If two agents' commits conflict (they edited the same file despite the ownership matrix — it happens), resolve at cherry-pick time. The conflict will be small and targeted because the ownership matrix kept the scope narrow.
After an agent's commits are on main, remove its worktree and branch. Do not leave them for "later cleanup."
# Remove a worktree
git worktree remove --force .claude/worktrees/agent-3
# Delete the branch
git branch -D feat/agent-3Stale worktrees cause two problems: they confuse re-dispatch (if you automate worktree names, a stale one blocks recreation), and they inflate git worktree list to the point where it's no longer a useful snapshot of active work.
After each batch completes:
# Verify clean state
git worktree list # should show only the main checkout
git branch -v # should show only main (+ origin/main)The invariant: between dispatch batches, zero worktrees and zero branches other than main. Start each new batch from this clean state.
The Power Pack includes a working implementation of this pattern: the file-ownership skill, a dispatch brief template, and a cleanup script. If you'd rather start from tested code than build from this tutorial, that's the place to start.
Pre-built MCP configs, prompt templates, and shell scripts that eliminate the setup work described here. Drop them in and start shipping.