Claude Code官方文档Hooks参考

Claude Code Hooks 参考手册 - 事件 / Schema / JSON I/O 完整文档

Claude Code hook 事件、配置架构、JSON 输入/输出格式、退出代码、异步 hooks、HTTP hooks、提示 hooks 和 MCP 工具 hooks 的完整参考。

· 阅读约 26 分钟

有关包含示例的快速入门指南,请参阅使用 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 请求体到达。您的处理程序随后可以检查输入、采取行动并可选地返回决定。事件分为三种频率:每个会话一次(SessionStartSessionEnd)、每轮一次(UserPromptSubmitStopStopFailure)以及代理循环内的每个工具调用(PreToolUsePostToolUse)。

下表总结了每个事件何时触发。

Event触发时机
SessionStart会话开始或恢复时
Setup使用 --init-only 启动 Claude Code,或在 -p 模式中使用 --init--maintenance
UserPromptSubmit您提交提示时,在 Claude 处理之前
UserPromptExpansion用户键入的命令展开为提示时,在到达 Claude 之前。可以阻止展开
PreToolUse工具调用执行前。可以阻止
PermissionRequest权限对话出现时
PermissionDenied工具调用被自动模式分类器拒绝时。返回 {retry: true} 告诉模型可以重试被拒绝的工具调用
PostToolUse工具调用成功后
PostToolUseFailure工具调用失败后
PostToolBatch一批并行工具调用全部完成后,在下次模型调用之前
NotificationClaude Code 发送通知时
SubagentStartsubagent 被生成时
SubagentStopsubagent 完成时
TaskCreated通过 TaskCreate 创建任务时
TaskCompleted任务被标记为完成时
StopClaude 完成响应时
StopFailure因 API 错误结束回合时。输出和退出代码被忽略
TeammateIdleagent team 队友即将进入空闲状态时
InstructionsLoaded当 CLAUDE.md 或 .claude/rules/*.md 文件被加载到上下文中时
ConfigChange会话期间配置文件更改时
CwdChanged工作目录更改时
FileChanged监视的文件在磁盘上更改时
WorktreeCreate创建 worktree 时
WorktreeRemoveworktree 被删除时
PreCompact上下文压缩前
PostCompact上下文压缩完成后
ElicitationMCP 服务器在工具调用期间请求用户输入时
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"。以下是发生的情况:

  1. 事件触发PreToolUse 事件触发。Claude Code 将工具输入作为 JSON 通过 stdin 发送到 hook:

    { "tool_name": "Bash", "tool_input": { "command": "rm -rf /tmp/build" } }
    
  2. 匹配器检查 — 匹配器 "Bash" 与工具名称匹配,因此此 hook 组激活。

  3. If 条件检查if 条件 "Bash(rm *)" 匹配,因为 rm -rf /tmp/build 是匹配 rm * 的子命令,因此此处理程序生成。

  4. Hook 处理程序运行 — 脚本检查完整命令并找到 rm -rf,因此它将决定打印到 stdout:

    {
      "hookSpecificOutput": {
        "hookEventName": "PreToolUse",
        "permissionDecision": "deny",
        "permissionDecisionReason": "Destructive command blocked by hook"
      }
    }
    
  5. Claude Code 对结果采取行动 — Claude Code 读取 JSON 决定,阻止工具调用,并向 Claude 显示原因。

配置

Hooks 在 JSON 设置文件中定义。配置有三个嵌套级别:

  1. 选择要响应的 hook 事件,如 PreToolUseStop
  2. 添加匹配器组以过滤何时触发,如”仅针对 Bash 工具”
  3. 定义一个或多个 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 提示或代理。有五种类型:

  • 命令 hookstype: "command"):运行 shell 命令
  • HTTP hookstype: "http"):将事件的 JSON 输入作为 HTTP POST 请求发送到 URL
  • MCP 工具 hookstype: "mcp_tool"):在已连接的 MCP 服务器上调用工具
  • 提示 hookstype: "prompt"):向 Claude 模型发送提示以进行单轮评估
  • 代理 hookstype: "agent"):生成一个可以使用 Read、Grep 和 Glob 等工具来验证条件的 subagent

通用字段

这些字段适用于所有 hook 类型:

字段必需描述
type"command""http""mcp_tool""prompt""agent"
if权限规则语法以过滤此 hook 何时运行,例如 "Bash(git *)""Edit(*.ts)"。仅当工具调用与模式匹配时,hook 才会生成
timeout取消前的秒数。默认值:命令 600、提示 30、代理 60
statusMessagehook 运行时显示的自定义加载程序消息
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"hookSpecificOutputpermissionDecision: "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 直接在 skillssubagents 中定义。这些 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.json
  • Project:来自 .claude/settings.json
  • Local:来自 .claude/settings.local.json
  • Plugin:来自插件的 hooks/hooks.json
  • Session:在当前会话中在内存中注册
  • 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

会话开始/恢复时触发。用于加载上下文。

匹配器值: startupresumeclearcompact

通过 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。