Claude Code Worktrees: Powerful Parallel Guide

Worktrees let Claude Code run parallel branches, isolate subagents, and scale development without context collision. Instead of stashing half-finished changes to switch tasks, you spin up a dedicated checkout for each effort. This guide covers the native --worktree flag, the EnterWorktree tool, subagent isolation, the /batch skill, hooks for non-git VCS, and the cleanup lifecycle every team should understand.

worktrees

Worktrees: What You’ll Learn

Worktrees are Claude Code’s first-class answer to parallel development. By the end of this tutorial you will know how to launch a session inside an isolated checkout, configure what gets copied into it, delegate work to subagents that each get their own tree, and clean up safely when branches merge or get discarded.

You will also learn how the /batch skill decomposes large changes into dozens of worktree-isolated agents, how the session picker stays aware of which tree you are in, and how to extend worktree behavior to non-git version control systems like Subversion or Perforce. This is the native, built-in feature set — not a shell-script workaround.

What Are Worktrees in Claude Code?

A worktree is a full, independent checkout of your repository that lives in its own directory on disk. Git has supported worktrees natively for years via git worktree add, but Claude Code now wraps that primitive into something far more useful: the agent creates the tree, starts inside it, tracks which tree each session belongs to, and removes the tree when work is done.

The practical payoff is context isolation. When you ask Claude to refactor an authentication module while another branch already has uncommitted database changes, the two efforts never collide. Each worktree is a clean room with its own working directory, its own branch, and its own view of the filesystem. You can run tests in one tree while editing source in another, all from the same project root.

Claude’s implementation stores worktrees under .claude/worktrees/<name>/ by default. The naming is deliberate: it keeps transient checkouts out of your main working tree while still sitting inside the project so relative paths, editor workspaces, and tooling continue to behave predictably.

Why Worktrees Matter for Parallel Development

The traditional single-checkout workflow forces a painful choice every time priorities shift: commit half-finished work, stash it and hope the stash survives, or abandon the new task. None of these scale. A developer juggling a bugfix, a feature branch, and a refactor ends up with a graveyard of stashes and a nervous habit of running git status before every command.

Worktrees eliminate that friction. Each task gets its own directory and its own branch, so you context-switch by changing directories rather than by juggling commits. For an AI agent the benefit is even sharper: Claude can spawn a subagent to investigate a regression on one branch while the main session continues building a feature on another, with zero risk that the two agents trip over each other’s uncommitted edits.

This is the foundation of Claude Code subagents that run in true isolation. A subagent marked isolation: worktree receives a private checkout, does its work, and either merges the result or gets torn down — the parent session never sees intermediate files, half-written tests, or conflicting dependency updates.

The throughput gains compound on large refactors. Instead of a single agent grinding through a 40-file change sequentially, you can fan the work out across a dozen worktrees and let each agent own a slice. This is exactly the pattern the /batch skill automates, which we cover in detail below.

Starting a Session in a Worktree

The fastest way into a worktree is the --worktree flag (short form -w). Pass it a name and Claude creates the checkout, creates or checks out a branch, and starts the interactive session inside the new directory.

# Named worktree — creates .claude/worktrees/feature-auth/
claude --worktree feature-auth

# Short flag, equivalent
claude -w bugfix-123

# No name — Claude generates one like "bright-running-fox"
claude --worktree

Each named worktree gets its own branch following the worktree-<name> convention. When you omit the name, Claude generates a human-readable adjective-noun handle so the directory is easy to identify later in the session picker.

You can also branch directly from a pull request. Pass the PR number or URL and Claude resolves the PR’s head ref, checks it out into a fresh worktree, and drops you into a session ready to review, test, or extend the changes.

# Branch from a PR by number
claude --worktree "#1234"

# Branch from a full PR URL
claude --worktree "https://github.com/owner/repo/pull/1234"

By default the new worktree is created from origin/HEAD, giving you a clean baseline with no uncommitted local changes. This is the safe choice for most workflows because it guarantees the worktree starts from a known-good state rather than inheriting half-finished work from your main checkout.

Choosing a Base Branch

Sometimes you need the worktree to carry your unpushed local commits — for example, when a feature depends on changes you have not pushed yet. The worktree.baseRef setting controls this. Set it to "head" and the worktree branches from your current HEAD, carrying everything you have committed locally. The default "fresh" always starts from the remote tracking branch.

{
  "worktree": {
    "baseRef": "head"
  }
}

Use "head" sparingly. It is powerful for chained work where one local commit builds on another, but it can also propagate unfinished or experimental commits into trees where you did not expect them. When in doubt, leave the default.

The EnterWorktree Tool — Switching Mid-Session

Starting a session with --worktree is convenient, but Claude can also create or switch worktrees in the middle of an existing session. The EnterWorktree tool does this on demand, which means an interactive session can decide mid-conversation that a task deserves its own isolated checkout.

The typical flow looks like this: you are pair-programming with Claude on a broad cleanup. Halfway through, you realize one subtask — say, migrating a config format — is risky enough to warrant isolation. Instead of stopping and restarting in a new worktree, Claude calls EnterWorktree, creates a branch named for the subtask, and continues the work there. When the subtask is done, the changes merge back and the temporary tree is removed.

This mid-session capability is what makes worktrees feel native rather than bolted on. You do not have to plan the isolation in advance or restructure your workflow around it; Claude creates the boundary exactly when the work demands one. The official worktrees reference documents the full tool contract.

Copying Files with .worktreeinclude

Some files should travel into every worktree but are not tracked by git: local environment files, decrypted secrets, generated certificates, or machine-specific configuration. The .worktreeinclude file handles this. It uses gitignore syntax to declare which untracked files should be copied into a new worktree at creation time.

.env
.env.local
config/secrets.json
docker/certs/*.pem

There is an important gating rule: a file is copied only if it matches a pattern in .worktreeinclude and it is gitignored. Tracked files are never duplicated because git already manages them across branches. This dual condition prevents .worktreeinclude from accidentally copying source files or build outputs that should stay under version control.

Keep the include list minimal. Every file you copy adds to worktree creation time and increases the risk of leaking secrets into a tree that gets shared or inspected later. If a secret is truly per-developer and per-machine, consider whether the worktree needs it at all or whether the session can resolve it from a central vault at runtime.

Subagent Worktree Isolation

Subagents are Claude Code’s mechanism for delegating focused subtasks to specialized agents. By default a subagent runs in the same working directory as its parent, which is fine for quick lookups but dangerous for anything that modifies files. Worktree isolation changes that.

To give a subagent its own checkout, add isolation: worktree to its frontmatter. When Claude spawns that subagent, it creates a temporary worktree, points the subagent’s working directory at it, and runs the agent’s commands from that root. The parent session is completely shielded from the subagent’s file changes until an explicit merge happens.

---
name: feature-builder
isolation: worktree
---
Build the requested feature as a self-contained commit. Run the test suite and fix any failures before finishing.

Because a worktree-isolated subagent’s working directory is set to the isolated checkout, shell commands it runs — npm test, cargo build, custom scripts — execute against that isolated tree automatically, without needing an explicit cd or hardcoded path.

When a subagent finishes, its worktree is handled according to the cleanup rules described below. If the subagent produced changes, those changes are available for the parent to review and merge. If the subagent made no changes — for example, it was a read-only investigation — the worktree is removed automatically with no trace left behind.

This is the same primitive that powers large-scale Claude Code workflows. A workflow that needs to touch many independent areas of a codebase can dispatch a fleet of isolated subagents, each owning its slice, and then assemble the results. Without worktree isolation, those agents would corrupt each other’s working state within seconds.

The /batch Skill — Massively Parallel Changes

The /batch skill is the most aggressive application of worktree isolation. It takes a large, complex change request and decomposes it into between five and thirty independent subtasks, each assigned to a worktree-isolated subagent. The agents work in parallel, each on its own branch, and the results are merged back when all agents complete.

Consider a monorepo migration that renames a shared utility across two hundred call sites spread across a dozen packages. A single agent would work through this sequentially, risking context exhaustion and drift. The /batch skill instead partitions the call sites by package, assigns each package to an agent, and lets all agents rename in parallel. Total wall-clock time drops from an hour to minutes.

The skill handles the hard parts automatically: partitioning the work to minimize cross-agent dependencies, creating and naming worktrees, collecting results, resolving trivial merge conflicts, and presenting a consolidated summary. Conflicts that require human judgment are surfaced clearly rather than silently resolved.

For this to work well, the change must be genuinely decomposable. A refactor where every file depends on every other file is a poor fit because agents will constantly conflict. The sweet spot is tasks with natural boundaries: package-scoped migrations, repetitive edits across independent modules, or parallel investigations that each produce a self-contained finding.

Session Picker and Worktree Awareness

Because worktrees create separate working directories, the session picker — invoked with /resume — is worktree-aware by default. When you run /resume from inside a worktree, the picker shows only sessions that were started in that same tree. This keeps the list focused and prevents you from accidentally resuming a session from a different branch context.

Three keyboard shortcuts let you widen the scope when needed. Press Ctrl+W to widen the filter from the current worktree to all worktrees in the project. Press Ctrl+A to widen further to all projects on your machine. Press Ctrl+B to filter sessions by the current git branch, which is useful when a single branch has been explored across multiple trees.

This awareness matters because a session’s context — the files it read, the commands it ran, the decisions it made — is meaningful only in the context of the tree it operated in. Resuming a feature-building session in a checkout that holds an unrelated bugfix would produce nonsense. The picker’s defaults protect you from that class of mistake.

Hooks for Non-Git Version Control

Worktrees are a git concept, but not every project uses git. Subversion, Perforce, and Mercurial are still common in enterprise environments. Claude Code does not leave these teams behind: the WorktreeCreate and WorktreeRemove hooks let you define custom logic for creating and tearing down isolated checkouts under any version control system.

The WorktreeCreate hook receives the requested worktree name and is responsible for materializing the checkout. It must echo the absolute path to the created directory so Claude knows where to point the session. The WorktreeRemove hook receives that same path and handles cleanup — deleting the directory, releasing locks, or running any VCS-specific teardown.

{
  "hooks": {
    "WorktreeCreate": [{
      "hooks": [{
        "type": "command",
        "command": "bash -c 'NAME=$(jq -r .name); DIR="$HOME/.claude/worktrees/$NAME"; svn checkout https://svn.example.com/repo/trunk "$DIR" >&2 && echo "$DIR"'"
      }]
    }]
  }
}

The example above checks out a Subversion trunk into a per-worktree directory. The >&2 redirection sends svn’s progress output to stderr so it does not pollute the path that Claude reads from stdout. The final echo "$DIR" is the only thing Claude consumes, and it must be an absolute path.

One caveat: the .worktreeinclude file is not processed when you use the WorktreeCreate hook. Because the hook takes full responsibility for creating the checkout, Claude assumes it also handles any file-copying logic your workflow needs. If you rely on .worktreeinclude for secrets or config, replicate that copying inside your hook command.

Cleanup Behavior and Lifecycle

Worktrees that are never cleaned up accumulate like old branches: they consume disk, clutter the session picker, and eventually someone has to write a script to purge them. Claude Code automates most of this, but the rules differ by context and you should understand each.

Interactive Sessions

In an interactive session, when you finish and the worktree has changes, Claude prompts you: keep the worktree or remove it. Keeping it means the directory and branch persist for later review or continued work. Removing it deletes the directory (after confirming the changes are committed or discarded).

If the worktree has no changes — you explored but did not modify anything — it is removed automatically with no prompt. This is the common case for investigation sessions and keeps your workspace tidy without manual intervention.

Non-Interactive and Programmatic Sessions

When you run Claude non-interactively, via the -p flag or in a pipeline, there is no terminal to receive a prompt. In this mode worktrees are not auto-cleaned even if they have changes, because auto-removing uncommitted work would be destructive. You are responsible for cleaning up with git worktree remove or the WorktreeRemove hook.

Subagent and Background Worktrees

Subagent and background-process worktrees follow a different rule. If the worktree is clean when the agent finishes, it is removed immediately. If it has changes, it is kept for a configurable window controlled by cleanupPeriodDays, after which it is removed if still clean. This gives you time to inspect what a background agent produced before the evidence disappears.

While an agent is actively running, Claude calls git worktree lock on the worktree. This prevents git’s own pruning operations — git worktree prune, garbage collection, or another tool — from removing a worktree that is still in use. The lock is released when the agent completes or errors out.

Plugins in Worktrees

As of v2.1.200, project-scope plugins installed in the main checkout also load inside worktrees of the same repository. This means the MCP servers, slash commands, and skills you depend on are available without reinstalling or reconfiguring them in each tree.

This was a real friction point in earlier versions: a plugin that worked perfectly in the main checkout would silently vanish inside a worktree, leaving you to debug why a favorite command or server was missing. The fix means worktrees are now first-class citizens in the plugin ecosystem, not second-class environments that lose half their tooling.

User-scope plugins — those installed globally for your account rather than per-project — have always been available everywhere, including worktrees, because they are not tied to a repository. The change specifically benefits teams that install shared plugins via the project’s .claude/ directory and expect them to follow developers into every branch.

Worktrees in the Desktop App

The Claude Code desktop application treats worktrees as the default rather than the exception. Every new session you start in the app is created inside its own worktree automatically. This means the app’s mental model is “one session, one branch, one isolated checkout” from the start, with no flag needed.

This default is worth understanding even if you primarily use the CLI, because it shapes how the app’s features behave. Session history, branching, and review all assume worktree isolation. If you later switch between the app and the CLI on the same project, the session picker’s worktree awareness (described above) keeps the two worlds consistent.

For teams adopting Claude Code through the desktop app first, this means worktree habits are built in rather than learned. The concepts in this guide — base refs, cleanup rules, subagent isolation — still apply; they are just configured and triggered through the app’s UI rather than through command-line flags.

Choosing Between Worktrees and Alternatives

Worktrees are powerful but not always the right tool. For a five-minute fix on the current branch, creating a worktree adds ceremony without benefit. For a focused investigation that only reads files, the overhead is rarely justified. Worktrees earn their cost when isolation matters: parallel branches, risky experiments, subagent delegation, or any change where you want a clean rollback boundary.

The advanced features ecosystem offers complementary primitives. Git stashing is faster for momentary context switches. Feature branches without worktrees work when you only need branch isolation, not directory isolation. Docker dev containers provide stronger isolation when you need a full filesystem boundary. Worktrees sit between these: lighter than containers, heavier than stashing, and uniquely suited to agent workflows.

The decision framework is simple. If you need to run two efforts on the same repo at the same time without them seeing each other’s changes, use a worktree. If you just need to save your place for ten minutes, use a stash. If you need an entirely separate runtime environment, use a container. Claude’s worktree support makes the middle option trivially easy, which is why it has become the default for non-trivial agent tasks.

A Worked Example

Let us walk through a realistic scenario end to end. You are maintaining a web application with a Vue frontend and an Express backend in a single repository. A user reports a critical login bug at the same time your product manager asks for a new “remember me” feature. Both touch the authentication module, so doing them sequentially in one checkout would mean juggling two incomplete changes.

You start by creating a worktree for the bugfix. From your project root you run claude -w login-bugfix-982. Claude creates .claude/worktrees/login-bugfix-982/, branches from origin/HEAD into worktree-login-bugfix-982, and opens an interactive session. You describe the bug, Claude reads the auth module, identifies a missing await on an async token check, and applies the fix. You run the test suite — it passes — and commit.

Now, without leaving your terminal, you open a second worktree for the feature. You run claude -w remember-me-feature in a new terminal pane. A second worktree appears, a second session starts, and Claude begins building the “remember me” checkbox. Because the bugfix worktree is a separate directory on a separate branch, the feature work never sees the bugfix’s changes. There is no stash to manage and no branch-switching dance.

Halfway through the feature, Claude suggests a subtask: migrating the session-token module from callbacks to async/await to make the new code cleaner. This is a thirty-file change with real risk. Rather than do it inline, Claude calls EnterWorktree and creates worktree-token-async-migration. The migration happens in full isolation. Tests run in that tree against the async version, and the changes only land back in the feature branch once they are green.

Meanwhile, the bugfix is ready to merge. You push the worktree-login-bugfix-982 branch, open a pull request, get review, and merge. Back in the feature worktree you pull the latest main to pick up the bugfix — which, as it happens, touches code the feature also modifies. Because the two were developed in isolation, the merge is clean: the bugfix changed one line, the feature changed surrounding lines, and there is no conflict.

When the feature merges, Claude prompts you about the two worktrees. You confirm removal for both. The directories are deleted, the branches are cleaned up, and your .claude/worktrees/ folder is empty again. Total disk used at peak: two checkouts of tracked source files — a modest overhead even on a multi-gigabyte project, since only git-tracked files are duplicated into each worktree.

Contrast this with the single-checkout alternative. You would have stashed the feature to start the bugfix, popped the stash to resume the feature, prayed the stash did not conflict, and done the token migration with fingers crossed. Worktrees turned a stressful juggling act into two calm, independent efforts that merged cleanly. That is the value proposition in a single concrete story.

Worktrees: Common Mistakes to Avoid

Even experienced developers trip over the same issues with worktrees. The feature is forgiving by design, but a handful of mistakes cause wasted time, lost changes, or confusing failures. Here are the four most common ones and how to sidestep them.

  • Forgetting the cleanupPeriodDays window. Background and subagent worktrees with changes are kept for a configurable number of days, not forever. If you wait too long to inspect a background agent’s output, the worktree may already be gone. Check the setting and inspect promptly.
  • Forgetting to gitignore .claude/worktrees/. Skip adding it to your project’s .gitignore and worktree contents show up as untracked files in your main checkout, cluttering git status until you clean it up.
  • Expecting .worktreeinclude to copy tracked files. The include file only copies untracked, gitignored files. Tracked files are managed by git and never duplicated. If you expect a source file to be copied, you are misunderstanding the mechanism.
  • Assuming non-interactive worktrees auto-clean. Sessions started with -p do not prompt for cleanup and do not auto-remove worktrees that have changes. You must explicitly run git worktree remove or rely on the WorktreeRemove hook.
worktrees key concepts
worktrees best practices

Worktrees: Best Practices

  • Give worktrees descriptive names that include the ticket number or purpose, so the session picker and .claude/worktrees/ listing stay readable weeks later.
  • Add .claude/worktrees/ to your project’s .gitignore so worktree contents don’t show up as untracked files in your main checkout.
  • Keep .worktreeinclude minimal and audit it regularly — every copied file is potential secret leakage and adds to creation time.
  • Prefer baseRef: "fresh" unless you have a specific reason to carry local commits; the default avoids propagating unfinished work into new trees.
  • Inspect subagent and background worktrees promptly after they finish, before the cleanup window expires, to capture their output before automatic removal.

Worktrees: Frequently Asked Questions

Where are worktrees stored on disk?

By default Claude stores worktrees under .claude/worktrees/<name>/ inside your project root. Each worktree gets its own subdirectory named after the worktree, and the session picker reads from this location to build its filtered list.

Do worktrees work without git?

Yes, with custom hooks. Define WorktreeCreate and WorktreeRemove hooks in your settings to handle checkout and cleanup for Subversion, Perforce, Mercurial, or any VCS. Note that .worktreeinclude is not processed when you use the create hook.

What happens to a worktree if the session crashes?

The worktree remains on disk. Claude runs git worktree lock while an agent is active, which blocks pruning; a crash can leave that lock in place, so run git worktree unlock before removing the directory.

Can multiple agents share one worktree?

Technically yes, but it defeats the purpose. Worktrees exist to provide isolation, so multiple agents writing to the same tree reintroduces the exact conflicts worktrees prevent. Give each agent its own isolated worktree instead.

How do worktrees interact with the desktop app?

The desktop app creates a worktree for every new session automatically, making isolation the default rather than optional. This shapes session history and branching in the app, and stays consistent with CLI worktrees via the shared session picker.

Worktrees give Claude Code a native, first-class way to run parallel branches, isolate subagents, and scale development without context collision. The --worktree flag and EnterWorktree tool create checkouts on demand, subagent isolation and the /batch skill fan work out safely, and configurable cleanup keeps your workspace tidy. Master these primitives and parallel development stops being a juggling act.