前言

在上一篇文章《深入理解 Agent Hooks:Claude Code 自动化扩展机制详解(一)》中,我们系统介绍了 Hooks 的核心概念、五种类型以及生命周期事件。相信你已经对 Hooks 有了初步的理论认识。

本文目标很简单:带你亲手完成第一个 Hook 的配置。

不管你是刚接触 Claude Code 的新手,还是想系统学习 Hooks 的开发者,跟着本文操作,你将在 10 分钟内掌握 Hooks 的基本配置方法,并获得多个可直接复用的实战配置。

主包以codebuddy来配置以下的hooks,如需下载cli,请到腾讯云官网查看文档!!

一、找到并打开配置文件

1.1 配置文件位置

CodeBuddy Code(兼容 Claude Code 规范)的 Hooks 配置存储在 JSON 格式的设置文件中,根据作用范围不同,有以下几个位置:

作用域 文件路径 说明
用户级 ~/.codebuddy/settings.json 适用于所有项目,个人配置
项目级 <项目根目录>/.codebuddy/settings.json 项目共享,可提交 Git
项目本地 <项目根目录>/.codebuddy/settings.local.json 本地配置,不提交 Git

用户级的配置位置

1.2 查看配置文件是否存在(Windows)

步骤一:找到 settings.json 文件,用任意文本编辑器(VS Code、记事本等)打开。

注意:如果该目录或文件不存在,请新建一个。

在这里插入图片描述

1.3 打开配置文件

然后用你喜欢的编辑器打开:
我的内容差不多是这样
在这里插入图片描述

1.4 配置优先级

当多个配置文件同时存在时,Hooks 会合并而非覆盖。优先级为:

项目本地 > 项目级 > 用户级

这意味着你可以在用户级配置通用规则,在项目级覆盖特定行为。

二、编写你的第一个 Hook

首先按传统给出我们的速通宝典—直接给出提示词,让AI自己配
这是一个会提醒你操作的hooks
在这里插入图片描述

我们直接回车-回车-回车:(可能会看到配置好了,如果没有以下配置,需要手动贴进去)
在这里插入图片描述

然后回来/reload一下:
在这里插入图片描述
然后就可以听到铺天盖地的notification 叮叮叮的声音 说明配置完成:请添加图片描述
每一次操作都会叮一下
在这里插入图片描述

正文:

2.1 场景说明

我们来实现一个最实用也最安全的 Hook:阻止 Claude 执行 rm -rf 危险命令

这个场景非常适合作为入门示例,因为:

  • 逻辑简单直观:检测命令是否包含危险字符串
  • 效果立竿见影:保护重要数据不被误删
  • 便于理解流程:PreToolUse 事件的典型应用

2.2 完整配置代码

settings.json 中写入以下内容:

{
  "hooks": {
    "PreToolUse": [
      {
        "matcher": "Bash",
        "hooks": [
          {
            "type": "command",
            "command": "echo '{\"hookSpecificOutput\":{\"hookEventName\":\"PreToolUse\",\"permissionDecision\":\"deny\",\"permissionDecisionReason\":\"禁止执行包含 rm -rf 的危险命令\"}}' && exit 2"
          }
        ]
      }
    ]
  }
}

等等!!!这个配置会阻止所有 Bash 命令,我们需要更精细的控制。让我们改进一下,配合脚本使用。

2.3 改进版:配合脚本检测

步骤一:创建脚本目录和文件

mkdir -p ~/.codebuddy/hooks

创建文件 ~/.codebuddy/hooks/check-dangerous-command.sh

#!/bin/bash

# 读取 stdin 中的 JSON 数据
input=$(cat)

# 提取命令内容(需要 jq 工具)
command=$(echo "$input" | jq -r '.tool_input.command // empty')

# 检查是否包含危险命令
if [[ "$command" == *"rm -rf"* ]] || [[ "$command" == *"rm -rf /"* ]]; then
    echo '{"hookSpecificOutput":{"hookEventName":"PreToolUse","permissionDecision":"deny","permissionDecisionReason":"禁止执行 rm -rf 危险命令,请手动操作"}}'
    exit 2
fi

# 安全,放行
exit 0

步骤二:给脚本执行权限

chmod +x ~/.codebuddy/hooks/check-dangerous-command.sh

步骤三:修改配置文件

{
  "hooks": {
    "PreToolUse": [
      {
        "matcher": "Bash",
        "hooks": [
          {
            "type": "command",
            "command": "~/.codebuddy/hooks/check-dangerous-command.sh"
          }
        ]
      }
    ]
  }
}

2.4 配置字段详解

让我们拆解这个配置:

字段 说明
hooks 顶层字段,所有 Hook 配置的容器
PreToolUse 事件名称,表示"工具执行前"
matcher 匹配器,"Bash" 表示匹配 Bash 工具调用
type Hook 类型,"command" 表示执行 Shell 命令
command 要执行的命令路径

执行流程

  1. Claude 准备执行 Bash 命令
  2. PreToolUse 事件触发
  3. 匹配器 "Bash" 匹配成功
  4. 执行脚本 check-dangerous-command.sh
  5. 脚本检查命令内容
  6. 返回 deny 阻止,或返回 0 放行

三、验证 Hook 是否生效

3.1 触发测试

在 CodeBuddy Code 中,尝试让 Claude 执行:

请帮我删除测试目录:rm -rf ./test-dir

预期结果

如果 Hook 配置正确,你会看到类似提示:

禁止执行 rm -rf 危险命令,请手动操作

3.2 查看执行日志

使用 --debug 模式启动 CodeBuddy Code:

codebuddy --debug

在日志中可以看到:

[DEBUG] Executing hooks for PreToolUse:Bash
[DEBUG] Found 1 hook matchers
[DEBUG] Matched 1 hooks for query "Bash"
[DEBUG] Hook command completed with status 2

3.3 常见问题排查

问题 可能原因 解决方案
Hook 未触发 配置文件格式错误 检查 JSON 语法
Hook 未触发 matcher 不匹配 确认工具名称正确
脚本执行失败 没有执行权限 chmod +x script.sh
脚本执行失败 路径错误 使用绝对路径
Windows 报错 脚本不兼容 确保 Git Bash 可用

3.4 使用 /hooks 命令检查

在 CodeBuddy Code 会话中输入:

/hooks

在这里插入图片描述

这会显示当前已注册的 Hooks 列表,确认你的 Hook 是否已被识别。
在这里插入图片描述

四、实战配置示例合集

以下是一系列开箱即用的配置,你可以根据需要复制到自己的配置文件中。

示例一:敏感文件保护

场景:阻止 Claude 修改 .env.git、密钥文件等敏感内容。

{
  "hooks": {
    "PreToolUse": [
      {
        "matcher": "Write|Edit",
        "hooks": [
          {
            "type": "command",
            "command": "python3 \"$CODEBUDDY_PROJECT_DIR/.codebuddy/hooks/protect-sensitive.py\" 2>/dev/null || python \"$CODEBUDDY_PROJECT_DIR/.codebuddy/hooks/protect-sensitive.py\""
          }
        ]
      }
    ]
  }
}

脚本 protect-sensitive.py

#!/usr/bin/env python3
import json
import sys

SENSITIVE_PATTERNS = ['.env', '.git', 'id_rsa', '.pem', 'credentials']

data = json.load(sys.stdin)
file_path = data.get('tool_input', {}).get('file_path', '')

for pattern in SENSITIVE_PATTERNS:
    if pattern in file_path:
        output = {
            "hookSpecificOutput": {
                "hookEventName": "PreToolUse",
                "permissionDecision": "deny",
                "permissionDecisionReason": f"禁止修改敏感文件:{file_path}"
            }
        }
        print(json.dumps(output))
        sys.exit(2)

sys.exit(0)

示例二:代码自动格式化

场景:每次编辑或新建文件后,自动运行代码格式化工具。

{
  "hooks": {
    "PostToolUse": [
      {
        "matcher": "Write|Edit",
        "hooks": [
          {
            "type": "command",
            "command": "FILE=$(cat | jq -r '.tool_input.file_path // empty'); if [ -n \"$FILE\" ]; then prettier --write \"$FILE\" 2>/dev/null || true; fi"
          }
        ]
      }
    ]
  }
}

注意:需要项目中有 prettierjq 安装。可根据项目替换为 blackgofmt 等工具。如果没有 jq,可以创建脚本文件来解析。

示例三:空闲提醒通知

场景:当 Claude 等待用户输入超过 60 秒时,发送桌面通知。

{
  "hooks": {
    "Notification": [
      {
        "matcher": "idle_prompt",
        "hooks": [
          {
            "type": "command",
            "command": "notify-send \"CodeBuddy Code\" \"Claude 正在等待你的输入\""
          }
        ]
      }
    ]
  }
}

macOS 可替换为:

osascript -e 'display notification "Claude 正在等待你的输入" with title "CodeBuddy Code"'

Windows PowerShell:

[Windows.UI.Notifications.ToastNotificationManager, Windows.UI.Notifications, ContentType = WindowsRuntime] > $null
$template = [Windows.UI.Notifications.ToastNotificationManager]::GetTemplateContent([Windows.UI.Notifications.ToastTemplateType]::ToastText02)
$textNodes = $template.GetElementsByTagName("text")
$textNodes.Item(0).AppendChild($template.CreateTextNode("CodeBuddy Code")) > $null
$textNodes.Item(1).AppendChild($template.CreateTextNode("Claude 正在等待你的输入")) > $null
$toast = [Windows.UI.Notifications.ToastNotification]::new($template)
[Windows.UI.Notifications.ToastNotificationManager]::CreateToastNotifier("CodeBuddy Code").Show($toast)

示例四:任务完成度智能检查(Prompt Hook)

场景:Claude 完成响应时,让 AI 判断是否真正完成了用户要求的任务。

{
  "hooks": {
    "Stop": [
      {
        "hooks": [
          {
            "type": "prompt",
            "prompt": "你是一个任务完成度检查器。分析以下对话上下文,判断 Claude 是否完成了用户要求的所有任务。\n\n上下文:$ARGUMENTS\n\n检查要点:\n1. 用户的核心需求是否被解决\n2. 是否有遗漏的子任务\n3. 代码是否可运行\n\n返回 JSON 格式:{\"ok\": true} 表示完成,{\"ok\": false, \"reason\": \"具体原因\"} 表示需要继续。",
            "timeout": 30
          }
        ]
      }
    ]
  }
}

示例五:会话启动自动加载上下文

场景:每次启动新会话时,自动注入项目特定的上下文信息。

{
  "hooks": {
    "SessionStart": [
      {
        "hooks": [
          {
            "type": "command",
            "command": "cat \"$CODEBUDDY_PROJECT_DIR/.codebuddy/context.md\" 2>/dev/null || echo '项目启动成功'"
          }
        ]
      }
    ]
  }
}

在项目根目录创建 .codebuddy/context.md

## 项目上下文

- 技术栈:Node.js + TypeScript + React
- 代码规范:ESLint + Prettier
- 提交规范:Conventional Commits
- 注意事项:请勿修改 .env 文件

五、总结

本文要点回顾

步骤 要点
配置位置 用户级 ~/.codebuddy/settings.json 或项目级
编写 Hook 理解 matchertypecommand 三个关键字段
验证方法 使用 /hooks 查看注册,--debug 查看日志
实战技巧 脚本放 .codebuddy/hooks/,用 $CODEBUDDY_PROJECT_DIR 引用项目路径

最佳实践建议

  1. 从小配置开始:先配置一个简单的 Hook,验证流程后再逐步扩展
  2. 脚本与配置分离:复杂逻辑放脚本文件,配置文件保持简洁
  3. 注意跨平台兼容:Windows 用户确保脚本能在 Git Bash 中运行
  4. 善用 $ARGUMENTS:Prompt Hook 中使用 $ARGUMENTS 获取完整上下文

下篇预告

本系列的第三篇文章将深入探讨 Hooks 进阶技巧,包括:

  • 如何修改工具输入参数(modifiedInput
  • 多 Hook 协作与执行顺序
  • MCP 工具的 Hook 配置
  • 复杂场景的完整实战案例

敬请期待!


参考资料:


本文首发于 CSDN,作者:kingwu

Logo

欢迎加入DeepSeek 技术社区。在这里,你可以找到志同道合的朋友,共同探索AI技术的奥秘。

更多推荐