返回

Everything Claude Code 教程 4:Hooks - 自动化触发器完全指南

本文详解 Everything Claude Code 的 Hooks 系统,包含 6 种 Hook 类型、配置语法和实战案例。

教程概述

Hooks 是 Everything Claude Code 的自动化核心,让你能够在特定事件发生时自动执行操作,无需手动干预。

你将学到

  • ✅ 6 种 Hook 类型及其用途
  • ✅ Hook 配置语法(matcher + hooks)
  • ✅ 5+ 个实战配置案例
  • ✅ hookify 插件使用
  • ✅ 常见问题排查

什么是 Hooks?

Hooks 是基于事件的自动化系统,在 Claude Code 的生命周期中的特定时刻触发:

flowchart TD
    subgraph 用户操作
        A[用户发送消息] --> B[UserPromptSubmit]
    end

    subgraph 工具执行
        C[准备执行工具] --> D[PreToolUse]
        D --> E[工具执行]
        E --> F[PostToolUse]
    end

    subgraph 会话管理
        G[Claude 停止响应] --> H[Stop]
        I[上下文压缩前] --> J[PreCompact]
        K[需要权限] --> L[Notification]
    end

    B --> C
    F --> G

6 种 Hook 类型详解

类型概览

Hook 类型 触发时机 典型用途
PreToolUse 工具执行前 验证、提醒、拦截
PostToolUse 工具执行后 格式化、反馈、记录
UserPromptSubmit 用户发送消息时 预处理、上下文注入
Stop Claude 停止响应时 清理、持久化、总结
PreCompact 上下文压缩前 保存状态、提取关键信息
Notification 需要权限时 自定义通知、日志

1. PreToolUse

在工具执行前触发,可用于验证、提醒或拦截操作。

sequenceDiagram
    participant C as Claude
    participant H as PreToolUse Hook
    participant T as Tool

    C->>H: 准备执行 Bash
    H->>H: 检查命令
    alt 命令需要 tmux
        H->>C: 提醒使用 tmux
    end
    C->>T: 执行命令

配置示例:tmux 提醒

{
  "PreToolUse": [
    {
      "matcher": "tool == \"Bash\" && tool_input.command matches \"(npm|pnpm|yarn|cargo|pytest)\"",
      "hooks": [
        {
          "type": "command",
          "command": "if [ -z \"$TMUX\" ]; then echo '[Hook] 考虑使用 tmux 以保持会话持久' >&2; fi"
        }
      ]
    }
  ]
}

配置示例:阻止写入非 README 的 Markdown 文件

{
  "PreToolUse": [
    {
      "matcher": "tool == \"Write\" && tool_input.file_path matches \".*\\.md$\" && !tool_input.file_path matches \"(README|CLAUDE)\"",
      "hooks": [
        {
          "type": "command",
          "command": "echo '[Hook] 阻止创建非 README 的 .md 文件。如需创建,请显式确认。' >&2; exit 1"
        }
      ]
    }
  ]
}

2. PostToolUse

在工具执行后触发,可用于格式化、反馈循环或记录。

sequenceDiagram
    participant T as Tool
    participant H as PostToolUse Hook
    participant F as 文件系统

    T->>H: Edit 完成
    H->>F: 运行 prettier
    H->>F: 运行 tsc --noEmit
    H->>H: 检查 console.log
    H->>T: 返回结果

配置示例:自动格式化

{
  "PostToolUse": [
    {
      "matcher": "tool == \"Edit\" && tool_input.file_path matches \"\\.(ts|tsx|js|jsx)$\"",
      "hooks": [
        {
          "type": "command",
          "command": "prettier --write \"$TOOL_INPUT_FILE_PATH\""
        }
      ]
    }
  ]
}

配置示例:TypeScript 类型检查

{
  "PostToolUse": [
    {
      "matcher": "tool == \"Edit\" && tool_input.file_path matches \"\\.(ts|tsx)$\"",
      "hooks": [
        {
          "type": "command",
          "command": "tsc --noEmit 2>&1 | head -20"
        }
      ]
    }
  ]
}

配置示例:console.log 检查

{
  "PostToolUse": [
    {
      "matcher": "tool == \"Edit\"",
      "hooks": [
        {
          "type": "command",
          "command": "grep -n 'console\\.log' \"$TOOL_INPUT_FILE_PATH\" && echo '[Hook] 发现 console.log,请确认是否需要移除' >&2 || true"
        }
      ]
    }
  ]
}

3. UserPromptSubmit

在用户发送消息时触发,可用于预处理或上下文注入。

配置示例:自动加载项目上下文

{
  "UserPromptSubmit": [
    {
      "matcher": "true",
      "hooks": [
        {
          "type": "command",
          "command": "cat ~/.claude/context/project-context.md 2>/dev/null || true"
        }
      ]
    }
  ]
}

4. Stop

在 Claude 停止响应时触发,非常适合清理工作或持久化学习。

sequenceDiagram
    participant C as Claude
    participant H as Stop Hook
    participant S as 存储

    C->>H: 会话结束
    H->>S: 保存会话摘要
    H->>S: 检查未提交更改
    H->>H: 检查 console.log

配置示例:会话摘要保存

{
  "Stop": [
    {
      "matcher": "true",
      "hooks": [
        {
          "type": "command",
          "command": "echo '## 会话摘要 ($DATE)' >> ~/.claude/sessions/log.md && echo '- 完成的任务: ...' >> ~/.claude/sessions/log.md"
        }
      ]
    }
  ]
}

配置示例:console.log 最终检查

{
  "Stop": [
    {
      "matcher": "true",
      "hooks": [
        {
          "type": "command",
          "command": "git diff --name-only | xargs grep -l 'console\\.log' 2>/dev/null && echo '[Hook] 以下文件包含 console.log,请检查' >&2 || true"
        }
      ]
    }
  ]
}

5. PreCompact

在上下文压缩前触发,用于保存重要状态。

配置示例:保存关键上下文

{
  "PreCompact": [
    {
      "matcher": "true",
      "hooks": [
        {
          "type": "command",
          "command": "cat > ~/.claude/.tmp/pre-compact-state.md << 'EOF'\n# 压缩前状态\n- 当前任务: $CURRENT_TASK\n- 关键决策: ...\n- 待办事项: ...\nEOF"
        }
      ]
    }
  ]
}

6. Notification

在需要权限时触发,用于自定义通知。

配置示例:发送桌面通知

{
  "Notification": [
    {
      "matcher": "true",
      "hooks": [
        {
          "type": "command",
          "command": "notify-send 'Claude Code' '需要您的确认'"
        }
      ]
    }
  ]
}

完整 Hooks 配置示例

以下是一个综合的 hooks.json 配置:

{
  "PreToolUse": [
    {
      "matcher": "tool == \"Bash\" && tool_input.command matches \"(npm|pnpm|yarn|cargo|pytest)\"",
      "hooks": [
        {
          "type": "command",
          "command": "if [ -z \"$TMUX\" ]; then echo '[Hook] 考虑使用 tmux' >&2; fi"
        }
      ]
    },
    {
      "matcher": "tool == \"Write\" && tool_input.file_path matches \".*\\.md$\" && !tool_input.file_path matches \"(README|CLAUDE)\"",
      "hooks": [
        {
          "type": "command",
          "command": "echo '[Hook] 阻止创建 .md 文件' >&2; exit 1"
        }
      ]
    },
    {
      "matcher": "tool == \"Bash\" && tool_input.command matches \"git push\"",
      "hooks": [
        {
          "type": "command",
          "command": "git diff --stat origin/$(git branch --show-current) && echo '[Hook] 请审查以上更改后再推送'"
        }
      ]
    }
  ],
  "PostToolUse": [
    {
      "matcher": "tool == \"Edit\" && tool_input.file_path matches \"\\.(ts|tsx|js|jsx)$\"",
      "hooks": [
        {
          "type": "command",
          "command": "prettier --write \"$TOOL_INPUT_FILE_PATH\" 2>/dev/null || true"
        }
      ]
    },
    {
      "matcher": "tool == \"Edit\" && tool_input.file_path matches \"\\.(ts|tsx)$\"",
      "hooks": [
        {
          "type": "command",
          "command": "tsc --noEmit 2>&1 | head -10 || true"
        }
      ]
    },
    {
      "matcher": "tool == \"Edit\"",
      "hooks": [
        {
          "type": "command",
          "command": "grep -n 'console\\.log' \"$TOOL_INPUT_FILE_PATH\" && echo '[Hook] 发现 console.log' >&2 || true"
        }
      ]
    }
  ],
  "Stop": [
    {
      "matcher": "true",
      "hooks": [
        {
          "type": "command",
          "command": "git diff --name-only | xargs grep -l 'console\\.log' 2>/dev/null && echo '[Hook] 检查 console.log' >&2 || true"
        }
      ]
    }
  ]
}

hookify 插件

不想手写 JSON?使用 hookify 插件通过自然语言创建 Hooks。

安装

# 通过插件市场安装
claude plugin marketplace add claude-plugins-official
claude plugin install hookify@claude-plugins-official

使用方法

/hookify

我想创建一个 Hook:
- 当 Claude 执行长时间运行的命令时提醒我使用 tmux
- 当编辑 TypeScript 文件后自动运行 prettier

hookify 会自动生成正确的 JSON 配置。

Matcher 语法

可用变量

变量 说明 示例
tool 工具名称 Bash, Edit, Write, Read
tool_input 工具输入 tool_input.command, tool_input.file_path
tool_result 工具结果 tool_result.exit_code

匹配操作

==          精确匹配
!=          不等于
matches     正则匹配
contains    包含
&&          与
||          或

示例

// 匹配所有 Bash 命令
"tool == \"Bash\""

// 匹配包含 npm 的命令
"tool == \"Bash\" && tool_input.command matches \"npm\""

// 匹配 TypeScript 文件
"tool == \"Edit\" && tool_input.file_path matches \"\\.tsx?$\""

// 匹配失败的操作
"tool_result.exit_code != 0"

常见问题排查

Q1:Hook 没有触发

排查步骤

  1. 检查 hooks.json 语法:

    cat ~/.claude/hooks/hooks.json | python -m json.tool
    
  2. 检查 matcher 是否正确:

    // 确保使用正确的转义
    "tool_input.file_path matches \"\\.ts$\""  // ✅
    "tool_input.file_path matches \".ts$\""    // ❌ 未转义
    
  3. 检查 hook 文件位置:

    ls ~/.claude/hooks/
    # 应该看到 hooks.json
    

Q2:Hook 执行失败

排查步骤

  1. 手动测试命令:

    # 复制 hook 中的命令,手动执行
    prettier --write "src/index.ts"
    
  2. 检查环境变量:

    echo $TOOL_INPUT_FILE_PATH
    
  3. 查看错误输出:

    • Hook 的 stderr 输出会显示在 Claude Code 中

Q3:Hook 影响性能

解决方案

// 限制 hook 执行时间
{
  "timeout": 5000  // 5 秒超时
}

// 只在特定目录触发
{
  "matcher": "tool == \"Edit\" && tool_input.file_path matches \"^src/\""
}

Q4:多个 Hook 执行顺序

Hook 按数组顺序执行:

{
  "PostToolUse": [
    { "matcher": "...", "hooks": [...] },  // 第一个执行
    { "matcher": "...", "hooks": [...] }   // 第二个执行
  ]
}

Q5:如何调试 Hook?

添加调试输出:

{
  "hooks": [
    {
      "type": "command",
      "command": "echo '[Debug] Hook triggered: '$TOOL_INPUT_FILE_PATH' >&2"
    }
  ]
}

小结

关键要点

  • ✅ 6 种 Hook 类型覆盖 Claude Code 完整生命周期
  • ✅ Matcher 语法灵活匹配各种条件
  • ✅ PostToolUse 最常用(格式化、检查)
  • ✅ Stop Hook 适合清理和持久化
  • ✅ hookify 插件让配置更简单

系列导航