Claude Code --worktree: built-in worktrees, explained

Run claude --worktree <name> (or -w) and Claude Code makes a git worktree at .claude/worktrees/<name> on a new branch, worktree-<name>, cut from your remote default branch, and starts the session there. On exit it deletes a clean worktree by itself only if you never named the session, and asks otherwise.

Contents

claude --worktree <name>, or claude -w <name>, makes a git worktree at .claude/worktrees/<name> in your repository, on a new branch called worktree-<name>, and starts Claude Code inside it. Leave the name out and Claude Code picks one, such as bright-running-fox. When you exit, it deletes a clean worktree by itself only if you never named the session; in every other case it asks first.

Every behaviour below comes from Anthropic's worktrees page, settings reference and CLI reference, read on 24 October 2026. Where a version number appears, it is the Claude Code release that behaviour needs. The method for running several agents side by side, with plain git commands and the limits to watch, is in how to run Claude Code agents in parallel.

What claude --worktree does, step by step#

bash
claude --worktree feature-auth     # .claude/worktrees/feature-auth, branch worktree-feature-auth
claude -w fix-login                # same thing, short flag, in a second terminal
claude -w feature-auth --tmux      # also opens a tmux session for it

Before the first run, open the repository once with plain claude and accept the trust dialog. An interactive --worktree run needs workspace trust and exits with an error telling you so if it's missing; claude -p --worktree skips the check. Add .claude/worktrees/ to your .gitignore too, as Anthropic suggests, or every worktree shows up as untracked files in your main checkout.

A new worktree is a fresh checkout: no installed dependencies, no gitignored files. Install in the worktree, or ask Claude to, and see .worktreeinclude below for .env.

You can also ask Claude mid-session to "work in a worktree". It then uses its EnterWorktree tool. Moving into a path outside .claude/worktrees/ asks for your approval every time, and only bypassPermissions mode skips that prompt.

Claude Code worktree location#

Unless a hook takes over, --worktree always uses .claude/worktrees/<name> at the repository root. The worktree.location setting exists, but the settings reference says it only applies to Desktop SSH sessions on a remote machine.

To put worktrees somewhere else you have two routes. A WorktreeCreate hook replaces Claude Code's git logic entirely, including the location. Or make the worktree yourself with git worktree add ../myapp-auth -b auth, cd into it and run claude. Unless you set worktree.sparsePaths (below), every worktree is a full checkout of your files, so the location decides which disk fills up; git worktree disk space shows how to measure it and prune the worktrees you're done with.

Which branch it starts from: worktree.baseRef#

By default a new worktree branches from your repository's default branch on the remote, usually origin/main, not from whatever you have checked out. So a worktree made while you are on a feature branch doesn't contain that branch's commits.

worktree.baseRef Starts from Use it when
"fresh" (default) origin/<default-branch> You want a clean tree that matches the remote
"head" Your local HEAD, unpushed commits included The session or a subagent must build on work in progress
json
{
  "worktree": {
    "baseRef": "head"
  }
}

Inside a worktree, "head" means that worktree's HEAD. You can't give it a branch name: for a specific existing branch, Anthropic's answer is git worktree add ../project-bugfix fix-issue-456 and claude in that folder.

With "fresh", Claude Code fetches the default branch when the repository hasn't been fetched in the last 24 hours. The fetch is capped at five seconds and never waits for a password or passphrase. If it fails, the cached ref is used; with no remote at all, the worktree falls back to your local HEAD.

Start a worktree from a pull request#

Pass the number with a #, in quotes so your shell doesn't read it as a comment:

bash
claude --worktree "#1234"
claude --worktree https://gitlab.com/group/repo/-/merge_requests/123

Claude Code fetches the change's head commit from origin and makes the worktree at .claude/worktrees/pr-<number>. It reads only the number from a URL. On github.com it fetches pull/<number>/head, on gitlab.com merge-requests/<number>/head, and on any other host it tries both. GitLab merge requests need v2.1.233 or later.

If git or ssh would ask for a password, a passphrase or a new host key, the fetch fails with Error creating worktree: Failed to fetch PR/MR #<number>. Load your key into ssh-agent and run git fetch once by hand, then retry.

Copy .env into every worktree with .worktreeinclude#

Put a .worktreeinclude file at the project root. It uses .gitignore syntax, and a file is copied only when it matches a pattern and is also gitignored, so tracked files are never duplicated:

text
.env
.env.local
config/secrets.json

It works for --worktree, subagent worktrees and parallel sessions in the desktop app. It is not read when a WorktreeCreate hook does the creating; copy the files in the hook script then. One catch from the docs: a **/ pattern reaches into a wholly ignored folder only in certain cases, so write vendor/**/config.json rather than **/config.json.

Two settings help with the heavy folders. worktree.symlinkDirectories (for example ["node_modules", ".cache"]) links them in from the main repository so they aren't duplicated on disk, and worktree.sparsePaths checks out only the directories you list, which the docs say is faster in large monorepos.

Reusing a worktree name#

Run claude --worktree feature-auth again while .claude/worktrees/feature-auth exists and Claude Code opens that worktree instead of making a new one. With the default "fresh" base it resets the worktree to the default branch if three things hold: no uncommitted or untracked files, still on the branch Claude Code made, and either no commits of its own or a pull request that was merged and its remote branch deleted. Otherwise, and always with "head" or a pull request name, it reopens at the old tip.

What happens on exit#

When you leave an interactive worktree session, Claude Code checks for anything removal would destroy: changed or untracked files, uncommitted work in submodules, new commits.

State on exit What Claude Code does
Clean, session never named (no -n or /rename) Removes the worktree and its branch, no question
Clean, named session Asks first, so you can keep it
Has work in it Asks: keep or remove. Keep prints claude --worktree <name> --resume for later
On another branch with new commits Asks; either way that other branch and its commits stay
State can't be checked Asks, and names what it couldn't check

Runs with -p have no exit prompt, so nothing is cleaned up and the lock Claude Code took stays until a later session's sweep releases it. Remove those with git worktree remove, after git worktree unlock if git refuses.

Resuming a session that ended inside a worktree puts it back in that worktree. If the folder is gone, the session carries on in the directory you launched from and Claude Code says so.

Worktrees for subagents: isolation: worktree#

A custom subagent in .claude/agents/ with isolation: worktree in its frontmatter always runs in its own temporary worktree. You can also just ask Claude to "use worktrees for your agents". A subagent that changes nothing has its worktree removed when it finishes. One with changes stays until a periodic sweep, run against your cleanupPeriodDays setting, can remove it without losing work. Subagent worktrees follow the same worktree.baseRef. A --worktree session you send to the background becomes a background-session worktree, which that sweep may also remove; Claude Code agent view covers background sessions.

What a worktree shares with your main checkout#

Its files and branch are its own. Four things are shared, whether the worktree came from --worktree or git worktree add:

  • the repository's .git directory, so git commit works inside a worktree even with the sandbox on;
  • plugins installed at project scope (v2.1.200 and later);
  • "Yes, and don't ask again" approvals for Bash commands, saved to the main checkout's .claude/settings.local.json (from v2.1.211; on Windows and a few other setups they stay with the worktree);
  • untracked skills, agents and commands: if the worktree has no .claude/skills of its own, it loads the main checkout's (for skills, v2.1.277 and later).

Git LFS pointer files and other errors#

If you set up Git LFS with git lfs install --local, a worktree Claude Code makes holds pointer files instead of the real ones, because it skips filter drivers defined in the repository's own .git/config. Run git lfs pull inside the worktree. A plain git lfs install writes to your global config and isn't affected.

Error starts with What to do
Could not read the repository git config to neutralize filter drivers Fix the permissions on .git/config and retry
The repository git config has a conditional include (includeIf) Move those settings into .git/config itself and remove the includeIf
Git was not run: the repository's own git config sets <key> Move that LFS key to your global config, or delete it if you don't recognise it
This repository is a partial clone Take the step the message names, then rerun claude --worktree
Refusing to use <path> as an isolation worktree Read the ending. launch from the parent checkout means start Claude from the main checkout; the other endings name their own fix

Claude Code also refuses to create a worktree when .claude, .claude/worktrees or the worktree folder is a symlink. Remove the symlink and retry.

Not on git: WorktreeCreate hooks#

Worktree isolation needs git. For SVN, Perforce or Mercurial, a WorktreeCreate hook in settings.json makes the working copy and prints its path, and a WorktreeRemove hook cleans up. The docs' example checks out an SVN trunk into a folder named after the worktree. Have the hook create its folders outside any git repository, or Claude Code refuses them.

How Shuriken does it#

In Shuriken, which we make, you don't type the flag. Every chat except the project's Main chat gets its own branch in its own git worktree, whichever agent it runs: Claude Code, Codex, Gemini CLI or any of the others. We wrote down why in every chat gets its own git worktree.

The chat and its branch are named from your first message. The worktrees live outside your project folder, so there is nothing to add to .gitignore. Shuriken reads the same .worktreeinclude file, editable in the project's settings as "Copy into new branch folders", and never copies over a file that is already there. It reads each line as a plain path, though, so a line with *, ? or ! is skipped, and a project with no .worktreeinclude still gets its gitignored .env files from the project root. When the new worktree's lockfile matches your checkout's, it clones node_modules in (APFS on macOS, reflink on Linux); when it can't and you wrote no setup commands in shuriken.json, it installs from the lockfile.

When the work is done, Finish commits what's left, rebases onto your default branch, runs your checks, squash-merges and removes the branch and the worktree, or opens a pull request with auto-merge for a GitHub project. It never closes a chat over work that hasn't been merged. When two branches touched the same lines, resolving merge conflicts with Claude Code has the merge order that keeps them small and how to hand one to Claude Code. For several agents at once in plain terminals, Claude Code sessions in tmux is the manual setup; to have the worktrees made, merged and cleaned up for you, download Shuriken.

Sources

  1. Claude Code docs: Run parallel sessions with worktrees (accessed 24 October 2026)
  2. Claude Code docs: Settings reference (worktree) (accessed 24 October 2026)
  3. Claude Code docs: CLI reference (accessed 24 October 2026)

Frequently asked questions

Where does claude --worktree put the worktree?

In .claude/worktrees/<name> at the root of your repository, on a new branch called worktree-<name>. There is no setting to move it for local sessions; a WorktreeCreate hook replaces the creation step, or you can make the worktree yourself with git worktree add.

Why doesn't my worktree have my .env file?

A worktree is a fresh checkout, so gitignored files aren't in it. List them in a .worktreeinclude file at the project root, in .gitignore syntax, and Claude Code copies the ones that match and are ignored into every new worktree.

Can I branch a Claude Code worktree from my current branch?

Yes. Set worktree.baseRef to "head" in your settings and new worktrees start from your local HEAD, unpushed commits included. You can't set it to a branch name; for an existing branch, use git worktree add.

How do I get back to a worktree I kept?

Run the claude --worktree <name> --resume command that Claude Code prints when you exit. Passing --worktree a name whose folder already exists opens that worktree instead of making a new one.

Does claude -p --worktree clean up after itself?

No. Non-interactive runs have no exit prompt, so their worktrees stay. Remove one with git worktree remove, and run git worktree unlock on it first if git says it is locked.

Free tools