<!-- title: Claude Code Hooks自动化：四类钩子构建生产工作流 -->

# Claude Code Hooks自动化实战：四类钩子构建生产级工作流

## 概述

本文系统讲解Claude Code的Hooks机制——一个被大多数开发者忽视的自动化层。你将学会使用PreToolUse、PostToolUse、Notification、SessionStart四类生命周期钩子，构建安全防护、自动格式化、质量门禁和上下文注入的完整工作流。适合已掌握Claude Code基础操作、希望将AI编码效率提升到团队级生产环境的中高级开发者。

## 前置条件

- Claude Code已安装（`npm install -g @anthropic-ai/claude-code`）
- 了解`settings.json`配置结构
- 基础Shell脚本能力（bash/zsh）
- 一个已初始化的项目目录

## 一、Hooks机制全景：为什么你需要它

Claude Code在每次工具调用前后都会触发生命周期事件。Hooks允许你在这些关键节点注入**确定性逻辑**——一段Shell脚本，在AI的决策链中充当"护栏"和"加速器"。

与Skill不同，Hooks不是给AI的新能力，而是对AI行为的**约束与增强**。它在AI执行操作的前后运行确定性代码，确保输出符合团队标准。

### 四类生命周期事件

```mermaid
flowchart LR
    A[用户消息] --> B[SessionStart]
    B --> C[AI思考]
    C --> D{工具调用?}
    D -->|是| E[PreToolUse]
    E --> F[工具执行]
    F --> G[PostToolUse]
    G --> H[AI继续]
    H --> D
    D -->|否| I[AI回复]
    I --> J[Notification]
    J --> A
```

| 钩子类型 | 触发时机 | 核心用途 |
|----------|---------|---------|
| **SessionStart** | 会话开始时 | 注入上下文、加载项目规则 |
| **PreToolUse** | 工具执行前 | 安全拦截、参数校验 |
| **PostToolUse** | 工具执行后 | 自动格式化、质量检查 |
| **Notification** | 任务完成/需要关注时 | 桌面通知、日志记录 |

## 二、配置结构：Hooks的栖身之所

Hooks配置存储在`.claude/settings.json`中，支持项目级和用户级两个作用域。

### 2.1 配置文件位置

```
~/.claude/settings.json          # 用户级（所有项目生效）
.claude/settings.json            # 项目级（仅当前项目）
```

### 2.2 基本配置骨架

```json
{
  "hooks": {
    "PreToolUse": [
      {
        "matcher": "Write|Edit",
        "hooks": [
          {
            "type": "command",
            "command": "bash-script-here"
          }
        ]
      }
    ],
    "PostToolUse": [],
    "Notification": [],
    "SessionStart": []
  }
}
```

### 2.3 Matcher语法

Matcher是一个正则表达式，匹配工具名称：

```json
// 匹配所有文件写入操作
"matcher": "Write|Edit"

// 匹配所有Bash命令
"matcher": "Bash"

// 匹配所有工具（通配）
"matcher": ".*"

// 匹配特定文件路径的写入（需要配合脚本内判断）
"matcher": "Write"
```

### 2.4 Hook输入输出协议

每个Hook通过stdin接收JSON输入，通过stdout返回JSON输出，通过exit code控制行为：

```bash
# 输入格式（stdin JSON）
{
  "tool_name": "Write",
  "tool_input": {
    "file_path": "/src/app.ts",
    "content": "..."
  },
  "session_id": "abc123"
}

# 输出格式（stdout JSON）— 可选
{
  "decision": "block",       // "block" | "approve"（默认）
  "reason": "不允许修改生产环境配置"
}

# Exit Code语义
# 0 = 允许继续（approve）
# 2 = 阻止操作（block）
```

## 三、PreToolUse：安全防护的第一道门

PreToolUse在工具执行前触发，最核心的用途是**安全拦截**。你可以阻止AI执行危险操作，或对参数做预校验。

### 3.1 阻止修改敏感文件

创建`.claude/settings.json`：

```json
{
  "hooks": {
    "PreToolUse": [
      {
        "matcher": "Write|Edit",
        "hooks": [
          {
            "type": "command",
            "command": "cat | jq -r '.tool_input.file_path // empty' | grep -qE '(\\.env|credentials|secret|\\.pem)$' && echo '{\"decision\":\"block\",\"reason\":\"禁止修改敏感文件（.env/credentials/secret/证书）\"}' && exit 2 || exit 0"
          }
        ]
      }
    ]
  }
}
```

**工作原理**：
1. Claude Code通过stdin传入工具调用信息的JSON
2. `jq`提取目标文件路径
3. `grep`匹配敏感文件模式
4. 匹配到则返回`decision: block`并exit 2，阻止操作
5. 不匹配则exit 0，允许继续

### 3.2 阻止危险Bash命令

```json
{
  "hooks": {
    "PreToolUse": [
      {
        "matcher": "Bash",
        "hooks": [
          {
            "type": "command",
            "command": "INPUT=$(cat) && CMD=$(echo \"$INPUT\" | jq -r '.tool_input.command // empty') && echo \"$CMD\" | grep -qiE '(rm\\s+-rf\\s+/|DROP\\s+TABLE|truncate|mkfs|dd\\s+if=)' && echo '{\"decision\":\"block\",\"reason\":\"检测到危险命令，已拦截\"}' && exit 2 || exit 0"
          }
        ]
      }
    ]
  }
}
```

### 3.3 限制操作范围到项目目录

```json
{
  "matcher": "Write|Edit|Bash",
  "hooks": [
    {
      "type": "command",
      "command": "INPUT=$(cat) && PROJECT_DIR=$(pwd) && FP=$(echo \"$INPUT\" | jq -r '.tool_input.file_path // .tool_input.command // empty') && echo \"$FP\" | grep -qv \"$PROJECT_DIR\" && echo \"{\\\"decision\\\":\\\"block\\\",\\\"reason\\\":\\\"操作超出项目目录范围\\\"}\" && exit 2 || exit 0"
    }
  ]
}
```

### 常见问题

**Q: Hook脚本失败会怎样？**
A: 如果脚本exit非0且非2，Claude Code会显示错误但继续执行。只有exit 2明确阻止操作。

**Q: 可以有多个PreToolUse hook吗？**
A: 可以。按数组顺序执行，任一hook返回block即阻止。

## 四、PostToolUse：自动格式化与质量门

PostToolUse在工具执行完成后触发，最适合做**自动修复**和**质量检查**。

### 4.1 自动格式化代码

这是最高频使用的Hook——每次AI写入文件后自动运行格式化工具：

```json
{
  "hooks": {
    "PostToolUse": [
      {
        "matcher": "Write|Edit",
        "hooks": [
          {
            "type": "command",
            "command": "FILE=$(cat | jq -r '.tool_input.file_path // empty') && [ -n \"$FILE\" ] && [ -f \"$FILE\" ] && case \"$FILE\" in *.ts|*.tsx|*.js|*.jsx) npx prettier --write \"$FILE\" 2>/dev/null;; *.py) python -m black \"$FILE\" 2>/dev/null && python -m isort \"$FILE\" 2>/dev/null;; *.go) gofmt -w \"$FILE\" 2>/dev/null;; *.rs) rustfmt \"$FILE\" 2>/dev/null;; esac && exit 0"
          }
        ]
      }
    ]
  }
}
```

**执行流程**：
1. 从stdin JSON提取被修改的文件路径
2. 根据文件扩展名选择对应的格式化工具
3. 静默执行格式化（`2>/dev/null`抑制错误输出）
4. 始终exit 0（PostToolUse中block通常无意义）

### 4.2 自动运行Lint检查

```json
{
  "hooks": {
    "PostToolUse": [
      {
        "matcher": "Write|Edit",
        "hooks": [
          {
            "type": "command",
            "command": "FILE=$(cat | jq -r '.tool_input.file_path // empty') && [ -n \"$FILE\" ] && [ -f \"$FILE\" ] && case \"$FILE\" in *.ts|*.tsx|*.js|*.jsx) npx eslint --fix \"$FILE\" 2>/dev/null;; *.py) python -m ruff check --fix \"$FILE\" 2>/dev/null;; esac && exit 0"
          }
        ]
      }
    ]
  }
}
```

### 4.3 自动运行相关测试

对于修改了源码文件的情况，自动触发对应的测试：

```json
{
  "matcher": "Write|Edit",
  "hooks": [
    {
      "type": "command",
      "command": "FILE=$(cat | jq -r '.tool_input.file_path // empty') && TEST_FILE=$(echo \"$FILE\" | sed 's/\\.ts$/.test.ts/;s/src\\//test\\//') && [ -f \"$TEST_FILE\" ] && npx vitest run \"$TEST_FILE\" --reporter=verbose 2>&1 | tail -5 || exit 0"
    }
  ]
}
```

### 4.4 PostToolUse注入修复提示

PostToolUse还可以通过stdout向AI返回额外信息，引导AI自我修复：

```json
{
  "matcher": "Write|Edit",
  "hooks": [
    {
      "type": "command",
      "command": "FILE=$(cat | jq -r '.tool_input.file_path // empty') && [ -n \"$FILE\" ] && [ -f \"$FILE\" ] && LINT_OUT=$(npx eslint \"$FILE\" --format json 2>/dev/null) && ERRORS=$(echo \"$LINT_OUT\" | jq '[.[0].messages // [] | .[] | .message] | length') && [ \"$ERRORS\" -gt 0 ] && echo \"{\\\"decision\\\":\\\"block\\\",\\\"reason\\\":\\\"ESLint发现 $ERRORS 个错误，请修复：$(echo \\\"$LINT_OUT\\\" | jq -r '.[0].messages[:3] | .[] | .message')\\\"}\" && exit 2 || exit 0"
    }
  ]
}
```

这段Hook在格式化后运行ESLint检查，如果有错误，直接block并返回错误信息——AI会看到错误描述并自动尝试修复。

## 五、SessionStart：上下文注入引擎

SessionStart在每次新会话开始时触发，是注入项目规则和上下文的最佳时机。

### 5.1 注入项目规范

```json
{
  "hooks": {
    "SessionStart": [
      {
        "hooks": [
          {
            "type": "command",
            "command": "cat << 'CTX'\n本项目使用以下规范：\n- TypeScript严格模式，禁止any\n- 组件使用函数式组件+Hooks\n- 测试覆盖率≥80%\n- 提交信息遵循Conventional Commits\n- API响应统一使用{code, data, message}格式\nCTX"
          }
        ]
      }
    ]
  }
}
```

SessionStart hook的stdout内容会作为**上下文注入**到对话中，相当于自动在每次对话开头添加了一段系统提示。

### 5.2 动态加载CLAUDE.md规则

```json
{
  "SessionStart": [
    {
      "hooks": [
        {
          "type": "command",
          "command": "[ -f CLAUDE.md ] && cat CLAUDE.md || echo '未找到项目级CLAUDE.md，使用默认规则'"
        }
      ]
    }
  ]
}
```

### 5.3 加载环境信息

```json
{
  "SessionStart": [
    {
      "hooks": [
        {
          "type": "command",
          "command": "echo \"当前环境信息：\" && echo \"- Node: $(node -v)\" && echo \"- npm: $(npm -v)\" && echo \"- Git分支: $(git branch --show-current 2>/dev/null || echo '非Git仓库')\" && echo \"- 项目: $(basename $(pwd))\" && echo \"- 最近修改: $(git log --oneline -5 2>/dev/null || echo '无Git日志')\""
        }
      ]
    }
  ]
}
```

### 5.4 条件化上下文注入

根据项目类型加载不同的规则集：

```bash
#!/bin/bash
# .claude/hooks/session-start.sh

PROJECT_DIR=$(pwd)

if [ -f "$PROJECT_DIR/package.json" ]; then
  FRAMEWORK=$(jq -r '.dependencies | keys[] | select(. == "next" or . == "react" or . == "vue" or . == "svelte")' "$PROJECT_DIR/package.json" 2>/dev/null | head -1)
  
  case "$FRAMEWORK" in
    next)
      echo "检测到Next.js项目。规则：使用App Router，Server Components优先，API Routes使用RESTful风格。"
      ;;
    react)
      echo "检测到React项目。规则：使用函数式组件，状态管理使用zustand，样式使用CSS Modules。"
      ;;
    vue)
      echo "检测到Vue项目。规则：使用Composition API，组件命名PascalCase，状态管理使用Pinia。"
      ;;
    *)
      echo "检测到Node.js项目。规则：ES模块优先，错误处理使用自定义Error类。"
      ;;
  esac
fi

if [ -f "$PROJECT_DIR/requirements.txt" ] || [ -f "$PROJECT_DIR/pyproject.toml" ]; then
  echo "检测到Python项目。规则：类型注解必须，使用ruff格式化，FastAPI作为Web框架首选。"
fi

if [ -f "$PROJECT_DIR/go.mod" ]; then
  echo "检测到Go项目。规则：错误处理不使用panic，接口定义在消费方，测试使用table-driven。"
fi
```

在settings.json中引用：

```json
{
  "SessionStart": [
    {
      "hooks": [
        {
          "type": "command",
          "command": "bash .claude/hooks/session-start.sh"
        }
      ]
    }
  ]
}
```

## 六、Notification：任务完成通知

Notification在Claude Code完成任务或需要用户关注时触发，用于发送通知到外部系统。

### 6.1 桌面通知（macOS）

```json
{
  "Notification": [
    {
      "hooks": [
        {
          "type": "command",
          "command": "MSG=$(cat | jq -r '.message // empty') && osascript -e \"display notification \\\"$MSG\\\" with title \\\"Claude Code\\\"\" 2>/dev/null || exit 0"
        }
      ]
    }
  ]
}
```

### 6.2 桌面通知（Linux）

```json
{
  "Notification": [
    {
      "hooks": [
        {
          "type": "command",
          "command": "MSG=$(cat | jq -r '.message // empty') && notify-send \"Claude Code\" \"$MSG\" 2>/dev/null || exit 0"
        }
      ]
    }
  ]
}
```

### 6.3 发送到Slack

```json
{
  "Notification": [
    {
      "hooks": [
        {
          "type": "command",
          "command": "MSG=$(cat | jq -r '.message // \"任务完成\"') && curl -s -X POST \"$SLACK_WEBHOOK\" -H 'Content-type: application/json' -d \"{\\\"text\\\":\\\"[Claude Code] $MSG\\\"}\" > /dev/null 2>&1 || exit 0"
        }
      ]
    }
  ]
}
```

使用前设置环境变量：

```bash
export SLACK_WEBHOOK="https://hooks.slack.com/services/YOUR/WEBHOOK/URL"
```

### 6.4 记录操作日志

```json
{
  "Notification": [
    {
      "hooks": [
        {
          "type": "command",
          "command": "MSG=$(cat | jq -r '.message // empty') && TIMESTAMP=$(date '+%Y-%m-%d %H:%M:%S') && echo \"[$TIMESTAMP] $MSG\" >> .claude/notifications.log || exit 0"
        }
      ]
    }
  ]
}
```

## 七、完整实战案例：团队级Hooks配置

下面是一个完整的、可直接用于团队项目的settings.json配置，整合了所有四类钩子。

### 7.1 项目结构

```
my-project/
├── .claude/
│   ├── settings.json          # Hooks配置
│   └── hooks/
│       ├── pre-tool.sh        # PreToolUse脚本
│       ├── post-tool.sh       # PostToolUse脚本
│       ├── session-start.sh   # SessionStart脚本
│       └── notify.sh          # Notification脚本
├── src/
├── tests/
└── package.json
```

### 7.2 完整settings.json

```json
{
  "hooks": {
    "SessionStart": [
      {
        "hooks": [
          {
            "type": "command",
            "command": "bash .claude/hooks/session-start.sh"
          }
        ]
      }
    ],
    "PreToolUse": [
      {
        "matcher": "Write|Edit",
        "hooks": [
          {
            "type": "command",
            "command": "bash .claude/hooks/pre-tool.sh"
          }
        ]
      },
      {
        "matcher": "Bash",
        "hooks": [
          {
            "type": "command",
            "command": "bash .claude/hooks/pre-tool.sh"
          }
        ]
      }
    ],
    "PostToolUse": [
      {
        "matcher": "Write|Edit",
        "hooks": [
          {
            "type": "command",
            "command": "bash .claude/hooks/post-tool.sh"
          }
        ]
      }
    ],
    "Notification": [
      {
        "hooks": [
          {
            "type": "command",
            "command": "bash .claude/hooks/notify.sh"
          }
        ]
      }
    ]
  }
}
```

### 7.3 pre-tool.sh — 安全防护脚本

```bash
#!/bin/bash
set -euo pipefail

INPUT=$(cat)
TOOL=$(echo "$INPUT" | jq -r '.tool_name // empty')

case "$TOOL" in
  Write|Edit)
    FILE=$(echo "$INPUT" | jq -r '.tool_input.file_path // empty')
    
    # 规则1：禁止修改敏感文件
    if echo "$FILE" | grep -qE '\.(env|secret|credentials|pem|key)$'; then
      echo '{"decision":"block","reason":"安全策略：禁止修改敏感文件"}'
      exit 2
    fi
    
    # 规则2：禁止修改.git目录
    if echo "$FILE" | grep -qE '\.git/'; then
      echo '{"decision":"block","reason":"安全策略：禁止修改Git内部文件"}'
      exit 2
    fi
    
    # 规则3：禁止修改CI/CD配置（需人工审批）
    if echo "$FILE" | grep -qE '\.(github|gitlab-ci|Jenkinsfile|docker-compose)'; then
      echo '{"decision":"block","reason":"CI/CD配置修改需要人工审批"}'
      exit 2
    fi
    ;;
    
  Bash)
    CMD=$(echo "$INPUT" | jq -r '.tool_input.command // empty')
    
    # 规则4：阻止破坏性命令
    if echo "$CMD" | grep -qiE '(rm\s+-rf\s+/|DROP\s+TABLE|truncate\s+table|dd\s+if=|mkfs|:(){ :\|:& };:)'; then
      echo '{"decision":"block","reason":"检测到破坏性命令，已拦截"}'
      exit 2
    fi
    
    # 规则5：阻止强制推送
    if echo "$CMD" | grep -qiE 'git\s+push.*--force'; then
      echo '{"decision":"block","reason":"禁止强制推送（git push --force）"}'
      exit 2
    fi
    
    # 规则6：阻止直接推送main分支
    if echo "$CMD" | grep -qiE 'git\s+push.*main|git\s+push.*master'; then
      echo '{"decision":"block","reason":"禁止直接推送到主分支，请使用PR"}'
      exit 2
    fi
    ;;
esac

exit 0
```

### 7.4 post-tool.sh — 自动修复脚本

```bash
#!/bin/bash
set -euo pipefail

INPUT=$(cat)
FILE=$(echo "$INPUT" | jq -r '.tool_input.file_path // empty')

[ -z "$FILE" ] || [ ! -f "$FILE" ] && exit 0

case "$FILE" in
  *.ts|*.tsx|*.js|*.jsx)
    # 格式化
    npx prettier --write "$FILE" 2>/dev/null || true
    # Lint修复
    npx eslint --fix "$FILE" 2>/dev/null || true
    # 检查剩余错误
    LINT_ERRORS=$(npx eslint "$FILE" --format json 2>/dev/null | jq '[.[0].messages // [] | .[] | .message] | length' 2>/dev/null || echo "0")
    if [ "$LINT_ERRORS" -gt 0 ]; then
      ERROR_MSGS=$(npx eslint "$FILE" --format json 2>/dev/null | jq -r '.[0].messages[:3] | .[] | "\(.line):\(.message)"' 2>/dev/null || true)
      echo "{\"decision\":\"block\",\"reason\":\"ESLint仍有${LINT_ERRORS}个错误：${ERROR_MSGS}\"}"
      exit 2
    fi
    ;;
  *.py)
    python -m ruff check --fix "$FILE" 2>/dev/null || true
    python -m ruff format "$FILE" 2>/dev/null || true
    ;;
  *.go)
    gofmt -w "$FILE" 2>/dev/null || true
    goimports -w "$FILE" 2>/dev/null || true
    ;;
  *.rs)
    rustfmt "$FILE" 2>/dev/null || true
    ;;
  *.sql)
    # SQL格式化
    npx sql-formatter --fix "$FILE" 2>/dev/null || true
    ;;
esac

exit 0
```

### 7.5 session-start.sh — 上下文注入脚本

```bash
#!/bin/bash
set -euo pipefail

PROJECT_DIR=$(pwd)
PROJECT_NAME=$(basename "$PROJECT_DIR")

echo "=== 项目：$PROJECT_NAME ==="

# Git信息
BRANCH=$(git branch --show-current 2>/dev/null || echo "detached")
echo "分支：$BRANCH"

# 最近提交
echo "最近活动："
git log --oneline -3 2>/dev/null | while read -r line; do echo "  $line"; done

# 技术栈检测
if [ -f "package.json" ]; then
  echo "技术栈："
  jq -r '.dependencies // {} | keys[]' package.json 2>/dev/null | head -5 | while read -r dep; do echo "  - $dep"; done
fi

# 项目规则
echo ""
echo "项目规则："
echo "- 提交前必须通过所有测试"
echo "- 禁止使用any类型"
echo "- 新功能必须有对应测试"
echo "- API端点必须有JSDoc注释"
```

### 7.6 notify.sh — 通知脚本

```bash
#!/bin/bash
set -euo pipefail

INPUT=$(cat)
MSG=$(echo "$INPUT" | jq -r '.message // "任务完成"')
TIMESTAMP=$(date '+%Y-%m-%d %H:%M:%S')

# 写入日志
echo "[$TIMESTAMP] $MSG" >> .claude/notifications.log

# macOS桌面通知
if command -v osascript &>/dev/null; then
  osascript -e "display notification \"$MSG\" with title \"Claude Code\"" 2>/dev/null || true
fi

# Linux桌面通知
if command -v notify-send &>/dev/null; then
  notify-send "Claude Code" "$MSG" 2>/dev/null || true
fi

exit 0
```

### 7.7 执行流程全景

```mermaid
sequenceDiagram
    participant U as 用户
    participant CC as Claude Code
    participant SS as SessionStart
    participant PTU as PreToolUse
    participant Tool as 工具执行
    participant PostT as PostToolUse
    participant N as Notification

    U->>CC: 发送消息
    CC->>SS: 会话开始
    SS-->>CC: 注入项目上下文+规则
    CC->>CC: AI分析+规划
    CC->>PTU: 准备调用Write工具
    PTU->>PTU: 检查敏感文件/危险操作
    PTU-->>CC: approve/block
    alt approved
        CC->>Tool: 执行Write
        Tool-->>CC: 写入完成
        CC->>PostT: 文件已修改
        PostT->>PostT: prettier→eslint→检查错误
        alt 有lint错误
            PostT-->>CC: block+错误详情
            CC->>CC: 自动修复
        else 无错误
            PostT-->>CC: approve
        end
    else blocked
        CC->>CC: 调整方案重试
    end
    CC->>N: 任务完成
    N->>N: 桌面通知+日志
    N-->>CC: done
    CC-->>U: 返回结果
```

## 八、高级模式与最佳实践

### 8.1 多Hook串联

同一事件可以注册多个Hook，按顺序执行：

```json
{
  "PreToolUse": [
    {
      "matcher": "Write|Edit",
      "hooks": [
        {"type": "command", "command": "bash .claude/hooks/check-sensitive.sh"},
        {"type": "command", "command": "bash .claude/hooks/check-scope.sh"},
        {"type": "command", "command": "bash .claude/hooks/check-lock.sh"}
      ]
    }
  ]
}
```

执行规则：
- 顺序执行，任一返回`block`即停止后续
- 某个Hook失败（exit 1）会跳过，继续执行下一个
- 只有exit 2才真正阻止操作

### 8.2 项目级与用户级协作

```
~/.claude/settings.json          # 个人偏好（格式化工具版本等）
.claude/settings.json            # 团队规则（安全策略、质量门禁）
```

两者会合并执行，项目级优先。

### 8.3 调试Hooks

当Hook行为不符合预期时，可以添加日志：

```bash
#!/bin/bash
INPUT=$(cat)
echo "[$(date)] INPUT: $INPUT" >> .claude/hooks/debug.log

# ... 正常逻辑 ...

echo "[$(date)] RESULT: $RESULT" >> .claude/hooks/debug.log
```

也可以使用环境变量开启调试模式：

```json
{
  "type": "command",
  "command": "DEBUG=1 bash .claude/hooks/pre-tool.sh"
}
```

### 8.4 性能考量

Hooks在每个工具调用时都会执行，性能直接影响AI响应速度：

| 优化策略 | 说明 |
|---------|------|
| 保持脚本轻量 | 避免在Hook中运行耗时操作 |
| 使用内置命令 | 优先使用`grep`/`jq`而非外部工具 |
| 条件短路 | 快速判断是否需要执行完整逻辑 |
| 缓存结果 | 对重复计算使用临时文件缓存 |
| 异步通知 | Notification hook中用`&`后台发送 |

```bash
# 反模式：每次调用都安装依赖
npx -y prettier --write "$FILE"  # ❌ 首次需要下载

# 正模式：确保工具已安装
prettier --write "$FILE" 2>/dev/null || npx prettier --write "$FILE"
```

### 8.5 团队共享方案

将Hooks配置纳入版本控制，确保全团队一致：

```bash
# .claude/settings.json → Git跟踪
# .claude/hooks/ → Git跟踪
# .claude/hooks/local.sh → .gitignore（个人自定义）
```

```gitignore
# .gitignore
.claude/hooks/local.*
.claude/notifications.log
.claude/hooks/debug.log
```

## 九、从零搭建：5分钟快速上手

以下是一个最简可用的Hooks配置，适合立即开始：

**第一步**：创建目录

```bash
mkdir -p .claude/hooks
```

**第二步**：创建`.claude/settings.json`

```json
{
  "hooks": {
    "PreToolUse": [
      {
        "matcher": "Write|Edit",
        "hooks": [
          {
            "type": "command",
            "command": "FILE=$(cat | jq -r '.tool_input.file_path // empty') && echo \"$FILE\" | grep -qE '\\.(env|secret|credentials)$' && echo '{\"decision\":\"block\",\"reason\":\"禁止修改敏感文件\"}' && exit 2 || exit 0"
          }
        ]
      }
    ],
    "PostToolUse": [
      {
        "matcher": "Write|Edit",
        "hooks": [
          {
            "type": "command",
            "command": "FILE=$(cat | jq -r '.tool_input.file_path // empty') && [ -f \"$FILE\" ] && npx prettier --write \"$FILE\" 2>/dev/null; exit 0"
          }
        ]
      }
    ]
  }
}
```

**第三步**：验证

```bash
# 启动Claude Code
claude

# 在对话中让AI创建一个测试文件
> 创建一个 hello.ts 文件，内容是打印hello world
```

观察输出：AI写入文件后，prettier自动格式化。

**第四步**：测试安全拦截

```bash
> 修改 .env 文件，添加 DATABASE_URL

# 预期：AI会报告操作被拦截
```

## 十、常见问题排查手册

| 问题 | 原因 | 解决方案 |
|------|------|---------|
| Hook不触发 | matcher不匹配 | 检查正则是否正确，用`.*`测试 |
| Hook触发但无效果 | 脚本报错 | 添加debug日志，检查stderr |
| 格式化不执行 | 工具未安装 | 确保prettier/eslint在项目依赖中 |
| 阻止了不该阻止的操作 | matcher太宽泛 | 缩小匹配范围或添加白名单 |
| 通知不发送 | 环境变量缺失 | 检查SLACK_WEBHOOK等变量 |
| 性能变慢 | Hook太重 | 减少Hook中的外部调用 |

```mermaid
flowchart TD
    A[Hook不工作] --> B{触发了吗?}
    B -->|否| C[检查matcher正则]
    B -->|是| D{执行了吗?}
    D -->|否| E[检查脚本权限 chmod +x]
    D -->|是| F{返回正确?}
    F -->|否| G[检查jq语法和JSON输出]
    F -->|是| H[检查exit code逻辑]
    C --> I[修复matcher]
    E --> J[添加执行权限]
    G --> K[测试JSON输出]
    H --> L[确认0=通过 2=阻止]
```

## 延伸阅读

- [Claude Code Hooks官方文档](https://code.claude.com/docs/en/hooks-guide) — Hooks完整参考
- [Claude Code Hooks Reference](https://code.claude.com/docs/en/hooks) — 事件类型与JSON Schema
- [Claude Code Hooks Cookbook (GitHub)](https://github.com/meet-deshani/claude-code-hooks-cookbook) — 社区维护的Hook模式集合
- [MCP TypeScript SDK](https://github.com/modelcontextprotocol/typescript-sdk) — MCP服务端开发SDK
- [Anthropic Claude Code Blog](https://www.anthropic.com/blog) — Claude Code版本更新与最佳实践

## 训练营适用性评估

| 维度 | 评估 |
|------|------|
| 适合训练营类型 | 企业AI开发内训、团队Claude Code推广 |
| 学员基础要求 | 会用Claude Code基本操作，懂基础bash |
| 预计教学时长 | 2-3小时（含实操练习） |
| 实操难度 | 中等（配置调试需要一定Shell能力） |
| 交付物 | 一套可立即用于团队项目的Hooks配置 |

## 参考来源

1. [Automate workflows with hooks - Claude Code Docs](https://code.claude.com/docs/en/hooks-guide) — Anthropic官方Hooks指南，涵盖全部四类钩子配置
2. [Hooks reference - Claude Code Docs](https://code.claude.com/docs/en/hooks) — Hooks完整参考文档，含JSON输入输出Schema和Exit Code语义
3. [Claude Code Hooks: The Automation Layer Nobody Knows About](https://dev.to/whoffagents/claude-code-hooks-the-automation-layer-nobody-knows-about-3po0) — 深度分析Hooks架构设计与生产级模式
4. [meet-deshani/claude-code-hooks-cookbook](https://github.com/meet-deshani/claude-code-hooks-cookbook) — 社区维护的实战Hook模式集合，包含安全防护、质量门禁等20+模式
5. [Claude Code Hooks: 6 Production Patterns](https://www.pixelmojo.io/blogs/claude-code-hooks-production-quality-ci-cd-patterns) — 六种生产级Hook模式详解

> [!tip] 51学通信知识星球
> **星主：爱卫生**（微信：gprshome201101）——公众号「51学通信」创办者，19 年通信行业运维与讲师经验，著有《GPRS网络信令实例详解》《EPC原理与实践》《5G核心网原理与实践》三本纸质书（各大电商平台有售）。
> **星球定位**：深耕 5G 核心网、IMS、NFV/AI、云原生等 ICT 领域，主打运维岗位与信令分析。
> **当前规模**：5200 篇主题 / 990 个回答，198 元/年。
> **加入福利**：加入星球后请加爱卫生微信，拉您进知识星球年度陪伴与答疑群——不限量回复您的各种问题，另有群内分享。
> **AI 加持**：51学通信知识星球已作为 skill 接入 WorkBuddy，使用 deepseek-4-flash 在海量星球帖子中精准找贴、找视频、找 FAQ 和案例，做总结、找文档和 PPT 等场景全覆盖。

![51学通信知识星球海报-扫码加入](https://wiki.500nian.com/images/zhixingqiu_qrcode.png)
