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.

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.
claude --worktree — multiple terminals, one repoThe 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.json
Only 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.
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:
Shift+Down cycles through them; Enter drops you into a teammate's session; Esc interrupts their current turn; Ctrl+T toggles the shared task list. Works in any terminal.it2 CLI (and the Python API enabled in iTerm2 settings). tmux -CC inside 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.
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.
--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 |
Parallelize when:
apps/dashboard/, apps/customers/, apps/assets/).Don't parallelize when:
shared/types/, top-level urls.py, a monolithic schema).Merge strategy when the parallel branches come back:
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.
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.