Claude Code Hooks的原理、触发执行机制以及如何编写 Hooks

https://code.claude.com/docs/zh-CN/hooks-guide

Hooks介绍

1. Hooks 的原理是什么?

Hooks 是用户定义的自动化脚本或逻辑(可以是 Shell 命令、HTTP 端点、LLM 提示或子代理),它们嵌入在 Claude Code 的生命周期中。

  • 核心机制:当 Claude Code 运行到生命周期的特定节点(如会话开始、工具调用前、任务完成时)时,会检查配置文件中是否定义了匹配的 Hooks。
  • 数据交互
    • 输入 :Claude Code 将当前事件的上下文(如工具名称、命令内容、文件路径等)序列化为 JSON 数据。
      • 对于命令型 Hooks,JSON 通过 stdin 传递。
      • 对于 HTTP 型 Hooks,JSON 作为 POST 请求体发送。
    • 输出 :Hook 处理程序执行后,返回结果给 Claude Code。
      • 控制流 :通过退出代码(Exit Code)或返回特定的 JSON 字段(如 permissionDecision: "deny"decision: "block")来告诉 Claude Code 是允许继续阻止操作 还是修改输入
  • 目的 :用于实现安全验证(如禁止 rm -rf)、自动 linting、环境设置、审计日志记录或自定义工作流拦截。

2. 如何触发和执行?

Hooks 的触发和执行遵循以下流程:

A. 触发时机 (Lifecycle Events)

Hooks 在特定的生命周期事件发生时触发。常见的事件包括:

  • SessionStart: 会话开始时。
  • UserPromptSubmit: 用户提交提示后,Claude 处理前。
  • PreToolUse: 最常用 ,在工具(如 Bash, Write, Read)执行之前。可用于拦截和修改工具调用。
  • PostToolUse: 工具成功执行后。
  • Stop: Claude 准备结束回答时。
  • 其他:PermissionRequest, SubagentStart, TaskCompleted 等。
B. 匹配机制 (Matching)

当事件触发时,系统会检查配置文件中的 matcher(匹配器):

  • 如果事件支持匹配器(如 PreToolUse),它会检查工具名称(如 Bash, Write)是否匹配正则表达式。
  • 如果不匹配,Hook 被跳过;如果匹配(或未定义匹配器),则执行 Hook。
C. 执行流程
  1. 事件发生 :例如,Claude 决定运行 Bash: rm -rf /tmp
  2. 数据发送 :Claude 将包含 tool_name: "Bash"tool_input: { command: "rm -rf /tmp" } 的 JSON 发送给 Hook。
  3. Hook 运行
    • Command Hook: 运行本地 Shell 脚本。
    • HTTP Hook: 发送 HTTP POST 请求到指定 URL。
    • Prompt/Agent Hook: 调用 LLM 或生成子代理进行判断。
  4. 结果处理
    • 允许 :脚本退出码为 0 且无阻止指令 -> Claude 继续执行原操作。
    • 阻止 :脚本退出码为 2 或返回 JSON { "permissionDecision": "deny" } -> Claude 取消操作并报错。
    • 修改 :返回 JSON 包含 updatedInput -> Claude 使用修改后的参数执行。

3. 如何写一个 Hooks?

编写 Hooks 主要分为两步:配置定义实现逻辑

第一步:配置文件 (settings.json)

在项目根目录的 .claude/settings.json 或用户全局配置 ~/.claude/settings.json 中定义。

基本结构示例(拦截危险的 Bash 命令):

json 复制代码
{
  "hooks": {
    "PreToolUse": [ 
      {
        "matcher": "Bash", 
        "hooks": [
          {
            "type": "command",
            "command": ".claude/hooks/block-rm.sh"
          }
        ]
      }
    ]
  }
}
  • PreToolUse: 事件类型。
  • matcher: 过滤条件,这里只针对 Bash 工具。
  • type: 可以是 command (Shell), http, prompt, agent
  • command: 要执行的脚本路径。
第二步:实现脚本逻辑 (以 Command Hook 为例)

创建一个 Shell 脚本(如 .claude/hooks/block-rm.sh),使其可执行 (chmod +x)。

脚本逻辑模板:

  1. 读取输入 :从 stdin 读取 JSON。
  2. 解析数据:提取需要的信息(如命令字符串)。
  3. 判断逻辑:根据业务规则判断是否允许。
  4. 返回结果
    • 允许 :直接 exit 0
    • 阻止 :打印错误信息到 stderrexit 2或者 打印特定 JSON 到 stdoutexit 0

示例脚本内容 (block-rm.sh):

bash 复制代码
#!/bin/bash
# 从 stdin 读取 JSON 输入
INPUT=$(cat)
# 提取命令内容
COMMAND=$(echo "$INPUT" | jq -r '.tool_input.command')

# 检查是否包含危险命令
if echo "$COMMAND" | grep -q 'rm -rf'; then
  # 方法 A: 使用退出码 2 阻止 (简单粗暴)
  echo "Blocked: Destructive command detected!" >&2
  exit 2
  
  # 方法 B: 使用 JSON 输出阻止 (更灵活,可定制理由)
  # jq -n '{
  #   hookSpecificOutput: {
  #     hookEventName: "PreToolUse",
  #     permissionDecision: "deny",
  #     permissionDecisionReason: "Destructive command blocked by hook"
  #   }
  # }'
  # exit 0
else
  # 允许执行
  exit 0
fi
高级用法提示
  • 异步执行 :在配置中添加 "async": true,让 Hook 在后台运行(适用于耗时任务如运行测试套件),不会阻塞 Claude。
  • 基于 LLM 的判断 :设置 "type": "prompt",让 Claude 自己判断是否允许某个操作(例如:"检查这个文件修改是否符合代码规范")。
  • 环境变量 :脚本中可以使用 $CLAUDE_PROJECT_DIR 来获取项目根目录,确保路径正确。

通过以上步骤,您就可以根据需求定制 Claude Code 的行为,增强安全性或自动化工作流。


Hook 加载机制

Claude Code 有两种 hook 配置方式:

1. 插件 Hook(推荐方式)

在插件目录下的 hooks/hooks.json 中定义:

复制代码
插件目录/
└── hooks/
    └── hooks.json    ← Claude Code 启动时自动扫描发现

加载流程:

  1. Claude Code 启动时扫描所有已安装插件
  2. 检查每个插件是否存在 hooks/hooks.json
  3. 将发现的 hooks 加载到当前会话
  4. 插件必须被启用才能生效

2. 用户级 Hook

直接在 ~/.claude/settings.json 中配置:

json 复制代码
{
  "PreToolUse": [...],
  "Stop": [...]
}

特点:

  • 无需包裹层,直接在顶层定义事件
  • description 字段
  • 立即生效(下次会话)

大模型如何知道有 hooks?

不是大模型"知道",是 Claude Code 运行时框架在拦截事件时执行 hook 逻辑:

复制代码
用户发送消息
    ↓
Claude Code 拦截 [UserPromptSubmit hook 触发]
    ↓
执行 hook 配置的逻辑(prompt 或 command)
    ↓
根据 hook 输出决定如何处理
    ↓
大模型收到的是经过 hook 处理后的上下文

Hook 在框架层面执行,模型本身不知道有 hooks 存在。

生效条件

条件 说明
插件已启用 settings.jsonplugins 列表中
会话启动 Hook 在会话开始时加载
重启生效 修改 hooks 后需重启 Claude Code

配置位置对比

方式 配置文件 格式
插件 Hook 插件/hooks/hooks.json {"hooks": {...}}
用户 Hook ~/.claude/settings.json 直接顶层配置

常见误区

  • ❌ 不是用户手动定义的
  • ❌ 不是写在某处配置文件的
  • ✅ 由 Claude Code 运行时自动注入到 command hooks

可用场景

在所有 command hooks 中可直接使用:

json 复制代码
{
  "type": "command",
  "command": "bash $CLAUDE_PLUGIN_ROOT/scripts/validate.sh"
}

实际值示例

假设你正在使用 everything-claude-code 插件:

复制代码
CLAUDE_PLUGIN_ROOT = /Users/username/.claude/plugins/marketplaces/everything-claude-code

不同插件的 hook 运行时,CLAUDE_PLUGIN_ROOT 会指向各自插件目录。

相关的环境变量

变量 说明
$CLAUDE_PROJECT_DIR 项目根目录路径
$CLAUDE_PLUGIN_ROOT 插件目录路径
$CLAUDE_ENV_FILE SessionStart 专用:持久化环境变量的文件
$CLAUDE_CODE_REMOTE 是否运行在远程上下文

为什么使用它?

可移植性 :使用 $CLAUDE_PLUGIN_ROOT 而不是硬编码绝对路径,让 hook 脚本能在不同环境下复用。

bash 复制代码
# ✅ 好:可移植
bash $CLAUDE_PLUGIN_ROOT/scripts/validate.sh

# ❌ 差:硬编码路径
bash /Users/username/.claude/plugins/cache/claude-plugins-official/plugin-dev/55b58ec6e564/scripts/validate.sh
相关推荐
w_t_y_y1 小时前
codex(一)下载安装&使用
人工智能
唐兴通个人2 小时前
唐兴通应邀为平安财产险北京分公司高层主讲《新媒体营销》专项培训,引领保险业AI时代内容营销变革
人工智能
朗心心理2 小时前
朗心科技:以数智化引领心理健康服务新标杆
大数据·人工智能·科技·心理健康·朗心科技·数智化心理育人·一站式心理中心建设
LaughingZhu2 小时前
Product Hunt 每日热榜 | 2026-03-23
数据库·人工智能·经验分享·神经网络·chatgpt
一个帅气昵称啊3 小时前
基于.NET AgentFramework开发OpenClaw智能体框架
人工智能·自然语言处理·c#·.net·openclaw
Hello.Reader3 小时前
深度学习 — 从人工智能到深度学习的演进之路(一)
人工智能·深度学习
xingyuzhisuan4 小时前
适合推荐系统训练的GPU服务器配置选择
人工智能·ai
mwq301234 小时前
TencentOS Server 4 部署 Coze Studio 完整指南
人工智能