Lesson 28 of 32
Parallel Sessions and Worktrees
Why two Claude sessions in one directory tread on each other, how git worktrees fix it, and the ladder of options from a second terminal up to a coordinated team of agents.
You can run more than one Claude Code session at a time. On any machine with enough terminals, nothing stops you.
What stops you is that, by default, they are all standing in the same room. This lesson is about the room, why sharing it goes wrong, and the ladder of options for getting each session its own.
Why sessions collide
A project directory is one working copy of your code. Every process pointed at it reads and writes the same files.
So picture two sessions. Session A is halfway through a refactor and has read
src/api/client.ts into its context. Session B, working on something
unrelated, edits that same file. Session A now holds a version of the file
that no longer exists on disk, and its next edit is written against
assumptions that stopped being true a minute ago.
Nothing crashes. There is no error and no warning. You get a diff that looks plausible and does not work, and you spend the afternoon wondering which of the two sessions caused it. This is the worst kind of failure, because it is invisible until much later.
The same problem shows up in smaller ways too: two sessions running the same test suite over each other, two sessions switching branches underneath one another, two sessions committing halves of two different changes.
Git worktrees
Git already has the feature for this, and it predates any of this by years.
A worktree is a second working directory with its own files and its own checked-out branch, which shares the repository's history and remote with your main checkout. It is not a second clone: there is one repository underneath, one set of branches, one remote. You simply have two places on disk where different branches of it are checked out at once.
You can create one with git directly:
git worktree add ../project-feature-a -b feature-a
cd ../project-feature-a
claudeClaude Code also creates them for you. Pass --worktree, or its short form
-w, with a name:
claude --worktree feature-authThat creates a worktree under .claude/worktrees/ at your repository root, on
a new branch, and starts the session inside it. Run the same command with a
different name in another terminal and you have two sessions that cannot touch
each other's files. Omit the name and one is generated for you.
Claude Code enforces the isolation rather than trusting it. While a session is in a worktree, it blocks edits that target the main checkout, blocks commands whose working directory resolves back into it, and blocks git commands that redirect there through flags or environment variables. Claude sees each refusal as a tool error explaining where it is allowed to work.
The practical details
Three things surprise people the first time.
A worktree is a fresh checkout. Tracked files are there; everything
gitignored is not. No node_modules, no .env, no local database file. You
need to install dependencies in the new directory, and you need to arrange for
the environment files. For the latter, add a .worktreeinclude file to your
project root listing the gitignored paths to copy into each new worktree:
.env
.env.local
config/secrets.jsonIt uses gitignore syntax, and only copies files that match a pattern and are also gitignored, so tracked files are never duplicated.
The worktree directory shows up in git status. Add .claude/worktrees/ to
your .gitignore so the contents do not appear as untracked files in your main
checkout.
Cleanup is not automatic in every case. When you exit an interactive
session, Claude Code checks whether the worktree holds anything that removing
it would destroy — changed files, untracked files, new commits — and either
removes it quietly or asks you first. A non-interactive -p run has no exit
prompt, so its worktree is left behind. Remove those yourself with
git worktree remove.
The ladder
Worktrees give you isolation. What they do not give you is coordination — somebody still has to decide who works on what, and that somebody is you. There are several rungs above this, each trading a bit more of your judgement for a bit less of your attention.
Worktrees you drive
Two or three terminals, each with its own checkout. You decide what each session works on and you read each result. Most control, most of your attention. This is where to start, and where most people usefully stay.
Subagents in their own worktrees
Within one session, Claude delegates work to subagents, and those subagents can each get an isolated checkout so their parallel edits do not conflict. Ask Claude to use worktrees for its agents, or set it permanently in a custom subagent's definition.
Background sessions in agent view
Running claude agents opens one screen showing every session you have dispatched, its state, and which ones are waiting on you. You hand off independent tasks and check back rather than watching each one. Still a research preview.
Agent teams
One session becomes a lead that spawns teammates, each an independent session with its own context. They share a task list, claim work, and message each other. Experimental, disabled by default, and considerably more expensive.
Resist the urge to jump to the bottom rung. Coordination overhead is real, and the failure mode of an automated team is several agents confidently working on the same thing. Teams do not isolate teammates in worktrees, so if you use them, split the work such that each teammate owns a different set of files.
Sessions that can talk to each other
Isolation solves collisions and creates a smaller problem in their place: two sessions working on related things have no idea the other exists. You end up being the message bus, noticing in session A that something has changed and retyping it into session B.
Claude Code can carry those messages itself. Where the feature is available, a session can list the others you have running and send one a plain-text note — so the session that just renamed a function can warn the session building on it, and a session that settles a question can answer another that is blocked on it. Nothing needs turning on, but it does not reach everywhere: it runs on macOS and Linux rather than native Windows, is absent on some cloud providers, and two sessions can only find each other if they can see the same files, so one inside a container and one on the host are invisible to each other.
Two things follow, and both matter more than the mechanics. The first is that a message costs a turn in the session that receives it, and that turn carries its whole context — so sessions chattering at each other is a real expense rather than a free convenience. The second is a security property worth remembering from the lesson ahead: a message arriving from another session is treated as untrusted input, so one session cannot grant another a permission you withheld.
Writer and Reviewer
There is a second reason to run two sessions, and it has nothing to do with speed.
Ask the session that just wrote a piece of code to review it, and you are asking it to grade its own homework with the answer sheet still open. It has the whole argument that led to the current design sitting in its context. That reasoning is evidence to it, and it tends to defend the result rather than attack it.
A second session that sees only the diff and the criteria has none of that. It does not know what was considered and rejected, or how confident the first session felt. It reads what is actually there.
WhySession A has just finished a rate limiter in its own worktree and pushed the branch. This is a different session, in a different checkout, that has never seen that conversation.
You typed: Review the rate limiter in @src/middleware/rateLimiter.ts against PLAN.md. Check every requirement is implemented, the listed edge cases have tests, and nothing outside the task's scope changed. Report gaps, not style preferences.
Claude ran: Read PLAN.md
Claude ran: Read src/middleware/rateLimiter.ts
Claude ran: Read src/middleware/rateLimiter.test.ts
Claude replied: Three gaps. PLAN.md requires the limit to be per API key; the implementation keys on IP address. The burst case in PLAN.md line 24 has no test. The plan says existing middleware order must not change, and rateLimiter was inserted before the auth middleware, so unauthenticated requests are counted against the key that has not been read yet.
WhyThe third finding is the interesting one. Session A introduced the ordering itself, so its context contains the reasoning that made it seem right. A reader who arrives cold sees only that the middleware needs a key it cannot have yet.
WhyNote the last sentence of the prompt. A reviewer asked to find problems will find some, because that is the job it was given. Telling it what counts as a finding is what stops the review turning into a list of preferences.
You then take those findings back to session A and have it address them. The same shape works with tests: one session writes the tests from the specification, another writes the code that has to pass them.
A lighter version of this exists inside a single session — a review subagent runs in a fresh context and reports back — and for a quick check that is often enough. Reach for a separate session when the review needs to be genuinely independent, or when you want to keep going in the first one while the review happens.
What to take away
Parallel sessions collide because a project directory is a single working copy,
and the collision does not announce itself — it shows up later as a diff that
looks fine and is not. A git worktree is a second working directory with its
own files and branch, sharing the repository underneath, and claude -w will
create and enter one for you. Expect a fresh checkout, so dependencies and
gitignored files need arranging, and add .claude/worktrees/ to your gitignore.
From there the options ladder upwards, from worktrees you drive yourself
through isolated subagents and background sessions to experimental agent teams,
each rung trading control for less attention. Sessions isolated from each other
can still pass messages where the platform supports it, which saves you being
the message bus between them, though each message costs the receiving session a
full turn. The most valuable use of a second session may not be speed at all: a
reviewer that never saw the code being written judges it on what is there rather
than on how it got there.
Next: handing the same work to a machine that has no keyboard at all, by running Claude inside your CI pipeline.
Check yourself
5 questions · pass 4/5 to unlock Claude Code in CI
1.Two Claude Code sessions are running in the same project directory. What is the underlying problem?
2.What is a git worktree?
3.Why is a review by a second, fresh session usually better than asking the session that wrote the code to check its own work?
4.You start a session with
claude --worktree feature-auth. What should you expect about the new directory?5.Agent teams differ from subagents mainly in that
5 left to answer