一句话需求:"以最近热门电影牛来主角为模型,threejs 跑酷游戏,网页能玩,无限地图,参照神庙逃亡,有道具有钻石,基础 UI、得分、结算。"
我没让 Claude Code 直接写。先用
grill-me技能被审问了 10 轮,然后一次成型,没有一次方向性返工。这篇记录 grill-me 的安装、组成、三个脚本的真实用法,以及这次实战里验证出的技巧和坑。

1. 它解决什么问题
常见失败模式:用户给一句话需求("做个跑酷游戏,无限地图,有道具"),Agent 直接开始写代码,脑补掉所有没说清的地方,写完发现方向错了。
grill-me 强行插入一个审问阶段。它的三条纪律来自 Matt Pocock 的原始版本:
- 一次一个问题,禁止打包成问题清单(打包等于让用户挑简单的答、跳过难的)
- 每个问题自带推荐答案 + 理由,不许问"你觉得呢"(把判断责任推回用户是偷懒)
- 能靠读代码解决的,就不要问(先 grep/Read,省一轮对话)
第 2 条是关键差异。普通的"澄清需求"会产出一串开放问题让用户填空;grill-me 要求 Agent 每次都先给出自己的判断和理由,用户只需要"同意 / 反对 / 修正"。认知负担差一个量级。
2. 安装
来源(注意:第三方,非官方)
| 项 | 值 |
|---|---|
| marketplace 名 | claude-code-skills |
| 仓库 | alirezarezvani/claude-skills(GitHub) |
| 插件名 | grill-me |
| 本机版本 | 2.9.0 |
| 作者 | Alireza Rezvani |
| 许可 | MIT |
| 上游原作 | Matt Pocock's grill-me(MIT) |
这是社区插件 ,不在 anthropics/claude-plugins-official 里。装第三方 marketplace 等于执行别人仓库里的代码,装之前值得扫一眼 scripts 内容(好消息是这三个脚本都是纯 stdlib、无网络、无 LLM 调用,见 §4)。
实操
bash
# 1. 添加 marketplace
/plugin marketplace add alirezarezvani/claude-skills
# 2. 安装插件(user scope,全局可用)
/plugin install grill-me@claude-code-skills
装完的落盘位置:
bash
~/.claude/plugins/
├── known_marketplaces.json # 记录 marketplace → repo 映射
├── installed_plugins.json # 记录版本 / scope / gitCommitSha
├── marketplaces/claude-code-skills/ # marketplace 元数据
└── cache/claude-code-skills/grill-me/2.9.0/ # 插件实体
installed_plugins.json 里会记 gitCommitSha。这个字段有用:第三方插件没有稳定的版本承诺,出问题时靠 sha 才能定位到当时的代码。
验证装好了
bash
ls ~/.claude/plugins/cache/claude-code-skills/grill-me/2.9.0/
3. 组成结构
bash
grill-me/2.9.0/
├── .claude-plugin/plugin.json
├── README.md
├── agents/cs-grill-master.md # 人格 agent(model: opus)
├── commands/cs-grill-me.md # slash command 定义
└── skills/grill-me/
├── SKILL.md # 主技能(Matt 原文 + 包装)
├── references/
│ ├── forcing_question_patterns.md # 6 种"逼问"句式
│ ├── when_to_stop_grilling.md # 何时停止的判据
│ └── companion_tooling.md
└── scripts/
├── decision_tree_extractor.py # 从方案文档抽决策点
├── question_generator.py # 生成带推荐答案的问题
└── grill_session_tracker.py # 跨轮次记录会话状态
⚠️ 坑:slash command 的真实名字和文档不一致
插件自己的 README 和 commands/cs-grill-me.md 里都写调用方式是 /cs:grill-me。实际不是。 Claude Code 会用插件名做命名空间,真实可用的是:
| 文档写的 | 实际可用 |
|---|---|
/cs:grill-me |
/grill-me:cs-grill-me |
| (主技能) | /grill-me:grill-me |
agent cs-grill-master |
agent grill-me:cs-grill-master |
agents/cs-grill-master.md 的 frontmatter 里 skills: engineering/grill-me/skills/grill-me 指的是上游仓库的目录布局,和安装后的实际路径不一致。我没有实测这个引用是否还能解析,用 agent 模式前留意一下。
两个入口的区别:/grill-me:grill-me 是主技能,在当前对话里直接执行审问;/grill-me:cs-grill-master 是独立 agent(配置为 opus),跑在子上下文里。审问需要和用户来回对话,建议用主技能而不是 agent------subagent 拿不到用户的逐轮回答。
4. 三个脚本
都是 python3 + 纯标准库,无网络、无 LLM 调用,本质是正则 + 逐行扫描。可以单独当命令行工具用。
decision_tree_extractor.py --- 抽决策点
扫 markdown 方案文档,靠 5 类信号识别决策分支:
- 意图动词:
we'll/we will/we plan to/we should/we could - 开放问题:以
?结尾的句子 - 二选一:
X or Y/either...or/vs - 待定:
TBD/to be decided/open question - 取舍标记:
trade-off/tradeoff/pros/cons
bash
cd ~/.claude/plugins/cache/claude-code-skills/grill-me/2.9.0/skills/grill-me/scripts
python3 decision_tree_extractor.py # 不给参数 = 跑内置样例
python3 decision_tree_extractor.py path/to/plan.md
python3 decision_tree_extractor.py plan.md --output json
内置样例的真实输出:
css
Total decision branches found: 8
By kind: {'intent': 3, 'tradeoff': 1, 'open': 3, 'choice': 1}
[ 1] L 4 (intent ) We'll move to a single-tenant database per customer. Or maybe we should
[ 2] L 5 (tradeoff ) do schema-per-tenant for cost. This is a trade-off between isolation and ops cost.
[ 3] L 8 (open ) TBD: SSO provider --- Okta or Auth0?
边界:信号词是英文的。 中文方案文档("我们打算..." / "待定" / "二选一")基本抽不出东西。这是这套脚本最大的实用限制。
question_generator.py --- 生成带推荐答案的问题
先跑 extractor,再按分支类型套模板出问题,并按依赖排序(独立的在前)。
bash
python3 question_generator.py path/to/plan.md
模板映射:
| 分支类型 | 生成的问题 |
|---|---|
| intent | "你说要 X。为什么是 X 而不是显而易见的替代方案?" |
| choice | "X 和 Y 之间选哪个,决定性约束是什么?" |
| open | "X 标了 TBD。什么在阻塞这个决定?今天能解开吗?" |
| tradeoff | "取舍偏向哪一侧,kill criterion 是什么?" |
真实输出片段:
sql
Q 2: L5: ...trade-off between isolation and ops cost.
-> Which side of the trade-off are you optimizing for, and what's the kill criterion?
Recommended: Choose the side that's reversible later.
Trade-offs are usually one-way; pick the one with the escape hatch.
注意 Q2 那条推荐答案的逻辑------取舍倾向选"以后能反悔"的那一侧。这条启发式本身就值得记住,比脚本本身有用。
grill_session_tracker.py --- 跨轮次会话状态
JSON 落盘在 ~/.grill_sessions/<session_name>.json,用于长审问跨会话续接。
bash
# 开始
python3 grill_session_tracker.py --action start --session NAME --plan path/to/plan.md
# 记录一个回答
python3 grill_session_tracker.py --action record --session NAME --question-id 1 --answer "选方案B"
# 查进度(含 percent_complete)
python3 grill_session_tracker.py --action status --session NAME
# 收尾
python3 grill_session_tracker.py --action close --session NAME
实战里我没用它 (~/.grill_sessions/ 至今不存在)。单次会话内 10 个问题,上下文本身就是状态,额外维护一份 JSON 是纯开销。它的适用场景是审问跨天、跨会话,或者要把决策记录交给别人。
5. 六种"逼问"句式
出自 references/forcing_question_patterns.md。判定标准:软问题给对方留逃生口,逼问不留。
一个逼问式问题必须满足:不能用是/否回答完事、点名替代方案("X 还是 Y"而不是"X 行吗")、索要证据、显式摆出取舍。
| # | 场景 | 逼问 | 软问题(错误示范) |
|---|---|---|---|
| 1 | 对方说"用 Postgres" | 为什么 Postgres 不是 MySQL? | 你确定用 Postgres 吗? |
| 2 | 对方说"先试试 X" | 什么情况会让你判定 X 是错的? | 万一不行怎么办? |
| 3 | 对方说"TBD" | 缺哪个输入,什么时候到? | 这个你想过吗? |
| 4 | 对方说"这里有取舍" | 你优化哪一侧,决定性约束是什么? | 取舍你考虑过吗? |
| 5 | 对方说"取决于 X" | X 定了吗?没定就先决定 X。 | 依赖关系想过吗? |
| 6 | 对方说"不确定" | 就算只有 60% 信心,你的最佳猜测是什么? | 那再想想? |
第 1 条的价值是暴露这个选择是深思熟虑还是默认惯性------答不出替代方案,说明根本没选过。
第 6 条最实用:它拆掉"不确定"这个万能挡箭牌。多数"待定"其实现在就能在不确定下决定。
6. 何时停止
出自 references/when_to_stop_grilling.md。停止条件是"达成共识",可操作化为三条:
停:
- 每个决策分支都有答案(tracker 显示 100%)
- 最近 3 个回答没有引出新问题(新问题产生率降到 0)
- 审问方能准确预测对方的回答------问之前先写下你猜的答案,猜对了就不用问
继续(对方在闪避):
- "以后再说"(没有日期)
- "看情况"(没点名依赖)
- 答的不是问的那个问题
- 每个回答都挂着"大概 / 可能 / 也许"
对策:用一模一样的话再问一遍。躲第二次就点名:"你说'以后再说'------最晚什么时候必须定,还能赶上发布?"
另外还有条实用上限:超过 ~15 个问题收益递减,以及用户表达疲劳时立刻停。
7. 实战:threejs 跑酷游戏(10 问锁定方案)
输入是一句话需求:"以最近热门电影牛来主角为模型,threejs 跑酷游戏,网页能玩,无限地图,参照神庙逃亡,有道具有钻石,基础 UI、得分、结算。"
关键发现:有方案文档时才用脚本,一句话需求用不上
三个脚本全部以 markdown 方案文档 为输入。这次是口头一句话,没有文档,extractor 无从下手。所以实际流程里脚本一个都没用,价值 100% 来自审问纪律本身。
这不是缺陷,是适用边界:
| 输入形态 | 用法 |
|---|---|
| 已有方案/设计文档 | 跑 extractor + generator,按生成的问题走 |
| 一句话想法(更常见) | 跳过脚本,直接按纪律逐个问 |
走过的 10 个问题
| # | 问题 | 结论 |
|---|---|---|
| 1 | 主角和电影 IP 什么关系? | 原创低模牛,不碰原 IP(法律风险) |
| 2 | 几何体拼 vs GLTF 模型? | 几何体(省掉整条资源管线) |
| 3 | 直道 vs 神庙逃亡式转角? | 直道 |
| 4 | 手写区块模板 vs 纯随机? | 纯随机(用户要先跑通) |
| 5 | 随机怎么保证不出死局? | 固定节拍 + 每行强制留空一道 + 速度封顶 |
| 6 | Vite vs 单 HTML 文件? | Vite |
| 7 | 换道插值和碰撞判定怎么做? | 逻辑瞬切 + 视觉 lerp,碰撞只比车道整数 + Z 窗口 |
| 8 | 做哪几种道具? | 只做磁铁 + 无敌 |
| 9 | 要手机触屏吗? | 只做键盘 |
| 10 | UI 用 DOM 还是画在 canvas? | DOM 覆盖层 |
第 10 问后用户说"先按照最简单的来"------这是明确的疲劳信号,对应 §6 的停止条件。剩下的数值细节(分数公式、相机偏移、配色、手感初值)我打包成一个清单让用户扫一眼,而不是继续逐个问。逐个问的纪律是为了防止用户跳过难题,当剩下的都是不影响架构的数值时,打包才是对的。
三条可复用的技巧
技巧一:推荐答案要包含"我在削减你要的东西"这句话。
Q3 用户明确要求"参照神庙逃亡",而神庙逃亡的标志就是转角。推荐直道等于砍掉用户点名要的特性。这时候必须说清代价:转角需要路径游标状态机 + 局部坐标系碰撞 + 过弯相机,世界生成复杂度约翻 2.5 倍。然后把决定权交回去。藏着代价让用户"同意"一个被悄悄阉割的方案,是最坏的结果。
技巧二:拒绝"为将来预留"的中间选项。
Q3 有个诱人的折中:现在做直道,但把世界生成写成"路径游标"抽象,将来加转角就不用重写。我明确拒绝了------为一个可能不来的需求把简单代码写复杂,是最贵的一种预埋。给出的是二元选择加重写代价估算(1-2 天),而不是一个"两头都不得罪"的抽象层。
技巧三:一个回答会强制生出新问题,别跳过。
Q4 用户选了纯随机,这直接引出 Q5"随机 + 加速 = 迟早生成死局,怎么防"。Q5 不在原始问题列表里,是 Q4 的答案逼出来的。审问树是动态生长的,不是一开始就列全的清单。
结果
4 个模块(main.js / cow.js / world.js / ui.js),Vite 构建通过,dev server 正常。自查发现 3 个真 bug(对象池按形状复用错、地面段在牛身后留空洞、横杆高度让滑铲专属障碍失效)。
📌 配图位置二:游戏运行画面截图(在编辑器里拖入本地文件替换本行)
没有一次方向性返工。 这是审问阶段真正买到的东西------10 轮对话换掉了"写完发现方向错了"的风险。
顺带产出一份"被砍掉的功能 + 各自补回来的代价"清单(转角 1-2 天、区块模板几小时、触屏约 20 行、加速/双倍分道具、暂停),下次提起时不用重新论证该不该做。
8. 边界与坑汇总
- slash command 名字和文档不符 :用
/grill-me:cs-grill-me,不是文档写的/cs:grill-me - 脚本只吃英文 markdown:信号词是英文正则,中文方案文档抽不出决策点
- 脚本需要方案文档:一句话需求场景下三个脚本全用不上,价值在纪律本身
- agent 模式不适合审问:subagent 拿不到用户逐轮回答,用主技能
- session tracker 多数时候是开销:单次会话内上下文就是状态,只在跨会话/要交付决策记录时用
- 第三方插件 :非官方 marketplace,注意记录
gitCommitSha以便回溯 - ~15 问是收益递减线,用户表达疲劳时立刻停
9. 小结
这套东西真正值钱的不是三个 python 脚本,而是三条纪律:一次一个问题、每个问题自带推荐答案和理由、能读代码解决的不要问。脚本只在你已经有一份英文 markdown 方案文档时才派得上用场;日常那种"一句话想法"的场景,纪律本身就够了。
如果你也在用 Claude Code 之类的 Agent 写完整功能,最划算的改动可能就是在动手写代码前,强制插入这么一段审问。10 轮对话换掉一次方向性返工,账很好算。