Isolation 与 Worktree
当多个 agent 同时操作同一代码库时,需要 isolation 来避免相互影响。Claude Code 以 git worktree 作为主要的 isolation 机制——每个 agent 获得仓库自己的工作副本,共享相同的 git 历史,但拥有独立的文件系统。
为什么选择 Git Worktree?
Section titled “为什么选择 Git Worktree?”其他方案及其被排除的原因:
| 方案 | 问题 |
|---|---|
| 同一目录 | 并发 agent 间的文件冲突 |
| 完整克隆 | 占用磁盘空间大、速度慢、历史分离 |
| Docker/容器 | 重量级、配置复杂、非普遍可用 |
| Git worktree | ✅ 轻量级、共享历史、独立文件 |
Git worktree 是 git 的原生特性(git worktree add),可创建链接到同一仓库的新工作目录。各 agent 可以独立修改文件、创建分支和提交,互不影响。
Isolation 模式
Section titled “Isolation 模式”Agent 定义在 BaseAgentDefinition 中支持两种 isolation 模式:
isolation?: 'worktree' | 'remote'| 模式 | 可用范围 | 描述 |
|---|---|---|
worktree | 所有用户 | 本地磁盘上的 git worktree |
remote | 仅 Anthropic 内部 | 在 Claude Code Remote(CCR)中远程执行 |
remote 模式在解析时受限:
// src/tools/AgentTool/loadAgentsDir.ts — AgentJsonSchemaisolation: (process.env.USER_TYPE === 'ant' ? z.enum(['worktree', 'remote']) : z.enum(['worktree'])).optional(),外部用户只能使用 worktree。在 agent 定义中设置 remote 将导致验证失败。
Worktree 生命周期
Section titled “Worktree 生命周期”sequenceDiagram
participant L as Leader Agent
participant W as Worktree System
participant G as Git
participant A as Agent (in worktree)
L->>W: Spawn agent with isolation: 'worktree'
W->>G: git worktree add <path> <branch>
G-->>W: Worktree created at <path>
W->>A: Start agent with cwd = worktree path
Note over A: Agent works independently<br/>in its own working copy
A->>A: Read, Edit, Bash, Commit...
A-->>L: Report results
L->>W: Cleanup / Kill agent
W->>G: git worktree remove --force <path>
G-->>W: Worktree removed
Team 成员中的 Worktree
Section titled “Team 成员中的 Worktree”每个 team 成员可以拥有自己的 worktree,存储在 team 配置中:
// teamHelpers.ts 中的 TeamMembertype TeamMember = { agentId: string worktreePath?: string // 该成员的 worktree 路径 // ...}team 解散或成员被终止时,worktree 必须被清理。destroyWorktree() 函数会谨慎处理这一过程:
// src/utils/swarm/teamHelpers.ts — destroyWorktree(概念性代码)async function destroyWorktree(worktreePath: string): Promise<void> { // 1. 读取 .git 文件以找到主仓库 // (worktree 的 .git 是文件而非目录:"gitdir: /path/to/main/.git/worktrees/...") const gitContent = await readFile(join(worktreePath, '.git'), 'utf-8')
// 2. 从 gitdir 引用中提取主仓库路径 const mainRepoPath = resolveMainRepo(gitContent)
// 3. 使用 git worktree remove 进行干净移除 try { await exec(`git worktree remove --force ${worktreePath}`, { cwd: mainRepoPath }) } catch { // 4. 回退:强制删除目录 await exec(`rm -rf ${worktreePath}`) }}Fork + Worktree 集成
Section titled “Fork + Worktree 集成”当 fork mechanism 在隔离的 worktree 中创建子进程时,会向子进程的 context 注入一条特殊说明:
export function buildWorktreeNotice(parentCwd: string, worktreeCwd: string): string { return `You've inherited the conversation context above from a parent agentworking in ${parentCwd}. You are operating in an isolated git worktree at${worktreeCwd} — same repository, same relative file structure, separateworking copy.
Paths in the inherited context refer to the parent's working directory;translate them to your worktree root.
Re-read files before editing if the parent may have modified them sincethey appear in the context.
Your changes stay in this worktree and will not affect the parent's files.`}这条说明解决了三个关键问题:
- 路径转换 — 继承的路径指向父级目录,而非 worktree
- 过时 context — 父级 context 中读取的文件可能已发生变化
- isolation 保证 — 修改不会影响父级的工作副本
Team 目录清理
Section titled “Team 目录清理”清理 team 时,必须先销毁所有 worktree,再删除目录:
flowchart TD
A[cleanupTeamDirectories<br/>teamName] --> B[Read team config.json]
B --> C[For each member<br/>with worktreePath]
C --> D[destroyWorktree<br/>member.worktreePath]
D --> E{Success?}
E -->|yes| F[Continue]
E -->|no| G[Log error, continue]
F --> H[Remove task directories<br/>for each member]
H --> I[Delete team config file]
session 级清理(cleanupSessionTeams)在 session 结束时运行,确保不留下孤立的 worktree:
// 清理函数查找该 session 的所有 team 文件并销毁其 worktreeasync function cleanupSessionTeams(sessionId: string): Promise<void> { const teamFiles = await findTeamFilesForSession(sessionId) for (const teamFile of teamFiles) { await cleanupTeamDirectories(teamFile.name) }}Worktree Session 管理
Section titled “Worktree Session 管理”worktree 系统还支持独立 session(不仅限于 team 成员)。src/utils/worktree.ts 中的 getCurrentWorktreeSession() 追踪当前 session 的 worktree 元数据:
// 在 prompts.ts 中用于 statusLine agent 的输入type WorktreeSession = { name: string // worktree 名称/slug path: string // worktree 的完整路径 branch?: string // git 分支 original_cwd: string // 进入 worktree 前的目录 original_branch?: string}这些元数据流入状态栏配置,让用户能看到当前所在的 worktree 并快速返回。
安全注意事项
Section titled “安全注意事项”Worktree 路径经过验证以防止路径穿越:
- 路径必须为绝对路径
- 路径不能逃逸项目根目录
- 读取 worktree 中的
.git文件以验证其指向合法仓库
src/memdir/paths.ts 中的 validateMemoryPath() 函数展示了系统中广泛使用的路径验证模式——拒绝相对路径、根路径、null 字节和 UNC 路径。