我之前写过一篇 grill-me skill 的博客,讲动手之前把需求拷问清楚。用久了发现,拷问清楚只是第一步。想清楚之后还有一长条链路:把对齐的共识落成文档,把文档写成 spec,把 spec 切成任务,再把任务实现掉。这四个环节的产物如果只存在于对话里,会话一断就全没了。
Monorail 就是冲着这个问题去的,它是一组 Agent Skills,把"从想法到实现"的工程流程写成 Agent 可执行的工作方式。这篇讲讲它为什么长成这样,以及我在几个设计岔路口是怎么取舍的,希望可以抛砖引玉。
核心是四段式主链路:align → spec → slice → build,对齐、规格化、切片、构建。
一条命令安装 Skills
安装走 skills.sh 生态,一条命令:
sh
npx skills add guangzan/monorail
主链路
| Skill | 作用 |
|---|---|
rail-setup |
配置:所有 rail 文档统一在 docs/monorail/ |
rail-align |
对齐需求(light → align.md;或 map 模式) |
rail-spec |
从 align.md / 已清完的 map 写 spec.md |
rail-slice |
将 spec.md 拆成带 blockers 的 tasks/NN-*.md |
rail-build |
实现 task------或每会话跑一小批(并发须 worktree) |
旁路与辅助
| Skill | 作用 |
|---|---|
rail |
路由 --- 选哪个 skill/流程 |
rail-grill |
无状态拷问 |
rail-pass |
跨会话接力文档(pass-*.md) |
rail-debug |
疑难 bug 诊断循环 |
rail-review |
Standards + Spec 审查 |
底层能力
| Skill | 作用 |
|---|---|
rail-tdd |
Red-green-refactor(rail-build 内用到) |
所有 Monorail 技能都以 rail 开头,方便调用。
主链路:从想法到实现的四段式
装完之后,在业务仓库里先跑一次 /rail-setup。我讨厌各种 skills 生成的文档散落到各处。Monorail 会先探查仓库现状,然后把约定文件建好:所有 rail 文档统一收在 docs/monorail/ 下,包括工作追踪表、领域术语、ADR,并在 CLAUDE.md 或 AGENTS.md 里写一段 ## Agent skills 说明。跑完这一步,后面的流程才有落点。
flowchart LR A"/rail-setup" --> B"/rail-align" B -->|light| C"align.md" B -->|map| D"map.md + decisions/" C ==> E"/rail-spec" D ==> E E ==> F"/rail-slice" F -.->|新会话| G"/rail-build" G --> H"task done"
对齐是入口,负责把模糊的想法磨成明确的共识。它有两种模式。light 是默认,思路清楚就直接进:Agent 一次一个问题拷问你,每个问题都给出它推荐的答案,同时维护领域文档,模糊的说法收进 CONTEXT.md 变成术语,难以回头的决定写成 ADR。决策树走完,它把共识写进 docs/monorail/<slug>/align.md,然后自动续到下一阶段,不需要你再敲命令。
有个设计细节我想说说:工作目录的 slug 由 Agent 自己定,绝不来问你,也绝不复用已有目录。理由是 slug 只是路径簿记,不该占用决策树的提问额度。这种不为流程而流程的克制,我尽量贯穿到每个 skill 里。
规格化阶段从 align.md(或已清完的 map)出发写 spec.md,但它有一道 fail-closed 的门禁:没有 align.md、没有清完的 map、本会话也没有实质性的对齐讨论,它就拒绝写,叫你回去跑 /rail-align。宁可停下来,也不从空气里发明一份薄薄的 spec。这里有个隐含的前提:spec 的源头必须是落盘的对齐产物,不是对话记忆,所以接力文档只能当补充,不能当依据。
切片把 spec.md 拆成带依赖关系的实现任务,每张任务是一份 issues/NN-*.md,垂直切分,一张任务就是一条贯穿各层的完整路径,标注 Blocked by。到这里规划链结束,下一步 build 需要新开会话。
构建实现一张未被阻塞的任务。动手前先派只读的侦察子 Agent 摸地形,代码地图、测试 seams、领域文档各一个,回来后合成 seam 提案跟你确认,然后在约定的 seams 上驱动 /rail-tdd,红绿循环,typecheck 和相关测试全绿才标 done。还支持 Batch mode,一小批小任务可以在一个会话里顺序跑,每张任务派一个全新的实现子 Agent,预检时先核对文件所有权,两张任务碰同一批文件就调整顺序或踢出批次。
会话边界
align → spec → slice 叫规划链,这三段在同一会话里自动续跑。前一阶段完成, Agent 直接读下一个 skill 的 SKILL.md 继续,不让你手动敲下一个命令。build 则反过来,永远建议 fresh session。
这个不对称是刻意的。规划链的产物都是文档,写文档不占实现需要的上下文;build 要在干净的窗口里装下整张任务、spec 和代码地形。planning 把上下文耗掉一半,再让 build 挤在后面,实现质量会明显下滑。所以宁可让规划链一气呵成,也不让实现阶段沾到前面会话的余温。
任务切片:想什么时候做,就什么时候做
把工作拆成独立任务,除了可并行的工程收益,还有个很实际的好处:实现节奏由你定 。每张任务都是一份带 Status 的文件,open、claimed、done 三态,标注了 Blocked by。想干活的时候开个新会话,照着 work-tracker 里的 Frontier 挑一张未被阻塞、编号最小的任务,claim 它,实现,标 done,提交。全程不需要重新对齐------需求在 spec 里,上下文在任务文件和领域文档里,都是落盘的东西。
所以任务可以攒着。随时可以捡一张来 build,任务在文件系统里等着,状态不会丢,也不会过期。每张任务都可以开新会话实现,前一张任务留下的上下文垃圾不会污染这一张。
本地优先:文档全部落在仓库里
Monorail 的所有工作产物都落在 docs/monorail/,任务追踪就是 work-tracker.md,spec、任务、ADR、术语表都是普通 Markdown 文件。README 里写得很直白:不依赖 GitHub/GitLab Issues。
下面是我在 tona 这个 monorepo 里实际跑出来的目录树,就是普通 Markdown 文件,没有任何特殊格式:
text
docs/monorail/
├── CONTEXT.md # 领域术语表
├── domain.md # 领域文档约定
├── work-tracker.md # 任务追踪表
├── adr/
│ ├── 001-tona-vite-optimize-deps-entries.md
│ ├── 002-theme-release-artifacts.md
│ ├── 003-plugin-css-variables.md
│ └── 004-package-entry-contract.md
├── geek-collapsed-links-popover/
│ ├── align.md # 对齐共识
│ ├── spec.md # 规格
│ └── tasks/
│ └── 01-collapsed-custom-links-popover.md
├── geek-sidebar-toggle/
├── live2d-mute/
├── reacg-restore-migration/
└── ...
本地优先换来几样实在的东西。首先,文档能 diff、能 review、能跟代码一起提交,每次改动都有据可查;其次,不绑定平台,私有仓库和内网环境照用, Agent 读本地文件比调远程 API 可靠得多。
只要仓库共享,docs/monorail 就跟着共享。领域术语、ADR、任务状态,所有成员各自的 Agent 都能读到同一份。这对真实公司项目特别重要:很多公司的代码放在内网自建的 GitLab、Gitea 上,或者业务项目压根不允许依赖 GitHub 这类外部 SaaS。mattpocock/skills 的 setup 会让你在 GitHub、Linear、本地文件三种 issue tracker 里三选一,对能用 GitHub Issues 的个人项目很顺手;可一旦你的项目上不了 GitHub、用不了 Linear,这一条路就断了。Monorail 把追踪直接建成文件,git 本身就是 issue tracker,只要能 clone 仓库,流程就能跑。也可以把 docs/monorail 加入 .gitignore,仅你可见。这些事我在真实项目里验证过的场景,也是"本地优先"最实在的理由。
代价当然也有:放弃了 Issues 的评论流、指派和看板,协作设施得靠 git 和文档自己长出来。跟 obra 在 superpowers 博客里抱怨的 slop PR 现象对照着看也很有意思:AI 生成的贡献鱼龙混杂,而文件化的流程产物至少是可审查、可追溯的。
构建:串行 & 并行
推荐单个 task 较重才考虑一个任务一个会话完成。小 spec 直接在单个会话内串行完成全部 task,推荐大多数场景都这么做,当前各主流 Agent 已经对单会话优化得很好。

如果同时开多张任务时,规矩是一个 task 一个 git worktree,同一工作目录并行是明令禁止的。两个 Agent 在同一棵工作树上改文件,冲突是必然的,一个 Agent 的中间状态还会污染另一个的上下文。
flowchart TD A"主 worktree:claim + commit" --> B"worktree A:rail/build/f-01" A --> C"worktree B:rail/build/f-02" A --> D"worktree C:rail/build/f-03" B --> E"串行合并回集成分支" C --> E D --> E E --> F"集成后删除 worktree"
先在主工作树上 claim 任务并提交,让状态持久化,再给每张任务 git worktree add 一个独立分支 rail/build/<feature>-<NN>,各开新会话实现,最后串行合并回集成分支,一次一个,冲突在主分支上解决,合完删掉 worktree。注意 rail-build 的 Batch mode 是顺序吞吐,不是并行,并行需要 worktree。
review 不进 build
rail-review 不会被 rail-build 调用,是我刻意做的取舍。
最直接的理由是自审没有意义。写完代码的当下,Agent 脑子里全是"我为什么这么写"的辩护理由,让它回头审自己的 diff,等于让厨子给自己刚出锅的菜打分------它只会把每个决定再合理化一遍。superpowers 的解法是把审查制度化:每张任务强制先审 spec 符合度、再审代码质量,最多五轮修复,这是它默认执行者品味可疑、需要制度兜底;Monorail 靠人在场,谁动手、什么时候动手、要不要审,都由你发令。把 review 塞进 build,只是把作者拆成几份子 Agent,换个姿势自我确认。
第二个理由是上下文预算。build 会话的窗口要装下任务、spec 和代码地形,塞进一整轮双轴审查------两个并行子 Agent、一份带 Blocking/Non-blocking 的报告------既拖长会话,也让"实现"和"挑错"挤在同一窗口里互相污染。这跟会话边界是同一条逻辑:一个会话只装一件事。规划链一气呵成,是因为产物都是文档,不占实现上下文;审查同理,它需要的是独立视角,不是同一窗口里的追加动作。
第三个理由最实在:fresh eyes 才有价值。review 抓的是测试管不着的东西------实现是否忠实于 spec、有没有撞上仓库规范和坏味道。这两类问题恰恰需要跟实现拉开距离才看得清。隔一阵子、开个新会话、甚至睡一觉回来再审,才能看到写代码时看不见的东西。所以 review 不进 build,不只是节奏选择,更是让"审查"保有其意义的前提。
那 build 的质量靠什么兜底?靠 TDD 红绿循环、seam 确认和 typecheck---,一条客观的反馈回路,走到绿就是绿。rail-review 是挂在旁边独立的一张网,什么时候张开、张不张,你自己定;它给完报告不 commit、不 push、不标 done,结论怎么处理还是你说了算。
最后还有一笔务实的账:superpowers 慢,很大一部分就慢在强制 review 上。每张任务先审 spec 符合度、再审代码质量,最多五轮修复循环,每一轮都是一次完整的子 Agent 会话往返,真跑起来这一块吃掉的时间相当可观。Monorail 把 review 从 build 里拆出去之后,build 会话里只剩 TDD 红绿循环和 typecheck 这条最短的反馈回路,少了双轴审查的几轮往返,单张任务明显快一截。速度不是白捡的副产品,而是取舍的直接结果:把审查从主链路挪到旁路,既保住了独立视角,又不再拖慢"实现"本身。
map 模式:雾状项目的另一条路
light 模式要求思路清楚。有些需求天生是雾状的:需求模糊、要跨好几个会话、不少问题得先调研或做原型。这时 rail-align 切到 map 模式,画一张 map.md,把"还没想清楚"的部分变成一张张带类型的决策票据。decision 是偏好权衡,research 是缺口,prototype 是讨论保真度不够;每张票据有状态、有阻塞关系,research 票据要求查一手资料并写 notes,prototype 票据要求做个一次能跑的弃用原型。雾散了、票据清完,map 就 clear,可以进 spec。
我刻意没有做 mattpocock/skills 的 research 或 prototype 这两个 skill,它们是票据类型,不是独立命令。一个 skill,两种用法,避免了 skill 数量膨胀。
老实说,我对 mattpocock/skills 的 map 模式持保留意见,light 模式在 99% 真实业务的场景下已足够。我认为 map 模式更偏向 vibe coding 或者完成一个又大又模糊的想法,我会考虑优化 map 模式。
主链路之外
rail-grill 值得单独说说,它是主链路之外可独立使用的一项技能。它的定位是随时拷问,解决小问题效果立竿见影。一次一个问题、每个问题都给出推荐答案。什么时候用?
- 想法还在萌芽、连要不要做都没定。
- 手头根本没有一个可以落盘的仓库:在空白目录里聊一个点子,不值得跑
/rail-align建出一堆文档。 - 要做一个小改动,小 bug 修复、UI 调整等。
它刻意无状态,拷问全程不写任何 docs/monorail/ 文件,不建 CONTEXT.md、不写 ADR。决策树走完,它只把共识浓缩成一份计划摘要摆给你,问一句"要不要开始实现",之后什么都不留下。这正好是 align 的另一面:align 把共识落盘、供 spec 接续,grill 把拷问当成一次性消费。我写 grill-me 博客时讲的"动手之前把需求拷问清楚",就是它的前身------在 Monorail 里被做成了独立命令,而不是对齐链的一环。
其余几个主链之外的 skill:
- rail 是路由器,告诉你当前该走哪条流程,虽然我很少用,但是有它你就不用去扒 docs 文件了。
- rail-pass 前面说过,用来搞跨会话接力,我也很少用。
- rail-debug 用来诊断疑难 bug。类似 Cursor 的 debug 模式,先构建反馈循环再诊断问题。
- rail-review 做双轴审查,一边审查编码规范,一边对照 spec 查实现是否忠实。为什么不进 build 前面说过,按需单独跑。
- rail-tdd 是红绿重构的底层参考,rail-build 内部使用。
跟 mattpocock/skills 的区别:零件箱与流水线
mattpocock/skills 不是一堆零散的小玩具,它本身也是一套完整的工程方法论。mattpocock/skills README 开头就把"为什么存在"讲得很清楚------它总结了 Agent 开发的四个典型失败模式:没按你说的做、话太多、代码跑不通、代码变成大泥球。然后逐个给出对策:grill-me / grill-with-docs 解决对齐,shared language(CONTEXT.md)解决啰嗦,tdd / diagnosing-bugs 解决代码不工作,improve-codebase-architecture / to-prd 对抗大泥球;setup-matt-pocock-skills、to-issues、triage 也各司其职。grill-me 确实可以单独用,它是这套流程里最出名的入口,但你完全可以顺着 setup → grill-with-docs → to-prd → to-issues → implement 走完整条链路。
那 Monorail 和它的区别在哪?在流程的所有权。mattpocock 的立场在 README 里写得很直白:它反对 GSD、BMAD、Spec-Kit 这类"替你拥有流程"的方案,理由是流程一旦被框架接管,你就失去控制,流程本身的 bug 还很难排。所以它的 skill 刻意做小、做独立、做可改编,README 原话是 "Hack around with them. Make them your own.",而且声称任何模型都能用。它把整套流程的零件都给你,装哪几个、怎么串,你自己定------甚至可以只装 grill-me 一个。
Monorail 走的是另一条路:把链子焊死。align 完自动续到 spec,spec 没有 align.md 就拒绝开工,规划链在同一会话里一口气跑完。一个给你自由,一个给你规范保障,两种产品观,没有对错。
还有个实质差异:mattpocock 的 setup 让你在 GitHub、Linear、本地文件三种 issue tracker 里三选一(注意是 Linear,不是 GitLab),Monorail 则是纯本地。
跟 superpowers 的区别:自动触发与显式命令
obra 的 superpowers 自称 complete software development methodology,它不是"一套打法"那么简单。brainstorming 带着 HARD-GATE,设计没获批前不许碰实现,spec 要写进 docs/superpowers/specs/ 并提交;writing-plans 把计划拆成 2-5 分钟的任务,每步给全文件路径、完整代码和验证命令,还假设执行者零上下文、品味可疑;subagent-driven-development 每张任务派一个全新的实现子 Agent,做完先审 spec 符合度再审代码质量,最多五轮修复循环,进度记在 ledger 里。ledger 的诞生理由跟 Monorail 的会话边界是同一个问题:上下文压缩后控制器会丢进度,甚至把已完成的任务重派一遍。就工程纪律而言,两家是同等级的硬。
真正的分岔在触发方式。superpowers 是自动触发,模型看到任务就自己进流程,README 原话是 mandatory workflows, not suggestions,你装好它之后要做的只是信任它。它甚至带 hooks------session-start 钩子在每次会话开始就把流程塞进 Agent 的上下文,保证不依赖你发令。Monorail 是显式命令,user-invoked 的 skill 都要你亲自敲;规划链虽然自动续跑,但每一段的入口都在你手里。
这不是偷懒,是我刻意要的掌控感:
- 每个阶段前你都看得见产物。 align.md 写完了,你可以读一遍再放行;spec.md 想改,改的是普通文件;任务切片的粒度不满意,改完再 build。
- build 动手前有 seam 提案确认。 侦察子 Agent 摸完地形,会把"我要在哪些接缝上动手"摆给你看,你点头它才开工。superpowers 的子 Agent 拿到计划就直接执行,没有这个中间确认。
- review 按需跑。 rail-review 双轴审查刻意不进 build 流程,你想什么时候审、审不审,自己定;superpowers 的每任务双阶段审查是强制的,还有收尾的全分支审查。
- 连续推进不是默认动作。 规划链(align → spec → slice)一气呵成,是因为你发令之后它自动续跑;不想要三连跳的人,随时可以在一段结束后叫停。
产物的去向也不一样。superpowers 的产出是一份带完整代码的实施计划,计划本身就是给执行者的全部上下文;Monorail 的产出是 align.md、spec.md、tasks 文件,build 时再派侦察子 Agent 摸地形。另外 superpowers 覆盖了 Claude Code、Cursor、Codex、Gemini、Kimi、OpenCode、Pi 一长串 harness,还带 hooks 和可视化伴侣,Monorail 则安分地待在 skills 生态里,一条 npx 命令装完。一个是跨平台的流程平台,一个是本地优先的小流程包。如果你的目标是让 Agent 最大限度地自主干活,superpowers 很强;如果你更想在每一步都保持介入权、看清楚再放行,Monorail 的显式命令更合手。
局限
掌控感是双刃剑,关键步骤都要你发令,也意味着你得在场。
Monorail 想把"跟 AI 协作做工程"从对话重新拉回工程的坐标系:有产物、有门禁、有隔离、有边界,值得试一下。