这不是一份"让 AI 帮你写代码"的教程。这是一套把决策、词汇与流程从聊天框里搬出来、落成文件的工作方法——写给已经用过 AI 写代码、却发现它时而惊艳时而失控的人。
为什么"会写 prompt"远远不够——这套技能集解决的真问题。
大多数人对 AI 编程的第一印象是:快。第二印象是:它怎么又自作主张了?
把"帮我实现这个登录功能"丢给一个全新的 agent,常见结局是它边写边重新设计你的方案——因为它手里只有一句话,没有被你否决过的三个备选、没有"我们必须兼容旧 token"这条约束、没有你项目里管"取消"叫 void 而不是 cancel 的惯例。它只能猜,而猜错了你也往往在三天后才发现。
Matt Pocock 的这套技能集(以下简称"这套技能")给出的答案可以概括为一句话:
人负责决策,agent 负责执行,文件负责记忆。聊天框里什么都不会留下,文件才会。
具体拆开来是三个心智模型,后面所有技能都是它们的推论:
你在一场长对话里敲定的每个决定,都活在那个即将被清空的窗口里。所以要有 spec(规格)——一份"已做决策的记录",让全新会话不用你重新解释就能接手。
指着一份纯词汇参考说"开始吧",agent 会自己编一个流程——重探你已探明的代码、跑很久才问你。所以"参考"和"司机"必须分清:有些 skill 只给词,有些 skill 负责开车。
问"这次改动安全吗"该得到的不是一段回答,而是一份带引用的文件;分工作该得到的不是聊天里的编号步骤,而是追踪器上一张带阻塞边的票。能留存的,才是交付物。
模型会忘记 session 中段的挣扎、会凭摘要描述别的 skill、会过度触发正式流程。每个 skill 的"验收清单"就是为此准备的:别信它说"完成了",对照清单验。
二十二个 skill 不是二十二个工具,是一张分工图。先看懂图,再学工具。
整条技能体系是一张手绘的地图( literally——路由 skill ask-matt 就是它的人肉查询版)。结构如下:
别人发来的 bug 报文、功能请求、不请自来的 PR。与自己规划的工作是两条平行车道,终点相同:ready-for-agent + 一份 agent brief。
装不进一个 session 的工程,先画"决策地图"(decision tickets),逐个清空后再汇回主链的 to-spec。
两个"参考"而非"司机":前者给模块形状的七个词(module / interface / depth / seam / adapter / leverage / locality),后者给领域的词(GLOSSARY.md + ADR)。别的 skill 在"词"出问题时自动拉它们进来。
三个"原语":一轮一问的访谈法、测试先行循环、给 agent 写指令的文风。它们被多个 skill 复用,你也可以单独用。
| Skill | 一句话职责 | 什么时候想起它 |
|---|---|---|
prototype | 回答一个设计问题的用完即弃代码 | 聊不决的问题:"这状态机感觉对吗?" |
research | 读一手来源,留一份带引用的 Markdown | 决策在等一个外部事实 |
wizard | 生成交互式 bash 脚本带人走完手动流程 | 撞上只有你能点的 dashboard |
diagnosing-bugs | 六相诊断:先造红循环,再谈理论 | 一眼解不了的硬 bug、间歇 flake |
improve-codebase-architecture | 周期性扫描"浅模块→深模块"的加深机会 | 每隔几天的结构保养 |
handoff | 把工作搬进/搬出 session 的标准交接 | session 太大、要换 harness、同事接手 |
ask-matt 是这张地图的查询接口,描述你的处境,它告诉你下一步输入什么。但记住它有两个已知 bug:会报"技能未安装"(多数 skill 带 disable-model-invocation,harness 不把它们的说明注进上下文——它们装着的,直接输斜杠命令);会凭一行摘要描述别的 skill(要它先打开那个 SKILL.md 再回答)。每个仓库跑一次。它是其余一切技能默认你做过的事。
setup-matt-pocock-skills 回答三个问题:issue 住在哪、triage 标签叫什么、域文档放哪,答案写成 docs/agents/ 下的 markdown。核心设计思想值得单独强调:
docs/agents/ 里的几个 markdown。skill 运行时才读这些文件——所以换 tracker 永远改文件、永远不要改 skill 本身。这就是它不绑死 GitHub 的原因。docs/agents/issue-tracker.md — tracker 选择 + 工作流描述(含 wayfinder 的 "Wayfinding operations" 一节)docs/agents/domain.md — 域文档布局docs/agents/triage-labels.md — 仅当装了 triageCLAUDE.md 或 AGENTS.md 里的 ## Agent skills 块 — 指向上面每个文件| 选项 | 需求 | 备注 |
|---|---|---|
| GitHub / GitLab | gh / glab CLI | 出厂模板,开箱即用 |
| Local markdown | 什么都不需要,连 remote 都不要 | 完整选项而非退路;与 GitHub 是替代品,别同时用 |
| Other | 你写一段工作流描述 | Jira / Linear / Azure DevOps / Beads 全走这条路;已有 Jira-over-MCP 等实例 |
triage-labels.md 是"哪个字符串对应哪个角色"的映射。tracker 已用规范名 = 恒等表,无需配置。但 wayfinder 的 wayfinder:map / wayfinder:<type> 标签它也不建——GitHub 上首次跑 wayfinder 前手工创建,否则 gh issue create --label 直接报错。grilling 家族、GLOSSARY.md 与 ADR——以及那两道最容易搞混的"写杠"。
所有 skill 的源头是一个共同原语:grilling——一轮问题、等你回答、再下一轮。套在它外面的三个 skill 各管一段:
grill-with-docs 与其他 grilling skill 的全部差别在于:它是 stateful 的——术语敲定那一刻就写进 GLOSSARY.md,决策过三道杠就落成一条 ADR。别的 grilling 把 session 留在你脑子里,它把文件留在磁盘上。
GLOSSARY.md | docs/adr/ | |
|---|---|---|
| 装什么 | 术语:一物是什么,一两句;弃用同义词列在 _Avoid_ 下 | 一个决策:背景、选择、理由,一到三句 |
| 写杠 | 一个含糊词被敲定 | 三道全过:难逆转 + 无背景会意外 + 真实取舍 |
| 时机 | 内联,敲定那一刻 | 被提议,不是默认 |
| 永不装 | 实现细节、spec、草稿、通用编程概念 | 本场每个选择的日记 |
这套体系给模块设计强制了一套语言:module(任何"接口+实现"的东西,与规模无关)、interface(签名 + 不变量 + 顺序约束 + 错误模式 + 配置 + 性能特征)、depth(每学一个单位接口能行使多少行为)、seam(不改此处就能改变行为的地方——Feathers 的术语)、adapter(接缝处满足接口的具体角色)、leverage(调用方得到什么)、locality(维护者得到什么)。
同时禁掉四个松散词:component、service、API、boundary。这条纪律看着形式主义,实际效果立竿见影——当讨论里有人说"这里该拆个组件",你可以追问"拆出来的接口是什么、深度够吗、过没过删除测试",争论就从口味变成可判定的题。
to-spec 与 to-tickets——以及那个被违反最多的规则:竖切。
规划阶段只有两个 skill,但分工极清:
到你调用它时,决策已经做完。它综合对话、代码库、GLOSSARY.md 和 ADR,用你自己的词汇写下"已决定的事"。如果 spec 里出现了你没说过的东西,那是缺陷。它存在的理由:上下文窗口会结束。
每张票是一发 tracer bullet:窄而完整、穿过 schema→API→UI→tests 每一层,落地即可独立演示,并声明阻塞边(哪些票必须先完成)。
按层切(先全部 schema、再全部 API)是最直觉的分法,也是这套体系明确反对的分法:
另外,装得进一个上下文窗口的改动根本不该走 spec+tickets——grilling 之后直接 /implement。spec 只在跨 session 的工作上才值回成本。
implement 的"清空→一票→提交→再清空",与 implement-spec 的并行编排。
implement 的立身之本:绝不重新打开计划。没有访谈、没有澄清轮、没有"换个方案怎么样"——上游敲定什么是输入,它的全部工作是把输入变成一个 commit。这正是它和对全新 agent 说"build this"的区别:后者常边做边重新设计。
一次运行五步:① 读票/spec、定接缝 → ② 在预先敲定的接缝上驱动 tdd(一个 red-green 切片接一个)→ ③ 频繁 typecheck、随跑单测 → ④ 收尾完整测试套件跑一遍 → ⑤ 跑 code-review,提交到当前分支。
清空上下文 → 实现一张 → 提交 → 再清空。每张 tracer-bullet 票按单窗口裁好,前一张的上下文直接丢弃。
它提交到你所在的分支——不建分支、不问。确认 HEAD 在你想要的分支上再开始。
没有完成步骤:跑完停在 commit,不关 ticket、不勾验收框、不处理 review 发现。依赖链上这最要命——frontier 只看"阻塞者全关闭",你不关票就没有任何票 visibly 解锁。
一张非平凡票烧过 10 万 token 是常态(探索 + 每接缝一轮 red-green + 全量测试 + review)。反复超限的票,解法在上游:拆票,不是调高档位。
整张 spec 一次落地时,调度者从"你"换成一个编排 agent:frontier 上的票全部同时开工,每个 implementer 在自己的 git worktree 里构建,汇入一条集成分支(fast-forward 合并),最后统一 code-review 并 resolve 票。
tdd 是 reference:装着"什么是好测试"的规则,跑 session 的是 implement(或你)。要点三则:接缝在任何代码存在之前商定(未确认的接缝上它拒绝写测试——没人商定,运行就静默退化成"直接写码");三个让套件一文不值的反模式要会认——实现耦合(重命名内部函数测试就红)、重言式(期望值用代码同款算法算出)、横切(一批测试先于任何实现落地);mocks 只用于系统边界,绝不 mock 自己的模块。
code-review 拒绝混合裁决,pr 把直觉变成可反驳的明示。
它评审 <fixed-point>...HEAD 的 diff,分两条轴、各由一个独立 sub-agent 跑:Standards(构建得对不对——仓库自己的规范 + Fowler 十二 smell 基线)与 Spec(构建的是不是对的东西——来源 issue/spec 逐条对照)。报告分两个块,每轴各给一个最差项,拒绝评总冠军。
pr 只塑形正文、不开 PR:① Summary——是图不是段落,从六种视图(伪代码、调用树、组件树、文件树、Mermaid、shaped diff)里挑最小的讲清形状;② Evidence——前后对照(截图,或"曾失败现通过"的确切测试),"tests are green" 是主张不是证据;③ Merge Danger——一扇门(one-way:破坏性迁移、对外发出、公开 API 移除)还是两扇门,加爆炸半径。
retro 修环境不修代码;improve-codebase-architecture 修代码不修环境。
在"比本该更难"的 session 末尾跑 retro。它一行代码都不修——被 ship 的 bug、找了一万年的文件、reviewer 漏掉的规则,它一个都不直接修;它问"仓库里什么允许了它发生",然后提议检查、指针或标准。只提议,你选中之前什么都不变(human-in-the-loop 是刻意的:判断什么值得变成永久检查需要人)。
机械性错误 → 会失败的 check(lint/类型/测试/CI);真正的判断题 → CODING_STANDARDS.md 里给 reviewer 的规则。标准属于 reviewer 不属于 implementer——实现 agent 上下文压力最大,reviewer 只拿 diff、有余地应用新规则。
"agent 反复犯错就往 CLAUDE.md 加一行"——通常不要。CLAUDE.md 每行都加载进每个 session、稀释其他内容、随代码过期。AGENTS.md / CLAUDE.md 只留导航指针。
它不审计自己上月提议的规则——只能删 prose,看不见某条 lint 是否已 fire 太频。在好代码上频繁 fire 的规则 = 该删的信号,修剪归你。
AGENTS.md 随时间变短而不是变长;重复的错误变成会失败的 check;每个候选能指回 session 里的一个具体时刻(指不回去的 = 编的,丢弃)。
每隔几天跑一次,扫描"浅模块可变深"的地方。两道过滤器挡掉泛泛建议:删除测试(删掉这个模块,复杂度退到更小接口后 = 配得一张卡;摊回调用方 = 不配)+ 聚焦常变路径(没人碰的代码里的加深永远不回本)。产出是一份 HTML 报告 + 你选中一张后的 grilling——产出决策,不是 diff,重构走正常构建流。
Speculative 徽章,那就是它"没找到"的表达方式。与自己规划的工作是两条平行车道,终点相同。
triage 只处理你没创建过的 issue:原始 bug 报文、外来功能请求、不请自来的外部 PR。它给类别(bug / enhancement)和五个状态(needs-triage / needs-info / ready-for-agent / ready-for-human / wontfix)的建议,附带理由并停下来等你。
bug 按 reporter 步骤复现;PR checkout 跑测试。三结果:Confirmed / 复现失败 / 细节不够(最强的 needs-info 信号)。同趟车跑冗余查 + 前次拒绝查,命中即 wontfix。
写类型、签名、行为契约,永不写文件路径和行号(票可能躺几周,代码一直在变)。brief 贴上后,原报文只是上下文。
每概念一文件(非每 issue 一文件),按概念匹配——"night theme" 命中 dark-mode.md。被拒请求回来时,它引用旧理由问你还要不要坚持,而不是从头再吵。
to-tickets 的票已自动贴 ready-for-agent,别再 triage;bulk 跑 backlog 时它只读正文不读评论——明说"每个 issue 必须读评论"。
装不进一个 session 的工程,先绘图,再逐个清空。
wayfinder 的触发条件极窄:工程大于一个 session,且路线看不清。分界是 session 数而非项目大小——一场对话装得下就 grilling,装不下才 wayfinder。greenfield 不是前提:legacy 的雾常是"这里已经什么是真的"。
| 类型 | 模式 | 何时用 | 由谁 resolve |
|---|---|---|---|
grilling | HITL | 默认;能聊透的问题 | grilling + domain-modeling,新 session |
prototype | HITL | "该长什么样/该怎么表现",聊不决 | prototype,ticket 链接工件 |
research | AFK | 外部事实挡着决策 | research subagent 并行跑(唯一可并行的类型) |
task | Either | 无决策可定但手工劳动挡路 | agent 能独立做就独立做 |
wayfinder:task 当作类型标错。/to-spec #<map_issue> 收拢——直接灌进 implement 会丢掉链接细节。四个"随时取用"的 standalone,各自守着一条清晰的边界。
"用完即弃"约束的是写法(无测试/无错误处理/无抽象),不是销毁承诺。两个幸存者:答案进 main,原型进 prototype/<name> 分支永不合并、issue 留指针——下一个接手的人要的是能重跑的证据,不是 prose 摘要。逻辑分支产出单个可双击分享的 HTML;视觉分支产出结构互不同意的多变体。开始加固它 = 停止原型。
答案不落进对话,落进一份每条声明带链接的文件。分界线是保质期:事实(短寿)→ research;决策(耐久)→ grilling / grill-with-docs。你唯一的质检是引用——随机跟两三条,落在"关于它的转述"而非"它本身" = 这场失败。委托后盯后台任务列表:恰好一个新任务,多出来的分身停掉(已知嵌套 bug,单任务烧过 45 万 token)。
agent 撞上只有你能点的 dashboard 时,它写脚本、你本机跑——key 盲输直写 .env/gh secret,不过模型上下文。先确认有序 stage 清单再生成;没有后退键,答错 Ctrl-C 重跑(已存的值回显为默认值)。比写进 README 强:某一步失效时它显眼地失败,而不是安静地错。
session 太大、换 harness、同事接手、mid-phase 分支线——该搬的不是聊天记录而是"决策 + 指针"。它是把上下文当一等公民搬运的纪律,进图出图两侧都靠它。
diagnosing-bugs 的铁律:没有红的循环,就没有理论。
给定 bug report,coding agent 的默认动作是读代码然后猜。diagnosing-bugs 把这条路堵死:在一条"紧的反馈环"存在之前,不允许形成任何理论。紧 = 秒级、确定性、断言的是你那个确切症状、agent 无需你就能跑。
按"会在什么时候咬你"排序。建议打印贴墙。
| 什么时候 | 坑 | 对策 |
|---|---|---|
| 路由时 | ask-matt 报"技能未安装" | 多数是 disable-model-invocation 假象。装着的——直接输斜杠命令,或查 .claude-plugin/plugin.json |
| 路由时 | ask-matt 凭摘要描述别的 skill | 要它先打开那个 SKILL.md 再回答;router 与 SKILL.md 冲突时 SKILL.md 是对的 |
| 访谈中 | grilling 跑完 GLOSSARY.md 没变 | domain-modeling 被跳过了。按名字把它与别的 skill 并列调用 |
| 访谈中 | codebase-design 被指成任务,烧 10 万 token | 它是参考不是司机。跑司机 skill,把它当词汇 |
| 写词汇表 | GLOSSARY.md 膨胀成运行中的 spec | 「make my GLOSSARY.md more concise and remove any implementation details」;先精简再谈拆分 |
| 拆票 | 按层横切 | 逐票问"做完我能演示什么";验收标准伸手到别的票 = 横切信号 |
| 拆票 | 三行改动十二张票 | quiz 环节要求合并;装得进单窗口根本不该拆 |
| spec → tickets | spec 读取一直截断 | 两者之间不要 clear / compact,同一窗口跑完 |
| 构建 | implement 提交到了错误的分支 | 它不建分支不问。动手前确认 HEAD——这是唯一要人工检查的事 |
| 构建 | 跑完票还开着,frontier 饿死 | 它没有完成步骤。票和验收框自己关——依赖链上最要命 |
| 并行构建 | 两 implementer 撞文件 / 起名分歧 | 补一条阻塞边让它们串行,或探索笔记写死确切名称 |
| 并行构建 | blocked 票在 blocker 已合并后仍不开工 | GitHub 计数只在关闭时下降;让编排者跟踪并入集成分支的票 |
| 评审 | 审自己刚写的代码 = 确认偏误 | 干净 session 里对 fixed point 跑 code-review |
| 评审 | code-review 看不到改动 | 三点式 diff 不含未提交内容。先 commit,再审 |
| 评审 | 每次跑都发现新问题,永不收敛 | 当线索清单用:只处理有规则引用的,然后停 |
| 写 PR | door call 是自评 | 对"两扇门、小爆炸半径"最警惕;给 agent ticket/spec,立仓库级单行道清单 |
| 复盘 | agent 反复犯同一个错就想加 CLAUDE.md | 机械错误 → 会失败的 check;判断题 → reviewer 的 standards。CLAUDE.md 只留导航指针 |
| 复盘 | lint 规则无限堆积 | retro 不审计旧规则。好代码上频繁 fire = 删 |
| 外来报文 | 给 to-tickets 的票又跑 triage | 发布时已 ready-for-agent。两车道只在终点汇合 |
| 外来报文 | bulk 跑 backlog 漏看评论 | 明说"每个 issue 必须读评论"——廉价列表只回正文 |
| 大工程 | agent 在地图里写生产代码 | 读非你绘图的地图的 Notes;可疑的 wayfinder:task 当类型标错 |
| 调试 | 理论先于复现 | 理论先到 = skill 没在跑;造不出环就停下来要权限 |
从 setup 到第一个 retro 的最短路径。
/setup-matt-pocock-skills。确认 docs/agents/ 三个文件和 CLAUDE.md/AGENTS.md 的指针块都在——以及它们在你的 harness 实际读的那个文件里。/grill-with-docs 敲定 → 直接 /implement。故意跳过 spec 和 tickets,体会「什么尺寸才值得拆」的那条分界线。/retro,挑一条候选落地(比如一个会失败的 check)。顺手跑一次 /improve-codebase-architecture,感受"调查不改码"的节奏。/ask-matt;外来报文进 triage;硬 bug 进 diagnosing-bugs;每隔几天 wayfinder/improve-codebase-architecture 做保养。每周把第 13 章清单过一遍。最后一条经验:这套技能集最强的部分不是任何单个 skill,而是它背后的态度——把"AI 写代码"当成一门需要流程、词汇和纪律的工程学科。工具会过时(resolving-merge-conflicts 已因模型进步归档),纪律不会。