三条钩子串成一条质量流水线:改完自动格式化(工具调用后)、 lint 不通过就把意见回给模型(工具调用后)、测试没过不许结束(完成时)。 实测八次改动:格式化修掉五个,剩三个进对话。省下五轮,而钩子本身的成本是零。
上一节是安全(拦坏的),这一节是质量(补好的)。两者的位置一样,方向相反。 这一节也是「钩子省对话轮次」这件事最直观的一次实测。
一、三条钩子串成一条线
第一条:改完文件就跑格式化。挂工具调用后,匹配写和改。它修格式,不修语义。 第二条:跑 lint,把输出回给模型。格式化修不了的(未使用变量、复杂度超标)交给它发现。 第三条:模型说干完了,先跑测试。没过就打回去,不许结束。
三条的顺序是有讲究的:越靠前的越便宜、越机械;越靠后的越贵、越接近「能不能交」。 所以判断一条质量规则该挂哪儿,问一句:它需要理解代码吗?不需要就挂前面,需要就挂后面。
二、八次改动,格式化修掉五个
演示里八处问题:三处缩进和引号、一处行太长、一处未使用变量、一处缺类型注解、一处复杂度超标、 一处引号。 格式化能修的是纯格式的那五个(缩进、引号、行太长)。 剩下三个——未使用变量、缺类型注解、复杂度超标——格式化修不了。 这三类要交给 lint。lint 不修,只报;报了之后由模型改。
这就是「格式归工具、规则归 lint」的分界线:改得动的交给工具一次做完,改不动的交给模型判断。 分不清这条线,就会写出一个「什么都想修」的格式化钩子——它会把语义也改坏。
三、省下多少轮对话
没有钩子时:每发现一个问题要一轮——模型改、你看、再让它改。八轮,约六千四 token。 有格式化钩子时:五个问题在保存那一刻就被修掉了,零轮;剩三个才进对话。三轮,约两千四。 省下五轮、约四千 token。而钩子本身的成本是零——格式化工具本来就要跑。
这是钩子最划算的一类用法:用一次本来就有的动作,换掉五次往返。 注意这里省的不只是 token,还有人的注意力:五个格式问题你根本不用看见。
四、lint 反馈循环的价值
格式化只管格式。语义类的问题格式化修不了,但 lint 能发现。 做法是:钩子跑 lint,把输出写进 stderr 或者返回体里。模型下一轮就看到了,自己改,不用人来传话。 这一步的价值是「闭环」:发现问题的人和改问题的人在同一个回合里。
没有这个闭环,流程就是「lint 报错 → 人看见 → 人转述给模型 → 模型改」,中间多两个人。 这也是「钩子不是给人用的,是给模型用的」这句话最具体的例子。
五、完成时门控:最值钱的那一条
完成事件发生在模型认为「我干完了」的时候。它能阻止,所以可以在这里卡一道:跑测试,没过就打回去。 演示里设了两处测试没过:没有门控,这两次都会「结束」;有门控,模型被打回继续改。 它约束的不是「写的时候」,是「交的时候」。而「交的时候」恰恰是质量最容易松的一刻。
三条合起来是一条流水线:格式化的归工具、规则的归 lint、能不能交的归测试。 一句话:越靠前的越便宜,越靠后的越值钱。四条都挂上,才叫自动化;只挂第一条,只是省事。
六、动手 Demo:八次改动,三条质量钩子各跑了几次、省了几轮对话
八次改动、八处问题。三条钩子:格式化(工具调用后)、lint 反馈(工具调用后)、测试门控(完成时)。 先看格式化修掉几个,再算对话轮次省了多少。
EDITS = [(u"src/a.py", u"缩进错", True), (u"src/d.py", u"未使用变量", False)]
fmt = sum(1 for _f, _p, auto in EDITS if auto) # 格式化能修的
left = len(EDITS) - fmt # 交给模型的
实跑输出:
--------------------------------------------------------------------
八次改动,三条质量钩子各跑了几次、省了几轮对话
--------------------------------------------------------------------
三条钩子:改完自动格式化(PostToolUse)、lint 不通过就把意见回给模型(PostToolUse)、
测试没过就不许结束(Stop)。
① 八次改动,格式化跑了几次
--------------------------------------------------------------------
| 文件 | 问题 | 结果 |
|---|---|---|
| src/a.py | 缩进错 | 自动修好 |
| src/b.py | 引号不统一 | 自动修好 |
| src/c.py | 行太长 | 自动修好 |
| src/d.py | 未使用变量 | 交回模型 |
| src/e.py | 缺类型注解 | 交回模型 |
| src/f.py | 缩进错 | 自动修好 |
| src/g.py | 复杂度超标 | 交回模型 |
| src/h.py | 引号不统一 | 自动修好 |
格式化在 8 次改动后自动跑,修掉了 5 个问题;剩 3 个交回模型。
② 省了几轮对话
--------------------------------------------------------------------
没有钩子时:每发现一个问题要一轮——模型改、你看、再让它改。八轮。
有格式化钩子时:5 个问题在保存那一刻就被修掉了,零轮。剩 3 个才进对话。
| 做法 | 对话轮次 | 这些轮次的 token |
|---|---:|---:|
| 没有钩子 | 8 轮 | 6400 |
| 有格式化钩子 | 3 轮 | 2400 |
省下 5 轮,按每轮八百 token 算约 4000。而钩子本身的成本是零——格式化工具本来就要跑。
③ lint 反馈循环:把意见回给模型
--------------------------------------------------------------------
格式化只管格式。语义类的问题(未使用变量、复杂度超标)格式化修不了,但 lint 能发现。
做法是:钩子跑 lint,把输出写进 stderr 或者返回体里。模型下一轮就看到了,自己改,不用人来传话。
这一步的价值是「闭环」:发现问题的人和改问题的人在同一个回合里。
④ Stop 门控:测试没过不许结束
--------------------------------------------------------------------
Stop 事件发生在模型认为「我干完了」的时候。
它能阻止,所以可以在这里卡一道:跑测试,没过就打回去。
演示里设了两处测试没过:第 3 次和第 7 次改动后。没有门控,这两次都会「结束」;
有门控,模型被打回继续改。
这是质量钩子里最值钱的一个——它约束的不是「写的时候」,是「交的时候」。
! 三条合起来是一条流水线:格式化的归工具、规则的归 lint、能不能交的归测试。
越靠前的越便宜,越靠后的越值钱。
①八处问题里格式化修掉五个(缩进、引号、行太长),剩三个交给模型(未使用变量、缺类型注解、 复杂度超标)。 这就是「格式归工具、规则归 lint」的分界线:改得动的交给工具一次做完,改不动的交给模型判断。 ②省了几轮:没有钩子时八轮、约六千四 token;有格式化钩子时三轮、约两千四。省下五轮、约四千。 而钩子本身的成本是零——格式化工具本来就要跑。 这是钩子最划算的一类用法:用一次本来就有的动作,换掉五次往返。 省的不只是 token,还有人的注意力:五个格式问题你根本不用看见。 ③lint 反馈循环的价值是「闭环」:发现问题的人和改问题的人在同一个回合里。 没有它,流程是「lint 报错、人看见、人转述、模型改」,中间多两个人。 ④完成时门控是三条里最值钱的:它约束的不是「写的时候」,是「交的时候」, 而那一刻恰恰是质量最容易松的一刻。 三条合起来是一条流水线:格式化的归工具、规则的归 lint、能不能交的归测试。 越靠前的越便宜,越靠后的越值钱。
30 秒实验
- 把「缺类型注解」改成能自动修(假设工具支持),重跑第 ② 步。对话轮次降到几轮? 这说明「工具能力边界」直接决定省多少?
- 给 lint 钩子加一条「只报前三条」,重跑一遍。模型收到的信息少了,它改得完吗?这个截断该不该做?
- 把测试门控去掉,只留前两条,重跑一遍。对话轮次不变,但风险变了——变在哪?
常见误区
- 让格式化钩子顺手修语义问题(「顺便把未使用变量删了」)。工具不该改语义,会改坏。
- 只挂格式化,不挂 lint。格式修好了,未使用变量和复杂度还在,而且没人发现。
- 不挂完成时门控。模型说干完了就真结束,测试没跑谁也不知道。
- 把 lint 输出写进 stdout。那会冲掉钩子的协议 JSON,整条钩子失效。
- 以为钩子省的是 token。省的主要是往返轮次和人的注意力,token 是顺带的。
自测三问(点开对答案)
1. 格式化钩子和 lint 钩子的分工是什么? —— 格式化修得动格式(缩进、引号、行长度),一次做完;lint 只报不修,把语义类问题回给模型判断。 2. 为什么说完成时门控最值钱? —— 因为它约束的是「交的时候」,而不是「写的时候」。质量最容易在「我觉得干完了」那一刻松掉。 3. lint 钩子的输出为什么要走 stderr 或返回体? —— 因为 stdout 是钩子的协议通道,必须是一段 JSON。 把 lint 输出写进 stdout 会冲掉协议,整条钩子失效。质量这套装完了,下一节把钩子挂到子智能体身上:进去注入什么、出来验收什么。
- ☐ (本篇完,下一篇 5.8 子智能体 Hooks:精准的上下文管理)
相关笔记
- 安全防护:安全防护那一套
- 子智能体 Hooks:子智能体的两道口
- Claude Code 橙皮书 · 索引
- 🐎 Claude Code 实战 · 索引