Claude Code Parallel Worktrees — Boris Cherny's Canonical Workflow
In short: Stand up a working 3-5 session parallel Claude Code workflow on one real repo using git worktrees, with automatic per-worktree ports and databases, a status view of all worktrees, and a measured answer to whether it actually raised your merged-PR throughput.
| Key fact | Detail |
|---|---|
| What it covers | agents, software development, LLM, open source |
| Tools | Claude, Claude Code, Anthropic, BigQuery, Ghostty |
| Posts covered | 2 posts (1 S-tier) · top: Claude Code Team Tips — Boris Cherny's 10… · CLAUDE.md Workflow Template — plan mode… |
| Creators | @evolving.ai, @mindwired.ai |
| Sources dated | Feb 2026 |
| Prompt system | Run-it-yourself prompts |
| Last verified | 2026-10-22 |
Category: Claude Code workflow / productivity
Confidence: High — documented by Claude Code's creator on X/Threads, shipped as a native --worktree flag, and covered in official Anthropic docs.
Primary sources:
- Boris Cherny on X, "Do more in parallel": https://x.com/bcherny/status/2017742743125299476
- Boris Cherny on X, "Use claude --worktree for isolation": https://x.com/bcherny/status/2025007394967957720
- Anthropic official docs, "Orchestrate teams of Claude Code sessions": https://code.claude.com/docs/en/agent-teams
- "How Boris Uses Claude Code": https://howborisusesclaudecode.com/
- Community guides: shareuhack.com, thepromptshelf.dev, botmonster.com
What it is
Boris Cherny — creator of Claude Code — runs 3 to 15 Claude Code sessions in parallel, each in its own git worktree. It is, in his own words, "the single biggest productivity unlock" and "the top tip from the team." This pattern became the canonical Anthropic-internal workflow in late 2025 / early 2026 and got native CLI support via the claude --worktree flag.
The core insight is boring and load-bearing: LLM coding is I/O-bound on the human, not the machine. You spend 80% of your time reviewing, 20% typing the next prompt. If you run one Claude at a time, the model is idle while you read. If you run five, you are always reviewing something while the other four work. This is not "multi-agent orchestration" — it is single-operator parallelism. You are a director, not a coder.
Git worktrees are the enabling primitive because they give each session its own working directory on its own branch, sharing the same .git object store. Five worktrees = five isolated checkouts of the same repo, zero disk duplication of git history, zero merge conflicts between running sessions.
How it works
The git worktree primitive
git worktree is a vanilla git feature from 2015 that almost nobody uses. It lets one repo have multiple working directories:
# From inside a normal repo
git worktree add ../myproject-feature-a feature-a # new branch
git worktree add ../myproject-bugfix main # existing branch
git worktree list # show all
git worktree remove ../myproject-feature-a # clean up
Each worktree is a full checkout with its own HEAD, its own index, its own untracked files. They share the .git directory (via .git file pointing back to the main repo), so object storage is deduplicated. Branch safety is enforced: you can't check out the same branch in two worktrees simultaneously.
The Boris pattern, step by step
- Start from a clean main.
git checkout main && git pull. - Spin up N worktrees, one per independent task:
git worktree add ../proj-auth -b feat/auth git worktree add ../proj-billing -b feat/billing git worktree add ../proj-refactor -b chore/refactor-api git worktree add ../proj-bugfix -b fix/issue-412 - Open a terminal tab (or tmux pane) per worktree and launch Claude in each:
cd ../proj-auth && claude cd ../proj-billing && claude cd ../proj-refactor && claude cd ../proj-bugfix && claude - Prompt each session with one focused task. One task = one worktree = one session. Do not multiplex tasks inside a single session.
- Cycle through the sessions while they work. When one finishes, review, commit, push, open a PR, then either give it the next task or
git worktree removeit. - Merge back via normal PRs. The worktrees never touch each other's filesystems; all coordination happens through git + PRs, the same as any human team.
The claude --worktree shortcut
In late 2025 / early 2026 Anthropic shipped native worktree support so you do not have to manage them by hand:
claude --worktree # auto-creates a worktree, Claude picks the name
claude --worktree my-feature-name # explicit name
claude --worktree --tmux # also launch inside its own tmux session
This handles the git worktree add, cd into it, and launches Claude in one command. The Desktop app has had this for longer; it was ported to the CLI because the team realized everyone was doing it manually.
Sub-agents with worktree isolation
The Task tool (sub-agents) can also be worktree-isolated. In your sub-agent frontmatter:
---
name: migration-worker
isolation: worktree
---
When dispatched, the sub-agent gets its own worktree. When it finishes, the worktree path and branch name are returned to the parent agent for review/merge. This is the power move for large batched changes — migrations, codemod-style refactors, mass dependency bumps — where you want 10 sub-agents each handling a subdirectory without stomping on each other.
This is also the pattern behind Anthropic's "Agent Teams" feature (code.claude.com/docs/en/agent-teams): teammates coordinate through git commits in their respective worktrees.
Quick start — 3-worktree minimum viable parallel workflow
# 1. From your project root on main
cd ~/projects/myproject
git checkout main && git pull
# 2. Create three worktrees beside the main checkout
git worktree add ../myproject-a -b task/a
git worktree add ../myproject-b -b task/b
git worktree add ../myproject-c -b task/c
# 3. Open three terminal tabs (or tmux windows) and launch Claude in each
# tab 1
cd ../myproject-a && claude
# tab 2
cd ../myproject-b && claude
# tab 3
cd ../myproject-c && claude
# 4. Prompt each with one focused task. Cycle between tabs.
# 5. When a task is done: review, commit, push, open PR
cd ../myproject-a
git add -A && git commit -m "feat: task a"
git push -u origin task/a
gh pr create --fill
# 6. Clean up after merge
git worktree remove ../myproject-a
Or, the native way:
claude --worktree task-a
claude --worktree task-b
claude --worktree task-c
Each command spawns a fresh Claude session in its own worktree in one line.
With tmux (recommended for 5+ sessions)
Beyond ~4 terminal tabs, tmux becomes essential — you want a single keystroke to cycle through sessions and a persistent layout that survives terminal closure.
tmux new -s claude-parallel
# inside tmux
claude --worktree --tmux task-a # spawns in its own tmux window
claude --worktree --tmux task-b
claude --worktree --tmux task-c
# Ctrl-b n / Ctrl-b p to cycle windows
Tools worth knowing:
workmux(github.com/raine/workmux) — turns "create worktree + open tmux window + cd in + launch Claude" into one command.claude-tmux(github.com/nielsgroen/claude-tmux) — tmux popup TUI that manages multiple Claude Code sessions, worktrees, and PRs from one view.muxtree— simpler alternative with the same idea.
When to use it (and when not to)
Use parallel worktrees when:
- You have 2+ genuinely independent tasks — different files, different concerns, no shared state.
- You are doing a large migration where chunks can be parallelized (e.g. "convert all 40 React class components to function components").
- You are exploring N alternative approaches to the same problem and want to compare results side-by-side.
- You are bug-hunting across multiple issues and want each fix in its own branch/PR.
- You are reviewing work on one task while another runs — the "director mode" benefit.
Do not use parallel worktrees when:
- Tasks depend on each other — one needs the other's output. Chain them in a single session instead.
- You are exploring an unfamiliar codebase — you need focus, not five things shouting at you.
- You are debugging a subtle issue — context-switching kills debugging flow.
- You have shared global state outside git (a single dev database, a single running server on a single port). Two worktrees can't both
npm run devon port 3000. - You are on a laptop with <32GB RAM and each session spawns heavy dev servers. Each worktree is a full checkout; if each runs webpack, you will OOM.
What breaks at scale
Running 10–15 parallel sessions surfaces real problems:
- Port collisions. Dev servers default to the same port. Fix: env vars per worktree (
PORT=3001,PORT=3002), or a port-picker script. - Database state. SQLite is fine (each worktree gets its own file). Postgres/Mysql with a shared dev DB is a disaster — migrations from one worktree break another. Use per-worktree Docker containers, or schema namespaces.
node_modulesduplication. Each worktree gets its ownnode_modules, which at 500MB–2GB × 10 = bad. Fix: pnpm withshared-workspace-lockfile, or a global store (pnpm store,yarn berry pnp).- Review bottleneck shifts to you. At ~5 sessions the model is no longer the bottleneck — you are. More parallelism past your review capacity is wasted.
- Context fragmentation in your head. Switching between 10 tasks is exhausting. Most experienced users settle around 3–5 concurrent worktrees, not 15.
- Git hooks that assume one worktree. Pre-commit hooks that write to a shared cache can race. Configure hooks to be worktree-aware.
- IDE confusion. VS Code's git extension can get confused by worktrees; it sometimes shows the wrong branch. Open each worktree as its own window.
- CLAUDE.md drift. If each worktree edits CLAUDE.md, you get conflicts on merge. Convention: only edit CLAUDE.md on main, never in feature worktrees.
- API rate limits / billing. 10 parallel Claude sessions = 10x token spend. On a subscription plan you will hit rate limits fast. Monitor
~/.claude/usageif available. - Merge conflicts from adjacent edits. If two sessions both edit
package.json, you will merge-conflict. Plan tasks to touch disjoint file sets.
What we could build with it
- A
spawn-parallel.shscript that takes a list of task descriptions and spawns N worktrees + Claude sessions + tmux windows in one command, with auto port assignment per worktree. - A review dashboard (tmux statusbar or small TUI) showing the git status of all active worktrees so you know at a glance which ones are ready for review.
- A swarm runner that takes one large migration task, decomposes it into N independent chunks, spawns N worktrees, and reports back when all are done — essentially the Boris pattern behind the
/swarmskill. - A CLAUDE.md rule enforcing "never edit CLAUDE.md outside main" to avoid merge churn.
- A per-worktree env injector that sets
PORT,DATABASE_URL, andREDIS_URLto non-colliding values automatically based on the worktree name hash. - Integration with existing
/crankand/codex-teamskills: use worktree isolation as the default execution substrate for any multi-task epic.
Gotchas and limits
git worktree addrefuses to check out a branch already checked out elsewhere — this is a feature, not a bug. If you need two worktrees on the same branch, one of them must detach (--detach).- Worktrees share hooks. Husky/pre-commit hooks live in
.git/hookswhich is shared. If a hook writes to a cache directory, make that cache worktree-scoped. git worktree removerefuses to delete a dirty worktree. Use--forceif you really want to, but prefer committing or stashing first.- Sub-module behavior is awkward. Each worktree initializes its own submodules; this can double disk use.
- The
--worktreeflag is relatively new. On older Claude Code versions (pre late-2025) you have to do the manualgit worktree adddance. - Native worktree support in the Desktop app predates the CLI. If you use the Desktop app, you already have this; the CLI caught up later.
- The single biggest mistake newcomers make: running parallel sessions on the same task, racing them. Don't. One session per task. Parallelism is across independent tasks, not across attempts at the same task.
- Throughput gains cap around 3-5x, not 15x. Boris personally runs "3-5 at once"; the "10-15" number is the team's ceiling, not a target. Review bandwidth is the binding constraint.
Bottom line
claude --worktree is the single highest-leverage workflow change you can make to Claude Code usage. Two commands — git worktree add + claude — turn you from a serial coder into a director of 3-5 concurrent agents. Start with 3, add a 4th when you feel idle between reviews, stop when review stops being fun. Use tmux once you exceed 4. Never run parallel sessions on tasks that share state. The gains come from your own time being the bottleneck, not the model's.
Prompt system — run this yourself
Everything below is pasteable into Claude Code, Claude, or any agent. Use the one-shot when you want the whole result in one run; use the step prompts when you want to steer. Every step carries its own audit, and the gap audit at the end makes the agent find and fill what it missed.
Mission. Stand up a working 3-5 session parallel Claude Code workflow on one real repo using git worktrees, with automatic per-worktree ports and databases, a status view of all worktrees, and a measured answer to whether it actually raised your merged-PR throughput. Done means at least three independent tasks ran concurrently in isolated worktrees, merged through normal PRs without cross-session conflicts, and a before/after log shows the throughput and review-time numbers for your own work.
1 · Deeper, not bigger
Before running anything, make the task deeper rather than larger. Ask: what would a top professional do here that I am not asking for; what is the rawest material; which methods and tools; what, other than the model or me, proves it right. Then ask for exactly that.
- What a top professional would do (that you didn't ask for): An engineering lead would not start by opening fifteen tabs; they would first measure their own baseline (PRs merged per day, minutes of review per PR, idle minutes waiting on the model), then decompose a backlog into tasks with provably disjoint file sets before spawning anything. They would make the environment worktree-safe up front: ports, databases, caches, .env files, and git hooks keyed to the worktree, because those collisions are what actually break parallel runs. And they would treat the guide's own warning seriously: throughput caps around 3-5x because human review is the binding constraint, so the experiment is about finding your personal ceiling.
- Rawest material to start from: Boris Cherny's original posts (x.com/bcherny/status/2017742743125299476 and x.com/bcherny/status/2025007394967957720); the official agent teams page at code.claude.com/docs/en/agent-teams and the CLI reference for
--worktreeon your installed version (claude --help); the git-worktree man page (git help worktree), especially sections on locking, pruning, and --detach; your own repo's package.json, docker-compose.yml, .env.example, and .husky or .git/hooks, which determine what collides; and your own git log for the last 30 days as the baseline. - Methods and tools: git worktree add/list/remove/prune/lock;
claude --worktree <name>and--tmuxif present on your version; tmux with one window per worktree; a port allocator that hashes the worktree name into a range (e.g. 3100-3999) and writes PORT, DATABASE_URL, REDIS_URL into .env.local; per-worktree Postgres viadocker compose -p <worktree>or schema namespaces, SQLite files per worktree; pnpm's content-addressed store to avoid node_modules duplication;gh pr create --fillandgh pr list --jsonfor throughput counts;git diff --name-only main...to verify disjoint file sets. - What proves it right (other than you or the model): GitHub itself is the oracle:
gh pr list --state merged --author @me --json mergedAt,createdAtover the experiment week versus the baseline week gives merged-PR count and cycle time. CI results on each PR show nothing broke from isolation leaks.git worktree listanddocker psshow no orphaned worktrees or containers after cleanup. Two dev servers answering on different ports at the same time (curl both) prove port isolation.
Rewritten prompt — ask for exactly that:
Act as an engineering lead setting up parallel Claude Code work on my repo at <path>. First measure my baseline: use `gh pr list --state merged --author @me --json number,createdAt,mergedAt --limit 100` to compute merged PRs per day and median cycle time over the last 30 days. Then inspect the repo for collision points: dev-server ports, database URLs, Redis, caches, .env files, git hooks (husky, pre-commit), and node_modules size. Check `claude --help` for the --worktree and --tmux flags on my installed version and document exactly where worktrees are created and what gets copied. Build scripts/wt-spawn.sh that takes a task name, creates a worktree on a new branch, assigns a deterministic port from a hash of the name, creates an isolated database (docker compose project or SQLite file), writes .env.local, installs dependencies via the shared pnpm store, and opens a tmux window running Claude. Build scripts/wt-status.sh showing each worktree's branch, dirty count, ahead/behind, PR state, and port. Build scripts/wt-clean.sh that removes merged worktrees and their containers. Then help me pick three tasks from my backlog whose file sets are disjoint (prove it with a file-ownership list), run them concurrently for one week, log timestamps to worktree-log.csv, and report merged-PR throughput and review time versus baseline. Flag any guide claim (like the 3-5x cap) my data contradicts.
2 · One-shot prompt
ROLE AND STANCE
You are an engineering lead making one developer's repo safe and fast for parallel Claude Code sessions, following Boris Cherny's worktree pattern but measuring whether it works for this person. You prefer boring, deterministic scripts over clever orchestration. You do not trust throughput claims you have not measured.
CONTEXT
- Pattern: one task = one git worktree = one Claude session; all coordination via branches and PRs. Boris runs 3-5 at once; 10-15 is the team ceiling, not a target. Review bandwidth is the binding constraint.
- Primitives: `git worktree add ../proj-x -b feat/x`, `git worktree list`, `git worktree remove`, `git worktree prune`; native `claude --worktree [name]` and `--tmux` (verify on the installed version with `claude --help`); subagent frontmatter `isolation: worktree` (verify it exists in the installed version's subagent docs).
- Tools named in the guide: raine/workmux, nielsgroen/claude-tmux, muxtree, tmux.
- Known collisions from the guide: dev-server ports, shared Postgres/MySQL dev DB, node_modules at 500 MB-2 GB per worktree, shared .git/hooks writing to shared caches, IDE branch confusion, CLAUDE.md edits conflicting on merge, package.json adjacent edits, rate limits from N times token spend.
- Claims to TEST against this repo and this person: 'single biggest productivity unlock'; 'throughput gains cap around 3-5x'; 'zero merge conflicts between running sessions'; 'zero disk duplication of git history'.
HARD CONSTRAINTS
- Push the current branch before creating or removing any worktree. Never use `git worktree remove --force` on a dirty worktree without listing its uncommitted changes first and getting confirmation.
- Never `git add -A` in a worktree whose session is still editing; commit by explicit paths.
- No two concurrent tasks may share a file in their planned change set. Prove it before spawning.
- CLAUDE.md is edited only on main.
- Do not exceed the user's plan rate limits; start with three sessions.
ORDERED DELIVERABLES
1. baseline.md: merged PRs per day and median createdAt-to-mergedAt over the last 30 days from `gh pr list --state merged --author @me --json number,createdAt,mergedAt --limit 200`; repo size; node_modules size; list of collision points found in package.json scripts, docker-compose.yml, .env.example, and git hooks.
2. Native-flag notes in baseline.md: where `claude --worktree` puts worktrees, branch naming, whether .env files are copied, cleanup behaviour. Tested, not read.
3. scripts/wt-spawn.sh <task>: push check, worktree on branch wt/<task>, deterministic PORT from cksum of the name into 3100-3999, isolated DB (docker compose -p <task> or SQLite file path), .env.local with PORT, DATABASE_URL, REDIS_URL, `pnpm install --frozen-lockfile` (or the repo's package manager) using the shared store, then `tmux new-window -n <task> 'cd <path> && claude'`.
4. scripts/wt-status.sh: table of worktree, branch, dirty file count, ahead/behind main, PR number and state via gh, PORT, container status.
5. scripts/wt-clean.sh: for worktrees whose PR is merged, show dirty state, remove worktree, delete branch, `docker compose -p <task> down -v`, then `git worktree prune`.
6. tasks.md: three backlog tasks with planned file sets and a pairwise-overlap check that shows zero shared files.
7. worktree-log.csv: task, spawn time, first review time, PR open time, merge time, conflicts (y/n), rework rounds.
8. results.md after the trial: merged PRs per day and median cycle time versus baseline, number of sessions at which review became the bottleneck, verdicts on the four claims.
BUILT-IN GAP ANALYSIS
Before declaring done, list in gaps.md: collision points you found but did not isolate (shared caches, external APIs with per-account rate limits, ports hard-coded in source), anything about the native flag you could not determine, tasks that conflicted despite the overlap check and why, and whether the measurement window is long enough to mean anything (one week with three tasks is anecdote; say so). Fix any isolation gap that a script change can fix now.
SELF-QUESTIONS BEFORE FINISHING
- Did two dev servers actually run at once on different ports, and did I curl both?
- Does any hook in .git/hooks write to a path shared across worktrees?
- What happens to Docker volumes and SQLite files when a worktree is removed?
- Does the repo hard-code port 3000 anywhere that .env.local does not override?
- Did I count review time, or only model time?
- Did any session edit CLAUDE.md, package.json, or a lockfile?
- Does wt-clean refuse to delete unmerged or dirty work?
STOP CONDITIONS
Stop after scripts and tasks.md exist and a dry run of three spawns and one clean succeeds, then hand control to the user for the trial week. Stop and ask before removing any worktree with uncommitted changes, before dropping any database volume that existed before this work, and if the repo needs a shared external resource (single staging DB, single OAuth callback URL) that cannot be isolated.
RETURN FORMAT
One message: baseline numbers table; native-flag findings; the three scripts' paths with usage lines; tasks.md overlap matrix; dry-run output of wt-status.sh with three worktrees; gaps.md contents; the instructions for the trial week, including what to log.
3 · Step-by-step prompts
Step 1 — Ground truth: baseline and collision inventory
Goal: Measure current throughput and find every resource two worktrees would fight over.
In the repo at <path>, run `gh pr list --state merged --author @me --json number,title,createdAt,mergedAt --limit 200` and compute merged PRs per working day and median hours from createdAt to mergedAt over the last 30 days; write both to baseline.md with the raw counts. Record `du -sh .git`, `du -sh node_modules` (or the venv / target dir), and the package manager in use. Then inventory collision points: grep package.json scripts, Procfile, docker-compose.yml, vite/next/webpack configs, and source for hard-coded ports (`grep -rnE '(PORT|:3000|:5173|:8000|:5432|:6379)' --include='*.{js,ts,json,yml,yaml,py,env*}'`); list database and Redis URLs and where they come from; list .git/hooks and husky or pre-commit configs and any paths they write; list caches (.next, .turbo, .pytest_cache, ~/.cache tool dirs) and whether they are inside or outside the checkout. Read Boris Cherny's two posts linked in the guide and note his own concurrency number. Finally, in a scratch clone, run `claude --help | grep -iA3 worktree` and one `claude --worktree probe-a` session; record where the worktree lands, its branch name, whether .env files are copied, and what happens on exit, then remove it. Write everything to baseline.md as tables.
Expect: baseline.md with a throughput table (PRs/day, median cycle hours, sample size) and a collision table (resource, current value, where configured, shared across worktrees yes/no), plus a short native-flag findings list.
Audit before moving on: Re-count PRs with a second query (for example the GitHub web search is:pr is:merged author:@me merged:>DATE) and confirm the number matches within one. Any port or URL found in source but not in env config is flagged as hard-coded; do not move on until each collision row has a 'how to isolate' note.
Step 2 — Build the spawn script with isolation
Goal: One command creates an isolated, ready-to-run worktree with its own port, database, and Claude session.
Write scripts/wt-spawn.sh <task-name>. It must: refuse if the current branch has unpushed commits; refuse if a worktree or branch wt/<task> exists; create the worktree at ../<repo>-<task> on new branch wt/<task> from origin/main (or call `claude --worktree <task>` instead if native-flag.md shows it supports what follows); compute PORT as 3100 + (cksum of the task name mod 900) and check it is free with `ss -ltn`; create an isolated database per the collision table (for Postgres `docker compose -p <task> up -d db` with a port also derived from the hash, or a SQLite path inside the worktree); write .env.local with PORT, DATABASE_URL, REDIS_URL, and copy any other .env keys from the main checkout without printing their values; run the repo's install with the shared store (`pnpm install --frozen-lockfile`, `uv sync`, or equivalent); run migrations against the isolated DB; finally open `tmux new-window -n <task> -c <path> claude`. Make it idempotent on failure: if any step fails, print what was created and how to remove it. Run shellcheck.
Expect: An executable script under 150 lines that spawns a worktree in under two minutes, with shellcheck clean.
Audit before moving on: Spawn two test tasks, start the dev server in each, and curl both ports at the same time; both must answer. Confirm docker ps shows two separate DB containers or two SQLite files. Grep the script output for any secret value; none may appear. On any fail, fix and re-run both spawns.
Step 3 — Build status and cleanup
Goal: See every worktree's state at a glance and remove merged ones safely.
Write scripts/wt-status.sh that prints one row per worktree from `git worktree list --porcelain`: path, branch, dirty file count (`git -C <path> status --porcelain | wc -l`), commits ahead/behind origin/main, PR number and state from `gh pr list --head <branch> --json number,state`, PORT from .env.local, and DB container status from `docker compose -p <task> ps --format json`. Sort with dirty-and-no-PR first, because those need attention. Write scripts/wt-clean.sh that, for each worktree whose PR is MERGED: prints its dirty files; if any exist, skips it and says why; otherwise runs `git worktree remove <path>`, `git branch -d wt/<task>`, `docker compose -p <task> down -v` (only for projects it created, recognised by the wt/ prefix), and finally `git worktree prune`. Add `--dry-run` as the default; require `--yes` to act. Optionally bind wt-status.sh to a tmux status-right refresh every 30 seconds.
Expect: Two scripts; a status table for the two test worktrees; a dry-run cleanup listing what would be removed.
Audit before moving on: Mark one test PR merged (or simulate by merging locally into a throwaway main) and run the cleaner with --yes; verify the worktree, branch, and containers are gone and the other worktree is untouched. Create a dirty file in the remaining worktree and confirm the cleaner skips it.
Step 4 — Decompose the backlog into disjoint tasks
Goal: Pick three real tasks that cannot collide and prove it.
From the user's open issues (`gh issue list --limit 50 --json number,title,body`) or a provided list, choose candidates that are independent by the guide's rules: no output dependency between them, no shared global state, not deep debugging of an unfamiliar area. For each candidate, have Claude in read-only mode produce a planned change set: the files it expects to create or modify, derived from grepping the code involved. Build an overlap matrix of planned file sets; reject any pair that shares a file, and treat package.json, lockfiles, CLAUDE.md, shared config, and migration directories as always-conflicting unless only one task touches them. Pick the three with zero overlap and the smallest expected review time. Write tasks.md with, per task: issue link, one-paragraph prompt to give the session, planned files, acceptance test command, and expected review minutes. Include the overlap matrix.
Expect: tasks.md with three tasks, three prompts, and a 3x3 matrix of shared-file counts all zero.
Audit before moving on: Re-derive one task's file set independently (grep the identifiers involved) and compare; if the sets differ by more than two files, redo the plan for that task. Any task whose acceptance test cannot run in an isolated worktree is replaced.
Step 5 — Run the parallel trial and log it
Goal: Execute the three tasks concurrently and capture the timing data that will judge the workflow.
Spawn the three tasks with scripts/wt-spawn.sh. In each tmux window, paste that task's prompt from tasks.md, adding: 'Work only in this worktree. Commit by explicit file paths. Do not edit CLAUDE.md, package.json, or lockfiles unless the task requires it, and say so if it does. When done, run the acceptance test, push, and open a PR with gh pr create --fill.' Cycle through windows; while one runs, review another. Log to worktree-log.csv for every task: spawn time, time you first started reviewing, number of review rounds, PR open time, merge time, any merge conflict and its file, minutes you were idle waiting on all sessions. After merging, run wt-clean.sh --yes. If you feel idle between reviews, spawn a fourth task from the backlog with the same overlap check; if review starts queuing, stop spawning and note the session count where that happened.
Expect: worktree-log.csv with at least three complete rows, three merged PRs, and a note of the session count at which review saturated.
Audit before moving on: After each merge, run git diff --name-only between each pair of task branches to confirm no shared file slipped in; any conflict gets a row explaining which check missed it. Run wt-status.sh at the end; no orphaned worktrees or containers may remain.
Step 6 — Validate against oracles and write the gap report
Goal: Compare to baseline with GitHub's own data and state what the trial proves and does not.
Re-run the baseline query for the trial window and compute merged PRs per working day and median cycle hours; put them beside baseline.md numbers in results.md. Check CI status on every trial PR (`gh pr checks <n>`) and record any failure caused by isolation leaks (wrong port, wrong DB, stale cache). Confirm with `git worktree list` and `docker ps -a --filter name=wt-` that cleanup left nothing behind. Give verdicts on the guide's claims with your numbers: productivity unlock (throughput ratio), 3-5x cap (where review saturated for you), zero merge conflicts (count), zero history duplication (`du -sh` of each worktree versus .git). Write gaps.md: unisolated resources, untested native-flag behaviour, conflicts and their causes, and an honest statement of sample size. Recommend the concurrency number to use going forward, with the evidence.
Expect: results.md with a before/after table and four claim verdicts; gaps.md; a recommended concurrency number.
Audit before moving on: If the trial window has fewer than five merged PRs, state that the throughput comparison is not statistically meaningful and recommend extending the trial rather than concluding. Every verdict must cite a number from worktree-log.csv or gh output.
4 · Gap analysis and audit
Run this after the build. It makes the agent enumerate its own claims, mark what is verified, rank the gaps and fix the top ones.
You are reviewing a parallel-worktree setup and its trial results that someone else built in <repo>. Do not trust results.md. (1) List every claim: each script's guarantees (isolation of port, DB, env, cache; safe cleanup; push-before-destroy), each verdict on the guide's claims, the recommended concurrency. (2) For each, mark verified, unverified, or false with evidence: run the scripts yourself on a scratch task, curl two dev servers concurrently, inspect .env.local files for collisions, grep source for hard-coded ports, check .git/hooks for shared writes, re-run the gh queries. (3) Try to break isolation: spawn two tasks whose names hash to the same port (search for a collision with a quick loop) and see what happens; run migrations in both; run the test suite in both at once; check whether a shared cache under ~/.cache causes flaky results. (4) Try to break cleanup safety: leave an uncommitted file and an unpushed commit in a worktree with a merged PR and run wt-clean.sh --yes. (5) Rank gaps by impact (lost work first, then wrong results, then friction), fix the top three now, re-run, and report what remains with the reproduction command for each.
Questions the agent must ask itself before it says done:
- Did I prove two dev servers ran simultaneously on different ports, or just assume it from .env.local?
- What happens when two task names hash to the same port, and does the script detect it?
- Do git hooks or husky write to a cache shared by all worktrees?
- Does
claude --worktreeon this version copy .env files, and did my script duplicate or conflict with that? - Could wt-clean delete unpushed commits on a branch whose PR merged from an older commit?
- Did any task touch package.json, a lockfile, CLAUDE.md, or migrations despite the plan?
- Is my baseline window comparable in task type and working days to the trial window?
- Did I log human review time and idle time, or only model run time?
5 · What proves it right
- GitHub data:
gh pr list --state merged --author @mefor baseline and trial windows gives merged PRs per day and median cycle time computed the same way. - Two dev servers from different worktrees both return HTTP 200 when curled at the same moment on their assigned ports.
- CI checks (
gh pr checks) pass on every trial PR with no failures traced to wrong port, DB, or cache. git worktree listanddocker ps -ashow no orphaned worktrees or containers after wt-clean.sh runs.
6 · Failure modes
- Port collisions. Tell: second dev server fails with EADDRINUSE or silently serves the other worktree. Fix: hash-derived ports checked with ss -ltn, and remove hard-coded ports from source.
- Shared dev database corrupted by migrations. Tell: a worktree's tests fail on schema it never changed. Fix: per-worktree docker compose project or SQLite file, migrations per worktree.
- Racing one task in several sessions. Tell: two PRs solving the same issue differently. Fix: one task per worktree, enforce with the tasks.md overlap matrix.
- Review becomes the bottleneck. Tell: PRs wait hours for you while sessions sit idle. Fix: drop to the concurrency where review kept pace, usually 3-5.
7 · Agent direction (unattended runs)
Work in a scratch clone for all experiments with the native flag and cleanup scripts; touch the user's real checkout only to install the final scripts under scripts/. Push the current branch before creating or removing any worktree, every time. Reach first for git worktree list --porcelain, gh pr list --json, and claude --help; cache baseline query results in baseline.md so they are not recomputed. Never print .env values; copy keys without echoing. Spawn subagents only for read-only planning of each task's change set in step 5, never for the parallel sessions themselves (the user runs those). Stop and ask before removing any dirty worktree, dropping a pre-existing database volume, or if the app depends on an unisolatable shared resource. The trial week requires the user; hand off after the dry run with exact logging instructions. Return files: baseline.md, scripts/wt-spawn.sh, scripts/wt-status.sh, scripts/wt-clean.sh, tasks.md, worktree-log.csv template, and later results.md and gaps.md.
Prompt system updated 2026-10-22 · all prompt systems · JSON