Claude Code的Hooks操作

一、Hooks 的核心定位

Claude Code Hooks 是一套面向 AI Agent 生命周期的事件驱动自动化机制。

它允许你在 执行前、执行后以及对话过程中 注入自定义逻辑,让 Claude 自动遵循你的工程规范与工作流约束。

其运行机制如下:

  • 监听事件:Claude 在特定生命周期节点触发事件
  • 执行脚本:Hook 自动调用预设的外部脚本
  • 接收上下文:脚本以标准 JSON 格式获取运行时信息
  • 反馈控制:通过 退出码 + JSON 输出 决定 Claude 的下一步行为

二、hooks配置文件

项目级别的 Claude Code 的 Hooks 配置通常放在:

plain 复制代码
.claude/settings.json

示例json:

plain 复制代码
{
  "hooks": {
    "事件名": [
      {
        "matcher": "工具匹配",
        "if": "条件过滤",
        "hooks": [
          {
            "type": "command",
            "command": "执行脚本",
            "timeout": 10
          }
        ]
      }
    ]
  }
}

matcher 与 if 的区别

  1. matcher:监听哪个工具
  • 表示: 只监听 Bash 工具
plain 复制代码
"matcher": "Bash"
  • 表示: 监听文件写入类工具
plain 复制代码
"matcher": "Write|Edit"
  • 表示:监听 GitHub MCP 工具
plain 复制代码
"matcher": "mcp__github__.*"
  1. if:这个工具的哪些调用才触发
  • 表示:Bash 工具里 只有 git push 才触发
plain 复制代码
"if": "Bash(git push*)"
  1. 二者同时满足才执行
plain 复制代码
matcher = 工具级过滤
if      = 调用级过滤

三、核心的Hook Event

3.1 Hook的输入机制

python 复制代码
Claude 内部事件发生
        ↓
构造 JSON payload
        ↓
写入 hook 程序 stdin
        ↓
执行你的脚本
        ↓
读取 stdout / exit code / stderr
        ↓
决定是否阻断 / 附加信息 / 继续执行
exitcode=2表示阻止执行 exitcode=0继续执行

3.2 PreToolUse

主要在工具执行前触发,用于校验、拦截、做安全限制

例如:

  • 禁止 rm -rf
  • 禁止生产库操作
  • 禁止 git push main
  • 限制 curl 外网

setting.json

plain 复制代码
{
  "hooks": {
    "PreToolUse": [
      {
        "matcher": "Bash",
        "hooks": [
          {
            "type": "command",
            "command": "python3 .claude/hooks/check-dangerous.py"
          }
        ]
      }
    ]
  }
}

**check-dangerous.py **

python 复制代码
import json
import sys
import os

data = json.load(sys.stdin)

cmd = data.get("tool_input", {}).get("command", "")

log_path = os.path.join(os.path.dirname(__file__), "hook.log")
with open(log_path, "a", encoding="utf-8") as f:
    f.write(f"[HOOK RUNNING] cmd={cmd}\n")
    f.write(f"[RAW DATA] {json.dumps(data, ensure_ascii=False)}\n")

dangerous = [
    "rm -rf",
    "sudo ",
    "git push origin main"
]

for d in dangerous:
    if d in cmd:
        with open(log_path, "a", encoding="utf-8") as f:
            f.write(f"[BLOCKED] dangerous command: {cmd}\n")
        print(f"Blocked dangerous command: {cmd}", file=sys.stderr)
        sys.exit(2)

with open(log_path, "a", encoding="utf-8") as f:
    f.write(f"[ALLOWED] cmd={cmd}\n")
sys.exit(0)

如果Claude 想执行:

plain 复制代码
rm -rf node_modules

直接被拦截:

plain 复制代码
Blocked dangerous command

3.3 PostToolUse

主要在工具执行后触发。当 Claude 调用的某个 tool(如 Bash / Write / Edit / MCP)执行完成之后,立刻触发。 主要用于:

  • 自动 lint
  • 自动 format
  • 自动记录
  • 自动补充上下文

setting.json

python 复制代码
{
  "hooks": {
    "PostToolUse": [
      {
        "matcher": "Write|Edit",
        "hooks": [
          {
            "type": "command",
            "command": "bash .claude/hooks/auto-lint.sh"
          }
        ]
      }
    ]
  }
}

auto-lint.sh

plain 复制代码
#!/bin/bash

npm run eslint
npm run prettier

3.4 UserPromptSubmit

用户输入后、Claude 处理前触发。主要用于:

  • Prompt 改写
  • 自动注入规范
  • 自动增加上下文
  • 敏感词过滤

setting.json

python 复制代码
{
  "hooks": {
    "UserPromptSubmit": [
      {
        "matcher": ".*",
        "hooks": [
          {
            "type": "command",
            "command": "python3 .claude/hooks/inject-rules.py"
          }
        ]
      }
    ]
  }
}

inject-rules.py

python 复制代码
import json
import sys

data = json.loads(sys.stdin.read())

prompt = data.get("prompt", "")

rules = """

【团队规范】
1. 不允许修改 public API
2. 必须兼容 Vue2
3. 必须写中文注释
"""

if "【团队规范】" not in prompt:
    data["prompt"] = prompt + rules

print(json.dumps(data), flush=True)

3.5 Stop

Claude 回复结束后触发。主要用于:

  • 最终检查
  • 自动测试
  • 自动总结
  • 自动提交日志

setting.json

python 复制代码
{
  "hooks": {
    "Stop": [
      {
        "matcher": ".*",
        "hooks": [
          {
            "type": "command",
            "command": "bash .claude/hooks/run-test.sh"
          }
        ]
      }
    ]
  }
}

run-test.sh

plain 复制代码
#!/bin/bash
echo "Running tests..."
mvn test

3.6 CwdChanged

主要用于目录变化触发, 自动切换环境

例如:

  • 自动切换 Python venv
  • 自动加载 .env
  • 自动切换 MCP 配置

settings.json

plain 复制代码
{
  "hooks": {
    "CwdChanged": [
      {
        "matcher": ".*",
        "hooks": [
          {
            "type": "command",
            "command": "bash .claude/hooks/load-env.sh"
          }
        ]
      }
    ]
  }
}

load-env.sh

plain 复制代码
#!/bin/bash

if [ -f .env ]; then
  export $(cat .env | xargs)
fi

3.7 TaskCreated

创建子任务时触发。

setting.json

python 复制代码
{
  "hooks": {
    "TaskCreated": [
      {
        "matcher": ".*",
        "hooks": [
          {
            "type": "command",
            "command": "python3 .claude/hooks/log-task.py"
          }
        ]
      }
    ]
  }
}

log-task.py

python 复制代码
import json
import sys

data = json.load(sys.stdin)

print("=== Task Created ===")
print(json.dumps(data, indent=2))

3.8 WorktreeCreate

当 Claude 遇到复杂任务,比如: 它可能不会在一个环境里做,而是拆成多个"并行 Agent"

例如:

  • Agent A:重构 service
  • Agent B:修 bug
  • Agent C:写测试
  • Agent D:性能优化

每个 Agent 会有不同的worktree

setting.json

python 复制代码
{
  "hooks": {
    "WorktreeCreate": [
      {
        "matcher": ".*",
        "hooks": [
          {
            "type": "command",
            "command": "python3 .claude/hooks/log-worktree.py"
          }
        ]
      }
    ]
  }
}

log-worktree.py

python 复制代码
import json
import sys

data = json.load(sys.stdin)

wt = data.get("worktree", {})

print("Worktree created:")
print("Path:", wt.get("path"))
print("Branch:", wt.get("branch"))
print("Task:", wt.get("task_id"))

3.9 PreCompact

Claude context 满了会压缩。PreCompact:压缩前触发,也可以阻止压缩

主要用于:

  • snapshot
  • 保存上下文
  • 防止关键上下文丢失

setting.json

plain 复制代码
{
  "hooks": {
    "PreCompact": [
      {
        "matcher": "auto",
        "hooks": [
          {
            "type": "command",
            "command": "python3 .claude/hooks/prevent-compact.py"
          }
        ]
      }
    ]
  }
}

** prevent-compact.py **

python 复制代码
import json

print(json.dumps({
    "decision": "block",
    "reason": "大型重构进行中,禁止压缩上下文"
}))

四、Hook Type(Hook 的执行方式)

Claude Hooks 目前支持 5 类型:

plain 复制代码
command
prompt
agent
http
mcp_tool

4.1 command hook

用于执行本地的命令

比如:

  • shell
  • python
  • node
  • bash

4.2 prompt hook

它不是跑脚本,而是再调用一次模型来做判断,Claude执行任务完成了,但你想强制它检查:

  • 有没有改完所有文件
  • 测试有没有通过
  • 是否遗漏 TODO
plain 复制代码
{
  "hooks": {
    "Stop": [
      {
        "hooks": [
          {
            "type": "prompt",
            "prompt": "检查当前任务是否真的完成:1.所有相关文件是否修改完整?2.是否遗漏测试?3.是否存在未解决的 TODO 或报错?如果未完成,请列出缺失点并要求继续工作。",
            "timeout": 30
          }
        ]
      }
    ]
  }
}

4.3 agent hook

这个是 直接启动一个"子agent"去完成一整套验证流程 ,比较重量级。比如Claude 改完代码后:开启一个自动重构验证 agent。

plain 复制代码
{
  "hooks": {
    "Stop": [
      {
        "hooks": [
          {
            "type": "agent",
            "prompt": "检查当前代码是否符合 Clean Architecture:Controller/Service/Repository 是否分层正确?是否存在跨层调用?如果不符合,请指出具体文件和修改建议。"
          }
        ]
      }
    ]
  }
}

4.4. http hook

把 hook 事件"转发到远程 HTTP 服务"的机制 ,POST JSON 到远程服务

plain 复制代码
{
  "hooks": {
    "PostToolUse": [
      {
        "hooks": [
          {
            "type": "http",
            "url": "https://api.my-company.com/claude/hooks"
          }
        ]
      }
    ]
  }
}

4.5 mcp_tool hook

用 Claude 的 MCP 工具系统来执行 hook 动作 。比如 Claude 完成任务后发 Slack 消息 。

plain 复制代码
{
  "hooks": {
    "Stop": [
      {
        "hooks": [
          {
            "type": "mcp_tool",
            "server": "slack",
            "tool": "send_message",
            "input": {
              "channel": "#deploys",
              "text": "Claude finished the task"
            }
          }
        ]
      }
    ]
  }
}

五、Skill Scoped Hooks

Hook 不一定是全局生效的,它可以只在某个 Claude Skill 运行期间才触发的 Hooks

5.1 普通 Hook vs Skill Hook

1. 全局 Hook(默认)

任何 Bash 都会触发

plain 复制代码
{
  "hooks": {
    "PreToolUse": [
      {
        "matcher": "Bash",
        "hooks": [
          {
            "type": "command",
            "command": "./check.sh"
          }
        ]
      }
    ]
  }
}

2. Skill Scoped Hook(局部)

在 Skill 内定义:

plain 复制代码
---
name: production-deploy
hooks:
  PreToolUse:
    - matcher: "Bash"
      hooks:
        - type: command
          command: "./scripts/production-safety-check.sh"
          once: true
---

执行范围

类型 作用范围
Global hook 所有对话
Skill hook 仅当前 skill

六、once: true

这个 hook 在一个 session(会话)里只执行一次 , 防止这个 hook 在同一轮 Claude 工作流里重复触发

plain 复制代码
{
  "type": "command",
  "command": "./init-check.sh",
  "once": true
}

主要用于:

  • 环境检查
  • 初始化
  • login

初始化环境检查

plain 复制代码
{
  "hooks": {
    "PreToolUse": [
      {
        "matcher": "Bash",
        "hooks": [
          {
            "type": "command",
            "command": "./scripts/check-env.sh",
            "once": true
          }
        ]
      }
    ]
  }
}

check-env.sh

bash 复制代码
#!/bin/bash

echo "Checking environment..."

if [ ! -f ".env" ]; then
  echo "Missing .env file"
  exit 2
fi
相关推荐
shuangrenlong7 小时前
claude插件Superpowers安装
ai编程
ZZH_AI项目交付8 小时前
AI 改完代码后,下一轮不能只看它改了哪些文件
aigc·ai编程
孟健8 小时前
两个免费工具站月访 118 万,它们到底靠什么赚钱?
ai编程
浩风祭月8 小时前
把慢查询日志扔给 AI,从分析到修复只用了半小时:一份完整的实操手册
后端·ai编程
牛肉烧烤屋9 小时前
为什么大模型需要“思考模式”?
aigc·ai编程·deepseek
AINative软件工程10 小时前
OpenClaw 上下文瘦身:3 个实验
ai编程
冰凌时空10 小时前
30 Apps 第 2 天:待办清单 App —— MVVM + Combine 响应式 UI
ios·openai·ai编程
冰凌时空10 小时前
手写 Swift 运行时:objc_msgSend 的汇编级解析
ios·openai·ai编程
子兮曰10 小时前
AI Coding 为什么全选了 TUI?从 Claude Code 到 Codex CLI,终端架构的底层逻辑
前端·后端·ai编程