用 Worktree 运行并行会话¶
核心概念: 将多个 Claude Code 会话隔离在独立的 git worktree 中,避免文件变更冲突。涵盖
--worktree标志、子代理隔离、.worktreeinclude、清理机制以及非 git 版本控制的 hook 支持。
Worktree 是什么? Git worktree 是一个独立的工作目录,拥有自己的文件和分支,但与主 checkout 共享相同的仓库历史和远端。每个 Claude Code 会话运行在独立的 worktree 中,意味着一个会话的编辑不会影响另一个会话的文件。你可以在一个终端让 Claude 开发新功能,同时在另一个终端修复 bug。
注意: Worktree 需要 git 仓库;对于其他版本控制系统,请配置 hook 替代 git 逻辑。在桌面应用中,每个新会话会自动获得独立的 worktree。
Worktree 在并行方案中的定位: Worktree 是多种并行运行 Claude 的方式之一。它负责隔离文件编辑,而子代理和代理团队负责协调工作本身。可以参考并行运行代理来对比各种方案,或直接跳到用 Worktree 隔离子代理了解两者结合使用的方法。
阅读建议: 大多数会话只需前两个章节:在 Worktree 中启动 Claude,然后退出时清理。当你需要恢复会话、自定义创建行为或排查问题时再回来查看其余内容。
在 Worktree 中启动 Claude¶
使用 --worktree 或 -w 加名称创建隔离的 worktree 并启动 Claude。 默认情况下,worktree 创建在仓库根目录的 .claude/worktrees/<name>/ 下,所在分支命名为 worktree-<name>:
```bash theme={null}
claude --worktree feature-auth
在另一个终端用不同名称再次运行命令,即可启动第二个隔离会话。如果省略名称,Claude 会自动生成一个,例如 `bright-running-fox`。
**首次使用前需要信任确认:** 交互式运行需要[工作区信任](https://code.claude.com/docs/en/security)。如果你之前没有在该目录运行过 Claude,需要先运行一次 `claude` 来接受信任对话框,否则 `--worktree` 会报错退出并提示你先确认信任。使用 `-p` 的非交互式运行会跳过信任检查,因此 `claude -p --worktree` 可以直接执行。
> **提示:** 将 `.claude/worktrees/` 添加到 `.gitignore`,这样 worktree 的内容不会在主 checkout 中显示为未跟踪文件。
### 初始化 Worktree 环境
**Worktree 是全新的 checkout,需要初始化开发环境。** 可以让 Claude 安装依赖,或者自己在 `.claude/worktrees/` 下的 worktree 目录中运行项目的设置步骤。要自动将 `.env` 等 gitignore 文件带入每个新 worktree,请添加 [`.worktreeinclude` 文件](#将-gitignore-文件复制到-worktree)。
### 让 Claude 创建 Worktree
**你可以在会话中要求 Claude "work in a worktree",它会通过 [`EnterWorktree`](https://code.claude.com/docs/en/tools-reference) 工具创建一个 worktree。** 进入 worktree 后,Claude 可以通过调用 `EnterWorktree` 并指定目标路径,直接切换到 `.claude/worktrees/` 下的另一个 worktree。之前的 worktree 保留在磁盘上不受影响。
**进入仓库外的 worktree 需要审批:** 当 Claude 进入仓库 `.claude/worktrees/` 目录之外的路径时,Claude Code 会先征求你的批准,因为这会将会话的工作目录、写入权限以及项目配置(如 `CLAUDE.md` 和设置)转移到该位置。即使设置了 `EnterWorktree` [权限规则](https://code.claude.com/docs/en/permissions)或选择"不再询问"也不会跳过此提示;只有 `bypassPermissions` 模式才会跳过。v2.1.206 之前,Claude 可以不经询问直接进入任何已有的 worktree 路径。
## 清理 Worktree
**退出交互式 worktree 会话时,Claude 会检查是否有需要保留的工作内容:** 包括变更或未跟踪的文件,以及新的 commit。
| 场景 | 行为 |
|------|------|
| Worktree 干净(无变更) | 对于未命名会话,自动删除 worktree 及其分支。[命名](https://code.claude.com/docs/en/sessions#name-your-sessions)会话会先提示是否保留 |
| Worktree 有工作内容 | Claude 提示你选择保留或删除。保留会保留目录和分支以便后续返回;删除会移除 worktree 目录及其分支,连同其中所有工作 |
| 非交互式运行(`-p`) | 没有退出提示,因此 Claude 不会清理 worktree。需要手动用 `git worktree remove` 删除 |
**Windows 注意事项:** 在 Windows 上,删除 worktree 不会删除其外部的文件。如果 worktree 内的文件夹实际是指向其他位置的链接(如 NTFS junction 或目录符号链接),Claude Code 只删除链接本身,保留其指向的文件夹。v2.1.205 之前,删除包含子目录中嵌套链接的 worktree 可能会删除链接指向的文件夹。
## 恢复 Worktree 会话
**恢复之前在 worktree 中的会话时,Claude Code 会将会话返回到该 worktree。** 这适用于交互式恢复、使用 `--continue` 和 `--resume` 的[非交互模式](https://code.claude.com/docs/en/headless)(配合 `-p`),以及 Agent SDK。回到 worktree 后,Claude 仍可使用 [`ExitWorktree`](https://code.claude.com/docs/en/tools-reference) 工具退出。
**分叉和路径不存在的情况:** 使用 `--fork-session` 恢复会话时,从你启动 Claude 的目录开始,原始会话的 worktree 不受影响。如果 worktree 目录已不存在,会话会在你启动 Claude 的目录中恢复。
> **注意:** v2.1.212 之前,非交互式恢复停留在启动目录,`ExitWorktree` 会报告没有活跃的 worktree 会话可退出。
**会话记录跟随 worktree 移动:** 当 Claude 进入或退出由 Claude Code 用 git 创建的 worktree 时,会话记录(transcript)也随之移动——Claude Code 将会话记录在新的工作目录下,就像 [`/cd`](https://code.claude.com/docs/en/commands) 一样,因此 `/desktop` 和 `--resume` 能在那里找到它。退出时以相同方式移回。通过 [`WorktreeCreate` hook](#非-git-版本控制) 创建的 worktree 的会话记录保留在启动目录。需要 Claude Code v2.1.198 或更高版本。
## 用 Worktree 隔离子代理
**子代理可以运行在独立的 worktree 中,避免并行编辑产生冲突。** 你可以要求 Claude "use worktrees for your agents",或者在[自定义子代理](https://code.claude.com/docs/en/sub-agents#supported-frontmatter-fields)的 frontmatter 中添加 `isolation: worktree` 来永久启用。
以下 `.claude/agents/` 中的子代理始终运行在独立 worktree 中:
```markdown theme={null}
---
name: refactorer
description: Applies mechanical refactors across many files
isolation: worktree
---
Apply the requested refactor across every affected file, then run the tests
and report the results.
每个子代理获得一个临时 worktree,当子代理完成且没有变更时会自动删除;有变更的 worktree 保留在磁盘上,直到定期清理在不丢失工作的前提下将其删除。
子代理 worktree 使用与 --worktree 相同的基础分支,即默认从仓库默认分支创建,除非 worktree.baseRef 设为 "head"。
子代理和后台会话 Worktree 的清理¶
定期清理会自动删除 Claude 为子代理和后台会话创建的 worktree, 条件是超过 cleanupPeriodDays 设置的天数。如果 worktree 仍有工作内容(变更或未跟踪文件、未推送的 commit),清理会跳过。通过 --worktree 创建的 worktree 不受此清理影响。
运行中的锁保护: 代理运行时,Claude 会对其 worktree 执行 git worktree lock,防止并发清理删除它。代理完成后释放锁。
自动解锁已退出的会话: 清理还会释放 Claude Code 为已退出进程的会话设置的锁,因此被 kill 的后台会话不会让 worktree 永久锁定。清理不会释放你自己用 git worktree lock 手动设置的锁。v2.1.210 之前,被 kill 的会话留下的锁需要手动运行 git worktree unlock 才能解除。
如果需要清理被跳过的 worktree,运行 git worktree remove,如有未提交变更或未跟踪文件需加 --force。
自定义 Worktree 创建¶
Claude Code 创建 worktree 的默认行为可以满足大多数会话: 在 .claude/worktrees/ 下创建,从仓库默认分支创建新分支,只 checkout 已跟踪文件。本节中的选项用于修改这些默认行为。
选择基础分支¶
新 worktree 默认从仓库的默认分支创建新分支,大多数会话不需要修改此设置。 在设置中设置 worktree.baseRef 可改为从当前工作创建分支。该设置接受两个值:
| 值 | 行为 |
|---|---|
"fresh"(默认) |
从远端的仓库默认分支(通常是 main)创建分支,worktree 从干净的远端状态开始 |
"head" |
从当前本地 HEAD 创建分支,worktree 携带你未推送的 commit 和特性分支状态。适用于需要子代理在进行中的工作上操作的场景。在 worktree 内部,"head" 解析为该 worktree 的 HEAD,而非主 checkout 的 |
不支持将 worktree.baseRef 设为分支名。要从特定已有分支创建 worktree,请直接使用 git。
"fresh" 模式下保持 origin/HEAD 最新: 当仓库在过去 24 小时内没有 fetch 过时,Claude Code 会 fetch 默认分支(最多等 5 秒),如果 fetch 失败则使用本地缓存的 ref。如果没有配置远端,或 origin/HEAD 本地未缓存且无法 fetch,则回退到当前本地 HEAD。v2.1.208 之前,fresh worktree 使用本地已缓存的 origin/HEAD。
以下示例让每个新 worktree 从当前工作创建分支:
```json theme={null}
{
"worktree": {
"baseRef": "head"
}
}
### 从 Pull Request 创建分支
**传入以 `#` 开头的 PR 编号或完整的 GitHub PR URL,可以从特定 PR 创建 worktree。** Claude Code 会从 `origin` 获取 `pull/<number>/head` 并在 `.claude/worktrees/pr-<number>` 创建 worktree。需要给参数加引号,防止 shell 将 `#` 视为注释开头:
```bash theme={null}
claude --worktree "#1234"
将 gitignore 文件复制到 Worktree¶
Worktree 是全新的 checkout,不包含主仓库中的未跟踪文件, 如 .env 或 .env.local。要在 Claude 创建 worktree 时自动复制这些文件,可以在项目根目录添加 .worktreeinclude 文件。
该文件使用 .gitignore 语法。只有匹配模式且同时被 gitignore 的文件才会被复制,已跟踪的文件不会被重复复制。
以下 .worktreeinclude 会将两个 env 文件和一个 secrets 配置复制到每个新 worktree 中:
```text .worktreeinclude theme={null}
.env
.env.local
config/secrets.json
这适用于 Claude Code 通过 git 创建的所有 worktree:`--worktree` worktree、[子代理 worktree](#用-worktree-隔离子代理) 以及[桌面应用](https://code.claude.com/docs/en/desktop#work-in-parallel-with-sessions)中的并行会话。使用 [`WorktreeCreate` hook](#非-git-版本控制) 时,请在 hook 脚本中自行复制文件。
### 复用 Worktree 名称
**传入 `--worktree` 的名称如果对应的目录已存在,则打开已有的 worktree 而不是创建新的。**
使用默认的 `"fresh"` [基础分支](#选择基础分支)时,在以下所有条件都满足的情况下,重新打开的 worktree 会重置到仓库默认分支,而不是继续在旧的 tip:
- 没有未提交变更或未跟踪文件
- 仍在 Claude Code 为其创建的分支上
- 没有自己的 commit,或其 PR 已合并且远端分支已删除
Claude Code 完全通过 git 状态判断"已合并":worktree 推送到的远端分支已不存在,且 worktree 中的所有 commit 都已在默认分支上。
其他情况均在旧的 tip 重新打开:不满足上述任一条件的 worktree、无法验证状态的 worktree,以及 `worktree.baseRef` 设为 `"head"` 或名称是 PR 编号时的复用。v2.1.208 之前,复用名称总是在旧的 tip 重新打开。
### 用 Hook 替代 Worktree 创建
**配置 [`WorktreeCreate` hook](https://code.claude.com/docs/en/hooks#worktreecreate) 可以完全替代默认的 `git worktree` 逻辑,** 包括将 worktree 放在 `.claude/worktrees/` 之外的位置。完整示例见[非 git 版本控制](#非-git-版本控制)。
## Worktree 与主 Checkout 共享的内容
**Worktree 拥有自己的文件和分支,但与主 checkout 共享以下资源:**
| 共享内容 | 说明 |
|------|------|
| 仓库的 `.git` 目录 | Worktree 中的 git 命令写入主仓库的共享 `.git` 目录,[沙盒](https://code.claude.com/docs/en/sandboxing#filesystem-isolation)允许这些写入,因此 `git commit` 等命令在沙盒启用时也能正常工作 |
| 插件 | 从主 checkout 安装的[项目级](https://code.claude.com/docs/en/plugins-reference#plugin-installation-scopes)插件也会在同一仓库的 worktree 中加载,无需每个 worktree 重新安装。需要 Claude Code v2.1.200 或更高版本 |
| 权限审批 | 在 worktree 会话中选择"Yes, don't ask again"保存的规则会写入主 checkout 的 `.claude/settings.local.json`,因此同时适用于主 checkout 和该仓库的所有其他 worktree,且在 worktree 被删除后仍然保留。v2.1.211 之前,在 worktree 中授予的审批保存在该 worktree 内部,不适用于其他地方,且在 worktree 删除时丢失。详见[权限审批保存位置](https://code.claude.com/docs/en/permissions#permission-system) |
以上三项无论通过 `--worktree`、`git worktree add` 还是[桌面应用](https://code.claude.com/docs/en/desktop#work-in-parallel-with-sessions)创建的 worktree 均适用。
## 手动管理 Worktree
**如果需要检出特定已有分支或将 worktree 放在仓库外,可以直接使用 Git 命令创建。**
在新分支上创建 worktree:
```bash theme={null}
git worktree add ../project-feature-a -b feature-a
从已有分支创建 worktree(将 fix-issue-456 替换为仓库中已有的分支名):
```bash theme={null}
git worktree add ../project-bugfix fix-issue-456
在 worktree 中启动 Claude:
```bash theme={null}
cd ../project-feature-a
claude
列出所有 worktree:
```bash theme={null}
git worktree list
完成后删除 worktree:
```bash theme={null}
git worktree remove ../project-feature-a
完整命令参考见 Git worktree 文档。
非 git 版本控制¶
Worktree 隔离默认基于 git。 对于 SVN、Perforce、Mercurial 或其他系统,可以配置 WorktreeCreate 和 WorktreeRemove hook 来提供自定义的创建和清理逻辑。由于 hook 替代了默认的 git 行为,使用 --worktree 时不会处理 .worktreeinclude。请在 hook 脚本中自行复制所需的本地配置文件。
以下 WorktreeCreate hook 用 jq 从 stdin 的 JSON 中读取 worktree 名称,检出一份新的 SVN 工作副本,并输出目录路径供 Claude Code 用作会话的工作目录。将此配置添加到你的 settings.json:
json theme={null}
{
"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\"'"
}
]
}
]
}
}
配合 WorktreeRemove hook 在会话结束时进行清理。输入 schema 和删除示例见 hooks 参考文档。
故障排查¶
以下错误发生在 Claude Code 创建 worktree 或启动时进入 worktree 的过程中。
Claude Code 启动时无法进入 Worktree¶
当 Claude Code 启动时无法进入 worktree 目录,会打印错误信息并以退出码 1 退出。 这可能发生在 WorktreeCreate hook 输出了非其创建目录的内容,或目录在设置后被删除的情况下。v2.1.205 之前,这会导致会话崩溃;使用 -p 时则会卡住约 30 秒后以退出码 0 退出。
在符号链接路径上创建 Worktree 失败¶
当 .claude、.claude/worktrees 或 worktree 目录本身是符号链接时,Claude Code 拒绝创建 worktree, 错误信息会指出被符号链接的路径。移除符号链接后重试。v2.1.212 之前,如果仓库中已提交的文件包含这些路径之一的符号链接,worktree 创建会跟随它,可能导致在仓库外创建文件。
相关页面¶
Worktree 负责文件隔离。以下相关页面介绍如何将工作委派到这些隔离的 checkout 中,以及如何在会话间切换:
| 页面 | 说明 |
|---|---|
| 子代理 | 在会话内将工作委派给隔离的代理 |
| 代理团队 | 自动协调多个 Claude 会话 |
| 会话管理 | 命名、恢复和切换对话 |
| 桌面并行会话 | 桌面应用中基于 worktree 的并行会话 |