# 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`.

```flow
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.

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

- Claude Code refuses to start a second session
- They share one set of files, so edits and test runs interfere
- Git only allows one branch per repository
- The context windows get merged

**Answer:** They share one set of files, so edits and test runs interfere. One working directory holds one state. Two agents change it at the same time, and each one's test run sees the other's half-finished work.


## 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.

> **Git LFS can arrive as pointer files**
Claude Code skips repository-defined filter drivers when it creates a worktree. If Git LFS was installed with `--local`, you get pointer files instead of real content. Run `git lfs pull` inside the 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.

> **Not only git**
Outside git, the `WorktreeCreate` and `WorktreeRemove` hooks do the job: the hook prints the directory path. The same hooks let `/batch` run in a repository that is not git.


> **Run two at once**
In a repository, open two terminals. Start `claude -w one` in the first and `claude -w two` in the second, and give each a different small task. Afterwards look at `git branch` and compare the two branches before you merge either.


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

- worktree.baseRef set to "head"
- worktree.baseRef set to "fresh"
- Adding the commits to .worktreeinclude
- Using --fork-session

**Answer:** worktree.baseRef set to "head". "fresh" branches from the remote default branch. "head" branches from your local HEAD, so unpushed work comes along.
