SkillHub 多 Agent 并行开发工作流:用 git worktree 隔离 Claude 与 Codex,安全合并与联调
SkillHub 多 Agent 并行开发工作流:用 git worktree 隔离 Claude 与 Codex,安全合并与联调
导读
本文讲解 SkillHub 仓库推荐的 Claude + Codex 并行开发方案:为每个任务创建三个兄弟 git worktree,让两个 AI Agent 各自在独立目录写代码、互不覆盖,再由一个集成 worktree 统一合并并独占浏览器联调环境(http://localhost:3000)。读完本文,你将掌握 parallel-init / parallel-sync / parallel-up / parallel-down 四组命令的完整用法、底层脚本行为,以及一套"先隔离、后合并、再回归"的开 PR 流程。
适用前提:本文工作流面向 SkillHub 仓库本地开发场景,命令基于 Makefile 与 scripts/ 下的 bash 脚本;运行环境要求见 docs/dev-workflow.md(Docker、Java 21、Node.js 22 + pnpm、
ghCLI)。
为什么需要并行工作流:核心规则
SkillHub 的开发经验表明,不要让两个 Agent 在同一份 checkout 上同时写代码——这是整个方案的唯一核心规则。Claude 与 Codex 如果指向同一目录,会互相覆盖文件、破坏对方的中间状态,使集成变得不可预测。
因此,每个任务固定使用三个兄弟 git worktree(彼此是平级目录,而非嵌套目录):
| Worktree | 目录命名 | 分支命名 | 职责 |
|---|---|---|---|
| Claude 工作区 | <repo>-claude-<task> |
agent/claude/<task> |
Claude 在此写代码 |
| Codex 工作区 | <repo>-codex-<task> |
agent/codex/<task> |
Codex 在此写代码 |
| 集成工作区 | <repo>-integration-<task> |
agent/integration/<task> |
合并结果、浏览器验证、最终回归 |
三条配套约定:
- 只有 integration worktree 允许运行
make dev-all,从而让http://localhost:3000(Web UI)与http://localhost:8080(后端)始终反映合并后的最新特性,成为唯一事实来源; - 所有 worktree 共享同一套本地 Docker 依赖容器(Postgres、Redis、MinIO),
make dev/make dev-all复用同一批容器,避免多个 checkout 争抢端口; - 仓库仍保留
agent-worktrees、agent-sync等旧别名作为兼容垫片,但规范化命令集是parallel-init、parallel-sync、parallel-up、parallel-down。
一次性初始化:make parallel-init
在主仓库目录执行:
make parallel-init TASK=legal-pages
一次创建三个 worktree 与三条匹配的本地分支:
../skillhub-claude-legal-pages(分支agent/claude/legal-pages)../skillhub-codex-legal-pages(分支agent/codex/legal-pages)../skillhub-integration-legal-pages(分支agent/integration/legal-pages)
目录名中的仓库名取自 git common dir 的父目录(scripts/parallel-common.sh 中 repo_name() 函数),任务名会经 slugify() 统一规范为小写、以连字符分隔的 slug(tr '[:upper:]' '[:lower:]' 加正则清洗),因此 TASK 传 legal-pages、LegalPages 等写法都会被归一。
参数覆盖
# 指定基线分支与 worktree 落盘目录
make parallel-init TASK=legal-pages PARALLEL_BASE_REF=origin/main PARALLEL_WORKTREE_ROOT=/Users/wowo/workspace
# 若本工作流自身尚未合入 origin/main,则从当前分支派生
make parallel-init TASK=legal-pages PARALLEL_BASE_REF=HEAD
参数默认值与含义如下:
| Make 变量 | 默认值 | 作用 |
|---|---|---|
TASK |
必填 | 任务标识(slug),用于目录与分支命名 |
PARALLEL_BASE_REF |
origin/main |
三个分支的派生基线 git ref |
PARALLEL_WORKTREE_ROOT |
主仓库父目录(dirname $(repo_root)) |
worktree 的落盘根目录 |
源码级行为
scripts/parallel-init.sh 的核心是 ensure_worktree()(第 32-58 行),对每个角色依次执行幂等检查:
- 目标目录已含
.git→ 直接复用并提示"already exists",可安全重复执行; - 目录存在但非 git worktree → 报错退出,避免覆盖普通文件夹;
- 分支已在其他 worktree 检出(
branch_in_use()通过git worktree list --porcelain检测)→ 报错,防止同一分支被两个 checkout 占用; - 分支已存在(
git show-ref --verify)→git worktree add <dir> <branch>关联已有分支; - 否则 →
git worktree add -b <branch> <dir> <base-ref>从基线创建新分支。
脚本开头还会 git rev-parse --verify 校验 base-ref 确实存在,避免从一个不存在的 ref 派生。
责任分工:开工前先划分领地
文档建议在任一 Agent 开工前,把分工划分得粗粒度且明确:
- Claude:需求分析、评审、文案、UI 结构、边界场景、回归评审;
- Codex:实现、接线(wiring)、脚本、测试、重构、修复。
两条纪律:
- 避免把同一个文件同时分配给两个 Agent;
- 若某个文件必须由双方触碰,则对该文件改为串行编辑(一方完成并提交后,另一方再改)。
日常循环:实现 → 合并 → 验证
1. 并行实现
每个 Agent 只在被分配的工作区内工作:
- Claude 在
../skillhub-claude-<task> - Codex 在
../skillhub-codex-<task>
各自独立提交自己的工作成果,提交后再进入集成,保证 integration 合并时拿到的是干净的 commit。
2. 合并进 integration
在 integration worktree 中一条命令完成"合并 + 启动":
cd ../skillhub-integration-legal-pages
make parallel-up
parallel-up 等价于按顺序执行两个步骤:先把默认源分支合并进当前 integration 分支,再以 make dev-all 启动集成环境。默认源分支为:
agent/claude/legal-pagesagent/codex/legal-pages
需要手动分步控制时,可以拆开执行:
cd ../skillhub-integration-legal-pages
make parallel-sync
make dev-all
两条命令都支持用 SOURCES 覆盖源列表:
make parallel-sync SOURCES="agent/claude/legal-pages agent/codex/legal-pages"
make parallel-up SOURCES="agent/claude/legal-pages agent/codex/legal-pages"
冲突处理:合并冲突一律在 integration worktree 内解决;除非有意重写该分支,否则不要在 Claude 或 Codex 的 worktree 里解决冲突。
3. 浏览器验证
只允许在 integration worktree 运行本地栈:
cd ../skillhub-integration-legal-pages
make parallel-up
然后验证合并结果:
- Web UI:
http://localhost:3000 - 后端:
http://localhost:8080
验证完成后收尾:
make parallel-down
命令背后的实现细节(源码级)
四个命令在 Makefile 第 385-399 行定义,实际逻辑落在 scripts/ 下四个脚本中:
parallel-sync(scripts/parallel-sync.sh)
- 任务名可通过参数传入,也可从当前分支自动推断(
require_integration_task()要求当前分支匹配agent/integration/<task>前缀,见 scripts/parallel-common.sh); - 执行前强制校验 integration worktree 位于正确的 integration 分支,且工作树必须干净(
require_clean_worktree()检查git diff与git diff --cached,第 31-36 行); - 每个源分支先做
git rev-parse --verify存在性检查,再依次执行git merge --no-ff --no-edit(第 76-82 行);任一合并失败即报错退出并提示在 integration worktree 手动继续。
parallel-up(scripts/parallel-up.sh)
- 先以
PARALLEL_WORKTREE_ROOT环境变量透传调用parallel-sync.sh,合并完成后在 integration 目录执行make -C <dir> dev-all(第 45-47 行),并打印 Web UI / 后端地址。
parallel-down(scripts/parallel-down.sh)
- 同样要求从 integration 分支运行(
require_integration_task),随后执行make -C <repo> dev-all-down(第 23-27 行),即停掉后端与前端进程并docker compose down --remove-orphans回收依赖容器(见 Makefile 第 159-162 行dev-all-down)。
依赖容器共享原理:所有 worktree 能共用一套容器,关键在于本地开发环境固定了 Docker Compose 项目名——Makefile 中 DEV_COMPOSE_PROJECT_NAME ?= skillhub,make dev / make dev-all 一律以 docker compose -p skillhub 操作。因此无论从哪个 worktree 启动,Postgres(5432)、Redis(6379)、MinIO(9000/9001)、skill-scanner(8000)都命中同一批容器,多个 checkout 不会互相争抢端口;详见 docker-compose.yml 与 docs/dev-workflow.md 第 27 行的说明。
验证清单(开 PR 前)
从 integration 分支发起 PR 之前,按文档建议依次完成:
- 先做最小验证:例如
pnpm --dir web typecheck或后端测试; - 在 integration worktree 执行
make parallel-up; - 在
http://localhost:3000验证最终合并行为; - 若变更涉及 Docker 路径或需要 smoke test 信心,执行
make staging(该目标会构建后端镜像与前端静态文件、启动混合 staging 环境并运行 scripts/smoke-test.sh,见 Makefile 第 311-337 行)。
恢复规则
- 某个 Agent 分支方向走偏:只在该分支自己的工作树内 reset 或丢弃该分支;
- integration 变乱:从原始基线仅重建 integration 分支,再重新合并;
- 端口被占用:确认没有任何 Claude / Codex worktree 在运行自己的本地栈(端口唯一归属 integration)。
PR 策略
两种安全做法任选其一:
- 合并验证通过后,直接从 integration 分支开 PR;
- 或把验证过的 commit cherry-pick 到一条干净的特性分支,再从该分支开 PR。
对该仓库而言,文档推荐的最简路径通常为:
# 1. Claude 分支提交
# 2. Codex 分支提交
cd ../skillhub-integration-legal-pages
make parallel-up # 3. 合并并启动集成环境
# 4. 在 http://localhost:3000 验证
# 5. 从 integration 分支开 PR
命令速查
# 一次性初始化(主仓库目录执行)
make parallel-init TASK=legal-pages
# 进入集成工作树,合并 + 启动 + 验证
cd ../skillhub-integration-legal-pages
make parallel-up
open http://localhost:3000
# 完成后停止联调环境
make parallel-down
完整流程总览
make parallel-init TASK=<task> # 建三个 worktree:claude / codex / integration
├─ Claude 只在 ../skillhub-claude-<task> 编码并提交
├─ Codex 只在 ../skillhub-codex-<task> 编码并提交
└─ integration worktree:
make parallel-up # 合并两分支 + make dev-all(唯一联调入口)
http://localhost:3000 # 浏览器验证合并结果
make parallel-down # 停止栈
make staging # (可选)Docker 路径回归
make pr # 从 integration 分支发起 PR
这套工作流把"两个 Agent 并行写代码"从互相踩踏的混乱状态,收敛为"目录隔离 + 分支隔离 + 单一集成事实源"的可预测流程;命令全部由 scripts/parallel-*.sh 幂等实现,可随时重复执行、安全恢复。