Claude Code Hooks 参考手册 - 事件 / Schema / JSON I/O 完整文档
Claude Code hook 事件、配置架构、JSON 输入/输出格式、退出代码、异步 hooks、HTTP hooks、提示 hooks 和 MCP 工具 hooks 的完整参考。
有关包含示例的快速入门指南,请参阅使用 hooks 自动化工作流。
Hooks 是用户定义的 shell 命令、HTTP 端点或 LLM 提示,在 Claude Code 生命周期中的特定点自动执行。使用此参考查找事件架构、配置选项、JSON 输入/输出格式以及异步 hooks、HTTP hooks 和 MCP 工具 hooks 等高级功能。如果您是第一次设置 hooks,请改为从指南开始。
Hook 生命周期
Hooks 在 Claude Code 会话期间的特定点触发。当事件触发且匹配器匹配时,Claude Code 会将关于该事件的 JSON 上下文传递给您的 hook 处理程序。对于命令 hooks,输入通过 stdin 到达。对于 HTTP hooks,它作为 POST 请求体到达。您的处理程序随后可以检查输入、采取行动并可选地返回决定。事件分为三种频率:每个会话一次(SessionStart、SessionEnd)、每轮一次(UserPromptSubmit、Stop、StopFailure)以及代理循环内的每个工具调用(PreToolUse、PostToolUse)。
下表总结了每个事件何时触发。
| Event | 触发时机 |
|---|---|
SessionStart | 会话开始或恢复时 |
Setup | 使用 --init-only 启动 Claude Code,或在 -p 模式中使用 --init 或 --maintenance |
UserPromptSubmit | 您提交提示时,在 Claude 处理之前 |
UserPromptExpansion | 用户键入的命令展开为提示时,在到达 Claude 之前。可以阻止展开 |
PreToolUse | 工具调用执行前。可以阻止 |
PermissionRequest | 权限对话出现时 |
PermissionDenied | 工具调用被自动模式分类器拒绝时。返回 {retry: true} 告诉模型可以重试被拒绝的工具调用 |
PostToolUse | 工具调用成功后 |
PostToolUseFailure | 工具调用失败后 |
PostToolBatch | 一批并行工具调用全部完成后,在下次模型调用之前 |
Notification | Claude Code 发送通知时 |
SubagentStart | subagent 被生成时 |
SubagentStop | subagent 完成时 |
TaskCreated | 通过 TaskCreate 创建任务时 |
TaskCompleted | 任务被标记为完成时 |
Stop | Claude 完成响应时 |
StopFailure | 因 API 错误结束回合时。输出和退出代码被忽略 |
TeammateIdle | agent team 队友即将进入空闲状态时 |
InstructionsLoaded | 当 CLAUDE.md 或 .claude/rules/*.md 文件被加载到上下文中时 |
ConfigChange | 会话期间配置文件更改时 |
CwdChanged | 工作目录更改时 |
FileChanged | 监视的文件在磁盘上更改时 |
WorktreeCreate | 创建 worktree 时 |
WorktreeRemove | worktree 被删除时 |
PreCompact | 上下文压缩前 |
PostCompact | 上下文压缩完成后 |
Elicitation | MCP 服务器在工具调用期间请求用户输入时 |
ElicitationResult | 用户响应 MCP 引导后 |
SessionEnd | 会话终止时 |
Hook 如何解析
要了解这些部分如何组合在一起,请考虑这个 PreToolUse hook,它阻止破坏性 shell 命令。matcher 缩小到 Bash 工具调用,if 条件进一步缩小到匹配 rm * 的 Bash 子命令,因此 block-rm.sh 仅在两个过滤器都匹配时生成:
{
"hooks": {
"PreToolUse": [
{
"matcher": "Bash",
"hooks": [
{
"type": "command",
"if": "Bash(rm *)",
"command": "\"$CLAUDE_PROJECT_DIR\"/.claude/hooks/block-rm.sh"
}
]
}
]
}
}
该脚本从 stdin 读取 JSON 输入,提取命令,如果包含 rm -rf,则返回 permissionDecision 为 "deny":
#!/bin/bash
# .claude/hooks/block-rm.sh
COMMAND=$(jq -r '.tool_input.command')
if echo "$COMMAND" | grep -q 'rm -rf'; then
jq -n '{
hookSpecificOutput: {
hookEventName: "PreToolUse",
permissionDecision: "deny",
permissionDecisionReason: "Destructive command blocked by hook"
}
}'
else
exit 0
fi
现在假设 Claude Code 决定运行 Bash "rm -rf /tmp/build"。以下是发生的情况:
-
事件触发 —
PreToolUse事件触发。Claude Code 将工具输入作为 JSON 通过 stdin 发送到 hook:{ "tool_name": "Bash", "tool_input": { "command": "rm -rf /tmp/build" } } -
匹配器检查 — 匹配器
"Bash"与工具名称匹配,因此此 hook 组激活。 -
If 条件检查 —
if条件"Bash(rm *)"匹配,因为rm -rf /tmp/build是匹配rm *的子命令,因此此处理程序生成。 -
Hook 处理程序运行 — 脚本检查完整命令并找到
rm -rf,因此它将决定打印到 stdout:{ "hookSpecificOutput": { "hookEventName": "PreToolUse", "permissionDecision": "deny", "permissionDecisionReason": "Destructive command blocked by hook" } } -
Claude Code 对结果采取行动 — Claude Code 读取 JSON 决定,阻止工具调用,并向 Claude 显示原因。
配置
Hooks 在 JSON 设置文件中定义。配置有三个嵌套级别:
- 选择要响应的 hook 事件,如
PreToolUse或Stop - 添加匹配器组以过滤何时触发,如”仅针对 Bash 工具”
- 定义一个或多个 hook 处理程序以在匹配时运行
此页面为每个级别使用特定术语:hook 事件表示生命周期点,匹配器组表示过滤器,hook 处理程序表示运行的 shell 命令、HTTP 端点、MCP 工具、提示或代理。
Hook 位置
您定义 hook 的位置决定了其范围:
| 位置 | 范围 | 可共享 |
|---|---|---|
~/.claude/settings.json | 您的所有项目 | 否,本地于您的计算机 |
.claude/settings.json | 单个项目 | 是,可以提交到仓库 |
.claude/settings.local.json | 单个项目 | 否,gitignored |
| 托管策略设置 | 组织范围 | 是,管理员控制 |
Plugin hooks/hooks.json | 启用插件时 | 是,与插件捆绑 |
| Skill 或代理 frontmatter | 组件活跃时 | 是,在组件文件中定义 |
企业管理员可以使用 allowManagedHooksOnly 来阻止用户、项目和插件 hooks。在托管设置 enabledPlugins 中强制启用的插件中的 Hooks 是豁免的。
匹配器模式
matcher 字段过滤 hooks 何时触发。匹配器的评估方式取决于它包含的字符:
| 匹配器值 | 评估为 | 示例 |
|---|---|---|
"*"、"" 或省略 | 匹配所有 | 在事件的每次出现时触发 |
仅字母、数字、_ 和 | | 精确字符串或 | 分隔的精确字符串列表 | Bash 仅匹配 Bash 工具;Edit|Write 精确匹配任一工具 |
| 包含任何其他字符 | JavaScript 正则表达式 | ^Notebook 匹配任何以 Notebook 开头的工具;mcp__memory__.* 匹配来自 memory 服务器的每个工具 |
FileChanged 事件在构建其监视列表时不遵循这些规则。
每个事件类型在不同的字段上匹配(详见上文)。
匹配 MCP 工具
MCP 服务器工具在工具事件中显示为常规工具,因此您可以像匹配任何其他工具名称一样匹配它们。
MCP 工具遵循命名模式 mcp__<server>__<tool>,例如:
mcp__memory__create_entities:Memory 服务器的创建实体工具mcp__filesystem__read_file:Filesystem 服务器的读取文件工具mcp__github__search_repositories:GitHub 服务器的搜索工具
要匹配来自服务器的每个工具,请在服务器前缀后追加 .*。
mcp__memory__.*匹配来自memory服务器的所有工具mcp__.*__write.*匹配来自任何服务器的任何名称以write开头的工具
此示例记录所有内存服务器操作并验证来自任何 MCP 服务器的写入操作:
{
"hooks": {
"PreToolUse": [
{
"matcher": "mcp__memory__.*",
"hooks": [
{
"type": "command",
"command": "echo 'Memory operation initiated' >> ~/mcp-operations.log"
}
]
},
{
"matcher": "mcp__.*__write.*",
"hooks": [
{
"type": "command",
"command": "/home/user/scripts/validate-mcp-write.py"
}
]
}
]
}
}
Hook 处理程序字段
内部 hooks 数组中的每个对象都是一个 hook 处理程序:当匹配器匹配时运行的 shell 命令、HTTP 端点、MCP 工具、LLM 提示或代理。有五种类型:
- 命令 hooks(
type: "command"):运行 shell 命令 - HTTP hooks(
type: "http"):将事件的 JSON 输入作为 HTTP POST 请求发送到 URL - MCP 工具 hooks(
type: "mcp_tool"):在已连接的 MCP 服务器上调用工具 - 提示 hooks(
type: "prompt"):向 Claude 模型发送提示以进行单轮评估 - 代理 hooks(
type: "agent"):生成一个可以使用 Read、Grep 和 Glob 等工具来验证条件的 subagent
通用字段
这些字段适用于所有 hook 类型:
| 字段 | 必需 | 描述 |
|---|---|---|
type | 是 | "command"、"http"、"mcp_tool"、"prompt" 或 "agent" |
if | 否 | 权限规则语法以过滤此 hook 何时运行,例如 "Bash(git *)" 或 "Edit(*.ts)"。仅当工具调用与模式匹配时,hook 才会生成 |
timeout | 否 | 取消前的秒数。默认值:命令 600、提示 30、代理 60 |
statusMessage | 否 | hook 运行时显示的自定义加载程序消息 |
once | 否 | 如果为 true,每个会话仅运行一次,然后被移除。仅在 skill frontmatter 中声明的 hooks 中受尊重 |
命令 hook 字段
除了通用字段外,命令 hooks 还接受这些字段:
| 字段 | 必需 | 描述 |
|---|---|---|
command | 是 | 要执行的 shell 命令 |
async | 否 | 如果为 true,在后台运行而不阻止 |
asyncRewake | 否 | 如果为 true,在后台运行并在退出代码 2 时唤醒 Claude。暗示 async |
shell | 否 | 用于此 hook 的 shell。接受 "bash"(默认)或 "powershell" |
HTTP hook 字段
| 字段 | 必需 | 描述 |
|---|---|---|
url | 是 | 发送 POST 请求的 URL |
headers | 否 | 其他 HTTP 标头作为键值对。值支持使用 $VAR_NAME 或 ${VAR_NAME} 语法的环境变量插值 |
allowedEnvVars | 否 | 可能被插值到标头值中的环境变量名称列表 |
Claude Code 使用 Content-Type: application/json 将 hook 的 JSON 输入作为 POST 请求体发送。响应体使用与命令 hooks 相同的 JSON 输出格式。
错误处理与命令 hooks 不同:非 2xx 响应、连接失败和超时都会产生非阻止错误,允许执行继续。要阻止工具调用或拒绝权限,返回 2xx 响应,其 JSON 体包含 decision: "block" 或 hookSpecificOutput 与 permissionDecision: "deny"。
此示例将 PreToolUse 事件发送到本地验证服务:
{
"hooks": {
"PreToolUse": [
{
"matcher": "Bash",
"hooks": [
{
"type": "http",
"url": "http://localhost:8080/hooks/pre-tool-use",
"timeout": 30,
"headers": {
"Authorization": "Bearer $MY_TOKEN"
},
"allowedEnvVars": ["MY_TOKEN"]
}
]
}
]
}
}
MCP 工具 hook 字段
| 字段 | 必需 | 描述 |
|---|---|---|
server | 是 | 已配置的 MCP 服务器的名称 |
tool | 是 | 该服务器上要调用的工具的名称 |
input | 否 | 传递给工具的参数。字符串值支持从 hook 的 JSON 输入进行 ${path} 替换 |
工具的文本内容被视为命令 hook stdout:如果它解析为有效的 JSON 输出,则作为决定进行处理,否则显示为纯文本。
{
"hooks": {
"PostToolUse": [
{
"matcher": "Write|Edit",
"hooks": [
{
"type": "mcp_tool",
"server": "my_server",
"tool": "security_scan",
"input": { "file_path": "${tool_input.file_path}" }
}
]
}
]
}
}
提示和代理 hook 字段
| 字段 | 必需 | 描述 |
|---|---|---|
prompt | 是 | 要发送给模型的提示文本。使用 $ARGUMENTS 作为 hook 输入 JSON 的占位符 |
model | 否 | 用于评估的模型。默认为快速模型 |
所有匹配的 hooks 并行运行,相同的处理程序会自动去重。命令 hooks 按命令字符串去重,HTTP hooks 按 URL 去重。处理程序在当前目录中运行,使用 Claude Code 的环境。
按路径引用脚本
使用环境变量按项目或插件根目录引用 hook 脚本:
$CLAUDE_PROJECT_DIR:项目根目录。用引号包装以处理包含空格的路径。${CLAUDE_PLUGIN_ROOT}:插件的安装目录${CLAUDE_PLUGIN_DATA}:插件的持久数据目录
项目脚本
{
"hooks": {
"PostToolUse": [
{
"matcher": "Write|Edit",
"hooks": [
{
"type": "command",
"command": "\"$CLAUDE_PROJECT_DIR\"/.claude/hooks/check-style.sh"
}
]
}
]
}
}
插件脚本
在 hooks/hooks.json 中定义插件 hooks,带有可选的顶级 description 字段:
{
"description": "Automatic code formatting",
"hooks": {
"PostToolUse": [
{
"matcher": "Write|Edit",
"hooks": [
{
"type": "command",
"command": "${CLAUDE_PLUGIN_ROOT}/scripts/format.sh",
"timeout": 30
}
]
}
]
}
}
Skills 和代理中的 Hooks
除了设置文件和插件外,hooks 还可以使用 frontmatter 直接在 skills 和 subagents 中定义。这些 hooks 的范围限于组件的生命周期,仅在该组件活跃时运行。
支持所有 hook 事件。对于 subagents,Stop hooks 会自动转换为 SubagentStop。
---
name: secure-operations
description: Perform operations with security checks
hooks:
PreToolUse:
- matcher: "Bash"
hooks:
- type: command
command: "./scripts/security-check.sh"
---
/hooks 菜单
在 Claude Code 中键入 /hooks 以打开您配置的 hooks 的只读浏览器。菜单显示每个 hook 事件及其配置的 hooks 计数。
每个 hook 都标有 [type] 前缀和指示其定义位置的源:
User:来自~/.claude/settings.jsonProject:来自.claude/settings.jsonLocal:来自.claude/settings.local.jsonPlugin:来自插件的hooks/hooks.jsonSession:在当前会话中在内存中注册Built-in:由 Claude Code 内部注册
禁用或移除 hooks
要移除 hook,请从设置 JSON 文件中删除其条目。
要临时禁用所有 hooks 而不移除它们,请在设置文件中设置 "disableAllHooks": true。
disableAllHooks 设置遵守托管设置层次结构。如果管理员通过托管策略设置配置了 hooks,则在用户、项目或本地设置中设置的 disableAllHooks 无法禁用这些托管 hooks。
Hook 输入和输出
通用输入字段
所有 hooks 接收:
{
"session_id": "abc123",
"transcript_path": "/path/to/transcript.jsonl",
"cwd": "/current/working/dir",
"permission_mode": "default",
"hook_event_name": "PreToolUse",
"effort": { "level": "medium" },
"agent_id": "...",
"agent_type": "Explore"
}
退出代码
- 0:成功。解析 stdout 中的 JSON 输出
- 2:阻止错误。stderr 作为错误消息反馈
- 其他:非阻止错误。执行继续,stderr 显示在成绩单中
JSON 输出格式
{
"continue": true,
"stopReason": "原因",
"suppressOutput": false,
"systemMessage": "警告消息",
"hookSpecificOutput": {
"hookEventName": "PreToolUse",
"additionalContext": "为 Claude 的上下文",
"permissionDecision": "allow|deny|ask|defer"
}
}
关键 Hook 事件
SessionStart
会话开始/恢复时触发。用于加载上下文。
匹配器值: startup、resume、clear、compact
通过 CLAUDE_ENV_FILE 设置环境变量:
if [ -n "$CLAUDE_ENV_FILE" ]; then
echo 'export NODE_ENV=production' >> "$CLAUDE_ENV_FILE"
fi
PreToolUse
工具执行前触发。可以阻止、修改或询问。
决定选项:
"allow":绕过权限提示"deny":阻止工具调用"ask":提示用户确认"defer":暂停以供稍后使用
{
"hookSpecificOutput": {
"hookEventName": "PreToolUse",
"permissionDecision": "allow",
"updatedInput": {
"command": "modified command"
},
"additionalContext": "生产环境。谨慎行动。"
}
}
PostToolUse
工具成功后触发。可以修改 Claude 看到的输出。
{
"hookSpecificOutput": {
"hookEventName": "PostToolUse",
"updatedToolOutput": {
"stdout": "[redacted]"
},
"additionalContext": "文件已生成。编辑源代码重新生成。"
}
}
PermissionRequest
权限对话框前触发。代表用户允许/拒绝。
{
"hookSpecificOutput": {
"hookEventName": "PermissionRequest",
"decision": {
"behavior": "allow",
"updatedInput": {"command": "npm run lint"},
"updatedPermissions": [
{
"type": "addRules",
"rules": [{"toolName": "Bash", "ruleContent": "rm -rf node_modules"}],
"behavior": "allow",
"destination": "projectSettings"
}
]
}
}
}
UserPromptSubmit
用户提交提示前触发。可以阻止提示或添加上下文。
Stop
Claude 完成响应时触发。可以强制继续。
{
"decision": "block",
"reason": "必须继续的原因"
}
WorktreeCreate / WorktreeRemove
使用 --worktree 或隔离 subagent 时触发。
WorktreeCreate 输出:
# 命令 hook 返回路径到 stdout
echo "/absolute/path/to/worktree"
HTTP hook 返回:
{
"hookSpecificOutput": {
"hookEventName": "WorktreeCreate",
"worktreePath": "/absolute/path"
}
}
环境变量
在 hooks 中可用:
$CLAUDE_PROJECT_DIR:项目根目录${CLAUDE_PLUGIN_ROOT}:插件安装目录${CLAUDE_PLUGIN_DATA}:插件持久数据目录$CLAUDE_ENV_FILE:环境变量持久化文件(SessionStart/Setup/CwdChanged/FileChanged)$CLAUDE_EFFORT:当前努力级别(SessionStart 后)
常见用途
1. 验证 Bash 命令
#!/bin/bash
INPUT=$(cat)
COMMAND=$(echo "$INPUT" | jq -r '.tool_input.command')
# 检查危险命令
if [[ "$COMMAND" =~ (rm|dd|mkfs) ]]; then
echo "危险命令被阻止" >&2
exit 2
fi
exit 0
2. 自动批准安全操作
{
"hooks": {
"PreToolUse": [
{
"matcher": "Read",
"hooks": [
{
"type": "command",
"command": "jq -n '{hookSpecificOutput: {hookEventName: \"PreToolUse\", permissionDecision: \"allow\"}}'"
}
]
}
]
}
}
3. 在目录更改时加载环境
#!/bin/bash
# CwdChanged hook
if [ -f "$1/.env" ]; then
set -a
source "$1/.env"
set +a
if [ -n "$CLAUDE_ENV_FILE" ]; then
grep -v '^#' "$1/.env" >> "$CLAUDE_ENV_FILE"
fi
fi
exit 0
4. 监视文件更改
{
"hooks": {
"FileChanged": [
{
"matcher": ".env|.envrc",
"hooks": [
{
"type": "command",
"command": "/path/to/reload-env.sh"
}
]
}
]
}
}
禁用 Hooks
临时禁用所有 hooks:
{
"disableAllHooks": true
}
此设置遵守托管策略层次结构。
安全考虑
Hooks 在共享或生产环境中部署时需要谨慎:
- 审查所有 hook 命令:Hooks 在您的系统上以您的用户权限运行任意 shell 命令
- 限制范围:使用尽可能狭窄的匹配器和
if条件 - 避免 hook 中的敏感数据:不要在命令字符串中嵌入凭证或令牌;改用环境变量
- 验证输入:来自 Claude 的 JSON 输入可能包含意外内容;正确转义和验证
- 避免共享:将
.claude/settings.local.json用于个人 hooks,将.claude/settings.json用于团队共享的 hooks
更多详情,请参阅 Bash 命令验证器示例。
本文翻译自 Anthropic Claude Code 官方文档,最近一次同步:2025-05-01。