TIP
mattpocock/skills 是由 TypeScript 专家 Matt Pocock 构建的一套 AI 编码技能集,GitHub 仓库:github.com/mattpocock/skills。如果你用过 Claude Code、Codex 等工具却感觉输出质量飘忽不定,这套 Skills 正是为你准备的。
项目简介
mattpocock/skills 是一组用于 AI 编程工具的「工程方法论技能包」。它的核心出发点很简单:AI 编程工具很快,但不等于 AI 编程工具靠谱。
Matt Pocock 在大量实践中发现,AI 编程有四个高频失败模式:
- 需求不对齐:你以为 AI 理解了,其实它跑偏了
- 输出太冗余:AI 用 20 个词表达 1 个词能说清楚的事
- 代码不 work:没有反馈循环,AI 在黑箱里蒙着写
- 架构烂得快:AI 加速了开发,也加速了软件熵增
这四个问题不是工具的 bug,而是方法论的缺失。mattpocock/skills 对症下药,把 decades 工程经验压缩成一组可组合的技能(Skills),让 AI 在任何模型上都遵循同样的工程纪律。
难度 / 时长 / 收获
难度:入门级 — 不需要 TDD 经验,只要会用命令行和 AI 编程工具
时长:约 30 分钟完整走一遍流程
收获:建立一套从需求对齐 → 测试驱动 → 结构化调试 → 架构反思的完整工作流
目标读者画像
- 1-5 年经验的后端 / 全栈开发者
- 已经用上 Claude Code、Codex 或类似 AI 编程工具
- 感觉 AI 生成的代码「能用但不稳定」,想建立可控的开发节奏
- 对 TDD 有兴趣但一直没找到合适的切入点
核心依赖与环境
| 依赖 | 最低版本 | 说明 |
|---|---|---|
| Node.js | 18+ | Skills 以 npx 方式分发 |
| pnpm / npm | 任意稳定版 | 包管理器,二选一即可 |
| AI 编程工具 | 任意支持 Skills 的版本 | Claude Code、Codex 等 |
WARNING
mattpocock/skills 通过 /slash 命令调用,AI 工具必须支持技能(Skills)机制。确认你的工具已启用 Skills 功能后再继续。
完整项目结构树
skills/
├── CLAUDE.md # 技能目录规范说明
├── README.md # 总览与使用文档
├── skills/
│ ├── engineering/
│ │ ├── diagnose/
│ │ │ └── SKILL.md # 结构化调试流程
│ │ ├── grill-with-docs/
│ │ │ └── SKILL.md # 附文档的深度访谈
│ │ ├── improve-codebase-architecture/
│ │ │ └── SKILL.md # 架构改进诊断
│ │ ├── setup-matt-pocock-skills/
│ │ │ └── SKILL.md # 初始化配置入口
│ │ ├── tdd/
│ │ │ ├── SKILL.md # TDD 垂直切片工作流
│ │ │ ├── tests.md # 好 / 坏测试示例
│ │ │ ├── mocking.md # Mock 最佳实践
│ │ │ ├── refactoring.md # 重构时机判断
│ │ │ ├── deep-modules.md # 深模块设计原则
│ │ │ └── interface-design.md # 可测试接口设计
│ │ ├── to-issues/
│ │ │ └── SKILL.md # 需求拆分到 GitHub Issues
│ │ ├── to-prd/
│ │ │ └── SKILL.md # PRD 生成
│ │ ├── triage/
│ │ │ └── SKILL.md # Issue 分诊状态机
│ │ └── zoom-out/
│ │ └── SKILL.md # 代码全局视角解读
│ ├── productivity/
│ │ ├── caveman/
│ │ │ └── SKILL.md # 压缩通信模式,省 75% token
│ │ ├── grill-me/
│ │ │ └── SKILL.md # 需求深度访谈
│ │ └── write-a-skill/
│ │ └── SKILL.md # 自定义技能编写指南
│ └── misc/
│ ├── git-guardrails-claude-code/
│ │ └── SKILL.md # Git 安全护栏
│ └── scaffold-exercises/
│ └── SKILL.md # 练习目录脚手架
└── .claude-plugin/
└── plugin.json # 插件元数据
手把手步骤
第一步:安装 mattpocock Skills
在任意支持 Skills 的 AI 编程工具中,运行以下命令完成安装:
npx skills@latest add mattpocock/skills
安装脚本会引导你选择要激活的技能,以及这些技能绑定到哪个 AI 工具。关键一步:确认选择 /setup-matt-pocock-skills,这是后续所有技能的初始化入口。
TIP
安装过程无需 sudo,也不需要修改项目代码。Skills 存储在你的 AI 工具配置目录中,与当前工作区完全隔离。
第二步:初始化配置
安装完成后,在 AI 编程工具中执行:
/setup-matt-pocock-skills
这个 Skill 会依次问你:
- Issue Tracker:选择你用哪个工具管理 Issues(GitHub / Linear / 本地文件)
- Triage Labels:给 Issue 打标签时用哪些词汇(
/triage技能会用到) - 文档保存路径:生成的 ADR 和文档放在哪里
完成配置后,会在项目根目录生成一个 CONTEXT.md,作为 AI 与你之间的「共享语言词典」。这个文件非常重要——它统一了项目中术语的使用方式,AI 之后所有命名和注释都会基于它。
第三步:用 /grill-me 对齐需求
当你有一个新需求或设计方案想交给 AI 做时,不要直接开干。先执行:
/grill-me
AI 会逐一向你提问,穷举决策树的每个分支。比如你打算「给支付模块加退款功能」,AI 会追问:
- 退款是全额还是部分?
- 退款的触发条件是什么(用户主动 / 风控自动 / 客服手动)?
- 退款后库存如何处理?
- 退款日志要不要持久化?
每个问题都会给你推荐答案,你只需要确认或纠正。这个过程像一场结构化访谈,确保 AI 真正理解你要做什么,而不是按字面意思跑偏。
TIP
/grill-me 适合非代码场景。如果你在已有代码库的项目中,可以用 /grill-with-docs——它做同样的访谈,但会顺便更新 CONTEXT.md 和 ADRs(架构决策记录)。
第四步:用 /tdd 做垂直切片测试驱动
需求对齐后,进入开发阶段。这里是 mattpocock/skills 最核心的部分——禁止水平切片。
什么是水平切片?先写完全部测试,再写完全部代码。这是 TDD 误解的重灾区,AI 特别容易这么干,结果是测试「测试的是想象出来的行为,而不是真实行为」。
正确做法:一次只做一个垂直切片。
RED: 写一个测试,描述第一个行为 → 测试失败
GREEN: 写最少的代码让测试通过 → 测试通过
REFACTOR: 重构(可选)
重复这个循环。AI 每写完一个测试,就已经「见过」了那段实现代码,因此它测的是真实行为,不是预期行为。
来看一个具体例子,假设我们要实现一个购物车结算功能:
// 第一轮:只测「购物车可以添加商品」
import { describe, it, expect } from 'vitest';
import { Cart } from './cart';
describe('Cart', () => {
it('allows adding an item', () => {
const cart = new Cart();
cart.addItem({ id: 'book-1', name: 'TypeScript 入门', price: 59 });
expect(cart.items).toHaveLength(1);
});
});
// cart.ts — 最少实现让测试通过
export interface CartItem {
id: string;
name: string;
price: number;
}
export class Cart {
items: CartItem[] = [];
addItem(item: CartItem) {
this.items.push(item);
}
}
// 第二轮:测「购物车可以计算总价」
it('calculates total price', () => {
const cart = new Cart();
cart.addItem({ id: 'book-1', name: 'TypeScript 入门', price: 59 });
cart.addItem({ id: 'book-2', name: 'React 实战', price: 79 });
expect(cart.totalPrice()).toBe(138);
});
// cart.ts — 添加 totalPrice 方法
export class Cart {
items: CartItem[] = [];
addItem(item: CartItem) {
this.items.push(item);
}
totalPrice(): number {
return this.items.reduce((sum, item) => sum + item.price, 0);
}
}
每一轮都是:测试失败 → 最少代码通过 → 下一轮。这就是垂直切片的核心节奏。
WARNING
/tdd 禁止「一次性写完所有测试再一次性写完所有代码」。违反这条规则,测试会变得对重构不敏感——重构后测试全红了,行为其实没变。
第五步:用 /diagnose 做结构化调试
当代码出了问题,不要直接让 AI「帮我修 bug」。先建立反馈循环,执行:
/diagnose
/diagnose 强制 AI 走完六阶段调试循环:
| 阶段 | 核心动作 |
|---|---|
| 1. Build a feedback loop | 找到可重复的失败信号 |
| 2. Reproduce | 让 bug 稳定复现 |
| 3. Hypothesise | 生成 3-5 个可证伪的假设 |
| 4. Instrument | 一次只改一个变量,定位根因 |
| 5. Fix + regression test | 先写回归测试,再动手修复 |
| 6. Cleanup + post-mortem | 清理调试日志,总结预防方案 |
为什么这个流程重要? 因为 AI 最常见的调试方式是「猜着改,改完看结果,不对再猜」。这在没有反馈循环时等于在黑暗中扔飞镖。/diagnose 把调试变成一门工程学科,不是玄学。
一个典型场景——假设你的支付接口突然报 500 错误:
// 阶段 1:构建反馈循环 —— 写一个失败测试定位到具体接口
import { describe, it, expect } from 'vitest';
import { createHonoServer } from './server';
import fetch from 'node-fetch';
describe('Payment API', () => {
it('returns 200 for valid checkout', async () => {
const app = createHonoServer();
const response = await fetch('http://localhost:3000/api/checkout', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
items: [{ id: 'book-1', quantity: 1 }],
userId: 'user-123',
}),
});
expect(response.status).toBe(200); // 目前失败,实际返回 500
});
});
阶段 3 会生成假设列表:
- 如果是「库存服务超时导致未捕获异常」,那么 mock 库存服务返回成功会消除 500
- 如果是「数据库事务未提交」,那么检查 transaction.commit() 调用会发现问题
- 如果是「支付网关返回格式解析错误」,那么验证网关 mock 数据格式会复现问题
AI 会一次验证一个假设,而不是把改动全堆在一起。
第六步:用 /write-a-skill 构建自定义技能
当你在某个项目里积累了一套专属工作流,可以把它封装成 Skill,让 AI 在这个项目中随时调用:
/write-a-skill
AI 会依次问你:
- 这个 Skill 覆盖哪个领域?
- 具体使用场景有哪些?
- 需要附带脚本还是纯指令?
- 有没有参考材料?
然后生成标准结构:
my-custom-skill/
├── SKILL.md # 主指令文件(必选)
├── REFERENCE.md # 详细文档(内容超过 100 行时拆分)
├── EXAMPLES.md # 使用示例
└── scripts/
└── helper.ts # 工具脚本(可选)
SKILL.md 的 description 字段是 AI 感知这个 Skill 的唯一入口,格式有严格要求:
---
name: my-custom-skill
description: 从 JSON Schema 生成类型安全的 API 客户端,并注入 Mock 数据。
Use when user mentions "API client", "generate types", or "mock data".
---
description 的第一句说「它做什么」,第二句说「在什么场景触发」,用触发词引导 AI 自动加载。
TIP
description 最大 1024 字符,要写得精确。泛泛的描述(如「帮助处理文档」)无法让 AI 区分这个 Skill 和其他 Skill。
常见问题排查
1. AI 不执行测试直接写代码
现象:你调用 /tdd,但 AI 直接跳到实现,跳过 RED 阶段。
排查:
- 确认
CONTEXT.md中已定义项目的测试框架和测试约定 - 在
/tdd开始时明确说「只写一个测试,不要写其他代码」 - 如果 AI 仍然跳过,手动在对话中输入「先写一个失败的测试」引导它回到 RED
根因:AI 对 TDD 概念的字面理解——它认为「写了测试」就算 TDD,不理解「测试失败」本身是信号。
2. 水平切片陷阱——一次写完全部测试
现象:AI 在 /tdd 中一次性生成 10 个测试文件,然后一次性写完所有实现。
排查:
- 直接干预:告诉 AI「只写第一个测试,然后实现它」
- 在
CONTEXT.md中加入反模式警告:「禁止水平切片,每次只做一个垂直切片」
根因:AI 喜欢「一次性搞定」的幻觉,水平切片让它感觉完整但实际产出脆弱。
3. 调试循环无反馈信号
现象:你调用 /diagnose,但 AI 只是反复改代码,没有建立可重复的失败信号。
排查:
- Phase 1 没有通过,不要进 Phase 2。明确告诉 AI:「还没有可重复的失败信号,继续构建反馈循环」
- 尝试用
node-fetch+ 真实 HTTP 请求构建端到端信号,而不是 mock 掉整个模块
根因:反馈循环才是调试的核心,没有它,所有后续动作都是盲动。
4. 技能描述失效——Skill 没有被自动触发
现象:你写了自定义 Skill,但 AI 不加载它。
排查:
- 检查
plugin.json中是否已注册该 Skill - 确认 description 中包含触发词(用户实际会说的词汇)
- 确认 SKILL.md 的
name和description格式符合要求(YAML frontmatter)
根因:Skills 的加载依赖 description 中的关键词匹配,描述不精确就无法触发。
5. /grill-me 访谈变成单向汇报
现象:/grill-me 执行时 AI 只在接收你的信息,没有主动追问。
排查:
- AI 追问时才说明它进入了访谈模式——继续回答,不要中断
- 如果 AI 沉默超过 3 轮,手动说「继续追问,我还有更多信息」
- 根源通常是 AI 觉得「已经理解」,实际只是字面理解
根因:AI 倾向于快速收敛到「看起来理解了」的状态,而不是穷举所有分支。
6. CONTEXT.md 过大导致 token 爆炸
现象:随着项目推进,CONTEXT.md 越来越大,AI 开始出现上下文溢出或响应变慢。
排查:
- 定期重构
CONTEXT.md,把「已稳定的通用术语」保留,把「临时决策记录」移到docs/adr/目录 /improve-codebase-architecture可以帮助识别哪些内容应该从CONTEXT.md中提取出去
根因:CONTEXT.md 是动态增长的文件,不做维护就会变成第二个 monorepo。
扩展阅读 / 进阶方向
方法论延伸:Matt Pocock 本人是 TypeScript 类型体操的倡导者,他的 Total TypeScript 课程是理解类型驱动开发的绝佳补充。
从 TDD 到架构改进:当你的代码库经过几轮 TDD 重构后,可以用 /improve-codebase-architecture 做架构诊断。它基于 CONTEXT.md 中的领域语言和 docs/adr/ 中的决策记录,识别「浅模块」(接口复杂但功能少)和重构机会。
自定义技能生态:mattpocock/skills 的设计哲学是「小而可组合」。你不一定要用它提供的全部技能——可以只装 /tdd 和 /diagnose,在日常开发中渐进引入。社区中也有其他开发者基于这个框架构建的技能集,值得关注。