2026年用Hook机制给Claude-Code加上-刹车-和-安全带-

用Hook机制给Claude-Code加上-刹车-和-安全带-Claude Code 写代码确实快 但它万一执行了个 rm rf 怎么办 这是很多刚上手 Claude Code 的开发者最真实的焦虑 AI 编程工具越来越强 自动读文件 写代码 跑命令 效率确实起飞 但问题也随之而来 你没法控制它的每一个动作 它改了代码你希望自动格式化 它执行 Bash 命令你希望做安全检查 它写完文件你希望扫描有没有泄露密钥

大家好,我是讯享网,很高兴认识大家。这里提供最前沿的Ai技术和互联网信息。



“Claude Code 写代码确实快,但它万一执行了个 rm -rf / 怎么办?”

这是很多刚上手 Claude Code 的开发者最真实的焦虑。

AI 编程工具越来越强,自动读文件、写代码、跑命令,效率确实起飞。但问题也随之而来 —— 你没法控制它的每一个动作。它改了代码你希望自动格式化,它执行 Bash 命令你希望做安全检查,它写完文件你希望扫描有没有泄露密钥……

如果你有前端经验,你一定熟悉 Vue 的 mountedbeforeDestroy 这些生命周期钩子;如果你写过后端,Spring 的 @Before@After AOP 切面肯定不陌生。它们的共同本质是:在特定事件节点,注入自定义逻辑。 Claude Code 的 Hook 机制,做的正是这件事。

今天这篇文章,我会基于 Anthropic 官方文档和 GitHub 热门教程 claude-howto,用你最熟悉的前后端概念做类比,带你彻底搞懂 Claude Code 的 Hook 机制,并给出 6 个可以直接复制使用的实战配置。


Hook = 在特定事件发生时,自动执行你预设的逻辑。

不管是 Vue、Spring 还是 Claude Code,核心思想一模一样:

框架 Hook 机制 本质 Vue mounted()updated() 组件生命周期的回调函数 React useEffect(() => {}, []) 函数组件的副作用钩子 Spring @Before@AfterReturning AOP 切面,拦截方法调用前后 Claude Code PreToolUsePostToolUse 工具调用生命周期的事件钩子

用一张图理解 Claude Code 的 Hook 工作流:

看到了吗?这和 Spring AOP 的 @Before → 方法执行 → @After 思路非常相似。


Claude Code 提供了四种 Hook 类型,满足不同场景:

类型 说明 类比 command 执行 Shell 脚本,通过 stdin 接收 JSON,通过 exit code 返回决策 最通用,就像 Shell 脚本 http POST JSON 到远程 URL,适合对接内部系统 像 Webhook,通知你的服务 prompt 让 LLM 评估当前状态,返回决策 让 AI 自己判断该不该继续 agent 启动一个专门的子代理,可以调用工具做多步推理 prompt 的加强版,能动手验证

重点区别prompt 只能”想”,agent 能”想”还能”做”。比如你要验证代码是否通过测试,prompt 只能看文本判断,agent 可以真的跑一遍测试。

上下文获取方式:不同类型获取事件上下文的方式不同:

类型 上下文来源 示例 command 通过 stdin 接收 JSON(用 cat 读取) input=\((cat) http POST 请求的 body 中携带 JSON 服务端从 request body 解析 prompt 模板变量 \)ARGUMENTS 自动注入 “prompt”: “检查任务是否完成。\(ARGUMENTS" agent 模板变量 \)ARGUMENTS 自动注入 “prompt”: “跑一遍测试。\(ARGUMENTS"

其中 \)ARGUMENTS 是 Claude Code 的内置模板变量,运行时会被替换为当前 Hook 事件的 JSON 输入数据(包含会话 ID、工具名、工具参数等字段,具体内容因事件类型而异)。如果 prompt 字符串中没有写 $ARGUMENTS,JSON 输入会自动追加到 prompt 末尾。这样 LLM 就能基于真实的事件上下**判断,而不是只靠你写的静态 prompt。


Claude Code 目前支持 26 个 Hook 事件,按阶段分为 7 组。先看全景图,有个整体印象:

在这里插入图片描述

上图从上到下就是一次 Claude Code 会话的完整生命周期。我按组快速过一下各自的职责:

🔄 会话生命周期(6 个):管理会话本身的状态 —— 启动、结束、加载配置、切换目录、监听文件变化。大多数不可拦截,属于”通知型”事件。

🔧 工具调用生命周期(5 个):这是最核心的一组PreToolUse 在工具执行前拦截(类比 @Before),PostToolUse 在执行后追加上下文(类比 @AfterReturning),PostToolUseFailure 处理异常(类比 @AfterThrowing)。日常 80% 的 Hook 都挂在这里。

🤖 子代理与团队(3 个):当 Claude Code 启动子代理或团队协作时触发。SubagentStop 可以拦截子代理的输出,TeammateIdle 可以在队友空闲时分配新任务。

📝 用户交互(2 个):UserPromptSubmit 是用户提交提示词时的”入口检查”,可以在这里拦截危险操作意图(比如”删库跑路”)。

🛑 停止与收尾(4 个):Stop 是 Claude Code 完成回复时的”出口检查”,可以用 prompt 类型让 AI 自己审查是否真的完成了任务。

🌲 Worktree 与压缩(4 个):管理 Git Worktree 和上下文压缩。PreCompact 可以在压缩前注入需要保留的关键信息。

🔗 MCP 交互(2 个):当 MCP 服务器请求用户输入时触发,适合做输入校验或自动填充。

记忆技巧:安全拦截和自动化这块,重点掌握 PreToolUsePostToolUseUserPromptSubmitStop 这四个事件就能覆盖大部分场景。但其他事件同样有实战价值 —— 比如 SessionStart 常被用来注入会话历史上下文,Notification 用来做桌面通知提醒,SubagentStop 用来审查子代理输出。按需取用就好。


🛡️ 场景一:PreToolUse 拦截危险 Bash 命令

类比:Spring 的 @Before 权限校验切面,方法执行前先检查权限。

在 Claude Code 执行 Bash 命令之前,先检查命令是否危险。

配置 settings.json

{ “hooks”: {

"PreToolUse": [ { "matcher": "Bash", "hooks": [ { "type": "command", "command": "bash "$CLAUDE_PROJECT_DIR/.claude/hooks/pre-tool-check.sh"" } ] } ] 

} }

对应的拦截脚本:

#!/bin/bash # 文件:.claude/hooks/pre-tool-check.sh

input=\((cat) command=\)(echo $input | jq -r ’.tool_input.command’)

# 🚫 直接拦截的危险命令(使用 grep -F 做字面量匹配) blocked_patterns=( “rm -rf /” “rm -rf /*” ”:(){ :|:& };:” “mkfs.” “dd if=/dev/zero” “dd if=/dev/random” )

for pattern in \({blocked_patterns[@]}"; do if echo "\)command | grep -qF $pattern; then

echo "}" exit 0 

fi done

# ⚠️ 警告但放行的命令(使用 grep -E 做正则匹配) warn_patterns=(“rm -rf” “git push –force” “git reset –hard” “DROP TABLE” “sudo rm”)

for pattern in \({warn_patterns[@]}"; do if echo "\)command | grep -qE $pattern; then

echo "}" exit 0 

fi done

exit 0

✨ 场景二:PostToolUse 自动格式化代码

类比:Vue 的 updated() 钩子,DOM 更新后自动执行副作用。

每次 Claude Code 用 Write 或 Edit 工具修改文件后,自动运行格式化工具:

{ “hooks”: {

"PostToolUse": [ { "matcher": "Edit|Write", "hooks": [ { "type": "command", "command": "bash "$CLAUDE_PROJECT_DIR/.claude/hooks/format-code.sh"" } ] } ] 

} }

对应的格式化脚本:

#!/bin/bash # 文件:.claude/hooks/format-code.sh

input=\((cat) file_path=\)(echo \(input" | jq -r '.tool_input.file_path') ext="\){file_path*.}

case \(ext" in js|ts|jsx|tsx) npx prettier --write "\)file_path 2>/dev/null ;; py) python3 -m black \(file_path" 2>/dev/null ;; go) gofmt -w "\)file_path 2>/dev/null ;; java) google-java-format -i \(file_path" 2>/dev/null ;; rs) rustfmt "\)file_path 2>/dev/null ;; esac

exit 0

效果:Claude Code 写的代码永远保持格式统一,再也不用人工跑 formatter。

🔍 场景三:PostToolUse 安全扫描

类比:Spring 的 @AfterReturning 日志切面,方法正常返回后记录日志。

扫描 Claude Code 写入的文件,检测是否包含硬编码的密钥和密码。

配置 settings.json

{ “hooks”: {

"PostToolUse": [ { "matcher": "Edit|Write", "hooks": [ { "type": "command", "command": "bash "$CLAUDE_PROJECT_DIR/.claude/hooks/security-scan.sh"" } ] } ] 

} }

对应的安全扫描脚本:

#!/bin/bash # 文件:.claude/hooks/security-scan.sh

input=\((cat) file_path=\)(echo $input | jq -r ’.tool_input.file_path’)

# 跳过敏感目录 [[ $file_path =~ .env|.git/ ]] && exit 0

warnings=””

# 检查常见密钥模式(注意:macOS BSD grep 不支持 x27,用单引号变量代替) QUOTE=”‘” if grep -qE ”(password|passwd|pwd)s=s[\({QUOTE}][^"\){QUOTE}]+[\({QUOTE}]" "\)file_path 2>/dev/null; then warnings+=“⚠️ 发现硬编码密码 fi

if grep -qE ”(api_key|apikey|secret_key|access_token)s=s[\({QUOTE}][^"\){QUOTE}]+[\({QUOTE}]" "\)file_path 2>/dev/null; then warnings+=“⚠️ 发现硬编码 API 密钥 fi

if grep -qE ’—–BEGIN (RSA |EC )?PRIVATE KEY—–’ $file_path 2>/dev/null; then warnings+=“🚨 发现私钥文件 fi

if [ -n $warnings ]; then # 以 additionalContext 形式返回,不阻断流程 echo ”}” fi

exit 0

📊 场景四:Stop 用 prompt hook 检查任务完成度

类比:这在 Vue/Spring 中没有直接对应,这是 Claude Code 独有的 —— 让 AI 自己审自己

当 Claude Code 认为自己完成工作时,让 LLM 再评估一遍:

{ “hooks”: {

"Stop": [ { "hooks": [ { "type": "prompt", "prompt": "请评估 Claude 是否完成了用户要求的所有任务。检查以下几点:1) 是否所有文件都已修改 2) 是否有遗漏的功能 3) 测试是否通过。如果任务未完成,说明还差什么。$ARGUMENTS", "timeout": 30 } ] } ] 

} }

更强大的 agent 版本:真的跑一遍测试来验证:

{ “hooks”: {

"Stop": [ { "hooks": [ { "type": "agent", "prompt": "运行项目测试套件,验证所有测试是否通过。如果有失败的测试,报告失败原因。$ARGUMENTS", "timeout": 120 } ] } ] 

} }

🔔 场景五:Notification 桌面通知

类比:Vue 的 watch 响应式监听,数据变化时触发回调。

当 Claude Code 需要你的注意时(比如权限弹窗、长时间等待),发送 macOS 桌面通知:

 ] } ] 

} }

Linux 用户替换为:

“command”: “notify-send ‘Claude Code’ ‘需要你的关注’” 

📝 场景六:UserPromptSubmit 拦截危险提示词

在用户提交提示词时就拦截危险操作意图。

配置 settings.json

{ “hooks”: {

"UserPromptSubmit": [ { "hooks": [ { "type": "command", "command": "bash "$CLAUDE_PROJECT_DIR/.claude/hooks/validate-prompt.sh"" } ] } ] 

} }

对应的提示词校验脚本:

#!/bin/bash # 文件:.claude/hooks/validate-prompt.sh

input=\((cat) prompt=\)(echo $input | jq -r ’.prompt’)

blocked_keywords=(“删除数据库” “drop database” “rm -rf /” “format c:” “删库跑路”)

for keyword in \({blocked_keywords[@]}"; do if echo "\)prompt | grep -qi $keyword; then

echo "{"decision":"block","reason":"⛔ 你的提示词包含危险操作: $keyword,已被安全钩子拦截。"}" >&2 exit 2 

fi done

exit 0


配置文件位置

Hooks 可以配置在多个位置,优先级从高到低:

位置 作用范围 是否可提交到 Git ~/.claude/settings.json 所有项目 否(个人设置) .claude/settings.json 当前项目 是(团队共享) .claude/settings.local.json 当前项目 否(本地覆盖)

核心配置结构

{ “hooks”: {

"事件名称": [ { "matcher": "工具名模式", "hooks": [ { "type": "command", "command": "你的脚本路径", "timeout": 60 } ] } ] 

} }

Matcher 模式规则

注意UserPromptSubmitStopTeammateIdleTaskCreatedTaskCompletedWorktreeCreateWorktreeRemoveCwdChanged 这些事件不支持 matcher,每次触发时都会执行,配置了 matcher 也会被静默忽略。Matcher 主要用于工具类事件(如 PreToolUsePostToolUse 等)。

模式 说明 示例 精确匹配 只匹配指定工具 “Write” 多选匹配 管道符分隔 “Edit|Write” 正则匹配 包含特殊字符则按正则解析 ”^Notebook” 通配符 匹配所有 ”” MCP 工具 匹配 MCP 服务器工具 “mcpmemory.”

Hook 脚本的核心机制

输入:通过 stdin 接收 JSON,包含工具名、参数、会话 ID 等。

输出:通过 exit code 和 JSON stdout 控制行为:

  • exit 0 → 继续(stdout 会被解析为 JSON,可通过 hookSpecificOutput 返回决策)
  • exit 2 → 阻断操作(stderr 会显示为错误信息)
  • 其他 exit code → 非阻断错误,继续执行

环境变量

  • \(CLAUDE_PROJECT_DIR — 项目根目录的绝对路径(所有 command hook 均可用)
  • \)CLAUDE_ENV_FILE — 用于持久化环境变量的文件路径(仅在 SessionStartCwdChangedFileChanged 事件的 command hook 中可用)

快速上手步骤

# 1. 创建 hooks 目录 mkdir -p .claude/hooks

# 2. 复制你需要的脚本 # (从上面六个场景中选)

# 3. 赋予执行权限 chmod +x .claude/hooks/*.sh

# 4. 配置 settings.json # (把对应的 JSON 配置加进去)

# 5. 测试 Hook echo ’{“tool_name”:“Bash”,“tool_input”:{“command”:“rm -rf /”}}’ | bash .claude/hooks/pre-tool-check.sh echo $? # 应该输出 2(被拦截)


Hook 机制是 Claude Code 从”AI 黑盒”变成”可控流程”的关键桥梁。

回顾一下我们今天讲的:

  1. Hook 的本质就是事件驱动的回调,和你熟悉的 Vue 生命周期、Spring AOP 是同一个思路
  2. 四个核心事件覆盖 80% 场景:PreToolUse(执行前拦截)、PostToolUse(执行后处理)、UserPromptSubmit(输入校验)、Stop(完成检查)
  3. 四种 Hook 类型满足不同需求:command(最通用)、http(对接外部系统)、prompt(AI 自评)、agent(AI 自验证)
  4. 六个实战配置可以直接复制到你的项目中使用

正如 Spring AOP 让企业级应用有了统一的事务管理和安全控制,Claude Code 的 Hook 让 AI 编程有了安全网质量门

你不需要每件事都盯着 AI 做 —— 配好 Hook,让它在你设定的规则里自由发挥就好。


参考资料


欢迎关注公众号 FishTech Notes,一块交流使用心得!

小讯
上一篇 2026-04-19 15:39
下一篇 2026-04-19 15:37

相关推荐

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容,请联系我们,一经查实,本站将立刻删除。
如需转载请保留出处:https://51itzy.com/kjqy/265755.html