Claude Code 自定义命令及HOOK

自定义文档格式化命令

一、什么是自定义命令

Claude Code 的自定义命令(Custom Slash Commands)是用户定义的快捷指令,通过 Markdown 文件将常用的 prompt 模板封装成可复用的命令。与内置命令(如 /clear/init/compact)类似,自定义命令能够一键调用预定义的工作流。

1.1 核心概念

自定义命令 = Prompt 模板 + 参数化 + 上下文注入

  • Markdown 文件:命令定义文件,文件名即命令名
  • Frontmatter:YAML 格式的元数据配置
  • 动态参数:支持 $1$2$ARGUMENTS 等参数传递
  • Shell 集成:可执行 shell 命令并嵌入输出(使用 ! 前缀)
  • 文件引用:通过 @<文件路径> 读取文件内容

1.2 命令类型

Claude Code 支持两种类型的自定义命令:

类型存储位置作用域共享方式
项目命令.claude/commands/仅当前项目通过 Git 仓库共享给团队
个人命令~/.claude/commands/所有项目仅个人使用

二、自定义命令语法详解

2.1 基础语法

最简命令:纯 Prompt

创建文件 .claude/commands/analyze.md

分析这段代码并解释其架构设计。

使用:/analyze

带参数的命令

创建文件 .claude/commands/fix-issue.md

修复 issue #$1,优先级为 $2。

使用:/fix-issue 123 high

参数说明

  • $1, $2, $3 ... - 位置参数
  • $ARGUMENTS - 捕获所有参数

2.2 执行 Shell 命令

需要在 Frontmatter 中配置 allowed-tools 权限。

创建文件 .claude/commands/git-diff.md

---
allowed-tools: Bash(git status:*), Bash(git diff:*), Bash(git log:*)
description: 解释当前的 Git 变更
---

# 上下文
- 当前 Git 状态: !`git status`
- 当前差异: !`git diff HEAD`

# 任务
基于上述变更,详细解释 git diff 的内容。

使用:/git-diff

Shell 命令执行机制

使用 ! 前缀的命令会在执行时运行,输出自动嵌入到 prompt 中。这对于注入动态上下文非常有用。

2.3 文件引用

创建文件 .claude/commands/compare-versions.md

比较 @src/old-version.js 和 @src/new-version.js,总结主要差异。

使用:/compare-versions

2.4 Frontmatter 配置

Frontmatter 是命令的元数据配置块,支持以下字段:

字段说明示例
allowed-tools预授权的工具列表Bash(git add:*)
argument-hint参数提示(自动补全)[message]
description命令描述创建 Git 提交
model指定使用的模型claude-3-5-haiku-20241022

完整示例:

---
allowed-tools: Bash(git add:*), Bash(git status:*), Bash(git commit:*)
argument-hint: [message]
description: 创建 Git 提交
model: claude-sonnet-4-5-20250929
---

使用以下消息创建 Git 提交: $ARGUMENTS

三、什么是 Hook(钩子)

Hook 是在 Claude Code 生命周期特定时刻自动执行的 shell 命令。与自定义命令不同,Hook 提供对 Claude Code 行为的确定性控制,确保某些操作总是发生,而不是依赖 LLM 选择运行它们。

3.1 Hook 与自定义命令的区别

特性自定义命令Hook
触发方式用户手动调用 /命令事件自动触发
执行时机用户主动生命周期被动
用途封装 prompt 模板自动化操作、权限控制
配置位置.claude/commands/.claude/settings.json

3.2 核心 Hook 事件

Hook 事件触发时机典型用途
PreToolUse工具调用前阻止危险操作、代码格式化
PostToolUse工具调用后自动格式化、日志记录
PermissionRequest权限请求时自定义权限规则
UserPromptSubmit用户提交 prompt 前注入上下文、预处理
StopClaude 完成响应时任务完成通知
SubagentStop子代理完成时子任务完成通知
Notification发送通知时自定义通知方式
SessionStart会话启动时初始化环境
SessionEnd会话结束时清理资源
安全考虑

Hook 使用当前环境凭证自动运行,存在安全风险。在注册 Hook 前务必审查代码,避免数据泄露。

四、Hook 实战示例

4.1 任务完成后发送企业微信通知

当 Claude Code 完成任务时,自动发送企业微信 Webhook 通知。

Stop Hook 在 Claude 完成响应时触发,适合任务完成通知。

步骤 1:获取企业微信 Webhook 地址

在企业微信中创建群机器人,获取 Webhook URL:

https://qyapi.weixin.qq.com/cgi-bin/webhook/send?key=YOUR_KEY

步骤 2:配置 Hook

运行 /hooks 命令,选择 Stop 事件,添加以下配置:

{
  "hooks": {
    "Stop": [
      {
        "matcher": "",
        "hooks": [
          {
            "type": "command",
            "command": "~/.claude/hooks/wecom_notify.sh"
          }
        ]
      }
    ]
  }
}

步骤 3:创建通知脚本

创建文件 ~/.claude/hooks/wecom_notify.sh

#!/bin/bash

WECOM_WEBHOOK="https://qyapi.weixin.qq.com/cgi-bin/webhook/send?key=YOUR_KEY"

EVENT_DATA=$(cat)

PROJECT_DIR=$(echo "$EVENT_DATA" | jq -r '.working_directory // "Unknown"')
PROJECT_NAME=$(basename "$PROJECT_DIR")

LAST_MESSAGE=$(echo "$EVENT_DATA" | jq -r '.conversation_history[-2].content // "任务已完成"' | head -c 100)

TIMESTAMP=$(date '+%Y-%m-%d %H:%M:%S')

MESSAGE=$(cat <<EOF
{
  "msgtype": "markdown",
  "markdown": {
    "content": "## Claude Code 任务完成通知\\n\\n**项目**: $PROJECT_NAME\\n**任务**: $LAST_MESSAGE\\n**时间**: $TIMESTAMP\\n\\n> 任务已完成,请查看结果"
  }
}
EOF
)

# 后台发送通知,避免阻塞
(curl -s -X POST "$WECOM_WEBHOOK" \
  -H 'Content-Type: application/json' \
  -d "$MESSAGE" &) > /dev/null 2>&1

exit 0

步骤 4:赋予执行权限

chmod +x ~/.claude/hooks/wecom_notify.sh
测试 Hook

运行一个简单的任务(如 帮我创建一个 hello.txt 文件),完成后应收到企业微信通知。

退出码说明

Hook 脚本的退出码控制执行流程:exit 0 表示成功继续执行,exit 1 表示失败但不阻断(仅记录错误),exit 2 表示阻断工具调用并向 Claude 发送反馈。

五、Hook 配置管理

5.1 配置位置

Hook 配置存储在两个位置:

位置作用域配置文件
用户级所有项目~/.claude/settings.json
项目级当前项目.claude/settings.json

项目级配置会覆盖用户级配置。

5.2 快速配置

方式一:使用 /hooks 命令(推荐)

  1. 运行 /hooks
  2. 选择 Hook 事件类型
  3. 选择工具匹配器(或输入 * 匹配所有)
  4. 输入命令
  5. 选择存储位置(User/Project)

方式二:直接编辑配置文件

编辑 ~/.claude/settings.json.claude/settings.json

{
  "hooks": {
    "PostToolUse": [
      {
        "matcher": "Edit|Write",
        "hooks": [
          {
            "type": "command",
            "command": "python3 ~/.claude/hooks/auto_format.py"
          }
        ]
      }
    ],
    "Stop": [
      {
        "matcher": "",
        "hooks": [
          {
            "type": "command",
            "command": "~/.claude/hooks/wecom_notify.sh"
          }
        ]
      }
    ]
  }
}

5.3 Hook 调试

如果 Hook 未按预期工作,可以使用以下方法调试:

1. 检查 Hook 输出

Hook 的 stdout 和 stderr 会显示在 Claude Code 日志中。

2. 添加调试日志

在 Hook 脚本中添加日志:

#!/bin/bash
echo "Hook triggered: $(date)" >> /tmp/claude-hook-debug.log
cat >> /tmp/claude-hook-debug.log

3. 测试 Hook 脚本

手动测试 Hook 脚本:

echo '{"tool_input":{"file_path":"test.ts"}}' | ~/.claude/hooks/auto_format.py

4. 检查退出码

确保脚本返回正确的退出码:

  • 0 - 成功
  • 1 - 错误(不阻断)
  • 2 - 阻断工具调用
Hook 执行顺序

如果同一事件配置了多个 Hook,它们会按配置顺序依次执行。任何一个 Hook 返回退出码 2 都会阻断后续执行。

六、最佳实践

6.1 Hook 设计原则

  1. 快速执行:Hook 应在 1-2 秒内完成,避免阻塞工作流
  2. 容错处理:网络请求应设置超时,失败不应阻断 Claude
  3. 安全优先:避免在 Hook 中执行不可信代码
  4. 日志记录:使用 stderr 输出调试信息

6.2 常见 Hook 场景

场景Hook 事件示例
代码格式化PostToolUsePrettier, Black, gofmt
任务通知Stop, SubagentStop企业微信、Slack、邮件
权限控制PreToolUse阻止删除生产文件
审计日志PreToolUse, PostToolUse记录所有操作
上下文注入SessionStart, UserPromptSubmit加载项目配置
自定义通知Notification替换默认通知方式

6.3 性能优化

异步执行(后台运行):

#!/bin/bash
# 使用 & 将通知放到后台,避免阻塞
(curl -X POST "$WECOM_WEBHOOK" -d "$MESSAGE" &) > /dev/null 2>&1
exit 0

缓存结果

import functools
import time

@functools.lru_cache(maxsize=128)
def expensive_check(file_path):
    # 缓存耗时检查结果
    pass

6.4 团队协作

共享项目级 Hook

.claude/settings.json 提交到 Git 仓库,团队成员自动获得相同 Hook 配置。

个性化配置

.gitignore 中排除个人配置:

.claude/settings.json.local

在代码中支持覆盖:

# 优先使用环境变量
WEBHOOK = os.getenv('WECOM_WEBHOOK') or 'default_webhook'

七、完整示例:企业开发工作流

综合使用自定义命令和 Hook 构建完整开发工作流。

7.1 配置文件

.claude/settings.json

{
  "hooks": {
    "PostToolUse": [
      {
        "matcher": "Edit|Write",
        "hooks": [
          {
            "type": "command",
            "command": "python3 .claude/hooks/auto_format.py"
          }
        ]
      }
    ],
    "Stop": [
      {
        "matcher": "",
        "hooks": [
          {
            "type": "command",
            "command": ".claude/hooks/notify_complete.sh"
          }
        ]
      }
    ],
    "PreToolUse": [
      {
        "matcher": "Bash",
        "hooks": [
          {
            "type": "command",
            "command": ".claude/hooks/log_command.sh"
          }
        ]
      }
    ]
  }
}

7.2 自定义命令

.claude/commands/commit.md

---
allowed-tools: Bash(git add:*), Bash(git status:*), Bash(git commit:*)
argument-hint: [message]
description: 提交代码到 Git
---

# 上下文
- 当前状态: !`git status --short`
- 最近提交: !`git log --oneline -5`

# 任务
使用以下消息创建符合 Conventional Commits 规范的提交: $ARGUMENTS

步骤:
1. 检查待提交文件
2. 添加到暂存区
3. 创建格式化的提交消息
4. 执行提交

.claude/commands/review.md

---
description: 代码审查当前分支
---

# 代码审查清单

请审查当前分支的变更,关注:

1. **代码质量**
   - 是否符合项目编码规范
   - 是否有重复代码
   - 命名是否清晰

2. **功能正确性**
   - 是否实现了预期功能
   - 边界条件处理是否完善
   - 错误处理是否合理

3. **性能**
   - 是否有性能瓶颈
   - 数据库查询是否优化

4. **安全性**
   - 是否有SQL注入风险
   - 是否有XSS风险
   - 敏感信息是否泄露

基于 !`git diff main...HEAD` 提供审查意见。

7.3 使用工作流

# 1. 开发功能
用户: 帮我实现用户登录功能

# 2. Claude 自动格式化(PostToolUse Hook)
# 3. 提交代码
用户: /commit 实现用户登录功能

# 4. 代码审查
用户: /review

# 5. 完成后收到企业微信通知(Stop Hook)

八、常见问题

8.1 Hook 未执行

原因

  • Hook 脚本没有执行权限
  • Hook 脚本路径错误
  • Matcher 不匹配

解决

# 检查权限
ls -la ~/.claude/hooks/

# 添加执行权限
chmod +x ~/.claude/hooks/*.sh ~/.claude/hooks/*.py

# 测试脚本
echo '{}' | ~/.claude/hooks/your_hook.sh

8.2 Hook 执行超时

解决:为网络请求添加超时:

requests.post(url, json=data, timeout=5)

8.3 企业微信通知失败

排查步骤

# 1. 测试 Webhook 地址
curl -X POST "https://qyapi.weixin.qq.com/cgi-bin/webhook/send?key=YOUR_KEY" \
  -H 'Content-Type: application/json' \
  -d '{"msgtype":"text","text":{"content":"测试消息"}}'

# 2. 检查返回值
# {"errcode":0,"errmsg":"ok"} - 成功
# {"errcode":93000,"errmsg":"invalid webhook url"} - URL 错误

8.4 Hook 影响性能

解决:使用后台执行:

#!/bin/bash
# 将耗时操作放到后台
(
  sleep 2
  curl -X POST "$WEBHOOK" -d "$DATA"
) &
exit 0

九、参考资源