Skip to content

Hooks自动化机制

Hooks是Claude Code的自动化框架,让你能在特定事件发生时自动执行Shell命令。这是实现工作流自动化的核心机制。

什么是Hooks?

Hooks是在Claude Code生命周期特定节点触发的Shell命令:

用户提交问题 → UserPromptSubmit Hook

Claude处理前 → PreToolUse Hook

工具执行 → 工具实际执行

执行完成后 → PostToolUse Hook

Claude响应结束 → Stop Hook

Hook类型

完整的8种Hook

Hook触发时机典型用途
UserPromptSubmit用户提交问题时日志记录、预处理
PreToolUse工具执行前安全检查、权限验证
PostToolUse工具执行后自动格式化、通知
Notification发送通知时桌面提醒、声音提示
StopClaude响应结束完成通知、状态更新
SubagentStop子Agent完成时进度跟踪
PreCompact上下文压缩前备份会话
SessionStart会话开始时加载上下文

配置Hooks

配置文件位置

bash
# 用户级配置
~/.claude/settings.json

# 项目级配置
./.claude/settings.json

配置格式

json
{
  "hooks": {
    "HookName": [{
      "matcher": "匹配规则",
      "hooks": [{
        "type": "command",
        "command": "要执行的命令"
      }]
    }]
  }
}

Hook详解与示例

1. UserPromptSubmit Hook

用户提交问题时触发:

json
{
  "hooks": {
    "UserPromptSubmit": [{
      "hooks": [{
        "type": "command",
        "command": "echo \"[$(date)] 用户提问\" >> ~/.claude/prompt-log.txt"
      }]
    }]
  }
}

用途:

  • 记录用户问题历史
  • 分析使用模式
  • 审计合规

2. PreToolUse Hook

工具执行前触发,可用于安全控制

json
{
  "hooks": {
    "PreToolUse": [{
      "matcher": "Bash",
      "hooks": [{
        "type": "command",
        "command": "if [[ \"$CLAUDE_TOOL_INPUT\" == *\"rm -rf\"* ]]; then echo '危险命令已阻止!' && exit 2; fi"
      }]
    }]
  }
}

阻止危险命令的完整示例:

json
{
  "hooks": {
    "PreToolUse": [{
      "matcher": "Bash",
      "hooks": [{
        "type": "command",
        "command": "for cmd in 'rm -rf' 'sudo' 'chmod 777' 'dd if='; do if [[ \"$CLAUDE_TOOL_INPUT\" == *\"$cmd\"* ]]; then echo \"禁止执行: $cmd\" && exit 2; fi; done"
      }]
    }]
  }
}

3. PostToolUse Hook

工具执行后触发,最适合自动格式化

json
{
  "hooks": {
    "PostToolUse": [{
      "matcher": "Edit|Write",
      "hooks": [{
        "type": "command",
        "command": "if [[ \"$CLAUDE_FILE_PATHS\" =~ \\.(ts|tsx|js|jsx)$ ]]; then prettier --write \"$CLAUDE_FILE_PATHS\" 2>/dev/null; fi"
      }]
    }]
  }
}

多格式化工具集成:

json
{
  "hooks": {
    "PostToolUse": [{
      "matcher": "Edit|Write",
      "hooks": [{
        "type": "command",
        "command": "ext=\"${CLAUDE_FILE_PATHS##*.}\"; case $ext in ts|tsx|js|jsx) prettier --write \"$CLAUDE_FILE_PATHS\";; py) black \"$CLAUDE_FILE_PATHS\";; go) gofmt -w \"$CLAUDE_FILE_PATHS\";; esac"
      }]
    }]
  }
}

4. Notification Hook

Claude发送通知时触发:

json
{
  "hooks": {
    "Notification": [{
      "hooks": [{
        "type": "command",
        "command": "osascript -e 'display notification \"Claude需要你的注意\" with title \"Claude Code\" sound name \"Glass\"'"
      }]
    }]
  }
}

Linux桌面通知:

json
{
  "hooks": {
    "Notification": [{
      "hooks": [{
        "type": "command",
        "command": "notify-send 'Claude Code' 'Claude需要你的注意' --icon=dialog-information"
      }]
    }]
  }
}

5. Stop Hook

Claude响应结束时触发:

json
{
  "hooks": {
    "Stop": [{
      "hooks": [{
        "type": "command",
        "command": "osascript -e 'display notification \"任务已完成\" with title \"Claude Code\"'"
      }]
    }]
  }
}

6. SubagentStop Hook

子Agent完成时触发:

json
{
  "hooks": {
    "SubagentStop": [{
      "hooks": [{
        "type": "command",
        "command": "echo \"[$(date)] 子Agent任务完成\" >> ~/.claude/subagent-log.txt"
      }]
    }]
  }
}

7. PreCompact Hook

上下文压缩前触发,用于备份:

json
{
  "hooks": {
    "PreCompact": [{
      "hooks": [{
        "type": "command",
        "command": "mkdir -p ~/.claude/backups && cp ~/.claude/current-session.jsonl ~/.claude/backups/session-$(date +%s).jsonl 2>/dev/null || true"
      }]
    }]
  }
}

8. SessionStart Hook

会话开始时触发:

json
{
  "hooks": {
    "SessionStart": [{
      "hooks": [{
        "type": "command",
        "command": "git status > /tmp/claude-git-context.txt 2>/dev/null; echo '上下文已加载'"
      }]
    }]
  }
}

环境变量

Hooks执行时可以访问以下环境变量:

变量说明示例
CLAUDE_PROJECT_DIR当前项目目录/home/user/my-project
CLAUDE_FILE_PATHS被修改的文件路径src/main.ts
CLAUDE_TOOL_INPUT工具输入参数(JSON){"command": "npm test"}
CLAUDE_TOOL_NAME工具名称Bash, Edit, Write

使用环境变量的Hook

json
{
  "hooks": {
    "PostToolUse": [{
      "matcher": "Edit|Write",
      "hooks": [{
        "type": "command",
        "command": "echo \"文件修改: $CLAUDE_FILE_PATHS\" >> ~/.claude/edit-log.txt"
      }]
    }]
  }
}

Matcher匹配规则

匹配单个工具

json
{ "matcher": "Bash" }

匹配多个工具

json
{ "matcher": "Edit|Write" }

匹配所有工具

json
{ "matcher": "*" }

正则匹配

json
{ "matcher": "Edit|Write|Bash" }

返回值控制

正常继续

bash
exit 0  # 正常执行,继续流程

阻止操作

bash
exit 2   # 阻止当前操作,显示错误信息

提供反馈

json
{
  "hooks": {
    "PreToolUse": [{
      "matcher": "Bash",
      "hooks": [{
        "type": "command",
        "command": "python ~/.claude/hooks/check-command.py"
      }]
    }]
  }
}
python
# check-command.py
import json
import sys

# 检查逻辑
response = {
    "continue": True,  # 是否继续
    "feedback": "检查通过",  # 反馈信息
    "modify_prompt": False  # 是否修改提示词
}

print(json.dumps(response))

实用Hook示例

自动运行测试

json
{
  "hooks": {
    "PostToolUse": [{
      "matcher": "Edit|Write",
      "hooks": [{
        "type": "command",
        "command": "if [[ -f package.json ]] && grep -q '\"test\"' package.json; then npm test -- --passWithNoTests 2>&1 | tail -5; fi"
      }]
    }]
  }
}

自动Lint检查

json
{
  "hooks": {
    "PostToolUse": [{
      "matcher": "Edit|Write",
      "hooks": [{
        "type": "command",
        "command": "if [[ -f .eslintrc.* ]] && [[ \"$CLAUDE_FILE_PATHS\" =~ \\.(ts|tsx|js|jsx)$ ]]; then npx eslint --fix \"$CLAUDE_FILE_PATHS\" 2>/dev/null; fi"
      }]
    }]
  }
}

自动Git提交

json
{
  "hooks": {
    "Stop": [{
      "hooks": [{
        "type": "command",
        "command": "if [[ -n $(git status --porcelain) ]]; then echo '有未提交的更改'; fi"
      }]
    }]
  }
}

审计日志

json
{
  "hooks": {
    "PreToolUse": [{
      "matcher": "*",
      "hooks": [{
        "type": "command",
        "command": "echo \"$(date '+%Y-%m-%d %H:%M:%S') | Tool: $CLAUDE_TOOL_NAME | User: $USER\" >> ~/.claude/audit.log"
      }]
    }]
  }
}

管理Hooks

查看当前Hooks

bash
claude /hooks

通过CLI添加Hook

bash
claude hook add PostToolUse "prettier --write \$CLAUDE_FILE_PATHS"

删除Hook

bash
claude hook remove PostToolUse <hook-id>

最佳实践

1. 渐进式添加

从简单的日志Hook开始,逐步添加复杂功能。

2. 错误处理

json
{
  "hooks": {
    "PostToolUse": [{
      "hooks": [{
        "type": "command",
        "command": "prettier --write \"$CLAUDE_FILE_PATHS\" 2>/dev/null || true"
      }]
    }]
  }
}

3. 条件执行

只在特定条件下执行:

json
{
  "hooks": {
    "PostToolUse": [{
      "hooks": [{
        "type": "command",
        "command": "if [[ -f prettier.config.js ]]; then prettier --write \"$CLAUDE_FILE_PATHS\"; fi"
      }]
    }]
  }
}

4. 性能考虑

避免耗时操作,Hooks应该快速执行完成。

下一步

学会了Hooks后,继续学习 自定义Slash命令