怕 AI 乱改代码?教你用 Hooks 给 Claude Code 戴上"紧箍咒"

用 Claude Code 撸代码的时候,经常会遇到这么个场景:AI 也就是刚上手那会儿老实,用久了就开始"放飞自我":

  • 动不动就想执行个 rm -rf,看得人心惊肉跳
  • 改完代码从来不记得跑 lint,格式乱七八八
  • 甚至有时候想知道它到底背着我调了多少次 API,也没个记录

其实,这些问题用 Hooks 都能治。

Hooks 是什么

说白了,Hooks 就是给 Claude Code 戴的"紧箍咒"。

它允许你在 AI 执行特定操作的前后插入你自己的脚本。这概念跟 Git Hooks(比如 pre-commit)几乎一模一样:在关键节点拦一道,运行个脚本,通过了才放行,不通过就打回。

区别在于,Git Hooks 拦的是代码提交,Claude Hooks 拦的是 AI 的工具调用。

支持哪些钩子

目前支持的事件有几个,但常用的就俩:

事件 什么时候触发 典型场景
PreToolUse 工具调用 拦住危险命令、检查参数、权限控制
PostToolUse 工具调用 自动格式化代码、触发测试、更新文档

剩下的 Notification(通知时)、Stop(结束时)用得比较少,一般写插件才用得上。

怎么配置

配置这玩意儿有三个地方能放,优先级从高到低:

  1. .claude/settings.local.json(本地独享,不进 Git,推荐
  2. .claude/settings.json(项目共享,进 Git)
  3. ~/.claude/settings.json(全局配置,所有项目生效)

一个最简单的配置长这样:

json 复制代码
{
  "hooks": {
    "PreToolUse": [
      {
        "matcher": "Bash",
        "hooks": [
          {
            "type": "command",
            "command": "python3 scripts/check_cmd.py"
          }
        ]
      }
    ]
  }
}

这里的 matcher 有讲究

matcher 决定了这个钩子管哪些闲事。支持这几种写法:

  • 精确匹配"Bash" ------ 只管 Bash 命令。
  • 多选匹配"Bash|Write" ------ 管 Bash 和写文件。
  • 通配符".*" ------ 所有工具全管(慎用,会慢)。
  • 反向匹配"^(?!Read).*" ------ 除了读文件,其他全管。

工具名称一般有:BashReadWriteEditGlobGrepWebFetch 等。

核心机制:JSON 协议

Hooks 的核心就是"一问一答"。

当钩子触发时,Claude Code 会通过 标准输入 (stdin) 扔给你一个 JSON:

json 复制代码
{
  "session_id": "会话ID",
  "tool_name": "Bash",
  "tool_input": {
    "command": "rm -rf /"
  }
}

你的脚本处理完,得通过 标准输出 (stdout) 扔回一个 JSON:

json 复制代码
{
  "continue": false,
  "decision": "block",
  "reason": "哥们,删库跑路可不行啊"
}

返回值说明

  • continue: true 继续,false 停下。
  • decision:
    • approve: 允许执行。
    • block: 禁止执行,并报错给 AI。
    • skip: 跳过执行,但不报错(假装执行了)。
  • reason: 给 AI 看的拒绝理由。

实战案例

光说不练假把式,整几个实用的例子。

场景一:防删库(拦截危险命令)

这个最实用。写个 Python 脚本拦截 rm 命令。

脚本 hooks/safe_bash.py:

python 复制代码
#!/usr/bin/env python3
import sys
import json

# 读取输入
data = json.loads(sys.stdin.read())

if data.get("tool_name") == "Bash":
    cmd = data.get("tool_input", {}).get("command", "")
    
    # 简单的关键词匹配,实际使用可以用正则
    if "rm -rf" in cmd and "/" in cmd:
        print(json.dumps({
            "continue": False,
            "decision": "block",
            "reason": "危险操作拦截:检测到高风险删除命令,请确认路径安全后再试。"
        }))
        sys.exit(0)

# 默认放行
print(json.dumps({"continue": True, "decision": "approve"}))

配置:

json 复制代码
{
  "hooks": {
    "PreToolUse": [
      {
        "matcher": "Bash",
        "hooks": [{ "type": "command", "command": "python3 hooks/safe_bash.py" }]
      }
    ]
  }
}

场景二:强迫症福音(改完文件自动格式化)

AI 写代码有时候格式不讲究,咱可以用 PostToolUse 帮它体面一下。

脚本 hooks/auto_fmt.sh:

bash 复制代码
#!/bin/bash

# 读取 JSON 输入
input=$(cat)
tool=$(echo "$input" | jq -r '.tool_name')
file=$(echo "$input" | jq -r '.tool_input.file_path // empty')

# 只处理写操作
if [[ "$tool" == "Write" || "$tool" == "Edit" ]]; then
    if [[ -n "$file" && "$file" == *.ts ]]; then
        # 悄悄给它跑个 prettier
        npx prettier --write "$file" >/dev/null 2>&1
    fi
fi

# Post 钩子不需要返回 decision,空对象就行
echo '{}'

配置:

json 复制代码
{
  "hooks": {
    "PostToolUse": [
      {
        "matcher": "Write|Edit",
        "hooks": [{ "type": "command", "command": "bash hooks/auto_fmt.sh" }]
      }
    ]
  }
}

这样 AI 改完 .ts 文件,Prettier 马上就跟进,代码永远整整齐齐。

场景三:审计日志

想知道 AI 到底干了啥?把所有操作记下来。

脚本 hooks/logger.py:

python 复制代码
#!/usr/bin/env python3
import sys
import json
import datetime

data = json.loads(sys.stdin.read())
log_entry = {
    "time": datetime.datetime.now().isoformat(),
    "tool": data.get("tool_name"),
    "input": data.get("tool_input")
}

# 追加到日志文件
with open(".claude/audit.log", "a") as f:
    f.write(json.dumps(log_entry) + "\n")

print(json.dumps({"continue": True}))

避坑指南

玩 Hooks 有几个坑得注意,掉进去容易摔跟头:

  1. 别太慢 Hooks 是同步执行的。脚本卡 1 秒,AI 就愣 1 秒。复杂逻辑(比如上传日志)最好在脚本里丢给后台进程异步做,别让 AI 等太久。

  2. 别死循环 别在 Hooks 里调用会触发 Hooks 的命令......虽然 Claude Code 的 Hooks 主要是拦截 AI 的工具调用,但如果你在脚本里又调了 CLI 可能会套娃。

  3. 容错要做好 脚本要是挂了(非 0 退出码),AI 操作也会跟着挂。记得处理好 JSON 解析失败、文件不存在这些边界情况。除非你是故意想阻断操作(退出码 2)。

  4. 安全第一 Hooks 权限很大,能读写文件、能联网。网上抄来的脚本,先看懂了再跑,别把后门带进来了。

  5. 怎么调试 脚本逻辑不对很难受。可以在返回 JSON 里带上 outputToStderr 字段,把调试信息打印到 stderr,方便排查:

    python 复制代码
    print(json.dumps({
        "continue": True,
        "outputToStderr": f"Debug: current tool is {data.get('tool_name')}"
    }))

这跟 Git Hooks / CI 有啥不一样?

你可能会问:我有 Git Hooks 还有 CI/CD,为啥还要搞这个?

关键在于时机粒度

方式 什么时候管 管什么
Git Hooks commit / push 时 代码变更
CI/CD 代码推送后 构建和部署流程
Claude Hooks AI 动手的瞬间 AI 的每一个操作

Claude Hooks 是实时介入的。

  • 等 Git Hooks 报错,rm -rf 可能已经执行完了。
  • 等 CI 挂了,错误代码已经进仓库了。
  • 而 Claude Hooks 可以把危险扼杀在摇篮里,或者让 AI 在修改配置前先过一遍你的"家规"。

进阶玩法

如果你想玩得更花一点:

1. 配合 MCP Server

如果你用了 MCP (Model Context Protocol) 扩展 AI 的能力,Hooks 照样能管。matcher 支持 mcp__serverName__toolName 这种格式:

json 复制代码
{
  "matcher": "mcp__myserver__.*",
  "hooks": [{ "type": "command", "command": "..." }]
}

这样即使是三方扩展的工具,也能被你安排得明明白白。

2. 动态规则

硬编码脚本不灵活?让脚本去读外部配置,实现不同项目不同规则。 比如从 .claude/rules.json 读取"禁止修改的文件列表":

python 复制代码
import json
import os

rules_file = ".claude/rules.json"
if os.path.exists(rules_file):
    with open(rules_file) as f:
        rules = json.load(f)
    protected_files = rules.get("protected_files", [])
    # ... 在这里写你的拦截逻辑

这样你只需要维护 JSON 配置文件,Hook 脚本逻辑可以保持通用。

3. 团队共享

把 Hooks 配置和脚本放在项目根目录的 .claude/ 下,提交到 Git。 这样团队里每个人用 Claude Code 的时候,都会自动遵守同一套代码规范和安全策略。即使是新来的实习生,AI 也不会在他的机器上乱来。

总结

Claude Code Hooks 给了我们一个介入 AI 决策环的机会。

以前我们是"监督者",看着 AI 跑;有了 Hooks,我们变成了"规则制定者"。把安全红线、代码规范这些死规矩写进 Hooks 里,让 AI 在笼子里跳舞,既用了它的脑子,又防了它的乱子。


如果你觉得这篇文章有帮助,欢迎关注我的 GitHub,下面是我的一些开源项目:

Claude Code Skills (按需加载,意图自动识别,不浪费 token,介绍文章):

全栈项目(适合学习现代技术栈):

  • prompt-vault - Prompt 管理器,用的都是最新的技术栈,适合用来学习了解最新的前端全栈开发范式:Next.js 15 + React 19 + tRPC 11 + Supabase 全栈示例,clone 下来配个免费 Supabase 就能跑
  • chat_edit - 双模式 AI 应用(聊天+富文本编辑),Vue 3.5 + TypeScript + Vite 5 + Quill 2.0 + IndexedDB
相关推荐
一只叫煤球的猫5 小时前
2025年终总结:我与AI——减少内耗、疯狂学习、享受乐趣
aigc·openai·ai编程
墨风如雪7 小时前
告别“手搓”场景:智元用LLM重构具身智能的“练功房”
aigc
努力的小郑7 小时前
2025年度总结:当我在 Cursor 里敲下 Tab 的那一刻,我知道时代变了
前端·后端·ai编程
linhx9 小时前
【AIGC工作流】解构AI短剧生产管线:从手动调用DeepSeek+MJ,到Agent一站式自动化的演进
人工智能·自动化·aigc
薛定谔的猫210 小时前
Cursor 系列(2):使用心得
前端·ai编程·cursor
深念Y10 小时前
仿B站项目 前端 4 首页 顶层导航栏
前端·vue·ai编程·导航栏·bilibili·ai开发
dragonZhang11 小时前
基于 Agent Skills 的 UI 重构实践:从 Demo 到主题化界面的升级之路
前端·ai编程·claude
peterfei11 小时前
当AI编辑器学会了Shell命令:IfAI v0.2.6深度测评与实战指南
ai编程·cursor
神秘的猪头11 小时前
从“抽卡”到“规范驱动”:Vibe Coding 的进化史与计分小程序实战 🚀
ai编程·trae·vibecoding
T112412 小时前
深入解析 OpenCode:下一代 AI 编程助手的架构艺术
typescript·aigc