Worktrees require a git repository; for other version control systems, configure hooks to replace the git logic. In the desktop app, every new session gets its own worktree automatically.
Start Claude in a worktree
Pass--worktree or -w with a name to create an isolated worktree and start Claude in it. By default, the worktree is created under .claude/worktrees/<name>/ at your repository root, on a new branch named worktree-<name>:
bright-running-fox.
Interactive runs require workspace trust: if you haven’t run Claude in the directory before, run claude once there to accept the trust dialog, or --worktree exits with an error prompting you to. Non-interactive runs with -p skip the trust check, so claude -p --worktree proceeds without it.
Set up the worktree environment
A worktree is a fresh checkout, so initialize your development environment there: ask Claude to install dependencies, or run your project’s setup yourself in the worktree directory under.claude/worktrees/. To carry gitignored files such as .env into every new worktree automatically, add a .worktreeinclude file.
Ask Claude to create a worktree
You can also ask Claude to “work in a worktree” during a session, and it creates one with theEnterWorktree tool. Once in a worktree, Claude can switch directly to another one under .claude/worktrees/ by calling EnterWorktree with the target path; the previous worktree stays on disk untouched.
When Claude enters a path outside the repository’s .claude/worktrees/ directory, Claude Code asks for your approval first, because the move takes the session’s working directory, write access, and project configuration such as CLAUDE.md and settings to that location. An EnterWorktree permission rule or choosing “don’t ask again” doesn’t suppress this prompt; only bypassPermissions mode skips it. Before v2.1.206, Claude could enter any existing worktree path without asking.
Clean up worktrees
When you exit an interactive worktree session, Claude checks the worktree for work that removal would delete: changed or untracked files, and new commits.- The worktree is clean: for an unnamed session, Claude removes the worktree and its branch automatically. A named session prompts you first so you can keep the worktree for later
- The worktree has work in it: Claude prompts you to keep or remove the worktree. Keeping preserves the directory and branch so you can return later. Removing deletes the worktree directory and its branch, along with all the work in them
-p have no exit prompt, so Claude doesn’t clean up their worktrees, and Claude Code leaves the lock it took on each one at creation in place until a later session’s stale-lock sweep releases it. To remove one, run git worktree remove; if git refuses because the worktree is locked, run git worktree unlock on it first.
On Windows, removing a worktree doesn’t delete files outside it. If a folder inside the worktree is really a link to somewhere else, such as an NTFS junction or a directory symlink, Claude Code deletes only the link and keeps the folder it points to. Before v2.1.205, removing a worktree with a link nested in a subdirectory could delete the folder it pointed to.
Resume a worktree session
When you resume a session that was inside a worktree, Claude Code returns the session to that worktree. This holds for interactive resumes, for--continue and --resume in non-interactive mode with -p, and for the Agent SDK. Back inside the worktree, Claude can still exit it with the ExitWorktree tool.
Before returning the session to its worktree, Claude Code verifies that the worktree is still a checkout separate from the main one, and declines to re-enter a worktree that fails the check. For a git worktree, the check reads its git metadata. A worktree without git metadata, such as one a WorktreeCreate hook created, can pass the check; the cases Claude Code still refuses are listed with their recoveries under Claude Code refuses to use a worktree. For the messages and how to recover from each, see The session resumes outside its worktree.
Where you launch from, and how you resume, change what Claude Code re-enters:
- Launch directory: resume from the main checkout or another directory of the repository. Claude Code re-enters a worktree it created with git under
.claude/worktrees/even when you launch from inside it. When you launch from inside any other worktree, Claude Code re-enters it only if it can vouch for it from there: a worktree that is its own repository, one without git metadata, or a launch from a subdirectory of a worktree you created withgit worktree adddeclines, so launch those from the main checkout. --fork-session: the forked session starts in the directory you launched Claude from, and Claude Code leaves the original session’s worktree untouched.- Deleted worktree: if the worktree directory no longer exists, Claude Code resumes the session in the directory you launched Claude from. It tells you the worktree is gone and clears the session’s worktree binding.
Before v2.1.212, a non-interactive resume stayed in the starting directory and
ExitWorktree reported that there was no active worktree session to exit./cd does, so /desktop and --resume find it there. Exiting moves it back the same way. A worktree created by a WorktreeCreate hook keeps its transcript at the launch directory. Requires Claude Code v2.1.198 or later.
How Claude Code enforces isolation
While a session is isolated in a worktree, Claude Code blocks the tool calls the checks below define. The same rules apply whether you started the session with--worktree, Claude entered a worktree with EnterWorktree, or you resumed a worktree session.
The same enforcement covers every subagent Claude spawns from the isolated session. It applies whether the session is interactive or runs in the background. Subagents that run in their own worktree carry the same checks. Their version history is under Write subagent files.
Claude Code applies four checks:
- File edits: Claude Code blocks an
Edit,Write, orNotebookEditthat targets a path in the main checkout. - Command working directory: Claude Code blocks a Bash, PowerShell, or Monitor command whose working directory resolves to the main checkout, or whose working directory it can’t verify stays outside it.
- Git redirects: Claude Code blocks a Bash or Monitor command that redirects git into the main checkout. The redirect can come through
git -C,--git-dir, aGIT_DIRorGIT_WORK_TREEvariable, or acdinto the main checkout before running git. - Command shape: Claude Code blocks a Bash or Monitor command it can’t verify stays inside the worktree. The block applies even when the command runs no git at all. Claude Code refuses shell constructs it can’t statically trace, such as brace expansion and heredocs with unquoted delimiters. It tells Claude to break the command into plain, separate commands. You can’t turn this check off.
Isolate subagents with worktrees
Subagents can run in their own worktrees so parallel edits don’t conflict. Ask Claude to “use worktrees for your agents”, or make the isolation permanent for a custom subagent by addingisolation: worktree to its frontmatter.
This subagent in .claude/agents/ always runs in its own worktree:
--worktree, so they branch from your repository’s default branch unless worktree.baseRef is set to "head".
Clean up subagent and background-session worktrees
A periodic sweep removes worktrees that Claude created for subagents and background sessions once they are older than yourcleanupPeriodDays setting, following the retention sweep rules. The sweep skips a worktree that still holds work: changed or untracked files, or unpushed commits. It never removes worktrees you create with --worktree.
While an agent is running, Claude runs git worktree lock on its worktree so that concurrent cleanup cannot remove it. The lock is released when the agent finishes.
The sweep also releases a lock Claude Code set for a session whose process has exited, so a killed background session doesn’t leave its worktree permanently locked. The sweep never releases a lock you set yourself with git worktree lock. Before v2.1.210, a lock left by a killed session stayed in place until you ran git worktree unlock.
To clean up a worktree that the sweep keeps, run git worktree remove, adding --force if the worktree has uncommitted changes or untracked files.
Customize worktree creation
Claude Code’s defaults for creating worktrees cover most sessions: it creates them under.claude/worktrees/, branches them from your repository’s default branch, and checks out only tracked files. The options in this section change those defaults.
Choose the base branch
New worktrees branch from the repository’s default branch, so most sessions don’t need this setting. Setworktree.baseRef in settings to branch from your current work instead. The setting accepts two values:
"fresh"(default): branch from the repository’s default branch on the remote, usuallymain, so the worktree starts from a clean tree matching the remote."head": branch from your current localHEAD, so the worktree carries your unpushed commits and feature-branch state. Use this when isolating subagents that need to operate on in-progress work. Inside a worktree,"head"resolves to that worktree’sHEAD, not the main checkout’s.
worktree.baseRef to a branch name. To start a worktree from a specific existing branch, create it with git directly.
For a "fresh" base, Claude Code keeps origin/HEAD current: when the repository hasn’t been fetched in the last 24 hours, it fetches the default branch, capped at five seconds, and uses the locally cached ref if the fetch fails. If no remote is configured, or origin/HEAD isn’t cached locally and can’t be fetched, the worktree falls back to your current local HEAD. Before v2.1.208, a fresh worktree used whatever origin/HEAD was already cached locally.
This example makes every new worktree branch from your current work:
Branch from a pull request
To branch from a specific pull request or merge request, pass--worktree the number prefixed with #, a GitHub pull request URL, or a GitLab merge request URL such as https://gitlab.com/group/repo/-/merge_requests/123. Claude Code fetches that change’s head commit from origin and creates the worktree at .claude/worktrees/pr-<number>. Quote the argument so your shell doesn’t treat # as the start of a comment:
origin remote, and picks the fetch path by origin’s host:
- github.com: fetches
pull/<number>/head - gitlab.com: fetches
merge-requests/<number>/head - GitHub Enterprise, self-managed GitLab, or any other host: tries
pull/<number>/headfirst, thenmerge-requests/<number>/head
#<number> and GitHub-style pull request URLs for --worktree, and always fetched pull/<number>/head.
Copy gitignored files into worktrees
A worktree is a fresh checkout, so untracked files like.env or .env.local from your main repository are not present. To copy them automatically when Claude creates a worktree, add a .worktreeinclude file to your project root.
The file uses .gitignore syntax. Only files that match a pattern and are also gitignored are copied, so tracked files are never duplicated.
This .worktreeinclude copies two env files and a secrets config into each new worktree:
.worktreeinclude
--worktree worktrees, subagent worktrees, and parallel sessions in the desktop app. With a WorktreeCreate hook, copy the files inside the hook script.
Reuse a worktree name
Passing--worktree a name whose directory already exists opens that existing worktree instead of creating a new one.
With the default "fresh" base, a reopened worktree resets to the repository’s default branch instead of continuing at its old tip when all of the following hold:
- It has no uncommitted changes or untracked files.
- It is still on the branch Claude Code created for it.
- It has no commits of its own, or its pull request or merge request was merged and its remote branch deleted.
- The worktree fails any of the conditions.
- Claude Code can’t verify the worktree’s state.
worktree.baseRefis"head".- The name is a pull request or merge request reference.