高级功能

Hooks:打造你的 专属工作流

在 Claude Code 工具调用的每个环节插入自定义逻辑——代码格式化、测试运行、安全检查,一切自动化

#Hooks #Automation #ClaudeCode #CI/CD

什么是 Claude Code Hooks?

Hooks 是 Claude Code 的事件钩子系统,允许你在工具调用前后执行自定义 shell 脚本。通过 Hooks,你可以在文件保存后自动运行 linter、在代码提交前执行测试、在操作敏感文件时触发告警——无需手动干预,完全自动化。

配置分三层:先挑事件,再用 matcher 过滤工具,处理脚本写在最内层的 hooks 数组里。脚本从标准输入读这次事件的 JSON,再用退出码表态:0 表示没有异议,2 在允许拦的事件上直接挡下这次调用;下面四种事件上,命令型钩子默认 600 秒才超时。这四种是最常用的,官方参考列出的时点不止它们(核于 2026-09-22)。

用户
输入一条指令
Hook 拦截点
PreToolUse 先检查,可当场拦下
工具执行
通过后才轮到工具干活

Hook 类型详解

Claude Code 的 Hook 覆盖工具调用、会话与压缩等生命周期节点,可挂命令、HTTP 与 agent 三类处理器

PreToolUse 工具调用前

工具执行前触发,可用于参数校验、权限检查、自动审批或拒绝操作

"PreToolUse": [{ "matcher": "Bash", "hooks": [{ "type": "command" }] }]

PostToolUse 工具调用后

工具执行后触发,可用于自动格式化、运行测试、发送通知

"PostToolUse": [{ "matcher": "Edit|Write", "hooks": [{ "type": "command" }] }]

Notification 通知发出时

Claude Code 发送通知时触发,可集成 Slack、邮件等外部通知渠道

"Notification": [{ "matcher": "permission_prompt", "hooks": [{ "type": "command" }] }]

Stop 回合结束时

Claude Code 结束响应时触发,可用于自动记录日志或执行清理操作

"Stop": [{ "hooks": [{ "type": "command", "command": "~/scripts/on-stop.sh" }] }]

常见自动化场景三例

下面三个场景走的是同一套结构:选定事件、用 matcher 收窄到具体工具、把脚本放进内层 hooks 数组。片段只示意意图,字段名与嵌套以官方参考为准;脚本要判断的东西,都从标准输入那份 JSON 里取。

1

提交前先跑格式化

Claude 准备执行 git commit 时,PreToolUse 先把参数交给你的脚本。脚本认出提交命令就先跑格式化,再用退出码表态:0 放行这次调用,2 直接挡下。这一切发生在命令执行之前,所以被挡住时工作目录没有被改过。

{
  "hooks": {
    "PreToolUse": [{
      "matcher": "Bash",
      "command": "if echo \"$TOOL_INPUT\" | grep -q 'git commit'; then npm run format; fi"
    }]
  }
}
2

测试跑完发通知

命令成功返回之后 PostToolUse 才触发,脚本认出 pytest 或 npm test 就发一条桌面通知。这个事件拦不回已经跑完的调用,命令失败时它也不响,所以通知的含义是「结果可以看了」,不是「测试通过了」。

{
  "hooks": {
    "PostToolUse": [{
      "matcher": "Bash",
      "command": "if echo \"$TOOL_INPUT\" | grep -q 'pytest\\|npm test'; then notify-send 'Tests completed'; fi"
    }]
  }
}
3

拦住改敏感文件的写入

给 Edit 和 Write 挂上 PreToolUse,脚本从标准输入拿到目标路径,命中 .env、credentials 这类名字就返回退出码 2。写入在落盘之前就被拒,不用事后回滚。matcher 写 Edit|Write 就能同时盯住两个工具。

{
  "hooks": {
    "PreToolUse": [{
      "matcher": "Edit|Write",
      "command": "if echo \"$TOOL_INPUT\" | grep -qE '\\.env|credentials|secrets'; then exit 2; fi"
    }]
  }
}

Headless 模式与 CI/CD

使用 claude -p 标志在 CI/CD 管道中运行 Claude Code,实现无人值守的自动化任务

-p 非交互模式

给 claude 命令加上 -p(即 --print),跳过交互界面直接跑完,把结果一次性输出。

接进 CI 管道

非交互模式读 stdin、写 stdout,成功返回退出码 0,构建脚本可据此判断下一步。

--output-format 结构化输出

输出形式由 --output-format 控制;选 json 时,结果会带上会话 ID 等元数据,方便脚本解析。

CI 里的非交互调用示例
# 非交互跑一次审查:JSON 输出,最多 5 轮
claude -p "Review this PR and suggest improvements" \
  --output-format json \
  --max-turns 5

settings.json 配置示例

在 .claude/settings.json 中定义你的 Hooks

.claude/settings.json
{
  "hooks": {
    "PreToolUse": [
      {
        "matcher": "Bash",
        "command": "~/scripts/pre-bash-hook.sh"
      },
      {
        "matcher": "Edit|Write",
        "command": "~/scripts/protect-sensitive-files.sh"
      }
    ],
    "PostToolUse": [
      {
        "matcher": "Bash",
        "command": "~/scripts/post-bash-hook.sh"
      }
    ],
    "Notification": [
      {
        "command": "~/scripts/send-notification.sh"
      }
    ],
    "Stop": [
      {
        "command": "~/scripts/on-stop.sh"
      }
    ]
  }
}

Hooks 编写最佳实践

下面四条按 Claude Code 官方 Hooks 文档整理,含其中的安全实践一节,核于 2026-09-22;讲的是脚本本身怎么写,配置形状见上面 settings.json 一节。

拦截请用退出码 2

官方写明,多数 Hook 事件里只有退出码 2 能凭自身拦下操作,其余退出码算非阻塞错误,动作照常进行。真要执行策略的脚本,失败时得显式 exit 2。

用 matcher 收窄触发

matcher 决定脚本在哪些调用上跑。官方说明它是过滤机制:只有名字本身时按精确匹配,掺进其他字符就当成未锚定的 JavaScript 正则求值。举例 Edit.* 会同时命中 Edit 与 NotebookEdit,要整串匹配得自己加首尾锚点。

超时不等于拦住

Claude Code 会取消到达超时的 Hook 并丢弃输出,多数事件上等于没给出决定;官方点名 PreToolUse 上超时的命令类 Hook 不拦这次调用,而 PreModelSwitch 上超时反而拦住切换。排查看 debug 日志,执行细节都写在里面。

把输入当成不可信

官方安全实践列了几条:别盲信输入数据、shell 变量一律加引号、检查 ../ 这类路径穿越、跳过 .env 与 .git 等敏感文件。Hook 拿到的输入本来就是一段 JSON,字段里可能塞着外部内容。

常见问题

Hook 脚本怎么拿到输入 JSON?

命令类 Hook 通过标准输入收到一段 JSON。公共字段有 session_id、transcript_path、cwd、hook_event_name 等,各事件再叠加自己的字段,工具类事件里就是 tool_name 与 tool_input。

怎么让 Hook 拦下一次工具调用?

把脚本挂到 PreToolUse 上,遇到不该放行的调用就返回退出码 2。官方事件表把 PreToolUse 标为可拦,退出码 2 直接挡住这次调用;想带条件放行,可以改输出含 permissionDecision 的 JSON。退出码 1 在多数事件上挡不住。

Hook 超时或脚本报错会怎样?

到超时的 Hook 会被取消、输出被丢弃,多数事件上等于没给出任何决定,只有 PreModelSwitch 会因超时被拦住。脚本路径写错也只算非阻塞错误,动作照常进行,官方建议策略 Hook 第一次跑就确认这条提示。

Hooks 配置写在哪个文件里?

作用范围由定义位置决定:~/.claude/settings.json 覆盖你的全部项目但只留在本机;项目里的 .claude/settings.json 只作用于单个项目,可以提交进仓库;.claude/settings.local.json 同样按项目走,Claude Code 往里存设置时会被 gitignore。

QCode.cc 企业自动化

结合 QCode.cc 开发者工具与 Hooks 系统,打造企业级 AI 编程自动化流水线

ANTHROPIC_BASE_URL 网关接入

Claude Code 官方变量表写明,ANTHROPIC_BASE_URL 可把 API 端点指向代理或网关;QCode 站内有一篇专讲这条链路的配置指南(核于 2026-09-22)。

先装刹车,再谈自动化

自动化上线前先装刹车:官方示例演示脚本按受保护模式清单检查目标路径,用退出码 2 拦下对敏感文件的编辑。

团队共用同一份配置

官方配置位置表说明 .claude/settings.json 可随项目提交进仓库;配一把团队共用的 QCode 密钥,全组的 Hook 口径就一致了。

同一套餐三平台共享

QCode 同时支持 OpenAI Codex / GPT-5.6

你的 QCode 套餐配额可同时用于 Claude Code 与 OpenAI Codex CLI,共享额度,无需重复购买。

开始自动化你的 Claude Code 工作流

用 Hooks + QCode.cc 释放 AI 编程的全部潜力

更新于 2026-09-22

先体验,再决定

不确定选哪档?先买体验版(¥60/月),满意再升级,旧套餐剩余价值按比例退回余额。