<!-- title: Claude Code自动化：从-p模式到Hooks全攻略 -->

# Claude Code自动化：从-p模式到Hooks全攻略

**概述**：本教程系统讲解Claude Code的三大自动化能力——Headless模式（`-p`标志）、Hooks生命周期钩子、以及Agent SDK编程式调用。学完本教程，你将能把Claude Code嵌入CI/CD流水线、构建批量代码审查工具、实现自动格式化和安全检查。适合有半年以上Claude Code使用经验的开发者，以及需要将AI编码能力产品化的工程团队。

**前置条件**：
- Claude Code CLI已安装并完成认证（`claude --version` ≥ 1.0.36）
- 熟悉命令行操作和shell脚本
- 了解JSON格式和基本的Node.js/Python知识
- 一个可用的项目目录作为实验环境

---

## 一、Headless模式：让Claude Code脱离终端

### 1.1 什么是Headless模式

Headless模式是Claude Code的非交互式运行方式。通过添加`-p`（或`--print`）标志，Claude Code不再启动交互式TUI界面，而是直接在标准输出中打印结果。这使得它可以在脚本、CI管道、定时任务中无人值守地运行。


![图表1](images/claude-code-tutorial-r4-0008-mermaid-0.png)

> *图表 1*


### 1.2 基础用法

最简单的headless调用只需要一个提示词：

```bash
# 单次问答，直接输出到终端
claude -p "解释一下这个项目的目录结构"

# 管道输入——将文件内容作为上下文
cat src/main.ts | claude -p "这段代码有什么问题？请用JSON格式返回问题列表"

# 指定工作目录
claude -p --cwd /path/to/project "运行所有测试并报告失败原因"
```

### 1.3 控制输出格式

`--output-format`标志决定了Claude Code如何返回结果，这在编程集成中至关重要：

```bash
# 纯文本输出（默认）
claude -p "列出所有TODO注释" --output-format text

# JSON输出——适合程序解析
claude -p "分析代码质量" --output-format json

# 流式JSON——逐条输出，适合实时处理
claude -p "重构这个模块" --output-format stream-json

# 获取JSON格式的完整对话记录
claude -p "解释架构设计" --output-format json --verbose
```

JSON输出格式的典型结构：

```json
{
  "type": "result",
  "subtype": "success",
  "cost_usd": 0.042,
  "duration_ms": 12340,
  "duration_api_ms": 8920,
  "is_error": false,
  "num_turns": 3,
  "result": "项目采用分层架构...",
  "session_id": "abc123"
}
```

### 1.4 限制工具权限

在自动化场景中，安全是第一要务。`--allowedTools`标志控制Claude Code可以使用哪些工具：

```bash
# 只允许读取——最安全的只读模式
claude -p "审查代码风格" \
  --allowedTools "Read,Glob,Grep"

# 允许读取和编辑——用于代码修改
claude -p "修复所有lint错误" \
  --allowedTools "Read,Edit,Glob,Grep"

# 允许执行bash命令——用于测试运行
claude -p "运行测试套件并修复失败用例" \
  --allowedTools "Read,Edit,Bash,Glob,Grep"

# 禁用网络访问工具——防止信息泄露
claude -p "分析代码逻辑" \
  --disallowedTools "WebSearch,WebFetch"
```

### 1.5 限制交互轮次

`--max-turns`防止Agent陷入无限循环，这在批量任务中尤其重要：

```bash
# 最多执行5轮工具调用
claude -p "修复所有TypeScript类型错误" \
  --max-turns 5 \
  --allowedTools "Read,Edit,Bash"
```

### 1.6 实战：批量代码审查脚本

下面是一个完整的shell脚本，用headless模式批量审查Git仓库中的变更文件：

```bash
#!/bin/bash
# batch-review.sh — 批量代码审查脚本

set -euo pipefail

# 获取main分支到当前HEAD之间变更的文件列表
CHANGED_FILES=$(git diff --name-only main...HEAD -- '*.ts' '*.tsx' '*.py')

if [ -z "$CHANGED_FILES" ]; then
  echo "没有发现变更文件"
  exit 0
fi

echo "=== 批量代码审查开始 ==="
echo "待审查文件："
echo "$CHANGED_FILES"
echo ""

# 逐文件审查
while IFS= read -r file; do
  echo "--- 审查: $file ---"
  
  # 使用-p模式进行非交互式审查
  claude -p "$(cat <<'PROMPT'
请审查以下文件的最新git diff，重点关注：
1. 潜在的安全漏洞
2. 性能问题
3. 代码可维护性
请用简洁的中文输出审查结果，如果没有问题就说"无问题"。
PROMPT
  )" \
    --allowedTools "Read,Bash" \
    --max-turns 3 \
    --cwd "$(git rev-parse --show-toplevel)"
  
  echo ""
done <<< "$CHANGED_FILES"

echo "=== 批量代码审查完成 ==="
```

运行方式：

```bash
chmod +x batch-review.sh
./batch-review.sh
```

### 1.7 常见问题

| 问题 | 原因 | 解决方案 |
|------|------|----------|
| `Error: No API key` | 未设置认证 | 运行 `claude login` 或设置 `ANTHROPIC_API_KEY` |
| 输出包含ANSI转义码 | 终端检测到TTY | 设置 `NO_COLOR=1` 环境变量 |
| 脚本卡住不返回 | Agent轮次过多 | 添加 `--max-turns` 限制 |
| 权限被拒绝 | 工具不在白名单 | 检查 `--allowedTools` 配置 |
| JSON解析失败 | 混合了文本和JSON | 使用 `--output-format json` |

---

## 二、Hooks：Claude Code的生命周期钩子

### 2.1 Hooks机制概述

Hooks是Claude Code中一个强大的自动化层，允许你在Agent执行的关键节点注入自定义逻辑。每个Hook本质上是一个shell命令，在特定事件触发时自动执行。


![图表2](images/claude-code-tutorial-r4-0008-mermaid-1.png)

> *图表 2*


### 2.2 Hook事件类型

Claude Code支持以下生命周期事件：

| 事件 | 触发时机 | 典型用途 |
|------|----------|----------|
| `PreToolUse` | 工具调用**之前** | 权限检查、参数验证、安全审计 |
| `PostToolUse` | 工具调用**之后** | 自动格式化、通知推送、日志记录 |
| `Notification` | Agent发送通知时 | Slack/邮件通知、状态同步 |
| `Stop` | Agent停止时 | 清理临时文件、汇总报告 |
| `SessionStart` | 会话开始时 | 加载环境变量、初始化上下文 |

### 2.3 配置Hooks

Hooks在`settings.json`中配置。配置文件位于：

- **全局配置**：`~/.claude/settings.json`
- **项目配置**：`.claude/settings.json`

```json
{
  "hooks": {
    "PreToolUse": [
      {
        "matcher": "Bash",
        "hooks": [
          {
            "type": "command",
            "command": "/path/to/pre-bash-guard.sh"
          }
        ]
      }
    ],
    "PostToolUse": [
      {
        "matcher": "Edit",
        "hooks": [
          {
            "type": "command",
            "command": "npx prettier --write $CLAUDE_FILE_PATH"
          }
        ]
      }
    ],
    "Notification": [
      {
        "matcher": "",
        "hooks": [
          {
            "type": "command",
            "command": "notify-send 'Claude Code' '$CLAUDE_NOTIFICATION'"
          }
        ]
      }
    ],
    "Stop": [
      {
        "matcher": "",
        "hooks": [
          {
            "type": "command",
            "command": "/path/to/session-summary.sh"
          }
        ]
      }
    ]
  }
}
```

### 2.4 Hook输入输出协议

每个Hook通过**标准输入**接收JSON格式的上下文信息，通过**退出码**控制Claude Code的行为。

**输入JSON结构**（PreToolUse）：

```json
{
  "session_id": "sess_abc123",
  "tool_name": "Bash",
  "tool_input": {
    "command": "rm -rf node_modules"
  }
}
```

**退出码含义**：

| 退出码 | 含义 | 效果 |
|--------|------|------|
| `0` | 通过 | 继续执行工具调用 |
| `2` | 阻止 | 取消本次工具调用，向Agent反馈阻止原因 |
| 其他 | 错误 | Hook执行出错，工具调用被取消 |

**通过stdout返回阻止原因**：

```bash
#!/bin/bash
# pre-bash-guard.sh — 阻止危险的bash命令

read -r INPUT
COMMAND=$(echo "$INPUT" | jq -r '.tool_input.command')

# 检查危险命令模式
DANGEROUS_PATTERNS=("rm -rf /" "rm -rf ~" "DROP TABLE" "format c:" "> /dev/sda")

for pattern in "${DANGEROUS_PATTERNS[@]}"; do
  if [[ "$COMMAND" == *"$pattern"* ]]; then
    echo "已阻止危险命令：检测到 '$pattern' 模式。如果确认需要执行，请手动操作。"
    exit 2
  fi
done

exit 0
```

### 2.5 实战：五层防护Hooks配置

以下是一套生产级别的Hooks配置，覆盖代码质量、安全防护、通知和日志四大维度：

**第一层：PreToolUse — 安全守卫**

```json
{
  "hooks": {
    "PreToolUse": [
      {
        "matcher": "Bash",
        "hooks": [
          {
            "type": "command",
            "command": "bash ~/.claude/hooks/guard-bash.sh"
          }
        ]
      },
      {
        "matcher": "Edit",
        "hooks": [
          {
            "type": "command",
            "command": "bash ~/.claude/hooks/guard-edit.sh"
          }
        ]
      }
    ]
  }
}
```

`guard-bash.sh`：

```bash
#!/bin/bash
# guard-bash.sh — Bash命令安全守卫
set -euo pipefail

INPUT=$(cat)
CMD=$(echo "$INPUT" | jq -r '.tool_input.command')

# 规则1：阻止强制推送
if echo "$CMD" | grep -qE 'git\s+push\s+.*--force|git\s+push\s+.*-f\b'; then
  echo "已阻止：禁止使用 --force 推送。如需覆盖远程历史，请使用 --force-with-lease。"
  exit 2
fi

# 规则2：阻止删除受保护分支
if echo "$CMD" | grep -qE 'git\s+branch\s+-[dD]\s+(main|master|release|develop)'; then
  echo "已阻止：禁止删除受保护分支 (main/master/release/develop)。"
  exit 2
fi

# 规则3：阻止操作生产环境文件
if echo "$CMD" | grep -qE '/etc/|/var/www/production|/usr/local/bin/deploy'; then
  echo "已阻止：检测到生产环境路径，请确认后再手动执行。"
  exit 2
fi

exit 0
```

`guard-edit.sh`：

```bash
#!/bin/bash
# guard-edit.sh — 文件编辑守卫
set -euo pipefail

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

# 阻止编辑敏感文件
PROTECTED_FILES=(".env" ".env.production" "credentials.json" "secrets.yaml" ".ssh/config")
for protected in "${PROTECTED_FILES[@]}"; do
  if [[ "$FILE_PATH" == *"$protected"* ]]; then
    echo "已阻止：禁止编辑敏感文件 $FILE_PATH。如需修改，请手动操作。"
    exit 2
  fi
done

exit 0
```

**第二层：PostToolUse — 自动格式化**

```json
{
  "PostToolUse": [
    {
      "matcher": "Edit|Write",
      "hooks": [
        {
          "type": "command",
          "command": "bash ~/.claude/hooks/auto-format.sh"
        }
      ]
    }
  ]
}
```

`auto-format.sh`：

```bash
#!/bin/bash
# auto-format.sh — 编辑后自动格式化
set -euo pipefail

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

# 根据文件扩展名选择格式化工具
case "$FILE_PATH" in
  *.ts|*.tsx|*.js|*.jsx)
    npx prettier --write "$FILE_PATH" 2>/dev/null || true
    npx eslint --fix "$FILE_PATH" 2>/dev/null || true
    ;;
  *.py)
    python -m black "$FILE_PATH" 2>/dev/null || true
    python -m isort "$FILE_PATH" 2>/dev/null || true
    ;;
  *.go)
    gofmt -w "$FILE_PATH" 2>/dev/null || true
    ;;
  *.rs)
    rustfmt "$FILE_PATH" 2>/dev/null || true
    ;;
esac
```

**第三层：PostToolUse — 测试自动运行**

```json
{
  "PostToolUse": [
    {
      "matcher": "Edit",
      "hooks": [
        {
          "type": "command",
          "command": "bash ~/.claude/hooks/auto-test.sh"
        }
      ]
    }
  ]
}
```

`auto-test.sh`：

```bash
#!/bin/bash
# auto-test.sh — 编辑后自动运行相关测试
set -euo pipefail

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

# 查找对应的测试文件
TEST_FILE=""
case "$FILE_PATH" in
  src/**/*.ts)
    # src/utils/helper.ts → src/utils/helper.test.ts
    TEST_FILE="${FILE_PATH%.ts}.test.ts"
    ;;
  **/*.py)
    # app/models/user.py → tests/test_user.py
    BASENAME=$(basename "${FILE_PATH%.py}")
    TEST_FILE="tests/test_${BASENAME}.py"
    ;;
esac

# 如果测试文件存在，运行测试
if [ -n "$TEST_FILE" ] && [ -f "$TEST_FILE" ]; then
  echo "检测到变更：$FILE_PATH"
  echo "运行关联测试：$TEST_FILE"
  
  case "$TEST_FILE" in
    *.test.ts) npx vitest run "$TEST_FILE" --reporter=verbose ;;
    *.test.py) python -m pytest "$TEST_FILE" -v ;;
  esac
fi
```

**第四层：Notification — 即时通知**

```json
{
  "Notification": [
    {
      "matcher": "",
      "hooks": [
        {
          "type": "command",
          "command": "bash ~/.claude/hooks/notify.sh"
        }
      ]
    }
  ]
}
```

`notify.sh`：

```bash
#!/bin/bash
# notify.sh — 多渠道通知
set -euo pipefail

INPUT=$(cat)
MESSAGE=$(echo "$INPUT" | jq -r '.message // .notification // empty')

# macOS系统通知
if [[ "$(uname)" == "Darwin" ]]; then
  osascript -e "display notification \"$MESSAGE\" with title \"Claude Code\""
fi

# Linux桌面通知
if [[ "$(uname)" == "Linux" ]]; then
  notify-send "Claude Code" "$MESSAGE" 2>/dev/null || true
fi

# 可选：Slack通知
# curl -s -X POST "$SLACK_WEBHOOK_URL" \
#   -H 'Content-Type: application/json' \
#   -d "{\"text\": \"🤖 Claude Code: $MESSAGE\"}"
```

**第五层：Stop — 会话日志**

```json
{
  "Stop": [
    {
      "matcher": "",
      "hooks": [
        {
          "type": "command",
          "command": "bash ~/.claude/hooks/log-session.sh"
        }
      ]
    }
  ]
}
```

`log-session.sh`：

```bash
#!/bin/bash
# log-session.sh — 记录会话摘要
set -euo pipefail

INPUT=$(cat)
SESSION_ID=$(echo "$INPUT" | jq -r '.session_id // "unknown"')
TIMESTAMP=$(date '+%Y-%m-%d_%H%M%S')
LOG_DIR="$HOME/.claude/logs"

mkdir -p "$LOG_DIR"

# 将会话信息追加到日志文件
echo "$INPUT" | jq '.' >> "$LOG_DIR/session_${TIMESTAMP}.jsonl"

# 输出摘要
echo "会话日志已保存到 $LOG_DIR/session_${TIMESTAMP}.jsonl"
```

### 2.6 Matcher匹配规则

`matcher`字段支持精确匹配和正则表达式两种模式：

```json
{
  "hooks": {
    "PreToolUse": [
      {
        "matcher": "Bash",
        "hooks": [{"type": "command", "command": "echo 'Bash工具将被调用'"}]
      },
      {
        "matcher": "Edit|Write",
        "hooks": [{"type": "command", "command": "echo '文件将被修改'"}]
      },
      {
        "matcher": "",
        "hooks": [{"type": "command", "command": "echo '任意工具将被调用'"}]
      }
    ]
  }
}
```

---

## 三、Agent SDK：编程式调用Claude Code

### 3.1 从CLI到SDK

如果说`-p`模式是"远程遥控"，那么Agent SDK就是"嵌入式控制"。Agent SDK允许你在TypeScript或Python代码中直接调用Claude Code的全部能力——包括工具调用、上下文管理、Agent循环。

### 3.2 安装Agent SDK

```bash
# TypeScript SDK
npm install @anthropic-ai/claude-code-sdk

# Python SDK
pip install claude-code-sdk
```

### 3.3 TypeScript基础用法

```typescript
import { claude } from '@anthropic-ai/claude-code-sdk';

async function main() {
  // 基础调用
  const result = await claude({
    prompt: '分析这个项目的依赖关系，找出过时的包',
    options: {
      maxTurns: 5,
      allowedTools: ['Read', 'Glob', 'Grep', 'Bash'],
      cwd: '/path/to/project',
    },
  });

  console.log('结果:', result.result);
  console.log('成本:', result.cost_usd, 'USD');
  console.log('耗时:', result.duration_ms, 'ms');
}

main();
```

### 3.4 流式输出处理

```typescript
import { claude } from '@anthropic-ai/claude-code-sdk';

async function streamExample() {
  const stream = claude({
    prompt: '重构认证模块',
    options: {
      maxTurns: 10,
      allowedTools: ['Read', 'Edit', 'Bash'],
    },
  });

  for await (const event of stream) {
    switch (event.type) {
      case 'assistant':
        // Agent的文本输出
        process.stdout.write(event.content);
        break;
      case 'tool_use':
        // 工具调用事件
        console.log(`\n[工具调用] ${event.tool_name}`);
        break;
      case 'tool_result':
        // 工具返回结果
        console.log(`[工具结果] ${event.tool_name} 完成`);
        break;
      case 'result':
        // 最终结果
        console.log('\n=== 完成 ===');
        console.log(`成本: $${event.cost_usd.toFixed(4)}`);
        console.log(`轮次: ${event.num_turns}`);
        break;
    }
  }
}

streamExample();
```

### 3.5 Subagent模式：并行任务分发

Subagent是Agent SDK中最重要的模式之一。它允许你同时启动多个Agent实例，各自独立完成任务，最终汇总结果。


![图表3](images/claude-code-tutorial-r4-0008-mermaid-2.png)

> *图表 3*


**TypeScript实现并行Subagent**：

```typescript
import { claude } from '@anthropic-ai/claude-code-sdk';

interface ReviewResult {
  category: string;
  issues: string[];
  score: number;
}

async function parallelCodeReview(projectPath: string): Promise<void> {
  const reviewTasks = [
    {
      category: '代码质量',
      prompt: `审查 ${projectPath} 中的所有TypeScript源文件，找出代码质量问题：命名不规范、重复代码、过长函数。返回JSON格式的结果。`,
      allowedTools: ['Read', 'Glob', 'Grep'],
    },
    {
      category: '安全审计',
      prompt: `检查 ${projectPath} 中的安全漏洞：SQL注入、XSS、硬编码密钥、不安全的依赖。返回JSON格式的结果。`,
      allowedTools: ['Read', 'Glob', 'Grep', 'Bash'],
    },
    {
      category: '性能瓶颈',
      prompt: `分析 ${projectPath} 中的性能问题：N+1查询、内存泄漏风险、不必要的同步操作。返回JSON格式的结果。`,
      allowedTools: ['Read', 'Glob', 'Grep'],
    },
    {
      category: '依赖健康',
      prompt: `检查 ${projectPath} 的 package.json 和 package-lock.json，找出过时的、有已知漏洞的、不再维护的依赖。返回JSON格式的结果。`,
      allowedTools: ['Read', 'Bash'],
    },
  ];

  // 并行启动所有审查任务
  const results = await Promise.all(
    reviewTasks.map(async (task) => {
      const result = await claude({
        prompt: task.prompt,
        options: {
          maxTurns: 5,
          allowedTools: task.allowedTools,
          cwd: projectPath,
        },
      });

      return {
        category: task.category,
        content: result.result,
        cost: result.cost_usd,
      };
    })
  );

  // 汇总结果
  console.log('\n========================================');
  console.log('       并行代码审查综合报告');
  console.log('========================================\n');

  let totalCost = 0;
  for (const r of results) {
    totalCost += r.cost;
    console.log(`## ${r.category}`);
    console.log(r.content);
    console.log(`(成本: $${r.cost.toFixed(4)})\n`);
  }

  console.log(`\n总成本: $${totalCost.toFixed(4)}`);
}

// 运行
parallelCodeReview(process.argv[2] || process.cwd());
```

### 3.6 Python版本

```python
import asyncio
from claude_code_sdk import claude

async def batch_analyze(repos: list[str]):
    """并行分析多个仓库"""
    tasks = [
        claude(
            prompt=f"分析 {repo} 的架构，输出技术栈和模块依赖关系",
            options={
                "max_turns": 3,
                "allowed_tools": ["Read", "Glob", "Grep"],
                "cwd": repo,
            },
        )
        for repo in repos
    ]
    
    results = await asyncio.gather(*tasks)
    
    for repo, result in zip(repos, results):
        print(f"\n{'='*50}")
        print(f"仓库: {repo}")
        print(f"{'='*50}")
        print(result.result)

if __name__ == "__main__":
    repos = [
        "/projects/frontend",
        "/projects/backend",
        "/projects/shared-libs",
    ]
    asyncio.run(batch_analyze(repos))
```

---

## 四、/loop与定时任务

### 4.1 /loop命令

`/loop`是Claude Code内置的循环执行命令（v2.1.71+引入），用于在会话中周期性地执行任务：

```
# 在Claude Code交互界面中使用
> /loop 每30秒检查一次测试状态，如果全部通过则停止

# 典型场景：监控部署状态
> /loop 每60秒检查一次 kubectl get pods 的状态，当所有pod都为Running时通知我
```

### 4.2 桌面定时任务

通过`/schedule`命令可以创建持久化的定时任务，即使关闭Claude Code终端也会按计划执行：

```
# 每天早上9点执行
> /schedule "每天早上9点总结昨天的git commits，生成日报" --cron "0 9 * * *"

# 每周一运行
> /schedule "运行完整的测试套件并报告覆盖率变化" --cron "0 10 * * 1"
```

### 4.3 cron表达式参考

```
┌──────── 分钟 (0-59)
│ ┌────── 小时 (0-23)
│ │ ┌──── 日 (1-31)
│ │ │ ┌── 月 (1-12)
│ │ │ │ ┌ 星期 (0-7, 0和7都是周日)
│ │ │ │ │
* * * * *
```

常用表达式：

| 表达式 | 含义 |
|--------|------|
| `*/5 * * * *` | 每5分钟 |
| `0 * * * *` | 每小时整点 |
| `0 9 * * *` | 每天上午9点 |
| `0 9 * * 1-5` | 工作日上午9点 |
| `0 0 1 * *` | 每月1号零点 |

---

## 五、实战项目：全自动CI代码审查机器人

将前面学到的所有技术整合为一个完整的CI/CD代码审查机器人。

### 5.1 项目结构

```
claude-review-bot/
├── package.json
├── tsconfig.json
├── src/
│   ├── index.ts            # 主入口
│   ├── reviewer.ts         # 代码审查逻辑
│   ├── hooks/
│   │   ├── guard-bash.sh   # Bash命令守卫
│   │   ├── guard-edit.sh   # 文件编辑守卫
│   │   └── auto-format.sh  # 自动格式化
│   └── reporters/
│       ├── console.ts      # 控制台报告
│       └── github.ts       # GitHub PR评论
├── .claude/
│   └── settings.json       # Hooks配置
└── config.json             # 审查规则配置
```

### 5.2 审查规则配置

```json
{
  "rules": {
    "security": {
      "enabled": true,
      "severity": "critical",
      "patterns": [
        "硬编码API密钥",
        "SQL拼接",
        "未验证的用户输入",
        "不安全的正则表达式"
      ]
    },
    "quality": {
      "enabled": true,
      "severity": "warning",
      "patterns": [
        "重复代码",
        "过长函数(>50行)",
        "过深嵌套(>4层)",
        "魔法数字"
      ]
    },
    "performance": {
      "enabled": true,
      "severity": "info",
      "patterns": [
        "N+1查询",
        "不必要的同步操作",
        "大循环内的内存分配"
      ]
    }
  },
  "parallel": true,
  "max_turns": 5,
  "output": {
    "format": "markdown",
    "post_to_github": true
  }
}
```

### 5.3 主入口

```typescript
// src/index.ts
import { claude } from '@anthropic-ai/claude-code-sdk';
import * as fs from 'fs';
import * as path from 'path';

interface ReviewConfig {
  rules: Record<string, {
    enabled: boolean;
    severity: string;
    patterns: string[];
  }>;
  parallel: boolean;
  max_turns: number;
}

async function main() {
  const config: ReviewConfig = JSON.parse(
    fs.readFileSync('config.json', 'utf-8')
  );

  const projectPath = process.argv[2] || process.cwd();
  const changedFiles = getChangedFiles();

  if (changedFiles.length === 0) {
    console.log('没有检测到变更文件，跳过审查。');
    return;
  }

  console.log(`📋 检测到 ${changedFiles.length} 个变更文件，开始审查...\n`);

  // 根据配置构建审查任务
  const tasks = Object.entries(config.rules)
    .filter(([_, rule]) => rule.enabled)
    .map(([category, rule]) => ({
      category,
      severity: rule.severity,
      prompt: buildPrompt(category, rule.patterns, changedFiles),
    }));

  // 并行执行
  if (config.parallel) {
    const results = await Promise.all(
      tasks.map(task => claude({
        prompt: task.prompt,
        options: {
          maxTurns: config.max_turns,
          allowedTools: ['Read', 'Glob', 'Grep'],
          cwd: projectPath,
        },
      }))
    );

    // 按严重级别排序输出
    const severityOrder = { critical: 0, warning: 1, info: 2 };
    const combined = tasks.map((t, i) => ({
      ...t,
      result: results[i].result,
      cost: results[i].cost_usd,
    }));
    combined.sort((a, b) =>
      severityOrder[a.severity] - severityOrder[b.severity]
    );

    printReport(combined);
  }
}

function getChangedFiles(): string[] {
  // 在CI环境中从git获取变更文件
  const { execSync } = require('child_process');
  try {
    const baseBranch = process.env.GITHUB_BASE_REF || 'main';
    return execSync(
      `git diff --name-only origin/${baseBranch}...HEAD`
    ).toString().trim().split('\n').filter(Boolean);
  } catch {
    return [];
  }
}

function buildPrompt(
  category: string,
  patterns: string[],
  files: string[]
): string {
  return `你是代码审查专家。请审查以下变更文件中是否存在 ${category} 相关问题。

重点关注：${patterns.join('、')}

变更文件列表：
${files.map(f => `- ${f}`).join('\n')}

请用以下JSON格式返回结果：
{
  "issues": [
    {
      "file": "文件路径",
      "line": 行号,
      "severity": "critical/warning/info",
      "message": "问题描述",
      "suggestion": "修复建议"
    }
  ]
}`;
}

function printReport(results: any[]): void {
  console.log('\n' + '='.repeat(60));
  console.log('          🔍 Claude Code 审查报告');
  console.log('='.repeat(60));

  let totalCost = 0;
  let totalIssues = 0;

  for (const r of results) {
    totalCost += r.cost;
    console.log(`\n### ${r.category} (${r.severity})`);
    console.log(r.result);
    totalIssues++;
  }

  console.log('\n' + '='.repeat(60));
  console.log(`📊 审查维度: ${results.length} | 总成本: $${totalCost.toFixed(4)}`);
  console.log('='.repeat(60) + '\n');
}

main().catch(console.error);
```

### 5.4 GitHub Actions集成

```yaml
# .github/workflows/claude-review.yml
name: Claude Code Review

on:
  pull_request:
    types: [opened, synchronize]

jobs:
  review:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
        with:
          fetch-depth: 0

      - name: Setup Node.js
        uses: actions/setup-node@v4
        with:
          node-version: '20'

      - name: Install dependencies
        run: npm ci

      - name: Run Claude Code Review
        env:
          ANTHROPIC_API_KEY: ${{ secrets.ANTHROPIC_API_KEY }}
          GITHUB_BASE_REF: ${{ github.base_ref }}
        run: npx tsx src/index.ts ${{ github.workspace }}

      - name: Post review comment
        if: always()
        uses: actions/github-script@v7
        with:
          script: |
            const fs = require('fs');
            const report = fs.readFileSync('review-report.md', 'utf-8');
            github.rest.issues.createComment({
              owner: context.repo.owner,
              repo: context.repo.repo,
              issue_number: context.issue.number,
              body: report
            });
```

---

## 六、完整工作流架构


![图表4](images/claude-code-tutorial-r4-0008-mermaid-3.png)

> *图表 4*


---

## 七、进阶模式与最佳实践

### 7.1 渐进式权限模型

在自动化场景中，建议采用分层权限策略：

```bash
# 第一级：纯只读（报告生成）
claude -p "生成项目架构文档" \
  --allowedTools "Read,Glob,Grep"

# 第二级：读写+受限Bash（代码修复）
claude -p "修复lint错误" \
  --allowedTools "Read,Edit,Glob,Grep" \
  --max-turns 10

# 第三级：完全权限（仅限CI环境）
if [ "$CI" = "true" ]; then
  claude -p "执行完整的代码质量检查流程" \
    --allowedTools "Read,Edit,Bash,Glob,Grep"
fi
```

### 7.2 成本控制策略

```bash
# 使用 --max-turns 控制单次成本上限
claude -p "快速检查" --max-turns 2

# 使用 --model 选择更经济的模型
claude -p "简单的文本总结" --model haiku

# 在SDK中实现成本预算
const result = await claude({
  prompt: '分析代码',
  options: {
    maxTurns: 5,
    maxCostUsd: 0.50, // 成本上限50美分
  },
});
```

### 7.3 错误处理与重试

```typescript
async function resilientClaudeCall(
  prompt: string,
  maxRetries = 3
): Promise<any> {
  for (let attempt = 1; attempt <= maxRetries; attempt++) {
    try {
      const result = await claude({
        prompt,
        options: {
          maxTurns: 5,
          allowedTools: ['Read', 'Edit', 'Bash'],
        },
      });

      if (result.is_error) {
        throw new Error(`Agent返回错误: ${result.result}`);
      }
      return result;
    } catch (error) {
      console.error(`第${attempt}次尝试失败:`, error);
      if (attempt === maxRetries) throw error;
      
      // 指数退避
      await new Promise(r =>
        setTimeout(r, Math.pow(2, attempt) * 1000)
      );
    }
  }
}
```

### 7.4 多仓库批量操作

```bash
#!/bin/bash
# multi-repo-sync.sh — 多仓库批量同步操作

REPOS=(
  "/projects/frontend"
  "/projects/backend"
  "/projects/mobile"
  "/projects/shared-libs"
)

PROMPT="检查并升级所有过时的npm依赖到最新稳定版本，运行测试确保没有破坏性变更"

for repo in "${REPOS[@]}"; do
  echo "=== 处理: $repo ==="
  
  claude -p "$PROMPT" \
    --cwd "$repo" \
    --allowedTools "Read,Edit,Bash,Glob,Grep" \
    --max-turns 8 \
    --output-format json \
    > "${repo##*/}-result.json" &
done

# 等待所有后台任务完成
wait

echo "=== 所有仓库处理完成 ==="

# 汇总结果
for repo in "${REPOS[@]}"; do
  RESULT_FILE="${repo##*/}-result.json"
  if [ -f "$RESULT_FILE" ]; then
    COST=$(jq -r '.cost_usd // 0' "$RESULT_FILE")
    echo "$repo: 成本 \$${COST}"
  fi
done
```

---

## 八、调试与排错

### 8.1 开启调试日志

```bash
# 环境变量方式
CLAUDE_CODE_DEBUG=1 claude -p "测试"

# 查看详细工具调用
claude -p "分析代码" --verbose --output-format stream-json 2>&1 | tee debug.log
```

### 8.2 常见问题排查清单

| 症状 | 可能原因 | 排查步骤 |
|------|----------|----------|
| Hook未触发 | 配置路径错误 | 检查 `~/.claude/settings.json` 中 `hooks` 字段JSON格式 |
| Hook脚本报错 | 权限不足 | `chmod +x` 添加执行权限 |
| `-p`模式超时 | max-turns太小或提示词太模糊 | 增大 `--max-turns`，优化提示词 |
| JSON输出损坏 | 混合了警告和JSON | 使用 `--output-format json` 并设置 `NO_COLOR=1` |
| 成本异常高 | Agent陷入循环 | 检查 `--max-turns` 和提示词的明确性 |
| SDK连接失败 | API Key问题 | 检查 `ANTHROPIC_API_KEY` 环境变量 |

### 8.3 监控Hook执行

```bash
# 在每个Hook脚本中添加日志
exec >> ~/.claude/hooks.log 2>&1
echo "[$(date)] Hook executed: $0"
echo "[$(date)] Input: $(cat)"
```

---

## 延伸阅读

- [Claude Code Headless模式官方文档](https://code.claude.com/docs/en/headless) — `-p`标志和输出格式的完整参考
- [Claude Code Hooks官方文档](https://code.claude.com/docs/en/hooks) — 所有Hook事件的JSON输入输出规范
- [Agent SDK TypeScript参考](https://code.claude.com/docs/en/agent-sdk/typescript) — TypeScript SDK完整API文档
- [Agent SDK Subagent指南](https://code.claude.com/docs/en/agent-sdk/subagents) — Subagent定义、隔离和并行模式
- [Claude Code定时任务文档](https://code.claude.com/docs/en/scheduled-tasks) — `/loop`和cron调度完整指南
- [Hooks自动化教程](https://code.claude.com/docs/en/hooks-guide) — 官方Hooks最佳实践和示例
- [Trail of Bits Claude Code配置](https://github.com/trailofbits/claude-code-config) — 安全团队的开源Hooks配置参考

**训练营适用性评估**：本教程适合中级训练营（第3-4天），学员需具备CLI和基本编程基础。预计教学时长4-5小时，其中Headless模式讲解1小时、Hands实战配置2小时、Agent SDK编程练习2小时。建议学员提前准备好一个真实的代码仓库作为实验环境。

> [!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)
