使用 Hooks 自动化工作流

使用 hooks 自动化工作流

当 Claude Code 编辑文件、完成任务或需要输入时自动运行 shell 命令。

设置你的第一个 hook

通过 /hooks 交互式菜单创建 hook:

  1. 在 Claude Code CLI 中输入 /hooks
  2. 选择 hook 事件(如 Notification
  3. 配置匹配器(或保留为空以匹配所有)
  4. 添加要运行的命令
  5. 选择存储位置(用户设置或项目设置)

你可以自动化什么

在 Claude 需要输入时获得通知

macOS:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
{
"hooks": {
"Notification": [
{
"matcher": "",
"hooks": [
{
"type": "command",
"command": "osascript -e 'display notification \"Claude Code needs your attention\" with title \"Claude Code\"'"
}
]
}
]
}
}

Linux:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
{
"hooks": {
"Notification": [
{
"matcher": "",
"hooks": [
{
"type": "command",
"command": "notify-send 'Claude Code' 'Claude Code needs your attention'"
}
]
}
]
}
}

编辑后自动格式化代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
{
"hooks": {
"PostToolUse": [
{
"matcher": "Edit|Write",
"hooks": [
{
"type": "command",
"command": "jq -r '.tool_input.file_path' | xargs npx prettier --write"
}
]
}
]
}
}

阻止对受保护文件的编辑

创建 hook 脚本 .claude/hooks/protect-files.sh

1
2
3
4
5
6
7
8
9
10
11
12
13
14
#!/bin/bash
INPUT=$(cat)
FILE_PATH=$(echo "$INPUT" | jq -r '.tool_input.file_path // empty')

PROTECTED_PATTERNS=(".env" "package-lock.json" ".git/")

for pattern in "${PROTECTED_PATTERNS[@]}"; do
if [[ "$FILE_PATH" == *"$pattern"* ]]; then
echo "Blocked: $FILE_PATH matches protected pattern '$pattern'" >&2
exit 2
fi
done

exit 0

注册 hook:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
{
"hooks": {
"PreToolUse": [
{
"matcher": "Edit|Write",
"hooks": [
{
"type": "command",
"command": "$CLAUDE_PROJECT_DIR/.claude/hooks/protect-files.sh"
}
]
}
]
}
}

压缩后重新注入上下文

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
{
"hooks": {
"SessionStart": [
{
"matcher": "compact",
"hooks": [
{
"type": "command",
"command": "echo 'Reminder: use Bun, not npm. Run bun test before committing.'"
}
]
}
]
}
}

审计配置更改

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
{
"hooks": {
"ConfigChange": [
{
"matcher": "",
"hooks": [
{
"type": "command",
"command": "jq -c '{timestamp: now | todate, source: .source, file: .file_path}' >> ~/claude-config-audit.log"
}
]
}
]
}
}

Hooks 如何工作

Hook 事件生命周期

Event 触发时机
SessionStart 会话开始或恢复时
UserPromptSubmit 提交提示时,在 Claude 处理之前
PreToolUse 工具调用执行前,可以阻止
PermissionRequest 权限对话框出现时
PostToolUse 工具调用成功后
PostToolUseFailure 工具调用失败后
Notification Claude Code 发送通知时
SubagentStart subagent 启动时
SubagentStop subagent 完成时
Stop Claude 完成响应时
ConfigChange 配置文件更改时
WorktreeCreate 创建 worktree 时
WorktreeRemove 删除 worktree 时
PreCompact 上下文压缩前
SessionEnd 会话终止时

Hook 类型

  • type: "command": 运行 shell 命令(最常见)
  • type: "http": 将事件数据 POST 到 URL
  • type: "prompt": 单轮 LLM 评估
  • type: "agent": 具有工具访问权限的多轮验证

Hook 输入

每个事件通过 stdin 传递 JSON 数据:

1
2
3
4
5
6
7
8
9
{
"session_id": "abc123",
"cwd": "/Users/sarah/myproject",
"hook_event_name": "PreToolUse",
"tool_name": "Bash",
"tool_input": {
"command": "npm test"
}
}

Hook 输出

退出代码确定行为:

  • Exit 0: 操作继续。写入 stdout 的内容添加到 Claude 的上下文
  • Exit 2: 操作被阻止。写入 stderr 的原因作为反馈给 Claude
  • 任何其他退出代码: 操作继续,stderr 被记录但不显示

结构化 JSON 输出

1
2
3
4
5
6
7
{
"hookSpecificOutput": {
"hookEventName": "PreToolUse",
"permissionDecision": "deny",
"permissionDecisionReason": "Use rg instead of grep for better performance"
}
}

使用匹配器过滤 hooks

事件 匹配器过滤的内容 示例
PreToolUsePostToolUse 工具名称 BashEdit|Writemcp__.*
SessionStart 会话如何开始 startupresumecompact
SessionEnd 会话为什么结束 clearlogoutprompt_input_exit
Notification 通知类型 permission_promptidle_prompt
SubagentStart 代理类型 BashExplorePlan

配置 hook 位置

位置 范围 可共享
~/.claude/settings.json 所有你的项目
.claude/settings.json 单个项目 是(可以提交到仓库)
.claude/settings.local.json 单个项目 否(gitignored)
Plugin hooks/hooks.json 启用插件时
Skill frontmatter 技能活跃时

Prompt-based hooks

对于需要判断的决策:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
{
"hooks": {
"Stop": [
{
"hooks": [
{
"type": "prompt",
"prompt": "Check if all tasks are complete. If not, respond with {\"ok\": false, \"reason\": \"what remains to be done\"}."
}
]
}
]
}
}

Agent-based hooks

当验证需要检查文件或运行命令时:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
{
"hooks": {
"Stop": [
{
"hooks": [
{
"type": "agent",
"prompt": "Verify that all unit tests pass. Run the test suite and check the results. $ARGUMENTS",
"timeout": 120
}
]
}
]
}
}

HTTP hooks

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
{
"hooks": {
"PostToolUse": [
{
"hooks": [
{
"type": "http",
"url": "http://localhost:8080/hooks/tool-use",
"headers": {
"Authorization": "Bearer $MY_TOKEN"
},
"allowedEnvVars": ["MY_TOKEN"]
}
]
}
]
}
}

限制和故障排除

限制

  • 命令 hooks 仅通过 stdout、stderr 和退出代码通信
  • Hook 超时默认为 10 分钟
  • PostToolUse hooks 无法撤销操作
  • PermissionRequest hooks 不在非交互模式中触发

Hook 未触发

  • 运行 /hooks 确认 hook 出现在正确的事件下
  • 检查匹配器模式是否与工具名称完全匹配
  • 验证你是否触发了正确的事件类型

Hook 输出中的错误

  • 确保脚本可执行:chmod +x ./my-hook.sh
  • 使用绝对路径或 $CLAUDE_PROJECT_DIR
  • 通过管道传递示例 JSON 手动测试

本文档来自 Claude Code 官方文档

© 2026 Generative AI Discovery All Rights Reserved.
Theme by hiero