Claude code:Hooks
很多人用 Claude Code 时,都想实现一些自定义功能:自动记录所有执行的命令、写完代码自动格式化、拦截危险操作、报错自动发通知。
常规改源码、写插件的方式又麻烦、又容易失效。而 Hooks (钩子系统) 就是 Claude Code 官方的轻量化解决方案:不改一行源码,只需简单配置脚本,就能在AI运行的关键节点,插入自定义逻辑。
本文用最简单直白的方式,讲懂 Hooks 的核心作用、运行逻辑、配置方法和实用案例。
一、Hooks 到底是什么?
Hooks 核心定义:Claude Code Hooks 是一套无侵入的轻量化扩展机制,本质是绑定指定AI事件的自定义脚本(Shell/Python 均可)。无需修改 Claude 源码,当AI执行命令、读写文件、提交输入等操作时,会自动触发预设脚本,实现个性化拓展能力。
通俗类比 Java AOP (核心精髓) :Hooks 的设计思想和 Java AOP 切面编程完全一致,都是不侵入核心业务,在关键节点横向扩展功能,精准对应关系如下:
PreToolUse工具执行前 =@Before前置切面PostToolUse工具执行后 =@After后置切面PostToolUseFailure工具执行失败 =@AfterThrowing异常切面
所有配置统一写在 ~/.claude/settings.json,支持跨语言编写、无需专属插件,核心实用场景覆盖:安全拦截高危操作、操作日志审计、代码自动格式化、执行异常告警、用户输入预处理。
日常最实用的场景全覆盖:
- 安全防护:禁止
git push --force、rm -rf等高危操作- 日志审计:自动记录所有命令、文件操作记录,方便溯源
- 工程提效:代码保存后自动格式化、自动修复格式问题
- 异常告警:命令执行失败,自动推送通知到 Slack 等工具
- 输入管控:统一预处理、过滤用户的提问内容
二、核心事件:哪些节点可以自定义?
Claude Code 预留了二十多种触发事件,新手只需要掌握 4个高频核心事件,就能搞定90%的场景:
- PreToolUse(工具执行前) :最常用!可以修改即将执行的命令、直接拦截危险操作、提前记录日志
- PostToolUse(工具执行后) :工具运行完触发,适合做后置处理,比如写完代码自动格式化
- PostToolUseFailure(工具执行失败) :专门捕获报错,用于异常通知、错误记录
- UserPromptSubmit(用户输入提交) :用户发送指令时触发,可过滤、修改用户输入
除此之外,还有会话启停、文件变更、配置修改等事件,满足进阶定制需求。
三、极简运行流程:钩子是怎么工作的?
整个执行链路非常清晰,新手只需记住顺序:
AI生成操作 → 前置钩子(PreToolUse) → 权限校验 → 执行操作 → 后置钩子(PostToolUse) → 返回结果
两个关键细节:
- 前置钩子在权限检查之前运行,能提前拦截危险操作,效率更高
- 所有钩子统一 30秒超时,避免脚本卡死导致AI助手瘫痪
这里我们可以简单的看一个工具执行的流程:

四、匹配规则:精准控制钩子生效范围
我们可以精准设置,让钩子只在指定操作触发,支持三种匹配方式:
- 精准匹配:只针对单个工具,比如只对 Bash 命令生效
- 正则匹配:批量匹配多个工具,比如同时匹配「写文件、改文件」操作
- 条件匹配:精准过滤内容,比如「只拦截包含 rm -rf 的命令」
极简配置示例:仅拦截高危删除命令
{
"hooks": {
"PreToolUse": [
{
"matcher": "Bash",
"if": "rm -rf",
"hooks": ["./block-danger.sh"]
}
]
}
}
整体拦截流程如下:

五、通信协议与核心源码
很多新手看不懂 Hook 的本质,是因为没看过底层执行逻辑。Claude Code Hook 整套机制完全可以通过 源码 看懂,且非常像 AOP 的环绕通知。
Hook 整套通信规则只有一句话:
主程序通过 stdin (标准输入) 灌入 JSON 上下文 → 脚本处理 → stdout ( 标准输出 )输出 JSON 控制结果
这是 Hook 能够跨语言、通用、解耦的核心。
5.1 官方底层核心执行源码(精简真实逻辑)
PreToolUse 前置钩子的运行逻辑(等同于 AOP @Before),这是 Claude 真实源码删减版:
// 工具执行前切面逻辑
async function runPreToolUseHooks(tool, input, context) {
// 1. 匹配当前工具对应的所有钩子
const hooks = getMatchingHooks('PreToolUse', tool.name)
for (const hook of hooks) {
// 2. 组装切面上下文(传给脚本的 stdin 数据)
const hookInput = {
event: 'PreToolUse',
tool_name: tool.name,
tool_input: input,
session_id: context.sessionId,
cwd: context.cwd
}
// 3. 执行外部脚本,30秒超时保护
const result = await execHook(hook.command, hookInput, { timeout: 30000 })
// 4. 读取脚本 stdout 返回的 JSON,实现切面控制
if (result.stdout) {
const output = JSON.parse(result.stdout)
// 切面能力1:修改入参(AOP 修改参数)
if (output.updatedInput) input = { ...input, ...output.updatedInput }
// 切面能力2:拦截本次执行(AOP 阻止放行)
if (output.block) {
return { blocked: true, message: output.message }
}
}
}
return { updatedInput: input }
}
5.2 标准通信协议图解(stdin / stdout)

每次触发 Hook,主程序和脚本的完整数据交互模型如下:
1)Claude Code 发给脚本的 stdin 输入数据
{
"event": "PreToolUse",
"tool_name": "Bash",
"tool_input": {
"command": "npm test"
},
"session_id": "xxx",
"cwd": "/当前项目路径"
}
2)脚本处理后返回给 Claude 的 stdout 输出数据
{
"block": false,
"message": "",
"updatedInput": null,
"notification": ""
}
5.3 可使用的全部返回字段(Hook 能力清单)
和 AOP 切面能力一一对应:
block: true:拦截工具执行(切面终止流程)message:拦截提示文案updatedInput:修改工具入参(前置切面改参)updatedResult:修改工具返回值(后置切面改结果)notification:弹窗通知
其输出的格式如下:
interface HookOutput {
// 阻止执行
block?: boolean
message?: string // 阻止原因
// 修改输入 (PreToolUse)
updatedInput?: Record<string, unknown>
// 修改结果 (PostToolUse)
updatedResult?: unknown
// 发送通知
notification?: string
// 静默 (不显示给用户)
silent?: boolean
}
六、4个开箱即用的实战脚本
分享4个最常用、可直接复制使用的钩子脚本,覆盖日常绝大多数场景。
1. 自动操作审计日志
记录所有终端命令,留存操作记录,方便溯源。
#!/bin/bash
INPUT=$(cat)
TOOL=$(echo "$INPUT" | jq -r '.tool_name')
COMMAND=$(echo "$INPUT" | jq -r '.tool_input.command // empty')
echo "$(date) | $TOOL | $COMMAND" >> ~/.claude/audit.log
echo '{}'
2. 代码自动格式化
文件写入完成后,自动用Prettier格式化TS/TSX代码。
#!/bin/bash
INPUT=$(cat)
FILE=$(echo "$INPUT" | jq -r '.tool_result.data.filePath // empty')
if [[ "$FILE" == *.ts ]] || [[ "$FILE" == *.tsx ]]; then
npx prettier --write "$FILE" 2>/dev/null
fi
echo '{}'
3. 拦截危险Git强推命令
禁止 git push --force,避免代码仓库被覆盖。
#!/bin/bash
INPUT=$(cat)
COMMAND=$(echo "$INPUT" | jq -r '.tool_input.command // empty')
if echo "$COMMAND" | grep -q "git push.*--force"; then
echo '{"block": true, "message": "禁止执行git强推命令,操作已拦截"}'
else
echo '{}'
fi
4. 执行失败自动通知
命令报错后,自动推送信息到Slack,及时感知异常。
#!/bin/bash
INPUT=$(cat)
ERROR=$(echo "$INPUT" | jq -r '.tool_result.error // empty')
SLACK_WEBHOOK="你的webhook地址"
if [ -n "$ERROR" ]; then
curl -X POST "$SLACK_WEBHOOK" -d "{"text": "Claude Code执行异常:$ERROR"}"
fi
echo '{}'
七、核心设计优势
很多人疑惑:为什么Claude Code要用「Shell脚本+JSON」的钩子模式?
- 不限语言:Shell、Python、Go都能写脚本,不用学专属插件语法
- 稳定不崩溃:钩子是独立进程,脚本出错不会影响主程序运行
- 数据完整:用JSON传结构化数据,比环境变量更稳定、无长度限制
- 安全高效:前置拦截危险操作,减少无效执行,30秒超时杜绝
感兴趣的宝子可以关注一波,后续会更新更多有用的知识!!!
更多推荐



所有评论(0)