商业产业 Hacker News Agent 2026-07-30T00:20 正文 ok 916 words

Show HN:面向并行 Claude Code Agent 的本地合并队列

英文标题:🔶 Show HN: A local merge queue for parallel Claude Code agents

Claude Code Merge Queue 是一款面向并行 Claude Code Agent 的本地零成本合并队列工具,通过 FIFO 队列串行化 rebase、测试与 push,避免推送竞争、重复重型构建及共享资源导致的测试不稳定。该工具以单个配置文件管理分支、worktree、端口、构建和检查命令,并可自动配置 Claude Code 的 WorktreeCreate hook、Husky pre-push hook 与常用 npm scripts。与 GitHub Merge Queue 相比,它不依赖 Pull Request 或 GitHub Actions,可用于任意计划和仓库,但仅适用于单机协作场景。工具明确不提供人工审查或安全边界,开发团队仍需依赖可靠的 `checkCommand`、测试套件和 Git 工作流治理。
打开原文相关 6 · 机会 1
media3.4 KB media1.2 KB media1.3 KB media2.2 KB media1.2 KB media1.3 KB media1.2 KB media1.3 KB media3.3 KB media121.8 KB

中文

Claude Code Merge Queue——面向并行 Claude Code Agent 的本地零成本合并队列

npm 版本 npm 下载量 CI 许可证:MIT TypeScript Node 运行时依赖

Claude Code Merge Queue 🚦

面向并行 Claude Code Agent 的本地零成本合并队列。 多个 Agent 可同时提交变更、构建和测试;该工具会将这些操作串行化,从而避免推送竞争、重复的重型构建,以及共享资源导致的测试不稳定。

npm install --save-dev claude-code-merge-queue   # 或:pnpm add -D / yarn add -D / bun add -d
npx claude-code-merge-queue init

终端演示:npm install --save-dev claude-code-merge-queue,然后运行 npx claude-code-merge-queue init——写入配置、CLAUDE.md、WorktreeCreate hook,以及 land/sync/promote/preview 脚本

所有内容都集中在一个文件中——各字段及其注释请参阅 examples/claude-code-merge-queue.config.mjs。简版如下:

export default {
  branchPrefix: "lane/",               // lane/1、lane/2,……
  worktreeSuffix: "-lane-",            // ../your-repo-lane-1
  portBase: 3000,                      // lane n 使用 portBase + n 端口
  integrationBranch: "main",           // Agent 在此落地——见下文
  productionBranch: null,              // 双阶段模型请设置此项——见下文
  protectedBranches: [],               // 除上述两个分支外的额外受保护分支;大多数仓库无需设置
  regenerableFiles: [],                // 构建工具会重写的文件——绝不应因这些文件阻止 rebase
  symlinks: [".env", ".env.local", "node_modules"],
  buildOutputDirs: ["dist", "build", ".next"], // preview 绝不会将这些复制到你的检出目录
  checkCommand: "npm run check",       // 实际决定能否落地的检查——见下文
  checksRequired: true,                // false = 有意不运行任何检查;见下文
};

格式错误的配置(空分支名、负端口、productionBranch 与 integrationBranch 相同等)会在任一命令加载配置的瞬间高声失败,并列出所有问题;而不是到三步之后才出现神秘错误。

🆚 与 GitHub Merge Queue 的对比

GitHub Merge Queue Claude Code Merge Queue
私有仓库 仅限 Enterprise Cloud
每次落地成本 GitHub Actions 分钟数,每次队列尝试均计费
要求 一个 Pull Request

理念相同——将落地操作串行化、在合并前测试、保持历史整洁——但它在本地运行,而非在他人计费的云端运行。

命令 功能
claude-code-merge-queue hook worktree-create Claude Code 的 WorktreeCreate hook。将 Claude Code Merge Queue 的编号 lane 接入 Claude 的原生 worktree 创建机制。
claude-code-merge-queue build-lock -- <cmd> 运行 <cmd>——即你的构建命令——并在整台机器的所有 lane 间将其串行化。
claude-code-merge-queue land 通过 FIFO 队列将你的 lane rebase 并 push 到集成分支,因此不会有两个 lane 同时处于推送过程中。Agent 自行运行此命令。
claude-code-merge-queue sync 快进你的主检出目录,让开发服务器实际看到刚刚落地的内容;如果 lockfile 发生变化,还会重新安装依赖。
claude-code-merge-queue promote 将集成分支发布到生产环境。仅限人工操作——绝不可写入 Agent 指令,也不可自动化。
claude-code-merge-queue preview 立即将某个 lane 的实时工作树——包括未提交的变更——镜像到主检出目录,因此无需构建即可查看。
claude-code-merge-queue port 输出某个 lane 的开发服务器端口,该端口从其自身目录名推导得出。
claude-code-merge-queue prune 按需移除已落地的同级 lane worktree。

pre-push hook 让 land 成为不可绕过的必选项:直接对集成分支执行 git push 会被拒绝,并提示应运行的实际命令。该 hook 还会在允许落地前运行 checkCommand——如果没有配置 checkCommand,默认情况下每次 push 都会失败。每一项拦截都有退出机制(见“🚨 紧急出口”),但必须明确指定特定分支,不能使用通用标志。

  • claude-code-merge-queue.config.mjs ——自动检测 integrationBranch 和 checkCommand。
  • CLAUDE.md(或追加到已有文件中)——告知 Claude Code:一旦通过检查,就自行落地其工作,无需等待请求。
  • .claude/settings.json ——接入 WorktreeCreate hook,不会改动其中已有的其他内容。
  • .husky/pre-push ——仅当你已经使用 Husky 时创建或追加。如果未使用 Husky,init 会告知你,而不会悄悄写入未跟踪的 .git/hooks/pre-push。
  • package.json scripts ——添加 land、sync、promote、preview、preview:restore,跳过你已自行定义的任何脚本。
  • claude-code-merge-queue-preflight.mjs ——在 land/sync 前运行的独立安全网,使过期分支能以真实诊断失败,而不是只报一个 command not found。

每一种被阻止的 push——集成分支、productionBranch、protectedBranches 中的任何分支——都有真正的放行方式。只需一个环境变量,无需提示,也无需记住第二重认证:

CLAUDE_CODE_MERGE_QUEUE_EMERGENCY_PUSH=1 git push origin HEAD:main

这是一项约定,而非硬性保证:它能够阻止误操作和意外 push,却无法阻止主动自行设置该变量的对抗性 Agent。

  • **在变更落地前,不会有人工审查其中任何内容。**通过 checkCommand 是唯一关卡——对该工具而言,真正的测试套件和 echo ok 没有区别。想让每项变更都经过人工?该工具刻意缺少这一步。
  • **锁通过 PID 存活状态而非超时机制实现崩溃安全。**如果在某个进程声明锁的中途对其执行 kill -9,下一个进程会发现该 PID 已死亡并重新取得锁——没有陈旧锁,也没有需要调优的超时参数。
  • **仅限一台机器,而非机器集群。**FIFO 队列存放在本地临时存储中——两台机器同时落地时,只会收到 Git 常规的非快进拒绝。
  • **它不是安全边界。**所有这些防护措施旨在防止错误和约定漂移,而不是对抗恶意 Agent——拥有 shell 访问权限始终意味着可以执行 git push --no-verify,或故意编辑配置。
  • **缓慢的 checkCommand 会成为实际吞吐量上限。**FIFO 锁在其完整执行期间一直持有——一个耗时 3 至 4 分钟的测试套件,会将吞吐量限制在远低于每小时 20 次落地的水平。
  • **遇到 rebase 冲突会中止,绝不猜测。**任何冲突都会执行 git rebase --abort,工作树保持干净;CLAUDE.md 会告知 Agent 解决冲突后重新运行 land。

MIT。Fork 它、重命名它、争论配置的形式——这正是目的。

English / 原文

Claude Code Merge Queue — the local, zero-cost merge queue for parallel Claude Code agents

npm version npm downloads CI License: MIT TypeScript Node Runtime deps

Claude Code Merge Queue 🚦

The local, zero-cost merge queue for parallel Claude Code agents. Several agents land, build, and test at the same time — this serializes it so push races, redundant heavy builds, and shared-resource test flakiness can't happen.

npm install --save-dev claude-code-merge-queue   # or: pnpm add -D / yarn add -D / bun add -d
npx claude-code-merge-queue init

Terminal demo: npm install --save-dev claude-code-merge-queue, then npx claude-code-merge-queue init — writes the config, CLAUDE.md, the WorktreeCreate hook, and land/sync/promote/preview scripts

Everything lives in one file — see examples/claude-code-merge-queue.config.mjs for every field with comments. The short version:

export default {
  branchPrefix: "lane/",               // lane/1, lane/2, ...
  worktreeSuffix: "-lane-",            // ../your-repo-lane-1
  portBase: 3000,                      // lane n gets portBase + n
  integrationBranch: "main",           // where agents land — see below
  productionBranch: null,              // set this for a two-stage model — see below
  protectedBranches: [],               // extra branches beyond the two above; most repos need none
  regenerableFiles: [],                // files a build tool rewrites — never block a rebase on these
  symlinks: [".env", ".env.local", "node_modules"],
  buildOutputDirs: ["dist", "build", ".next"], // preview never copies these onto your checkout
  checkCommand: "npm run check",       // what actually gates a landing — see below
  checksRequired: true,                // false = deliberately run with none; see below
};

A malformed config (empty branch names, a negative port, productionBranch equal to integrationBranch, ...) fails loud with every problem listed, the moment any command loads it — not a mysterious failure three steps later.

🆚 vs. GitHub's Merge Queue

| GitHub Merge Queue | Claude Code Merge Queue
---|---|---
Private repo | Enterprise Cloud only | Any plan, any repo
Cost per landing | GitHub Actions minutes, every queue attempt | $0 — runs on your own machine
Requires | A pull request | Nothing — direct rebase + push

Same idea — serialize landings, test before merge, keep history clean — run locally instead of in someone else's billed cloud.

Command What it does
claude-code-merge-queue hook worktree-create A Claude Code WorktreeCreate hook. Plugs Claude Code Merge Queue's numbered lanes into Claude's native worktree creation.
claude-code-merge-queue build-lock -- <cmd> Runs <cmd> — your build — serialized across every lane, machine-wide.
claude-code-merge-queue land Rebases and pushes your lane onto the integration branch through a FIFO queue, so two lanes are never mid-push at once. Agents run this themselves.
claude-code-merge-queue sync Fast-forwards your main checkout so a dev server actually sees what just landed — and re-installs dependencies if the lockfile changed.
claude-code-merge-queue promote Ships the integration branch to production. Human-only — never in an agent's instructions, never automated.
claude-code-merge-queue preview Instantly mirrors a lane's live working tree — uncommitted changes included — onto the main checkout, so you can look at it without a build.
claude-code-merge-queue port Prints a lane's dev-server port, derived from its own directory name.
claude-code-merge-queue prune Removes already-landed sibling lane worktrees on demand.

A pre-push hook makes land non-optional: a direct git push straight to the integration branch is rejected, with the actual command to run instead, and the same hook runs checkCommand before allowing a landing through — no checkCommand configured means every push fails by default. There's a way out for every block (see 🚨 The emergency hatch), but it takes naming the specific branch, not a generic flag.

  • claude-code-merge-queue.config.mjs — integrationBranch and checkCommand auto-detected.
  • CLAUDE.md (or appends to yours) — tells Claude Code to land its own work once green, without being asked.
  • .claude/settings.json — the WorktreeCreate hook wired in, without touching anything else already there.
  • .husky/pre-push — created or appended to, if you already have Husky. If you don't, init tells you rather than silently writing to the untracked .git/hooks/pre-push.
  • package.json scripts — land, sync, promote, preview, preview:restore, skipping any you've already defined yourself.
  • claude-code-merge-queue-preflight.mjs — a self-contained safety net that runs before land/sync, so a stale branch fails with a real diagnosis instead of a bare command not found.

Every blocked push — the integration branch, productionBranch, anything in protectedBranches — has a real way through it. One env var, no prompts, no second factor to remember:

CLAUDE_CODE_MERGE_QUEUE_EMERGENCY_PUSH=1 git push origin HEAD:main

This is a convention, not a hard guarantee: it stops mistakes and stray pushes, not an adversarial agent that sets the var itself.

  • No human reviews any of this before it lands. checkCommand passing is the only gate — a real test suite and echo ok look identical to this tool. Want a human on every change? This is missing that step on purpose.
  • Locks are crash-safe by PID liveness, not a timeout. kill -9 anything mid-claim and the next process notices the PID is dead and reclaims it — no stale locks, no timeout to tune.
  • One machine, not a fleet. The FIFO queue lives in local temp storage — two machines landing at once just get git's ordinary non-fast-forward rejection.
  • Not a security boundary. Every guardrail here stops mistakes and convention drift, not an adversarial agent — shell access always means git push --no-verify or editing the config on purpose.
  • A slowcheckCommand is a real throughput ceiling. The FIFO lock holds for its entire duration — a 3–4 minute suite caps you well under 20 landings/hour.
  • Rebase conflicts abort, they never guess. git rebase --abort on any conflict, working tree left clean — CLAUDE.md tells the agent to resolve it and re-run land.

MIT. Fork it, rename it, argue with the config shape — that's the point.