Claude Code 钩子机制实战:3 步让 AI 生成的命令符合你的习惯
【免费下载链接】claude-codeClaude Code is an agentic coding tool that lives in your terminal, understands your codebase, and helps you code faster by executing routine tasks, explaining complex code, and handling git workflows - all through natural language commands.项目地址: https://gitcode.com/GitHub_Trending/cl/claude-code
Claude Code 是跑在终端里的 AI 编码助手,能读懂代码库、执行常规任务、处理 git 流程。它有个常被忽略的能力——钩子机制:在 AI 真正执行命令之前,插入你自己的检查逻辑。这篇带你用它给 AI 装一道"命令守门员"🚦
跟到文末,AI 每次用grep搜文件都会被拦下来并提醒改用更快的rg;想禁掉哪些写法、提醒哪些命令,全由你自己定,不用改 Claude Code 本体 ✅
先别急:钩子到底能帮你挡什么
场景一:AI 总是用最慢的搜索
你让 Claude Code 在仓库里找某个函数,它很配合地吐出grep -r "xxx" .。小项目无所谓,几十万行的代码库里这条命令能跑半分钟。你纠正它一次,下次它大概率还是这么写——AI 不会把"你偏好 rg"记成长期习惯,除非流程里真有一道强制检查。钩子就是这道检查:命令执行前,先过你定的规则。
场景二:高危命令的最后一道闸
另一类更烦人的情况:AI 为了"快速搞定",偶尔会生成rm -rf或git push --force这类你根本不想要的命令。口头叮嘱没用,把拦截规则写进钩子才有用——命令还没落地就被挡住,AI 会收到你的提示并换一种写法。
最短路径:把第一个钩子挂上去
钩子是什么,一句大白话
钩子(Hook)就是"事件触发的脚本":Claude Code 在特定时刻(比如调用 Bash 工具前)自动运行你指定的程序,根据它的输出决定放行还是拦截。仓库的 examples/hooks/ 目录里有个现成样本,我们直接拿它起步。
钩子配置写在哪个文件
全局生效写在~/.claude/settings.json,只想在某个项目里生效就写到该项目根目录的.claude/settings.json。加上这段配置,注意把路径换成你本地脚本的真实位置:
{ "hooks": { "PreToolUse": [ { "matcher": "Bash", "hooks": [ { "type": "command", "command": "python3 /path/to/bash_command_validator_example.py" } ] } ] } }matcher是触发条件,填Bash表示只在 Bash 工具被调用时跑这个脚本;command才是钩子实际执行的命令。
最小可运行示例
先不接 Claude Code,用一行命令模拟它发给钩子的输入,确认脚本本身能跑:
echo '{"tool_name": "Bash", "tool_input": {"command": "grep hello *.txt"}}' \ | python3 examples/hooks/bash_command_validator_example.py看到Use 'rg' (ripgrep) instead of 'grep'...且退出码为 2,就说明链路通了。退出码(程序结束时返回的状态数字)是关键约定:0放行;1把报错信息只显示给你;2直接拦下这次调用,并把提示信息交给 Claude 参考。
规则清单:把命令偏好写进正则
打开 bash_command_validator_example.py,规则集中在一个列表里,每条就是"正则 + 提示语"一对:
_VALIDATION_RULES = [ ( r"^grep\b(?!.*\|)", "Use 'rg' (ripgrep) instead of 'grep' for better performance and features", ), ]验证逻辑只有一层循环:遍历列表,re.search命中就把对应的提示语收起来。规则越多,拦得越细。
加一条你自己的规则
比如你不希望 AI 写cat 文件 | grep 关键词这种管道,就想让它直接rg。在列表里追加一行元组即可:
( r"cat\s+\S+\s*\|\s*grep\b", "Use 'rg pattern file' directly instead of 'cat | grep'", ),存盘就完事,下一次会话里 AI 再写这条命令就会被拦下。
只提醒还是硬拦截,你说了算
现在的写法是硬拦截(exit 2)。如果只想温和提醒、不阻止执行,把脚本末尾改成打印提示后sys.exit(0)就行。至于"自动把命令替换成 rg 再放行"这类更强的玩法,需要让钩子按官方输出协议返回修改后的tool_input,示例脚本没实现,留给你照着 README.md 提到的钩子文档自己试。
钩子没触发?先查这 3 处 🛠️
1. 配置文件的 JSON 有没有写坏
最常见的翻车原因:多个逗号、少个引号,整个 settings 文件解析失败,钩子会静默失效。用下面这条命令校验,报错会直接告诉你行号:
python3 -m json.tool ~/.claude/settings.json2. 脚本路径和退出码对不对
command里写的是绝对路径,clone 仓库后忘了改路径,钩子就根本起不来。用前面那个echo ... | python3 ...命令单独试一次脚本:能输出提示且退出码为 2,脚本才算合格。
3. matcher 和事件名核对一遍
matcher填的是工具名(Bash、Read、Edit),事件名是PreToolUse这类,都区分大小写,填错一个字母就不触发。拿不准有没有被调度时,在脚本开头加一句print("hook fired", file=sys.stderr),跑一次会话就能看到痕迹。
收尾:从"能跑"到"顺手"
到这里你已经走完一轮完整的"场景 → 配置 → 自定义规则 → 排坑"循环:钩子把 AI 的命令习惯从"默认值"改成了"你的标准"。核心记住四件事——钩子监听工具调用、配置写在 settings.json、规则用正则表达、退出码决定放行还是拦截。想继续深入,可以往这两个方向走。
方向一:命令跑完之后的 PostToolUse
PreToolUse管的是执行前,PostToolUse管执行后:统计 AI 跑了哪些命令、记录耗时、对输出做二次检查。同一个配置文件里再加一个PostToolUse键,结构完全一样。
方向二:把偏好固化成项目级配置
个人习惯写全局,团队规范写项目级。examples/settings/ 里放了几份现成的 settings 模板(宽松版、严格版、Bash 沙箱版),可以照着搭一套只在本仓库生效的规则,再打包分享给同事复用。
【免费下载链接】claude-codeClaude Code is an agentic coding tool that lives in your terminal, understands your codebase, and helps you code faster by executing routine tasks, explaining complex code, and handling git workflows - all through natural language commands.项目地址: https://gitcode.com/GitHub_Trending/cl/claude-code
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考