Appearance
Text size
Typeface
Line spacing
1
Chapter 1 · 4 min

One checkout per agent

Two agents editing the same folder overwrite each other. A worktree gives each session its own files and its own branch, so parallel work stays separate until you merge it.


Why the same folder fails

Open two Claude Code sessions in one repository and ask them for two different features. Both read the same files, both edit the same files, and both run the test suite against a tree that the other one is changing under it. A failing test might be yours, or it might be half of the other agent's edit.

The problem is not the model. It is that one working directory can only hold one state at a time. The fix is to stop sharing the directory.

What a worktree gives you

A git worktree is a second checkout of the same repository, in its own folder, on its own branch. The history and objects are shared, so it is cheap. The files you edit are not shared, so the sessions cannot step on each other.

Claude Code builds this in. claude --worktree name (or -w) creates .claude/worktrees/<name>/ on a branch called worktree-<name> and starts the session there. Give no name and you get a random one such as bright-running-fox.

Session A starts in worktree "search"
Session B starts in worktree "billing"
Each edits only its own folder
Each commits to its own branch
You review and merge them one at a time

Add .claude/worktrees/ to .gitignore, otherwise the checkouts show up as untracked files in the main one.

Check yourself

Why are two sessions in one folder a problem even if they touch different features?

Starting from the right place

Where the new branch starts from is a setting: worktree.baseRef. The default, "fresh", branches from the remote default branch. Set it to "head" and the worktree starts from your local HEAD, which carries unpushed commits. Pick "head" when the new work depends on something you have not pushed yet.

To work on a pull request, claude --worktree "#1234" branches from that PR's head.

A fresh worktree contains only tracked files, so your .env is missing and nothing runs. List such files in .worktreeinclude, using gitignore syntax, and they are copied into every new worktree.

What happens when you leave

Cleanup depends on what you did.

  • A clean worktree with no name is removed automatically when the session ends.
  • A named one asks you.
  • One with changes asks whether to keep or remove it.

Reopening an existing name does one of two things. If the worktree is clean and has no commits, it is reset to the default branch. Otherwise it resumes at its old tip. So a name is a way back to unfinished work, not just a label.

Claude can also move itself: the EnterWorktree and ExitWorktree tools let it switch mid-session. A periodic sweep removes subagent and background worktrees older than cleanupPeriodDays, unless they hold work.

The limits of the isolation

Claude Code blocks edits, working directories and git redirects (git -C, GIT_DIR) that point at the main checkout. That covers the accidents, not every path: a plain cp into the main checkout is not blocked. Isolation protects you from mistakes. It does not replace reviewing what an agent did.

Two details are easy to miss.

  • A "don't ask again" approval made inside a worktree is saved to the main checkout's .claude/settings.local.json, so it applies everywhere, not only in that worktree.
  • --fork-session starts in the launch directory, not in the worktree the original session used.
Check yourself

You have unpushed commits that the new task builds on. Which setting makes the worktree include them?

Read further