claude-code-hooks-matcher-详解

hook执行时机匹配机制详解

matcher 是什么

matcher 是一个正则表达式,用于匹配 Claude Code 内置工具的名称。

它决定了 hook 在什么工具被调用时触发。


matcher 匹配规则

matcher 值匹配范围说明
"Bash"Bash 工具精准匹配单个工具
"Write"Write 工具精准匹配单个工具
"Edit|Write"Edit 或 Write| 分隔多个工具
"Bash|Write|Edit|MultiEdit"四个工具多工具组合
"*"所有工具广播模式,接收所有工具调用事件

两层过滤机制

Hook 系统使用两层过滤:

第一层:matcher 匹配工具名称

json
{
  "matcher": "Bash",
  "hooks": [{ "type": "command", "command": "check-script.sh" }]
}

作用:只在调用 Bash 工具时触发 hook

第二层:hook 脚本内部检查工具参数

Hook 脚本通过 stdin 接收 JSON 数据:

json
{
  "tool": "Bash",
  "input": {
    "command": "git push origin main"
  },
  "cwd": "/home/user/project",
  "session_id": "abc123"
}

脚本可以:

  • 检查 tool 字段判断工具类型
  • 检查 input.command 判断具体命令内容
  • 返回 exit code 0(允许继续)或 非0(阻止执行)

示例分析

精准狙击型

json
{
  "matcher": "Bash",
  "hooks": [{ "command": "npx block-no-verify@1.1.2" }],
  "description": "阻止 --no-verify 标志"
}

触发流程:

代码
Claude 准备执行 Bash 工具
    command: "git commit --no-verify -m 'xxx'"
    ↓
matcher: "Bash" 匹配 → hook 触发
    ↓
block-no-verify 检查命令内容
    发现 --no-verify 标志
    ↓
exit code 非0 → 阻止执行
    ↓
Claude 收到 hook 报错,不执行命令

广播型

json
{
  "matcher": "*",
  "hooks": [{ "command": "...mcp-health-check.js" }],
  "description": "MCP 健康检查"
}

触发流程:

代码
任何工具调用(Bash/Read/Write/...)
    ↓
matcher: "*" 匹配 → hook 触发
    ↓
mcp-health-check.js 读取 stdin
    检查 tool 字段是否是 MCP 相关工具
    ↓
如果是 MCP 工具且失败 → 执行健康检查逻辑

注意:matcher "*" 让脚本接收所有事件,但脚本内部判断是否需要处理。


Claude Code 内置工具列表

工具名称作用matcher 可用
Bash执行 shell 命令
Read读取文件
Write写入文件
Edit编辑文件
MultiEdit多处编辑
Glob文件模式匹配
Grep内容搜索
Agent启动子 agent
Skill执行 skill
TaskCreate创建任务
WebFetch获取网页
WebSearch搜索网络
AskUserQuestion询问用户

Hook 类型与时机

Hook 类型触发时机作用
PreToolUseClaude 准备调用工具门卫检查,决定是否执行
PostToolUseClaude 执行完工具质检员检查,后续处理
PostToolUseFailure工具执行失败错误处理、重试逻辑
SessionStart会话开始时加载上下文、初始化
PreCompact上下文压缩前保存状态
Stop会话结束时最终验证、清理

配置位置

Hook 配置文件位置:

  • 插件级~/.claude/plugins/cache/{plugin}/hooks/hooks.json
  • 用户级~/.claude/settings.json
  • 项目级:项目目录 .claude/settings.json

优先级:项目级 > 用户级 > 插件级(后加载覆盖)


总结

代码
matcher: "Bash"           → 精准狙击 Bash 工具
matcher: "Edit|Write"     → 精准狙击 Edit 和 Write
matcher: "*"              → 广播给所有工具

两层过滤:
1. matcher → 过滤工具名称
2. 脚本逻辑 → 过滤工具参数内容