Hook:规则之外,插入用户自定义逻辑
什么是 Hook? 想象 Claude Code 的运行过程是一条流水线:用户输入 → Claude 思考 → 工具执行 → 返回结果。Hook 就是在这条流水线的特定位置预留的"插座"——你可以在插座上接入自己的逻辑,在那个时机自动触发。
举个具体例子:PreToolUse(工具执行前)这个 Hook,可以让你接入一段脚本,每次 Claude 要执行 Bash 命令之前,先把命令发给你的安全审计系统做检查。如果检查不通过,脚本返回"拒绝",Claude 就不会执行这个命令。整个流水线不需要为你修改,你只是在关键位置"挂上了一个钩子"。
Hooks(钩子) 是这套安全机制里最灵活的部分。它允许用户/企业在 Claude 的操作生命周期各个关键节点,插入自定义逻辑。
所有 Hook 事件
// src/entrypoints/sdk/coreTypes.ts
const HOOK_EVENTS = [
'PreToolUse', // 工具执行前
'PostToolUse', // 工具执行后(成功)
'PostToolUseFailure', // 工具执行后(失败)
'UserPromptSubmit', // 用户提交消息时
'SessionStart', // 会话开始
'SessionEnd', // 会话结束
'Stop', // Claude 完成回复
'StopFailure', // Claude 回复失败
'SubagentStart', // 子 Agent 启动
'SubagentStop', // 子 Agent 结束
'PreCompact', // 上下文压缩前
'PostCompact', // 上下文压缩后
'PermissionRequest', // 权限请求时
'PermissionDenied', // 权限被拒绝时
'WorktreeCreate', // 创建 git worktree
'WorktreeRemove', // 删除 git worktree
'FileChanged', // 文件变更时
// ...还有更多
]
Hook 的四种类型
| 类型 | 做什么 | 典型用法 |
|---|---|---|
command | 执行一段 shell 脚本 | 保存后自动格式化、提交前运行 lint |
prompt | 让 Claude 处理一个提示词 | AI 审核即将执行的操作是否合理 |
agent | 启动一个子 Agent | 复杂的自动化审查逻辑 |
http | 发送 HTTP 请求 | 通知外部系统、写入审计日志 |
Hook 的来源与优先级
policySettings ← 企业强制(allowManagedHooksOnly 时,用户 hook 全部禁用)
userSettings ← 用户全局 (~/.claude/settings.json)
projectSettings ← 项目级 (.claude/settings.json)
localSettings ← 本地私有 (.claude/settings.local.json)
pluginHook ← 插件注册的 hook(最低优先级)
sessionHook ← 当次会话临时 hook
企业管控能力: 当 allowManagedHooksOnly = true 时,用户的所有 Hook 配置都被忽略,只执行管理员下发的 Hook。这是企业合规场景的关键能力。
实际示例
场景:防止 Claude 修改生产环境配置文件
// .claude/settings.json
{
"hooks": {
"PreToolUse": [{
"matcher": "FileEdit",
"hooks": [{
"type": "command",
"command": "if [[ '$CLAUDE_TOOL_INPUT_PATH' == *'/prod/'* ]]; then echo 'Blocked: production files are read-only'; exit 2; fi"
}]
}]
}
}
当 Claude 试图编辑任何 /prod/ 路径下的文件时,这个 Hook 就会拦截并返回错误,Claude 收到错误后会调整方案。