如果你手里同时跑着好几个 AI Agent——比如 Codex CLI 在改接口Claude Code 在写前端还有一个自动化脚本在补测试——大概率会遇到同一个头疼的问题它们全挤在同一个工作区里互相覆盖文件、抢分支、把对方刚写好的代码“恢复”掉。git worktree 本来能解决目录隔离但裸用又有一堆命名、清理、任务关联的麻烦。我做了个名为 Worktrunk 的 CLI 工具把 Git Worktree、分支管理和 Agent 任务绑定成一组直观的命令。这篇文章聊聊这个工具的来龙去脉、核心设计和实际踩坑记录适合正在搞多 Agent 并行开发的团队或个人也适合刚接触 AI Agent 编程、想给工作流加一层“秩序”的朋友。1. 为什么并行 AI Agent 工作流需要一个专用 CLI1.1 多个 Agent 抢同一个工作区的混乱先说痛点。AI 编程 Agent 和传统开发者不一样它们没有“我在改这个文件你别动”的自觉。你给它一句 prompt它就会自己去读代码、写文件、跑测试、提交 commit。听起来很爽但一旦你开了两个终端一个跑 Codex一个跑 Claude让它们同时改同一个仓库问题就来了。最典型的场景是Agent A 花了十分钟改完auth_service.go刚提交。Agent B 在另一个终端里并不知道这件事它读到的还是旧代码然后基于旧代码又改了一遍。等你把两个 Agent 的成果合并到一起要么全是冲突要么后提交的 Agent 直接把前面的改动覆盖了。更烦的是Agent B 在 checkout 分支时如果看到工作区有未提交修改它会停下来问“怎么办”或者干脆拒绝执行。我最早也试图通过“人工排队”的方式解决先让 Agent A 干活等它提交完再让 Agent B 上。但这样完全失去了并行能力任务一多就变成串行流水线。而且很多 Agent 任务并不依赖同一个文件比如“改登录接口”和“改支付页面样式”这两件事本来可以同时做。1.2 Git Worktree 刚好吃下这个需求Git 本身其实已经给出了标准答案git worktree。这个命令允许你在同一个仓库里创建多个工作目录每个目录可以 checkout 不同的分支所有目录共享同一套对象数据库和远端配置。也就是说你可以在一个仓库里同时开出两个目录一个在main分支一个在feature/login分支两边互不干扰各自提交各自推。实现原理其实不复杂。普通仓库的.git是一个目录而 worktree 里的.git是一个纯文本文件里面写着一行路径指向主仓库的.git/worktrees/name。这个name目录里存放着该 worktree 自己的 HEAD、index 和 pending refs。多个 worktree 共享对象库和 refs所以你在 worktree 里创建的 commit另一个 worktree 用git log能立刻看到。但工作区文件彼此完全独立。这正好解决了多 Agent 场景下的核心矛盾目录隔离、分支隔离、对象共享。1.3 Worktrunk 的设计目标与定位裸用git worktree能解决目录问题但离“好用”还有距离。你得自己记哪个目录对应哪个任务分支名要手动起任务完成后还得记得清理不然用久了满屏都是wt-xxxx这种看不懂的目录。更不用说多个 Agent 同时跑的时候每个 Agent 还要有自己独立的上下文文件比如 AGENTS.md、CLAUDE.md这些文件如果都放在主工作区Agent 之间又会互相污染。Worktrunk 的定位就是把这一层“日常管理”自动化。它是构建在 Git Worktree 之上的一个封装 CLI让开发者用 Agent 的语义来操作 worktree而不是用 Git 的底层命令。你可以这样理解git worktree 是发动机而 Worktrunk 是方向盘和仪表盘它帮你把任务、分支、目录、上下文、清理这些杂事变成几条好记的命令。2. Worktrunk 的核心设计从 Git 命令到 Agent 语义2.1 命令体系与命名规则Worktrunk 的命令我尽量设计成“一看就知道在干嘛”的风格。核心命令如下worktrunk init # 初始化项目配置 worktrunk status # 列出所有 Agent 工作区状态 worktrunk agent create --name codex --task 登录页改造 --base main worktrunk agent run --name codex --task 登录页改造 -- 请实现响应式登录页 worktrunk status --verbose # 查看每个工作区修改了哪些文件 worktrunk merge --name codex --task 登录页改造 --target main worktrunk destroy --name codex --task 登录页改造 --prune worktrunk doctor # 检查环境排查常见问题每条命令背后都有一串固定的 Git 操作。比如agent create实际上会经历这几步校验 base 分支存在并且与远端同步把任务描述转换成目录名和分支名默认的目录格式是wt/agent-task-slug分支格式是agent/agent/task-slug执行git worktree add 目录 -b 分支 base分支在 worktree 根目录写入一个.worktrunk-agent.yml文件记录 Agent 名称、任务描述、创建时间、关联 CLI根据配置为 Agent 生成上下文文件比如拼接 AGENTS.md 和任务说明。这些默认值都写死在代码里如果你不喜欢可以通过配置文件覆盖。2.2 一个 Agent 工作区的完整生命周期Worktrunk 把每个 Agent 任务看成一次“有开始、有结束”的会话。创建 worktree 只是第一步后续所有操作都围绕这个会话展开。任务进行中你可以随时用worktrunk status查看所有 Agent 工作区的状态。它的输出大概是这样的Repository: payment-service (branch: main) Base: main (ahead 0, behind 0) Agent worktrees: codex/feature-login-page ../payment-service-wt/codex-feature-login-page branch: agent/codex/feature-login-page state: 2 modified files, 1 new file, CI pending claude/fix-payment-timeout ../payment-service-wt/claude-fix-payment-timeout branch: agent/claude/fix-payment-timeout state: clean, ahead 3 commits这个状态面板是我日常用得最多的东西。它把“哪些 Agent 还在改、哪些已经提交完、哪些还在等 CI”一次性摊开不用再挨个目录去git status。等任务完成后worktrunk merge会按顺序执行检查是否有未提交修改有的话提示先提交或自动提交、切到目标分支、拉取远端、合并 Agent 分支、推送、调用 gh 或 glab 创建 MR/PR。这一条链路上每一步都可能出错所以命令会一步步打印执行日志出问题时能定位到具体是哪个环节。2.3 配置文件声明式定义 Agent 工作区Worktrunk 的配置采用 YAML 格式放在仓库根目录的.worktrunk.yml。下面是一个实际可用的示例version: 1 project: payment-service default_base: main worktree_dir: ../payment-service-wt # worktree 放项目外避免 Agent 扫描时互相干扰 context_files: - AGENTS.md - docs/ARCHITECTURE.md agents: codex: cli: codex entrypoint: exec auto_commit: true claude: cli: claude entrypoint: -p auto_commit: false重点说下worktree_dir。我强烈建议把 worktree 放到项目目录外面。原因很实际如果 worktree 建在项目内部比如.wt/目录Agent 扫描代码的时候很容易把其他 Agent 的工作区当成普通源码读进去导致它看到一堆重复代码产生错误判断。放到项目外Agent 眼里只有自己这一个干净的目录。context_files的作用是给每个 Agent 准备“背景材料”。每次创建 worktree 时Worktrunk 会把这些文件的内容复制到 worktree 的根目录并追加一段任务说明。这样每个 Agent 都有独立的任务上下文不会出现两个 Agent 同时改写同一个 AGENTS.md 的情况。3. 从零搭建安装、初始化和第一轮并行任务3.1 安装方式Worktrunk 是 Go 写的单二进制文件安装很简单。目前支持两种方式# 方式一HomebrewmacOS / Linux brew install worktrunk/tap/worktrunk # 方式二Go 直接安装 go install github.com/worktrunk/worktrunklatest安装完先跑一下worktrunk --version确认没问题然后worktrunk doctor帮你检查环境。这个命令会看几样东西Git 版本是否支持 worktree2.5 以上才支持、远端认证是否配置、当前目录是否在一个 Git 仓库里、操作系统是否有路径长度限制。我第一次在 Windows 上跑时就靠它发现路径太长的问题。3.2 初始化一个项目假设你有一个名为payment-service的仓库主分支是main当前工作区是干净的。初始化命令只需要一行cd ~/dev/payment-service worktrunk init这个命令会做三件事检查当前 Git 仓库状态、生成一个默认的.worktrunk.yml、打印一份“默认约定”说明。默认约定包括worktree 目录命名规则、分支命名规则、上下文文件的注入方式。如果你是第一次用建议先花五分钟看看这些默认值再决定要不要在配置文件里改。3.3 创建并运行并行任务现在模拟一个真实场景。今天有两个任务一个由 Codex 负责“实现登录/注册接口”另一个由 Claude Code 负责“实现登录页面 UI”。两个任务之间没有代码依赖可以并行。# 为 Codex 创建工作区 worktrunk agent create --name codex --task 实现登录注册接口 --base main # 为 Claude 创建工作区 worktrunk agent create --name claude --task 实现登录页面UI --base main执行完后项目外会出现两个目录../payment-service-wt/codex-实现登录注册接口和../payment-service-wt/claude-实现登录页面UI。我刚才的目录名里带了中文实际使用时 Worktrunk 默认会把中文转成拼音或英文字段避免某些工具链在非 ASCII 路径上出问题。接下来分别让两个 Agent 进入自己的目录干活。你可以手动 cd 进去跑也可以让 Worktrunk 代劳worktrunk agent run --name codex --task 实现登录注册接口 \ -- 请实现登录接口 /api/login包含参数校验和 token 签发并补上单元测试这条命令会在对应的 worktree 目录里执行 Agent CLI比如 Codexcd ../payment-service-wt/codex-实现登录注册接口 codex exec --skip-git-repo-check 请实现登录接口...加--skip-git-repo-check是因为 Codex 在某些情况下会嫌弃 worktree 里的 .git 不是标准目录结构跳过检查能避免它拒绝执行。两个 Agent 并行跑的时候你可以在第三个终端里用worktrunk status观察它们的进度。哪个 Agent 改了哪些文件、是否已经产生提交一眼就能看到。3.4 合并与清理任务完成后合并是一个高频操作。Worktrunk 的merge命令会把分支合并回目标分支并生成 MR/PRworktrunk merge --name codex --task 实现登录注册接口 --target main这背后做的事情是进入 worktree检查是否有未提交修改有的话按照auto_commit配置决定是自动提交还是停下来询问切回主工作区git checkout maingit pull拉取最新远端git merge --no-ff agent/codex/实现登录注册接口生成一个明确的合并提交git push推送如果配置了gh或glab自动创建 MR 草稿并把任务描述填进去。清理工作区对应destroy命令worktrunk destroy --name codex --task 实现登录注册接口 --prune它会执行git worktree remove删除 Agent 分支清理工作区元数据文件最后跑一次git worktree prune把残留引用清掉。这样整个任务生命周期结束不留垃圾。4. 实操中的典型问题与排查技巧4.1 常见问题速查表用了一段时间后我把遇到的典型问题整理成了下面这个表方便遇到问题时快速定位。现象原因解决方式报错xx is already checked out at ...同一个分支不能同时被两个 worktree 使用用git worktree list找到已占用的 worktree给它换分支或者选择另一个新分支报错fatal: worktrees/xxx already exists目录或元数据残留检查目录是否真的存在然后git worktree prune --expire now清理索引某些脚本/工具读不到 Git 配置worktree 里的.git是文件不是目录脚本按目录方式访问会失败脚本里应该用git rev-parse --git-common-dir而不是直接拼.git/config路径Agent 提交时提示缺少user.name全局 Git 配置没配好先配全局或仓库级配置git config --global user.name your nameWindows 下 Agent 执行失败worktree 目录路径太长超过 MAX_PATH把worktree_dir配置到尽量短的外部路径或开启系统长路径支持工作区里有来自其他分支的旧文件任务依赖关系没声明两个 Agent 改到了重叠文件使用worktrunk run的depends_on声明依赖强制串行执行冲突任务合并时新的提交被反复弹回两个 Agent 同时推了同一个目标分支远端处于中间状态先git pull --rebase再合入或者调整并行度避免同时推同一分支同一个 Agent CLI 同时跑两个任务导致串话Codex/Claude 这类 CLI 多数不支持并发执行同一 Agent 的任务在调度上排队worktrunk run默认不并行同一 Agent4.2 我踩过的几个坑第一个坑是 worktree 目录放项目内部。我最早把 worktree 建在.wt/下面结果 Agent 扫描目录时把其他 Agent 的工作区当成项目源码的一部分读了一堆重复代码进来给出的建议全都乱了。后来我把worktree_dir改成项目外这个问题彻底消失。如果你接手的项目已经把 worktree 建在了仓库内部至少要把这些目录加到.gitignore里并且在 Agent 的上下文文件里明确“不要扫描这些目录”。第二个坑是 pre-commit 钩子。很多 Python/Node 项目会在钩子里跑 lint钩子脚本里如果用pwd来定位仓库根目录在 worktree 里会定位到 worktree 自己的目录这其实是符合预期的但有些脚本会继续往上找.git目录找到的却是主仓库目录导致路径错乱。写钩子脚本时根目录定位应该统一用git rev-parse --show-toplevel这个命令在 worktree 里会返回正确的顶层目录。第三个坑和 Agent 上下文长度有关。如果一个 Agent 长时间待在同一个 worktree 里它会在文件末尾反复追加 helper 函数越写越长甚至出现重复定义。我的经验是一个任务一个 worktree任务结束立即 destroy不要让 Agent 在一个 worktree 里“续命”很久这样每个 Agent 的上下文都是干净的它也更专注。4.3 几个让我少走弯路的设计决定第一个决定是把上下文文件做成了“注入”而不是“共享”。最开始的版本里所有 Agent 共用一个 AGENTS.md结果 Codex 往里面加了“登录模块的说明”Claude 干 UI 任务时也读到了这段然后被带偏去做接口逻辑。现在每个 worktree 都会生成一份独立的任务说明文件相当于给每个 Agent 单独发了一份“项目背景 本次任务”的简报效果好了很多。第二个决定是默认禁用同一 Agent 的并行执行。虽然 Worktrunk 面向的是并行工作流但同一个 Agent CLI比如 codex同时跑两个任务大概率会在同一个缓存目录或者配置目录上打架。所以我在run的调度器里加了规则不同 Agent 可以并行同一 Agent 的任务必须排队。这是妥协但换来了稳定。第三个决定是提供doctor命令。很多 Git worktree 的兼容问题不是马上暴露的而是某个工具链在某个时刻突然爆出来。worktrunk doctor会把 Git 版本、远端认证、路径长度、hook 脚本、子模块状态都扫一遍并给出具体的修复建议。我从一开始就把这个命令当成一等公民因为并行 Agent 工作流一旦跑起来排查问题的成本非常高不如提前把基础检查好。5. 后续还可以怎么扩展我自己目前用的是命令行版本但心里已经有几个想做的扩展方向。第一个是按 Agent 维度的审计和计费——每个 Agent 任务改了多少文件、跑了多少次命令、花了多长时间这些数据如果能自动汇总到一张表格里对团队管理很有价值。Worktrunk 的 worktree 元数据文件已经记录了任务创建和完成时间后续只要在destroy时把统计信息输出到.worktrunk/audit/目录再配一条命令按项目汇总就行。第二个方向是把 DAG 任务调度做成可视化。现在worktrunk run plan.yml会在控制台输出执行顺序但并行的任务多了以后一张图比文字直观得多。我倾向于输出一个静态的 HTML 报告或者直接在终端里用树形结构展示依赖关系而不是引入额外的前端依赖。第三个方向是和 MCPModel Context Protocol集成。现在各种 Agent 都支持 MCP 工具如果能把 Worktrunk 封装成一个 MCP server让 Agent 自己在需要时创建 worktree、查看其他 worktree 的状态就能实现 Agent 之间的“互相感知”而不是仅靠外部调度。这个想法还在实验阶段但我觉得方向是对的。最后分享一个实际操作中的体会不要一上来就追求“全自动并行”。先从手工命令跑通两个 Agent 的完整生命周期再慢慢引入 task graph 和自动合并。多 Agent 并行的最大风险不是技术而是你没想清楚哪些任务可以真正并行哪些任务其实在读写同一批文件。Worktrunk 只能帮你解决目录和分支层面的隔离任务之间的数据依赖归根结底还是要靠人先想清楚。