Three Ways to Run Claude Code in Parallel
Worktrees, agent teams, and in-conversation subagents — when to reach for each, how they actually work under the hood, and the tradeoffs I've hit using them day-to-day.
- Author
- Henry Chen
- Published
- 16 April 2026
- Reading
- 7 min read
- Views
- 4 views
- Updated
- Apr 2026

The more I lean on Claude Code, the more the bottleneck shifts from "can it write this" to "how many of these can it write at once." A backend module, a frontend feature, and a docs pass are usually independent enough to run in parallel — the trick is keeping the file systems, branches, and contexts from stepping on each other.
Claude Code gives you three ways to do this, and they aren't interchangeable. This post is a tour of all three, what they actually do under the hood, and the rules I use to pick between them.
1. claude --worktree — multiple terminals, one repo
The simplest and most predictable. Each terminal launches its own Claude session against its own git worktree.
# Terminal 1
claude --worktree feat-dashboard
# Terminal 2
claude -w feat-customers # -w is the short form
# Terminal 3
claude -w feat-assetsWhat actually happens: Claude creates a worktree at .claude/worktrees/<name>/ and checks out a new branch called worktree-<name>. The base is whatever your local origin/HEAD points at — not your current branch. If your repo's default branch changed on GitHub and you haven't re-synced, you'll branch from a stale ref. Fix it with:
git remote set-head origin -aAdd .claude/worktrees/ to your .gitignore so the worktree directories don't show up as untracked files in your main checkout.
Copying ignored files. A fresh worktree has no .env or local config, because those are gitignored. Create a .worktreeinclude at the repo root with gitignore-style patterns, and Claude copies matching files into every new worktree:
.env
.env.local
config/secrets.jsonOnly files that are both matched and gitignored get copied, so tracked files are never duplicated.
Cleanup. When you exit a session with no changes, the worktree and its branch are removed automatically. If there are commits or dirty files, Claude prompts you to keep or discard. For anything created outside a session, use git worktree list and git worktree remove directly.
I reach for this 80% of the time. Each session stays fully isolated, I can jump between terminals the way I'd tab between editors, and there's zero coordination overhead.
2. Agent Teams — multiple Claudes that talk to each other
Agent teams are the newer, more ambitious mode. One session is the lead; it spawns teammates that each get their own context window and can message each other directly, not just report back to the lead. Requires Claude Code v2.1.32 or later, and it's experimental — opt in by adding this to settings.json or your shell:
{
"env": {
"CLAUDE_CODE_EXPERIMENTAL_AGENT_TEAMS": "1"
}
}Then just describe the team in natural language:
Create an agent team to build the dealer portal. Spawn three teammates:
- one for the dashboard backend (apps/dashboard/)
- one for the customers module (apps/customers/)
- one for the assets module (apps/assets/)
Have them share findings on shared types before touching overlapping files.Display modes. There are two:
- In-process — all teammates run inside the lead's terminal.
Shift+Downcycles through them;Enterdrops you into a teammate's session;Escinterrupts their current turn;Ctrl+Ttoggles the shared task list. Works in any terminal. - Split panes — each teammate in its own pane. Requires either tmux or iTerm2 with the
it2CLI (and the Python API enabled in iTerm2 settings).tmux -CCinside iTerm2 is the recommended combo on macOS.
Default is "auto" — split panes if you're already inside a tmux session, otherwise in-process. Override globally via teammateMode in ~/.claude.json, or per-session with claude --teammate-mode in-process.
What's actually shared. A task list with dependency tracking (blocked tasks auto-unblock when their parents finish), and a mailbox so teammates can message one peer or broadcast to all. Teammates load the same project context as a regular session — CLAUDE.md, MCP servers, skills — but not the lead's conversation history. Put task-specific context in the spawn prompt.
Known sharp edges. Session resumption doesn't restore in-process teammates. Task status sometimes lags (teammates forget to mark things complete, blocking dependents). Only one team per lead, no nested teams, and the lead is fixed for the team's lifetime. Split-pane mode doesn't work in VS Code's integrated terminal, Windows Terminal, or Ghostty.
Where it earns its keep is research and adversarial review — parallel investigators trying to disprove each other's hypotheses converge on root causes faster than a single agent that anchors on the first plausible explanation. For implementation work where teammates need to chat, it's genuinely powerful; for tasks that are really just "do these three things," worktrees are cheaper.
3. In-conversation subagents
The lightest option. Inside a single conversation, tell Claude to spawn parallel subagents:
Build these three modules in parallel:
Module A — Dashboard: implement the KPI stats API…
Module B — Customer profile: GET/PUT /api/customers/profile/…
Module C — Assets: tag filtering and detail view…Claude spawns each subagent with its own context window, and they report results back to the main conversation. They don't talk to each other. If you want them in isolated worktrees too, add isolation: worktree to the subagent's frontmatter — each gets its own worktree, auto-cleaned when the subagent finishes with no changes.
Subagents are cheap because only summaries come back to the main context. They're also the most fragile — if a subagent stalls or goes off the rails, you have less leverage to redirect than you do with a teammate you can Shift+Down into.
The comparison that actually matters
--worktree | Agent Teams | In-conversation subagents | |
|---|---|---|---|
| Communication | None — fully independent | Teammates message each other + lead | Only report to main session |
| Coordination | Manual (you switch terminals) | Shared task list, auto-dependency resolution | Lead session delegates manually |
| Token cost | Medium (independent sessions) | High (each teammate is a full instance) | Low (summaries only) |
| Setup | None | CLAUDE_CODE_EXPERIMENTAL_AGENT_TEAMS=1, v2.1.32+ | None |
| Best for | Independent modules, long-running work | Adversarial review, cross-layer features, hypothesis debugging | Quick parallel lookups or focused builds |
| Biggest risk | You forget which terminal is which | Teammates go idle silently, task status lags | Subagent stalls with no recovery |
Rules I actually follow
Parallelize when:
- Modules live in separate directories (
apps/dashboard/,apps/customers/,apps/assets/). - Work spans frontend + backend and each half has its own repo or package.
- You're doing a parallel code review with distinct lenses — security, performance, test coverage.
Don't parallelize when:
- More than one agent will touch the same shared file (
shared/types/, top-levelurls.py, a monolithic schema). - There's a real dependency chain — B needs A's API shape to exist first.
- A database migration is involved. Let one session own it; worktrees share the same database, and two agents racing migrations is pain you don't need.
Merge strategy when the parallel branches come back:
- Merge the foundational branch first (the one others implicitly depend on).
- Merge the rest one at a time, running tests between each.
- Resolve conflicts by hand, or drop back into Claude Code with both branches in context and let it do a three-way read.
A concrete example
The dealer portal rewrite I did recently, end-to-end:
# Terminal 1 — dashboard backend
claude -w feat-dashboard
> Under apps/dashboard/, implement KPI aggregates: recent orders, total
> revenue, pending count. Follow the repository pattern in apps/orders/.
# Terminal 2 — customer backend
claude -w feat-customers
> Under apps/customers/, implement sub-user CRUD: list, create, update, delete.
> Auth via existing JWT middleware.
# Terminal 3 — assets backend
claude -w feat-assets
> Under apps/assets/, add tag filtering and the detail-with-items endpoint.
> Match the serializer style in apps/orders/serializers.py.Three terminals, three worktrees, three branches. When each one finished I reviewed its diff, ran the tests, and merged in order. Total wall-clock for what would have been a week of sequential work: an afternoon.
Which one should you actually use?
If you're starting out: just use --worktree. It's the one you won't outgrow.
Reach for agent teams when your problem genuinely benefits from teammates talking to each other — debugging a gnarly bug with competing hypotheses, or a PR review where security, performance, and tests each deserve their own pass. The token bill is real, and so is the coordination overhead; don't use it for tasks where a single focused session would finish faster.
Reach for in-conversation subagents when you want results summarised back into a session you're already driving, and you're comfortable not being able to steer them mid-flight.
All three are the same underlying trick — more contexts, working in isolation, against the same repo. The differences are all about how much they need to talk, and how much you're willing to pay for that conversation.
Keep reading
Journal — AIHow I Set Up Claude Code as My Daily Development Companion
A walkthrough of Claude Code from the ground up — what it is, how configuration scopes work, and the rules, plugins, hooks, auto memory, and CLI glue that make it click for day-to-day engineering work.
18 min read · 14 AprAIMy Claude Code IDE: Zed for Review, Ghostty and tmux for the Agent
Why I split the editor and the agent across two apps, how tmux keeps Claude Code sessions alive when the window closes, and the small configuration quirks that make it all feel native.
11 min read · 15 AprAIBuilding a RAG Chatbot: From pgvector to an Agentic Loop
How I built the /ask assistant on this site — chunking and embedding the corpus with Voyage, semantic search over pgvector, a grounded citation prompt, and the agentic tool-calling loop that retrieves iteratively. Plus how it all ships to production.
26 min read · 25 Jun