【AI生成】学霸笔记:11|事件驱动:详解 Hooks 机制,让 AI 在关键节点自动触发

蛋蛋 2026年03月25日 3 0

📒 学霸笔记:11|事件驱动:详解 Hooks 机制,让 AI 在关键节点自动触发

Top Student Notes: 11 | Event-Driven Automation: Understanding Hooks So AI Can Trigger at Key Moments Automatically

课程 / Course: AI 原生开发工作流实战 / AI-Native Development Workflow in Practice
讲师 / Instructor: Tony Bai
章节 / Chapter: 11
主题 / Topic: Hooks、事件驱动、Claude Code 生命周期、PreToolUse、PostToolUse、Notification、自动化编排、Hook 调试


一、这一讲在解决什么问题?

What Problem Does This Lecture Solve?

前面我们已经学了很多让 AI 更强的能力:

  • @:给 AI 上下文
  • !:让 AI 执行动作
  • CLAUDE.md:给 AI 长期记忆
  • Slash Commands:把高频工作流封装成命令
  • Permissions / Sandbox / Checkpointing:给 AI 安全边界与反悔能力

但即使这样,我们和 AI 的协作方式,很多时候仍然是:

你触发一下,它动一下。

也就是说,本质上仍是:

  • 你先发起
  • AI 响应
  • 你再补一个动作
  • AI 再继续

于是会出现很多“机械但必须做”的尾部操作:

  • AI 改完 Go 文件后,你还要手动 gofmt
  • AI 修完 Bug 后,你还要手动 git add
  • AI 长时间任务结束了,你还要自己时不时回来查看
  • AI 正在等你批准权限,你却不知道它已经停在那里了

这些动作并不难,但非常烦,而且会打断流。

所以这一讲要解决的问题是:

能不能让系统在 AI 生命周期的关键节点上,自动触发预设动作?

答案就是:

Hooks 机制


二、本讲核心结论

Core Conclusion of This Lecture

一句话总结

Hooks 本质上是 Claude Code 的事件驱动自动化机制:不是“我命令 AI 做什么”,而是“当 AI 做了某件事时,系统自动响应什么”。


三、这一讲的真正升级点

The Real Upgrade in This Lecture

Tony 在这一讲里,真正推动的是一次协作模式升级:

从交互式调用,升级到事件驱动编排。


以前的模式

你像一个“微操型玩家”:

  • AI 改完文件
  • 你再手动格式化
  • AI 跑完任务
  • 你再手动检查
  • AI要调用工具
  • 你再手动决定后续处理

这种方式虽然可控,但不够顺滑。


Hooks 带来的变化

你开始预先埋好“触发器”:

  • 文件一改完,就自动格式化
  • AI 空闲下来,就自动通知你
  • AI 想改主分支文件,就自动被拦下
  • 会话一启动,就自动做初始化动作

这意味着你不再只是一个“操作员”,而更像:

AI 行为编排者 / 自动化流程设计者


四、必须先分清:Hooks vs Slash Commands

First, Distinguish Hooks vs Slash Commands

这是本讲最重要的认知点之一。

Tony 特别强调:

Slash Commands 和 Hooks 代表两种完全不同的自动化哲学。


五、Slash Commands 是“人驱动”

Slash Commands Are Human-Driven

Slash Commands 的特点是:

  • 你主动调用
  • 你决定何时执行
  • 它像一个工具箱里的工具

例如:

  • /commit
  • /review-go-code
  • /gen-test

这些都是:

人发起、AI执行


类比

Tony 的比喻很形象:

Slash Commands 像电动螺丝刀。你得先拿起来,再对准目标,再按开关。


六、Hooks 是“事件驱动”

Hooks Are Event-Driven

Hooks 不是你每次手动调用的命令。
它更像:

埋在 AI 生命周期里的传感器和响应器。

当某个事件发生时:

  • AI 刚写完文件
  • AI 即将调用工具
  • AI 进入等待状态
  • 会话刚开始 / 刚结束

Hook 就会自动触发。


类比

Hooks 不是工具本身,而像自动门、烟雾报警器、流水线感应器。
事件一发生,系统自己反应。


七、两者怎么配合?

How Do Hooks and Slash Commands Work Together?

Tony 提出一个非常成熟的工作流观念:

成熟的 AI 原生工作流 = Slash Commands 启动任务 + Hooks 负责自动收尾和过程联动。


例子

你可以:

  1. /review-go-code 发起一个复杂分析任务
  2. AI 在过程中修改文件
  3. PostToolUse 自动跑格式化
  4. AI 完成后,Notification 自动给你系统提醒

这才是完整的工程自动化。


八、Claude Code 生命周期:你要知道 AI 在哪里会“触发事件”

Claude Code Lifecycle: You Need to Know Where Events Happen

要用好 Hooks,你必须先理解:

AI 在一次工作流程中,经过哪些关键生命周期节点。

因为 Hook 本质就是:

对生命周期事件的监听与响应。


九、核心 Hook 事件概览

Overview of Core Hook Events

这一讲列出了多个 Claude Code 开放的关键事件。


1. SessionStart

时机

Claude Code 会话启动时

价值

适合做初始化

例如:

  • 切换 Node 版本
  • 初始化环境变量
  • 打印项目状态
  • 做会话级准备工作

2. SessionEnd

时机

会话退出时

价值

适合做清理工作

例如:

  • 写日志
  • 收尾统计
  • 清理临时文件
  • 结束时通知

3. UserPromptSubmit

时机

用户提交 Prompt 之后,AI 开始处理之前

价值

适合做 Prompt 前置检查或预处理

例如:

  • 检查敏感词
  • 发现危险请求则阻止提交
  • 自动注入额外上下文
  • 记录用户输入

4. PreToolUse

时机

AI 决定调用某个工具,但还没真正执行前

价值

这是最强控制点之一

你可以:

  • 看 AI 准备调用什么工具
  • 看工具参数
  • 在执行前做检查
  • 直接阻止这次调用

为什么它很强?

因为这是:

行动发生之前的拦截点

所以非常适合:

  • 安全策略
  • 行为约束
  • 组织规则强制执行

5. PostToolUse

时机

工具调用完成之后,AI 获得结果之前

价值

这是自动化收尾工作的黄金位置

适合:

  • 自动格式化
  • 自动跑 Linter
  • 自动补充分析
  • 写日志
  • 做后置加工

6. Notification

时机

AI 等待你下一步输入,或者等待你批准某个权限时

价值

解决“AI是不是在等我”的问题

非常适合:

  • 系统通知
  • 桌面提醒
  • 响铃提示

7. Stop

时机

一个主回合结束时

价值

适合做“回合结束”型动作

例如:

  • 记录 token 消耗
  • 汇总一次任务结果
  • 输出摘要日志

8. SubagentStop

时机

一个 Sub-agent 子任务结束时

价值

适合对子任务做收尾和观察


十、最值得记住的两个事件

The Two Most Important Hook Events to Remember

虽然事件很多,但本讲实战重点其实集中在两个:

  1. PostToolUse
  2. PreToolUse

为什么?

因为这两个恰好分别代表两种最常见价值:

  • PostToolUse:自动化收尾
  • PreToolUse:安全与策略拦截

一个偏效率,一个偏治理。


十一、Hooks 的配置位置

Where Hooks Are Configured

所有 Hooks 都配置在:

settings.json

可以是:

  • User 级
  • Project 级

Project 级更适合什么?

  • 团队共享规则
  • 项目自动化规范
  • 强制性流程

例如:

  • 修改 Go 文件后自动格式化
  • 禁止直接改 main 分支

User 级更适合什么?

  • 个人提醒
  • 个人工作习惯
  • 私有通知逻辑

十二、Hooks 的核心结构

Core Structure of Hooks

大体结构是:

{
  "hooks": {
    "<EventName>": [
      {
        "matcher": "<ToolPattern>",
        "hooks": [
          {
            "type": "command",
            "command": "<your-shell-command>",
            "timeout": 60
          }
        ]
      }
    ]
  }
}

关键字段理解

EventName

表示监听哪个生命周期事件
例如:

  • PreToolUse
  • PostToolUse

matcher

只对工具型事件有意义,表示匹配哪些工具调用

hooks

真正要执行的动作列表

type

当前主要是 command

command

要执行的 shell 命令或脚本

timeout

超时限制,避免 Hook 卡死整个流程


十三、matcher 是 Hooks 的过滤器

matcher Is the Filter for Hooks

matcher 决定:

不是所有事件都响应,而是只对特定工具调用响应。


例子

"Edit|Write"

表示:

  • 匹配 Edit
  • 或匹配 Write

"Bash(go:test:*)"

表示:

  • 只匹配 go test 相关命令

"*" 或空字符串

表示:

  • 匹配所有工具

学霸理解

matcher 决定的是:

“谁触发我”


十四、Hook 命令如何拿到上下文?

How Does a Hook Command Receive Context?

这是一个关键实现点。

Claude Code 会把当前事件的信息:

通过 stdin 以 JSON 格式传给你的 Hook 命令。

也就是说,Hook 脚本可以从标准输入读取:

  • 当前事件名
  • 当前工具名
  • 工具输入
  • 工具输出
  • 当前工作目录
  • 会话 ID
  • transcript 路径

这意味着什么?

你的 Hook 不是“盲执行”的,而是:

知道发生了什么,再决定怎么响应。


十五、实战一:PostToolUse 自动格式化 Go 文件

Practical Example 1: PostToolUse for Automatic Go Formatting

这是一个非常典型的“事件驱动自动收尾”场景。


目标

当 AI 用这些工具改了文件:

  • Edit
  • Write
  • MultiEdit

并且目标是 .go 文件时:

自动运行:

  • gofmt -w
  • goimports -w

这个实战体现了什么思想?

把“修改完成后的规范化处理”从手工步骤升级为事件响应。


步骤拆解

第一步:进入 /hooks

使用交互式界面配置 Hook

第二步:选 PostToolUse

因为你关心的是:

  • 工具已经执行完
  • 文件已经改完
  • 可以开始收尾

第三步:设置 matcher

Edit|Write|MultiEdit

表示只对编辑类工具做反应。


第四步:命令的本质

命令要做三件事:

  1. 从 stdin 读 JSON
  2. 解析出 tool_input.file_path
  3. 判断是不是 .go 文件
  4. 如果是,则运行 gofmtgoimports

jq 的作用

Tony 强调这里 jq 很重要。

因为 Hook 上下文是 JSON,jq 可以非常方便地提取字段,例如:

  • tool_input.file_path

学霸理解

这个例子真正要学的不是记命令,而是掌握模式:

读取事件 JSON → 提取关键字段 → 做条件判断 → 调用后置动作

这套模式以后可以推广到很多自动化场景。


十六、这个自动格式化 Hook 的意义

Why This Auto-Formatting Hook Matters

它解决了一个典型的“低价值人工步骤”:

  • AI 写了代码
  • 人再补格式化
  • 经常忘
  • 忘了又会污染 diff

有了 Hook 之后:

格式化成为“修改成功后的系统默认反应”,而不是开发者额外记忆负担。

这就是事件驱动自动化的价值。


十七、如何调试 Hook?

How to Debug Hooks?

Hook 不工作时,最怕的就是:

  • 不知道有没有触发
  • 不知道 matcher 是否命中
  • 不知道命令有没有跑
  • 不知道 stdout / stderr 返回了什么

Tony 给了标准方法:

claude --debug

启动后会得到什么?

Claude Code 会告诉你 debug 日志文件路径。
然后你可以用 tail 之类命令去观察日志。


Debug 日志能看到什么?

例如:

  • 工具是否匹配了某个 Hook
  • 匹配了几个 Hook
  • Hook 命令输出了什么
  • 返回内容是否被解析成功

学霸理解

调试 Hook 的核心链路是:

事件有没有发生
→ matcher 有没有命中
→ command 有没有执行
→ 输出是否符合预期

十八、实战二:PreToolUse 阻止在 main 分支直接改代码

Practical Example 2: PreToolUse to Prevent Direct Edits on the Main Branch

这是一个比自动格式化更“治理型”的案例。


目标

当 AI 准备用:

  • Edit
  • Write
  • MultiEdit

修改文件时,先检查当前 Git 分支。

如果在:

  • main
  • master

上,就直接阻止这次修改。


这类 Hook 解决了什么问题?

这是典型的:

把团队工程纪律,变成系统强制执行规则。

不再只是文档里写:

  • “不要直接改主分支”

而是真正做到:

  • 主分支禁止 AI 直接改

十九、为什么这个案例推荐用脚本文件而不是一长串 Bash?

Why a Script File Is Better Than a Long Bash One-Liner

Tony 这里非常实用地提醒了一点:

对复杂 Hook 逻辑,最好封装成脚本文件,而不是写一大串 Bash 管道命令。


原因

长 Bash 命令容易:

  • 难读
  • 难调试
  • 难维护
  • 容易转义出错

而独立脚本:

  • 更清晰
  • 更易扩展
  • 可以写注释
  • 可以本地单独测试

推荐位置

放在:

.claude/hooks/

例如:

.claude/hooks/check_main_branch.py

这是非常好的项目结构实践。


二十、这个 Python Hook 脚本的核心逻辑

Core Logic of the Python Hook Script

这个脚本做了几件事:

  1. 从 stdin 读取 JSON
  2. 看当前工具是不是 Edit / Write / MultiEdit
  3. 调用:
    git rev-parse --abbrev-ref HEAD
    
    获取当前分支
  4. 如果分支是 main / master
    • 输出错误信息到 stderr
    • exit 2
  5. 否则 exit 0

为什么 stderr 很重要?

因为 Tony 强调:

输出到 stderr 的错误信息,不只给用户看,也会让 Claude 理解“为什么这次操作被阻止”。

于是 AI 可能会进一步智能调整行为,比如:

  • 主动建议你先建 feature branch

这很关键。


二十一、退出码的语义很关键

Exit Code Semantics Matter

在 Hook 体系里:

  • exit 0:允许继续
  • 非 0:表示失败 / 拦截

特别是案例里:

  • exit 2:阻止工具调用,并把错误信息展示给 Claude 和用户

学霸理解

PreToolUse 里,脚本的退出码相当于:

是否放行工具调用的裁决结果

所以这其实是一个很强的“策略执行点”。


二十二、$CLAUDE_PROJECT_DIR 很实用

$CLAUDE_PROJECT_DIR Is Very Useful

Tony 提到的这个环境变量非常有价值:

"$CLAUDE_PROJECT_DIR"/.claude/hooks/check_main_branch.py

它会自动展开为项目根目录路径。


好处

这样你的 Hook 配置:

  • 不依赖硬编码绝对路径
  • 可以跨机器
  • 可以跟项目一起提交
  • 团队成员可复用

二十三、这两个实战分别代表什么?

What Do the Two Practical Examples Represent?

这两个例子很有代表性,因为它们分别体现 Hooks 的两种核心价值。


实战一:PostToolUse 自动格式化

代表:

效率型自动化

核心目标:

  • 减少重复劳动
  • 自动做收尾工作
  • 把规范执行“无感化”

实战二:PreToolUse 阻止改 main

代表:

治理型自动化

核心目标:

  • 在关键点前拦截危险动作
  • 强制执行团队纪律
  • 把规则从文档变成系统机制

二十四、Hooks 的本质总结

The Essence of Hooks

到这里可以把 Hooks 总结成一句话:

Hooks 是把“规则、习惯、最佳实践”嵌入 AI 生命周期关键节点的自动响应机制。


更通俗一点

以前:

  • 规范靠记忆
  • 流程靠自觉
  • 收尾靠手动
  • 安全靠盯着

现在:

  • 规范靠 Hook 自动执行
  • 流程靠事件自动推进
  • 收尾靠系统自动完成
  • 安全靠关键节点自动拦截

二十五、这一讲的真正方法论价值

The Methodological Value of This Lecture

这讲不是单纯多学了一个配置功能,而是在方法论上完成一次升级:

从 Prompt 工程,走向流程工程。


为什么这么说?

前面很多内容都在优化:

  • 你怎么问
  • AI 怎么答
  • 上下文怎么组织
  • 命令怎么复用

而 Hooks 开始优化的是:

AI 运行过程中的事件流。

也就是说,关注点从“单次交互质量”转向:

整个协作流程如何自动流动。


二十六、这一讲和前面课程的关系

How This Lecture Connects to Earlier Lessons

可以这样串起来看:

  • @ / !:建立感知-行动闭环
  • CLAUDE.md / constitution.md:建立规则与原则
  • Slash Commands:把高频协作封装成显式命令
  • Permissions / Sandbox / Checkpointing:建立安全与可反悔机制
  • Hooks:把 AI 生命周期变成可响应的事件流

这意味着什么?

你已经不只是“跟 AI 对话”,而是在:

设计一个带触发器、带约束、带收尾逻辑、带自动响应的 AI 工作流系统。


二十七、Hooks 最适合做哪些事?

What Are Hooks Best Suited For?


1. 自动收尾

  • 格式化代码
  • 运行 linter
  • 同步生成附加文件

2. 安全拦截

  • 禁止改主分支
  • 禁止危险文件写入
  • 检查敏感命令

3. 通知提醒

  • AI 完成任务提醒
  • AI 等待你批准提醒

4. 会话初始化

  • 加载环境
  • 切版本
  • 打印项目状态

5. 记录与审计

  • 写日志
  • 统计 token
  • 记录关键行为

二十八、使用 Hooks 的设计原则

Design Principles for Using Hooks

Tony 虽然没有专门列成条,但从实战里能总结出几个原则。


原则 1:让 Hook 做“高频、可预测、重复”的事

因为这些最适合自动化。


原则 2:复杂逻辑尽量写成脚本文件

不要把复杂业务判断堆进一长串 shell one-liner。


原则 3:收尾动作适合 PostToolUse

例如格式化、lint、日志。


原则 4:拦截与治理适合 PreToolUse

例如安全控制、流程保护、策略执行。


原则 5:团队共享规则优先放项目级

这样才真正形成工程实践,而不是个人偏好。


二十九、本讲知识结构图

Knowledge Structure of This Lecture

当前协作仍以“人触发 AI”为主
        ↓
出现大量机械收尾与监视动作
        ↓
需要事件驱动自动化
        ↓
Hooks
        ↓
两种自动化哲学对比
├── Slash Commands:人驱动
└── Hooks:事件驱动
        ↓
Claude Code 生命周期事件
├── SessionStart / SessionEnd
├── UserPromptSubmit
├── PreToolUse
├── PostToolUse
├── Notification
├── Stop
└── SubagentStop
        ↓
配置方式
├── settings.json
├── matcher 匹配工具
├── command 执行响应命令
└── stdin 传 JSON 上下文
        ↓
两类核心应用
├── PostToolUse:自动收尾
│   └── 例:Go 文件自动格式化
└── PreToolUse:行为拦截
    └── 例:阻止在 main 分支直接改文件
        ↓
最终目标
把最佳实践、规范、安全策略嵌入 AI 生命周期

三十、学霸速记表

Quick Revision Table

知识点 结论
Hooks 本质 事件驱动自动化机制
Slash Commands vs Hooks 前者人驱动,后者事件驱动
Hooks 配置位置 settings.json
核心字段 hooks / matcher / command / timeout
上下文传递方式 Claude Code 通过 stdin 传 JSON
SessionStart 会话启动时触发
SessionEnd 会话结束时触发
UserPromptSubmit 用户提交 Prompt 后、AI 处理前
PreToolUse 工具执行前,可拦截
PostToolUse 工具执行后,适合收尾
Notification AI 等待用户时触发
Stop / SubagentStop 回合 / 子任务结束时触发
自动格式化案例 PostToolUse + `Edit
主分支保护案例 PreToolUse + 分支检查脚本
调试方式 claude --debug 查看 Hook 执行日志

三十一、学霸自检题

Self-Check Questions

基础题

  1. Hooks 和 Slash Commands 的根本区别是什么?
  2. PreToolUsePostToolUse 分别在什么时候触发?
  3. Hook 命令如何获取事件上下文?

进阶题

  1. 为什么自动格式化更适合用 PostToolUse 而不是 PreToolUse
  2. 为什么保护主分支更适合用 PreToolUse
  3. 为什么复杂 Hook 逻辑推荐封装成独立脚本文件?

思辨题

  1. 在你的项目里,哪些重复动作最适合用 Hooks 自动化?
  2. 你是否会把团队规范写成 Hook,而不只写在文档中?为什么?
  3. 如果为一个前端项目设计 Hooks,你会在哪些事件节点做自动格式化、测试提醒和通知?

三十二、学霸总结

Top-Student Summary

这一讲讲的是 Claude Code 中非常关键、也非常“工程化”的能力:Hooks
它解决的不是 AI 会不会写代码,而是:

如何让 AI 生命周期中的关键节点,自动触发我们预设的系统响应。

Tony 首先区分了两种自动化哲学:

  • Slash Commands:用户驱动,由人主动调用
  • Hooks:事件驱动,由系统在事件发生时自动响应

这意味着,Hooks 的价值不在于替代 Slash Commands,而在于把单次 AI 行动之间那些重复、机械、可预测的“胶水步骤”自动化,从而把零散的交互连接成流畅的工作流。

Claude Code 暴露了多个关键生命周期事件,其中最重要的包括:

  • PreToolUse:工具执行前,可用于安全拦截与策略治理
  • PostToolUse:工具执行后,适合自动格式化、lint 等收尾动作
  • Notification:AI 等待用户时触发通知
  • SessionStart / SessionEnd:适合会话级初始化与清理

在配置层面,Hooks 定义于 settings.json,通过 matcher 指定监听哪些工具,通过 command 执行具体 shell 命令或脚本。Claude Code 还会通过 stdin 以 JSON 形式把事件上下文传给 Hook,使 Hook 具备“感知发生了什么”再作反应的能力。

两个实战例子非常典型:

  1. PostToolUse 自动格式化 Go 文件
    把“AI 修改代码后再手动 gofmt / goimports”的重复劳动,升级成无感自动执行的后置流程。

  2. PreToolUse 阻止在 main/master 分支直接修改文件
    把团队纪律从文档里的提醒,升级成真正可执行、可阻断的系统规则。

因此,Hooks 的真正价值在于:

让规范、最佳实践和安全策略,不再依赖人的记忆和自觉,而是成为一个永远在线、自动执行的事件响应系统。

这标志着开发者角色再次升级:
你不再只是 AI 的提问者、指令设计者,而正在成为:

AI 行为流程的编排者。


三十三、一句话记忆

One-Sentence Memory Hook

Slash Commands 是“我让 AI 做什么”,Hooks 是“当 AI 做了什么,系统自动接着做什么”;前者是人驱动,后者是事件驱动。

Last Updated: 2026/03/29 15:43:47
【AI生成】学霸笔记:11|实战笔记:创建`PostToolUse``PreToolUse` 【AI生成】学霸笔记:10|安全基石(下):Checkpointing,获得让 AI“时光倒流”的超能力