Claude Code /hooks:让 AI 按你的规矩办事
什么是 /hooks
用 Claude Code 的时候,你有没有想过:
- 每次 Claude Code 要跑
git push前,能不能自动跑一遍 lint? - 每次会话结束时,能不能自动把摘要发到 Slack?
- 每次 Claude Code 想删文件,能不能先让另一个 AI 审查一下?
/hooks 就是干这个的。 它是 Claude Code 的事件钩子系统——在特定事件发生时,自动执行你预设的逻辑。
如果说 /permissions 控制的是”能不能做”,那 /hooks 控制的是”做之前和做之后还要干什么”。
核心概念
事件(Event)
Hook 系统围绕”事件”运作。Claude Code 在运行过程中会触发各种事件,你可以在这些事件上挂载钩子。
常用事件一览:
| 事件 | 触发时机 | 匹配维度 |
|---|---|---|
| PreToolUse | 工具执行前 | 工具名(如 Bash、Edit) |
| PostToolUse | 工具执行后 | 工具名 |
| PostToolUseFailure | 工具执行失败后 | 工具名 |
| UserPromptSubmit | 用户提交消息时 | — |
| Notification | 通知事件 | 通知类型 |
| SessionStart | 会话开始 | 来源(startup/resume/clear/compact) |
| SessionEnd | 会话结束 | 结束原因 |
| Stop | Claude 停止响应 | — |
| SubagentStart | 子 Agent 启动 | Agent 类型 |
| SubagentStop | 子 Agent 停止 | Agent 类型 |
| PreCompact | 上下文压缩前 | — |
| PostCompact | 上下文压缩后 | — |
| PermissionRequest | 权限弹窗时 | 工具名 |
| PermissionDenied | 权限被拒绝 | 工具名 |
| ConfigChange | 配置变更 | 配置来源 |
| FileChanged | 文件变化 | 文件名 |
| CwdChanged | 工作目录变化 | — |
| InstructionsLoaded | 指令文件加载 | 加载原因 |
| Elicitation | MCP 服务器提问 | 服务器名 |
| ElicitationResult | MCP 提问结果 | 服务器名 |
| Setup | 初始化 | 触发类型(init/maintenance) |
| WorktreeCreate | Worktree 创建 | — |
| WorktreeRemove | Worktree 删除 | — |
| TaskCreated | 任务创建 | — |
| TaskCompleted | 任务完成 | — |
| TeammateIdle | Teammate 空闲 | — |
总共 27 个事件,覆盖了 Claude Code 运行的几乎每个关键节点。
匹配器(Matcher)
每个事件下可以挂多个钩子,用 matcher 来决定什么时候触发。
比如 PreToolUse 事件,你可以给不同的工具配不同的钩子:
{
"hooks": {
"PreToolUse": [
{
"matcher": "Bash",
"hooks": [{ "type": "command", "command": "echo 'about to run bash'" }]
},
{
"matcher": "Edit|Write",
"hooks": [{ "type": "command", "command": "echo 'about to modify file'" }]
}
]
}
}
匹配规则支持三种写法:
| 写法 | 示例 | 含义 |
|---|---|---|
| 精确匹配 | "Bash" | 只匹配 Bash 工具 |
| 管道分隔 | "Bash|Write|Edit" | 匹配其中任意一个 |
| 正则表达式 | "Bash|mcp__.*" | 匹配 Bash 或任意 MCP 工具 |
留空或写 "*" 表示匹配该事件的所有情况。
四种钩子类型
1. command —— Shell 命令
最基础也最常用的类型,直接执行一段 Shell 命令:
{
"type": "command",
"command": "npm run lint",
"timeout": 30000
}
钩子通过 stdin 接收 JSON 格式的上下文信息(工具名、工具输入、会话 ID 等),通过 stdout 返回结果,通过 退出码 控制行为:
| 退出码 | 含义 |
|---|---|
| 0 | 成功,stdout 内容会加入对话上下文 |
| 2 | 阻断,stderr 内容会告知 Claude,操作被拦截 |
| 其他 | 非阻断错误,stderr 作为警告显示 |
2. prompt —— 单轮 AI 判断
让一个轻量 AI 模型做单轮判断,适合需要”智能审查”的场景:
{
"type": "prompt",
"prompt": "检查这个命令是否可能删除重要文件,如果有风险返回 {\"decision\": \"block\", \"reason\": \"可能删除重要文件\"}",
"timeout": 30000
}
默认使用小快模型(通常是 Haiku),也可以通过 model 字段指定其他模型。
3. agent —— 多轮 AI Agent
当单轮判断不够时,用 Agent 类型——它会启动一个子 Agent,可以多轮对话、调用工具:
{
"type": "agent",
"prompt": "审查这段代码的安全性,如果发现问题请详细说明",
"timeout": 60000
}
Agent 最多执行 50 轮对话,默认超时 60 秒。
4. http —— HTTP 请求
向外部服务发送 POST 请求,适合集成 CI/CD、通知系统、审计日志等:
{
"type": "http",
"url": "https://your-webhook.example.com/hook",
"headers": {
"Authorization": "Bearer $API_TOKEN"
},
"allowedEnvVars": ["API_TOKEN"],
"timeout": 600000
}
HTTP 钩子有 SSRF 防护,请求体是 JSON 格式的 Hook 输入。Headers 支持环境变量插值,但必须在 allowedEnvVars 中显式声明。
怎么用 /hooks
在 Claude Code 交互模式下输入:
/hooks
会弹出一个 只读 的浏览面板,按事件分类展示当前生效的所有钩子。你可以:
- 逐层浏览:事件 → 匹配器 → 具体钩子
- 查看每个钩子的详细配置(类型、命令、超时等)
- 看到钩子来自哪个配置源(User / Project / Local / Plugin / Session)
注意:/hooks 命令本身是只读的。要添加或修改钩子,需要编辑 settings.json。
在 settings.json 中配置 Hooks
基本结构
{
"hooks": {
"事件名": [
{
"matcher": "匹配模式(可选)",
"hooks": [
{
"type": "command | prompt | agent | http",
"command": "...",
"timeout": 30000
}
]
}
]
}
}
配置源和优先级
钩子可以配置在不同层级,所有层级的钩子都会执行(不是覆盖,是累加):
| 来源 | 文件路径 |
|---|---|
| User | ~/.claude/settings.json |
| Project | <项目>/.claude/settings.json |
| Local | <项目>/.claude/settings.local.json |
| Plugin | ~/.claude/plugins/*/hooks/hooks.json |
| Managed | 企业托管策略 |
这跟权限规则不一样——权限规则是”后面覆盖前面”,但钩子是全部合并执行。
if 条件过滤
所有钩子类型都支持 if 字段,用权限规则语法做更精细的过滤:
{
"hooks": {
"PreToolUse": [
{
"matcher": "Bash",
"hooks": [
{
"type": "command",
"command": "echo 'dangerous command detected'",
"if": "Bash(rm -rf:*)"
}
]
}
]
}
}
这个钩子只在 Bash 工具要执行 rm -rf 开头的命令时才触发。if 的语法和 /permissions 中的规则格式一样。
实战示例
示例一:执行命令前自动 lint
{
"hooks": {
"PreToolUse": [
{
"matcher": "Bash",
"hooks": [
{
"type": "command",
"command": "echo '{\"decision\": \"approve\"}'"
}
]
}
]
}
}
示例二:文件变更时自动通知
{
"hooks": {
"FileChanged": [
{
"matcher": ".env|.envrc",
"hooks": [
{
"type": "command",
"command": "echo '⚠️ 敏感配置文件被修改' | tee /dev/stderr && exit 2"
}
]
}
]
}
}
当 .env 或 .envrc 文件被修改时,自动发出警告。退出码 2 会阻断后续操作。
示例三:用 AI 审查危险命令
{
"hooks": {
"PreToolUse": [
{
"matcher": "Bash",
"hooks": [
{
"type": "prompt",
"prompt": "分析 stdin 中的命令,如果它可能造成不可逆的数据丢失(如 rm -rf、DROP TABLE),返回 {\"decision\": \"block\", \"reason\": \"...\"},否则返回 {\"decision\": \"approve\"}"
}
]
}
]
}
}
示例四:会话结束时发送摘要
{
"hooks": {
"SessionEnd": [
{
"hooks": [
{
"type": "http",
"url": "https://hooks.slack.com/services/xxx/yyy/zzz",
"timeout": 10000
}
]
}
]
}
}
示例五:只跑一次的初始化钩子
{
"hooks": {
"SessionStart": [
{
"hooks": [
{
"type": "command",
"command": "echo 'Session initialized at $(date)'",
"once": true
}
]
}
]
}
}
once: true 表示这个钩子在每个会话中只执行一次。
Hook 输入和输出
输入(stdin)
每个钩子通过 stdin 收到一个 JSON 对象,包含通用字段和事件特有字段:
通用字段:
{
"session_id": "abc123",
"transcript_path": "/path/to/transcript.jsonl",
"cwd": "/your/project",
"permission_mode": "default"
}
事件特有字段:
| 事件 | 额外字段 |
|---|---|
| PreToolUse | tool_name, tool_input |
| PostToolUse | tool_name, tool_input, tool_output |
| UserPromptSubmit | user_prompt |
| Notification | notification_type, message |
| SessionStart | source |
| SessionEnd | reason |
| FileChanged | file_path, event |
输出(stdout JSON)
钩子可以输出结构化 JSON 控制 Claude Code 的行为:
{
"continue": true,
"decision": "approve",
"reason": "命令看起来是安全的",
"suppressOutput": false,
"systemMessage": "注意:这个命令已经被自动审查"
}
核心字段:
| 字段 | 类型 | 说明 |
|---|---|---|
continue | boolean | 是否继续执行 |
decision | string | "approve" 或 "block" |
reason | string | 人类可读的原因说明 |
suppressOutput | boolean | 是否隐藏钩子输出 |
systemMessage | string | 注入到对话中的系统消息 |
PreToolUse 特有输出:
{
"hookSpecificOutput": {
"permissionDecision": "allow",
"updatedInput": { "command": "npm test -- --coverage" },
"additionalContext": "已自动添加 coverage 参数"
}
}
通过 updatedInput,你可以在工具执行前修改它的输入——这是 Hook 系统最强大的能力之一。
异步钩子
有些钩子不需要阻塞主流程。比如发通知、写日志,你不想让 Claude Code 等它完成。
两种方式启用异步:
方式一:配置声明
{
"type": "command",
"command": "curl -X POST https://example.com/log",
"async": true,
"asyncRewake": true
}
async: true 让钩子在后台执行。asyncRewake: true 表示钩子完成后唤醒 Agent 处理结果。
方式二:运行时声明
钩子在 stdout 的第一行输出 {"async": true},即可转为异步模式。适合需要根据条件决定是否异步的场景。
权限决策优先级
当多个 PreToolUse 钩子同时对一个操作做出判断时,优先级如下:
deny > ask > allow
也就是说,只要有一个钩子说 deny,操作就会被拒绝。
重要: Hook 的 allow 决策 不会 绕过 settings.json 中的 deny/ask 权限规则。换句话说,你不能通过 Hook 来”解锁”被权限系统禁止的操作。
企业管控
企业管理员可以通过托管策略控制 Hook 系统:
| 策略 | 效果 |
|---|---|
allowManagedHooksOnly: true | 只执行托管钩子,忽略用户和项目配置的钩子 |
disableAllHooks: true | 禁用所有钩子(包括托管钩子) |
非托管设置中的 disableAllHooks 只能禁用非托管钩子——管理员的钩子永远不会被普通用户禁用。
实用技巧
技巧一:用 command 钩子做轻量检查
Shell 命令钩子启动快、开销小,适合做格式检查、文件存在性验证等轻量操作。退出码 2 是你的”紧急制动”——任何时候你都可以用它阻止一个操作。
技巧二:用 if 缩小触发范围
不要让每个 Bash 命令都触发钩子,用 if 字段精准过滤:
{
"type": "command",
"command": "run-safety-check.sh",
"if": "Bash(docker:*)"
}
只在 Docker 命令时才触发安全检查,避免不必要的开销。
技巧三:用 updatedInput 做命令增强
PreToolUse 钩子可以修改工具输入。比如,自动给所有 npm install 加上 --save-exact:
{
"type": "command",
"command": "read input && echo '{\"hookSpecificOutput\": {\"updatedInput\": {\"command\": \"'$(echo $input | jq -r .tool_input.command)' --save-exact\"}}}'"
}
技巧四:善用 once 避免重复
对于只需要跑一次的初始化逻辑(比如环境检查、依赖安装),加上 once: true 避免每次触发都重复执行。
技巧五:timeout 不要设太长
默认超时:command 无限制、prompt 30 秒、agent 60 秒、http 10 分钟。建议根据实际需求设一个合理的 timeout,防止钩子卡住拖慢整个会话。
写在最后
Hook 系统是 Claude Code 中最灵活的扩展机制。
/permissions 回答的是”能不能做”的问题,而 /hooks 回答的是”做的时候还能顺便干什么”。用好 Hook,你可以把 Claude Code 打造成一个高度自动化、符合团队规范的开发工作流。
不过也别过度设计——先从一两个简单的 command 钩子开始,比如”git push 前跑 lint”或”会话结束时发通知”。等你熟悉了 Hook 的输入输出机制,再逐步加入更复杂的 prompt 和 agent 钩子。
简单开始,按需增长。
更多同类文章
- 我做了个机器人,让团队在飞书里用 Claude Code
- Claude Code /fast:同样的 Opus,两倍速——值不值?
- Claude Code /init:10 秒自动生成 CLAUDE.md
- Claude Code MCP:让 AI 连接 GitHub、数据库等一切工具
- Claude Code /model:Opus、Sonnet、Haiku 怎么选?
- Claude Code 使用指南:从安装到实战,一篇就够(2026)
- Claude 全家桶:从聊天到写代码到自动办公,一文讲清楚
- CCBot - 研发提效 24 倍
- 震惊!程序员用这个工具,4分钟干完95分钟的活!效率暴涨24倍
- Claude Code /add-dir:被低估的 Monorepo 神器
- Claude Code /compact:释放上下文,不丢进度
- Claude Code /btw 命令详解:不打扰主线的快问快答
- Claude Code /stats:看看 AI 到底帮你写了多少代码
- Claude Code /status 命令详解:一眼看清会话全貌
- AI-first 创业公司,为什么只需要一种编程语言?
- Claude Code 引用外部知识的最佳实践:GitHub MCP + Context7
- Claude Code 省 Token 小技巧:感叹号的妙用
- Claude Code /resume 命令详解:别让对话白聊
- Claude Code /usage 命令详解:你的额度还剩多少
- Claude Code /tasks 命令详解:后台任务尽在掌控
- Claude Code Skills 详解:打造你的专属命令库
- Claude Code /plan 详解:先想清楚再动手
- Claude Code /memory 详解:让 AI 真正记住你的项目
- cc-ping:一行命令 Ping 所有 Claude Code 配置
- Claude Code /config:一文搞懂所有可调设置
- Claude Code /permissions:谁能干什么,你说了算
- Claude Code /review:让 AI 帮你做 Code Review
- Claude Code /context:你的上下文都被什么吃了?
- Claude Code /diff:这次对话改了什么,一目了然
- Claude Code /vim:在 AI 编程助手里用 Vim 键位
- Claude Code + Playwright MCP:AI 终于能"看见"页面了