<!-- title: Claude Code自动化全栈：-p模式到Hooks到Agent SDK -->

## 概述

本教程系统讲解 Claude Code 三大自动化能力：Print 无头模式（`-p`）、Hooks 事件驱动系统、Agent SDK 编程接口。学完后你将掌握从单条命令自动化到多 Agent 协作编排的完整技术栈，适用于 CI/CD 集成、批量代码操作、安全审计和生产级 Agent 构建场景。

**适用人群**：已熟悉 Claude Code 基本操作，希望将其集成到自动化流水线或构建生产级 AI Agent 的开发者。

**前置条件**：Claude Code v1.0.30+、Node.js 18+、`ANTHROPIC_API_KEY` 环境变量、基础 Shell 脚本能力。

---

## 第一部分：Print 无头模式 — 从终端到管道

### 1.1 核心概念

Print 模式（`-p` 或 `--print`）将 Claude Code 从交互式终端工具转变为非交互式命令行工具。它不会启动 TUI 界面，直接将结果输出到 stdout，可以像任何 Unix 命令一样被管道串联。

```text
flowchart LR
    A[用户/脚本] -->|claude -p "指令"| B[Print 模式]
    B --> C{--output-format}
    C -->|text| D[纯文本输出]
    C -->|json| E[结构化 JSON]
    C -->|stream-json| F[实时 JSON 事件流]
    D --> G[终端/文件]
    E --> H[jq 解析/程序处理]
    F --> I[Node.js/Python 消费者]
```

### 1.2 基础用法

```bash
# 最简形式 — 输出纯文本
claude -p "解释 src/auth.ts 中的 JWT 验证逻辑"

# 等价的长写法
claude --print "解释 src/auth.ts 中的 JWT 验证逻辑"

# 管道输入 — 将 stdin 作为上下文
cat error.log | claude -p "分析这段错误日志，给出修复建议"

# 输出重定向到文件
claude -p "为 src/api/ 下所有路由生成 OpenAPI 文档" > docs/api.md
```

### 1.3 三种输出格式详解

#### text 模式（默认）

```bash
claude -p "统计项目中 TODO 注释的数量"
# 输出：项目中存在 47 个 TODO 注释...
```

适合人类阅读和简单日志记录。

#### json 模式

```bash
claude -p "列出所有 TODO 注释及其位置" --output-format json
```

输出结构：

```json
{
  "result": "找到 47 个 TODO 注释...",
  "session_id": "sess_abc123",
  "is_error": false,
  "cost_usd": 0.032,
  "num_turns": 3,
  "duration_ms": 4500,
  "duration_api_ms": 3200,
  "usage": {
    "input_tokens": 12800,
    "output_tokens": 2400,
    "cache_creation_input_tokens": 0,
    "cache_read_input_tokens": 0,
    "server_tool_use": null
  }
}
```

结合 `jq` 提取关键字段：

```bash
# 提取纯文本结果
claude -p "代码审查" --output-format json | jq -r '.result'

# 提取成本信息
claude -p "重构模块" --output-format json | jq '{cost: .cost_usd, turns: .num_turns}'

# 提取 token 消耗
claude -p "生成文档" --output-format json | jq '.usage'
```

#### stream-json 模式

这是最强大的输出格式——实时逐行发出 JSON 事件，每个事件占一行（JSONL 格式）：

```bash
claude -p "分析整个项目的测试覆盖率" \
  --output-format stream-json \
  --verbose \
  --include-partial-messages
```

事件类型一览：

| 事件 | 触发时机 | 关键字段 |
|------|----------|----------|
| `system.init` | 会话初始化 | `session_id`, `tools` |
| `stream_event` | token 生成 | `event.delta.text` |
| `tool_use` | 工具调用 | `name`, `input` |
| `tool_result` | 工具结果 | `content` |
| `system.api_retry` | API 重试 | `attempt`, `error_status` |
| `result` | 最终结果 | `result`, `cost_usd` |

用 `jq` 实时提取文本流：

```bash
claude -p "编写一个排序算法" \
  --output-format stream-json \
  --verbose \
  --include-partial-messages \
  | jq -rj 'select(.type == "stream_event" and .event.delta.type? == "text_delta") | .event.delta.text'
```

### 1.4 高级标志组合

```bash
# 裸模式 — 跳过 skill 加载、LSP 初始化，速度最快
claude --bare -p "快速查询" --output-format json

# 指定模型
claude -p "深度代码审查" --model opus --output-format json

# 限制可用工具（只读模式）
claude -p "分析代码结构" --allowedTools "Read,Grep,Glob"

# 权限模式控制
claude -p "修复所有 lint 错误" \
  --permission-mode bypassPermissions \
  --output-format json

# 多轮会话续接
SESSION_ID=$(claude -p "开始代码审查" --output-format json | jq -r '.session_id')
claude -p "重点关注安全问题" --resume "$SESSION_ID"
```

### 1.5 常见问题

**Q: `-p` 模式下权限请求会怎样？**

A: 默认权限模式下遇到需要审批的操作会阻塞。在自动化场景中使用 `--permission-mode bypassPermissions` 自动批准，或用 `--allowedTools` 限制工具范围避免触发权限。

**Q: `--bare` 和普通 `-p` 的区别？**

A: `--bare` 跳过 skill 自动发现、hooks 注册、LSP 初始化、auto-memory 更新。启动速度更快，但会失去这些功能。必须通过环境变量提供 API Key。

**Q: 如何限制执行时间和成本？**

A: 使用 `--max-turns` 限制 Agent 轮次，在 SDK 中使用 `maxBudgetUsd` 控制预算上限。

---

## 第二部分：Hooks 系统 — 确定性事件驱动

### 2.1 Hooks 与 CLAUDE.md 的本质区别

```
CLAUDE.md = 建议性指令（LLM 可能忽略）
Hooks   = 强制性规则（Shell 命令，确定性执行）
```

Hooks 是用户定义的 Shell 命令，在 Claude Code 生命周期特定时刻自动触发。关键特性：

- **确定性**：不经过 LLM 判断，每次都执行
- **同步**：Claude Code 等待 Hook 完成后才继续
- **可阻断**：退出码 2 可阻止当前操作
- **上下文感知**：通过 stdin 接收 JSON 格式的完整操作详情

### 2.2 全部 Hook 事件类型

```mermaid
flowchart TD
    subgraph 会话生命周期
        SS[SessionStart] --> PRC[PreCompact]
        PRC --> POC[PostCompact]
        POC --> SE[SessionEnd]
    end

    subgraph 工具生命周期
        PTU[PreToolUse] --> EXEC[工具执行]
        EXEC --> |成功| POTU[PostToolUse]
        EXEC --> |失败| POTUF[PostToolUseFailure]
    end

    subgraph 权限控制
        PR[PermissionRequest] --> PD[PermissionDenied]
    end

    subgraph Agent 生命周期
        SAS[SubagentStart] --> SASTOP[SubagentStop]
        STOP[Stop] --> SF[StopFailure]
    end

    subgraph 用户交互
        UPS[UserPromptSubmit]
        NOTIF[Notification]
    end
```

### 2.3 配置层级

| 文件 | 范围 | Git 提交 | 典型用途 |
|------|------|----------|----------|
| `~/.claude/settings.json` | 全局所有项目 | 否 | 个人偏好、桌面通知 |
| `.claude/settings.json` | 项目级 | 是 | 团队共享规则 |
| `.claude/settings.local.json` | 项目本地 | 否（gitignore） | 个人本地覆盖 |

### 2.4 三种 Hook 类型

| 类型 | 执行方式 | 适用场景 |
|------|----------|----------|
| `command` | 执行 Shell 脚本 | 格式化、lint、安全检查、日志 |
| `prompt` | 发送给 LLM 判断 yes/no | 复杂语义验证 |
| `agent` | 启动多轮子 Agent（最多 50 轮） | 深度验证（需读文件+执行命令） |

### 2.5 配置结构

在 `.claude/settings.json` 中添加 `hooks` 字段：

```json
{
  "hooks": {
    "EventName": [
      {
        "matcher": "正则匹配工具名",
        "hooks": [
          {
            "type": "command",
            "command": "脚本路径或内联命令",
            "timeout": 60,
            "async": false
          }
        ]
      }
    ]
  }
}
```

### 2.6 七大实战配置

#### 配置 1：自动 Prettier 格式化

```json
{
  "hooks": {
    "PostToolUse": [
      {
        "matcher": "Edit|Write",
        "hooks": [
          {
            "type": "command",
            "command": "jq -r '.tool_input.file_path' | xargs npx prettier --write 2>/dev/null; exit 0"
          }
        ]
      }
    ]
  }
}
```

**效果**：每次 Claude 修改文件后自动格式化，退出码 0 确保不阻断流程。

#### 配置 2：阻止危险 Bash 命令

```bash
#!/bin/bash
# .claude/hooks/protect-bash.sh
INPUT=$(cat)
COMMAND=$(echo "$INPUT" | jq -r '.tool_input.command')

BLOCKED=("rm -rf /" "DROP TABLE" "DROP DATABASE" "terraform destroy" "git push --force" "npm publish")
for b in "${BLOCKED[@]}"; do
  if echo "$COMMAND" | grep -qi "$b"; then
    echo "BLOCKED: 危险命令检测到 '$b'" >&2
    exit 2
  fi
done
exit 0
```

```json
{
  "hooks": {
    "PreToolUse": [
      {
        "matcher": "Bash",
        "hooks": [
          {
            "type": "command",
            "command": "$CLAUDE_PROJECT_DIR/.claude/hooks/protect-bash.sh"
          }
        ]
      }
    ]
  }
}
```

**关键**：退出码 2 表示阻断操作，stderr 内容作为反馈显示给 Claude。即使使用 `--dangerously-skip-permissions`，PreToolUse hook 的 `deny` 决定也无法绕过。

#### 配置 3：保护敏感文件

```bash
#!/bin/bash
# .claude/hooks/protect-files.sh
INPUT=$(cat)
FILE_PATH=$(echo "$INPUT" | jq -r '.tool_input.file_path')

PROTECTED=(".env" ".env.local" ".env.production" "credentials.json" "package-lock.json" ".git/")
for p in "${PROTECTED[@]}"; do
  if echo "$FILE_PATH" | grep -q "$p"; then
    echo "BLOCKED: 受保护文件 '$FILE_PATH' 不可修改" >&2
    exit 2
  fi
done
exit 0
```

#### 配置 4：桌面通知

```json
{
  "hooks": {
    "Notification": [
      {
        "matcher": "permission_prompt",
        "hooks": [
          {
            "type": "command",
            "command": "osascript -e 'display notification \"Claude Code 需要你的输入\" with title \"Claude Code\"'"
          }
        ]
      }
    ]
  }
}
```

#### 配置 5：压缩后重新注入上下文

```json
{
  "hooks": {
    "SessionStart": [
      {
        "matcher": "compact",
        "hooks": [
          {
            "type": "command",
            "command": "echo '提醒：使用 Bun 而非 npm。当前 Sprint：auth 重构。所有 PR 必须通过 CI。'"
          }
        ]
      }
    ]
  }
}
```

**效果**：每次上下文压缩后自动注入关键项目约束，防止长时间对话后遗忘。

#### 配置 6：完成时自动运行测试

```json
{
  "hooks": {
    "Stop": [
      {
        "hooks": [
          {
            "type": "agent",
            "prompt": "验证工作是否完成：1) 运行测试套件 2) 检查 TypeScript 编译错误 3) 确认没有 console.log 遗留。报告结果。",
            "timeout": 120
          }
        ]
      }
    ]
  }
}
```

**注意**：Stop hook 中的 Agent 类型会启动一个独立子 Agent（最多 50 轮工具调用），非常适合深度验证。

#### 配置 7：自动批准特定权限

```json
{
  "hooks": {
    "PermissionRequest": [
      {
        "matcher": "Read|Glob|Grep",
        "hooks": [
          {
            "type": "command",
            "command": "echo '{\"hookSpecificOutput\": {\"hookEventName\": \"PermissionRequest\", \"decision\": {\"behavior\": \"allow\"}}}'"
          }
        ]
      }
    ]
  }
}
```

### 2.7 Hook 输入输出规范

#### stdin JSON 输入（PreToolUse）

```json
{
  "session_id": "sess_abc123",
  "cwd": "/home/dev/myproject",
  "hook_event_name": "PreToolUse",
  "tool_name": "Bash",
  "tool_input": {
    "command": "npm test"
  },
  "permission_mode": "default"
}
```

#### stdout JSON 输出（权限决策）

```json
{
  "hookSpecificOutput": {
    "hookEventName": "PreToolUse",
    "permissionDecision": "allow",
    "permissionDecisionReason": "项目策略自动批准只读操作"
  }
}
```

#### 退出码含义

| 退出码 | 含义 | 行为 |
|--------|------|------|
| 0 | 成功 | 操作继续。stdout 作为上下文添加 |
| 2 | 阻断 | 操作被阻止。stderr 显示给 Claude |
| 其他 | 非阻断错误 | 操作继续。stderr 在 verbose 模式可见 |

### 2.8 环境变量

| 变量 | 含义 |
|------|------|
| `$CLAUDE_PROJECT_DIR` | 项目根目录 |
| `$CLAUDE_ENV_FILE` | 持久化环境变量文件路径 |
| `$CLAUDE_TOOL_NAME` | 当前工具名称 |
| `$CLAUDE_FILE_PATH` | 当前文件路径 |
| `$CLAUDE_CODE_REMOTE` | 远程环境标记 |

### 2.9 调试技巧

```bash
# 在 Claude Code 内部查看已注册 hooks
/hooks

# 开启详细模式查看 hook 执行日志
Ctrl+O  # 切换 verbose 模式

# 手动测试 hook 脚本
echo '{"tool_name":"Bash","tool_input":{"command":"rm -rf /"}}' | bash .claude/hooks/protect-bash.sh
echo $?  # 应返回 2
```

---

## 第三部分：Agent SDK — 编程式 AI 代理

### 3.1 SDK 选择指南

```mermaid
flowchart TD
    A[自动化需求] --> B{需要什么能力?}
    B -->|只需简单调用| C[Claude Code SDK<br/>@anthropic-ai/claude-code]
    B -->|需要 MCP/子 Agent| D[Agent SDK<br/>@anthropic-ai/claude-agent-sdk]
    B -->|只需 Shell 脚本| E[CLI -p 模式]

    C --> F["claude() 函数<br/>简单直接"]
    D --> G["query() 函数<br/>流式 + MCP + 子 Agent"]
    E --> H["claude -p + jq<br/>零代码"]
```

| 特性 | CLI `-p` | Claude Code SDK | Agent SDK |
|------|----------|----------------|-----------|
| 安装 | 已内置 | `npm i @anthropic-ai/claude-code` | `npm i @anthropic-ai/claude-agent-sdk` |
| 语言 | Shell | TypeScript/JS | TypeScript/JS |
| 流式输出 | `stream-json` | `claude.stream()` | `query()` 异步迭代 |
| 子 Agent | 不支持 | 不支持 | 内置 `agents` 配置 |
| MCP 服务器 | 配置文件 | 不支持 | 进程内创建 |
| 预算控制 | `--max-turns` | `maxTurns` | `maxTurns` + `maxBudgetUsd` |

### 3.2 Claude Code SDK 基础用法

安装：

```bash
npm install @anthropic-ai/claude-code
```

一次性任务：

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

const result = await claude({
  prompt: "为 src/api/ 下所有端点添加错误处理中间件",
  options: {
    maxTurns: 30,
    model: "claude-sonnet-4-6",
    allowedTools: ["Read", "Edit", "Write", "Glob", "Grep", "Bash"],
  },
});

console.log("完成:", result.text);
console.log("成本:", result.cost.totalCost, "USD");
console.log("轮次:", result.turns);
```

流式处理：

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

const stream = claude.stream({
  prompt: "重构用户认证模块，提取为独立服务",
  options: { maxTurns: 20 },
});

for await (const event of stream) {
  if (event.type === "text") {
    process.stdout.write(event.text);
  } else if (event.type === "tool_use") {
    console.log(`\n[使用工具: ${event.name}]`);
  } else if (event.type === "tool_result") {
    console.log(`[工具结果: ${event.content?.slice(0, 100)}...]`);
  }
}
```

### 3.3 Agent SDK — query 函数

安装：

```bash
npm install @anthropic-ai/claude-agent-sdk
npm install -D typescript @types/node tsx
```

基础查询：

```typescript
import { query } from "@anthropic-ai/claude-agent-sdk";

async function main() {
  for await (const message of query({
    prompt: "分析项目结构并列出主要模块",
    options: {
      allowedTools: ["Bash", "Glob", "Read"],
      maxTurns: 10,
    },
  })) {
    switch (message.type) {
      case "assistant":
        const text = message.message.content
          .filter((b) => b.type === "text")
          .map((b) => b.text)
          .join("");
        if (text) console.log("[Claude]", text);
        break;
      case "tool_use":
        console.log(`[工具调用] ${message.name}`);
        break;
      case "result":
        if (message.subtype === "success") {
          console.log("\n完成:", message.result);
        } else {
          console.error("失败:", message.error);
        }
        break;
    }
  }
}

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

### 3.4 自定义安全回调

```typescript
import { query } from "@anthropic-ai/claude-agent-sdk";

for await (const msg of query({
  prompt: "清理并优化代码库",
  options: {
    allowedTools: ["Read", "Write", "Edit", "Bash", "Glob", "Grep"],
    maxTurns: 30,
    maxBudgetUsd: 2.0, // 成本上限 $2
    canUseTool: async (toolName, input) => {
      // 阻止危险 Bash 命令
      if (toolName === "Bash") {
        const cmd = (input as { command: string }).command;
        const dangerous = ["rm -rf", "DROP TABLE", "git push --force"];
        if (dangerous.some((d) => cmd.includes(d))) {
          return { allowed: false, reason: "破坏性命令被禁止" };
        }
      }
      // 保护敏感文件
      if (toolName === "Write" || toolName === "Edit") {
        const fp = (input as { file_path: string }).file_path;
        const protected_files = [".env", "package-lock.json", "prisma/schema.prisma"];
        if (protected_files.some((p) => fp.includes(p))) {
          return { allowed: false, reason: `受保护文件: ${fp}` };
        }
      }
      return { allowed: true };
    },
  },
})) {
  if ("result" in msg) console.log(msg.result);
}
```

### 3.5 进程内 MCP 服务器

```typescript
import { query } from "@anthropic-ai/claude-agent-sdk";
import { createSdkMcpServer, tool } from "@anthropic-ai/claude-agent-sdk/mcp";

// 创建内嵌 MCP 服务器
const analyticsServer = createSdkMcpServer({
  name: "analytics",
  version: "1.0.0",
  tools: [
    tool(
      "get_metrics",
      "获取指定日期范围的项目指标",
      {
        type: "object",
        properties: {
          metric: { type: "string", description: "指标名称" },
          startDate: { type: "string", description: "起始日期 YYYY-MM-DD" },
          endDate: { type: "string", description: "结束日期 YYYY-MM-DD" },
        },
        required: ["metric", "startDate", "endDate"],
      },
      async ({ metric, startDate, endDate }) => {
        const res = await fetch(
          `https://api.example.com/metrics?type=${metric}&from=${startDate}&to=${endDate}`
        );
        return JSON.stringify(await res.json());
      }
    ),
  ],
});

// Agent 可直接调用 MCP 工具
for await (const msg of query({
  prompt: "分析本月代码提交频率和 bug 修复趋势",
  options: {
    mcpServers: { analytics: analyticsServer },
    allowedTools: ["mcp__analytics__get_metrics", "Bash", "Read", "Glob"],
    maxTurns: 15,
  },
})) {
  if ("result" in msg) console.log(msg.result);
}
```

---

## 第四部分：批量任务与多 Agent 编排

### 4.1 Shell 批量脚本

```bash
#!/bin/bash
# batch-review.sh — 批量审查 Git 变更文件

set -euo pipefail

CHANGED_FILES=$(git diff --name-only main...HEAD -- "*.ts" "*.tsx")
RESULTS_DIR="reviews/$(date +%Y%m%d_%H%M%S)"
mkdir -p "$RESULTS_DIR"

for file in $CHANGED_FILES; do
  echo "审查: $file"
  claude -p "对这个文件进行代码审查，重点关注：
    1. 安全漏洞
    2. 性能问题
    3. 代码风格
    4. 缺失的错误处理
    文件: $file" \
    --output-format json \
    --allowedTools "Read,Grep,Glob" \
    > "$RESULTS_DIR/$(basename $file .ts).json"
done

echo "审查完成。结果保存在 $RESULTS_DIR/"
```

### 4.2 Node.js 批量处理器（带限流）

```typescript
import { claude } from "@anthropic-ai/claude-code";
import { readdir, readFile } from "fs/promises";
import pLimit from "p-limit";

const limit = pLimit(3); // 最多 3 个并发 Agent

async function batchAnalyze(directory: string) {
  const files = await readdir(directory);
  const tsFiles = files.filter((f) => f.endsWith(".ts"));

  const tasks = tsFiles.map((file) =>
    limit(async () => {
      console.log(`处理: ${file}`);
      const result = await claude({
        prompt: `分析 ${directory}/${file} 的代码质量，给出 1-10 评分和改进建议`,
        options: {
          maxTurns: 5,
          model: "claude-haiku-4-5", // 快速模型节省成本
          allowedTools: ["Read"],
        },
      });

      return {
        file,
        score: result.text.match(/(\d+)\/10/)?.[1] ?? "N/A",
        cost: result.cost.totalCost,
        summary: result.text.slice(0, 200),
      };
    })
  );

  const results = await Promise.all(tasks);

  // 按评分排序
  results
    .sort((a, b) => Number(b.score) - Number(a.score))
    .forEach((r) => {
      console.log(`${r.score}/10 | $${r.cost.toFixed(4)} | ${r.file}`);
    });

  const totalCost = results.reduce((sum, r) => sum + r.cost, 0);
  console.log(`\n总成本: $${totalCost.toFixed(4)}`);
}

batchAnalyze("./src").catch(console.error);
```

### 4.3 多 Agent 顺序协作

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

async function developFeature(requirement: string) {
  console.log("=== 阶段 1: 制定计划 ===");
  const plan = await claude({
    prompt: `阅读代码库，为实现以下需求制定详细计划：${requirement}`,
    options: {
      maxTurns: 15,
      allowedTools: ["Read", "Glob", "Grep"], // 只读阶段
    },
  });
  console.log("计划:", plan.text.slice(0, 500));

  console.log("\n=== 阶段 2: 执行实现 ===");
  const implementation = await claude({
    prompt: `按照以下计划实现代码修改：\n\n${plan.text}`,
    options: {
      maxTurns: 50,
      model: "claude-sonnet-4-6",
      permissionMode: "acceptEdits",
    },
  });

  console.log("\n=== 阶段 3: 代码审查 ===");
  const review = await claude({
    prompt: `审查所有修改，检查 bug、边界情况和测试覆盖。发现问题直接修复。`,
    options: { maxTurns: 20 },
  });

  const totalCost =
    plan.cost.totalCost +
    implementation.cost.totalCost +
    review.cost.totalCost;

  return {
    plan: plan.text,
    code: implementation.text,
    review: review.text,
    totalCost,
  };
}

// 使用
const result = await developFeature(
  "添加用户注册 API 端点，支持邮箱验证"
);
console.log(`\n总成本: $${result.totalCost.toFixed(4)}`);
```

### 4.4 Agent SDK 子 Agent 编排

```typescript
import { query } from "@anthropic-ai/claude-agent-sdk";

for await (const msg of query({
  prompt: "分析项目测试覆盖率，为未覆盖的函数编写测试",
  options: {
    allowedTools: ["Read", "Write", "Edit", "Bash", "Glob", "Grep", "Task"],
    agents: {
      "coverage-analyzer": {
        description: "分析测试覆盖率，识别未测试代码",
        tools: ["Bash", "Read", "Glob", "Grep"],
        prompt: "你是测试覆盖率分析师。运行覆盖率工具并识别未测试的函数。",
        model: "haiku",
      },
      "test-writer": {
        description: "为 TypeScript 函数编写全面的单元测试",
        tools: ["Read", "Write", "Edit", "Glob"],
        prompt: "你是测试工程师。使用 Vitest 编写全面的单元测试。",
        model: "sonnet",
      },
    },
    maxTurns: 30,
  },
})) {
  if ("result" in msg) console.log(msg.result);
}
```

工作原理：定义 `agents` 后，主 Agent 获得 `Task` 工具，可以按名称启动子 Agent。每个子 Agent 有独立上下文和工具集，可使用不同模型（分析用 Haiku 省钱，编写用 Sonnet 保证质量）。

---

## 第五部分：CI/CD 集成实战

### 5.1 GitHub Actions 自动 PR 审查

```yaml
# .github/workflows/claude-review.yml
name: Claude Code Review
on:
  pull_request:
    types: [opened, synchronize]

jobs:
  review:
    runs-on: ubuntu-latest
    permissions:
      contents: read
      pull-requests: write

    steps:
      - uses: actions/checkout@v4
        with:
          fetch-depth: 0

      - name: Install Claude Code
        run: |
          curl -fsSL https://claude.ai/install.sh | bash

      - name: Run Review
        env:
          ANTHROPIC_API_KEY: ${{ secrets.ANTHROPIC_API_KEY }}
        run: |
          claude --bare -p "审查这个 PR 的所有变更。
            重点关注：安全漏洞、性能退化、代码风格。
            用中文输出审查结果。" \
            --output-format json \
            --permission-mode bypassPermissions \
            --allowedTools "Read,Grep,Glob,Bash" \
            > review_result.json

      - name: Post Review Comment
        env:
          GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
        run: |
          REVIEW=$(jq -r '.result' review_result.json)
          gh pr comment ${{ github.event.pull_request.number }} \
            --body "## Claude Code 审查结果

          $REVIEW

          ---
          *成本: \`$(jq -r '.cost_usd' review_result.json)\` USD*
          *轮次: \`$(jq -r '.num_turns' review_result.json)\`*"
```

### 5.2 Git Pre-commit Hook 自动检查

```bash
#!/bin/bash
# .git/hooks/pre-commit

STAGED=$(git diff --cached --name-only -- "*.ts" "*.tsx" "*.js")
if [ -z "$STAGED" ]; then exit 0; fi

for file in $STAGED; do
  echo "AI 检查: $file"
  RESULT=$(claude --bare -p "检查此文件是否有明显的 bug 或安全问题。只需回答 PASS 或 FAIL + 原因。
文件: $file" \
    --output-format text \
    --allowedTools "Read" \
    --max-turns 3 \
    2>/dev/null)

  if echo "$RESULT" | grep -q "FAIL"; then
    echo "❌ $file 未通过检查:"
    echo "$RESULT"
    exit 1
  fi
  echo "✅ $file 通过"
done
```

### 5.3 定时巡检 Cron Job

```bash
#!/bin/bash
# daily-health-check.sh — 每日代码健康巡检

REPORT_FILE="reports/health-$(date +%Y%m%d).md"
mkdir -p reports

claude --bare -p "执行代码库健康检查：
1. 检查依赖是否有安全漏洞 (npm audit)
2. 统计 TODO/FIXME 数量
3. 检查测试覆盖率趋势
4. 识别最大的文件和函数
5. 检查是否有未使用的依赖

输出 Markdown 格式的报告。" \
  --output-format text \
  --permission-mode bypassPermissions \
  > "$REPORT_FILE"

echo "报告已生成: $REPORT_FILE"

# 可选：发送到 Slack
curl -X POST "$SLACK_WEBHOOK" \
  -H "Content-Type: application/json" \
  -d "{\"text\": \"每日代码健康报告已生成。\n$(head -5 $REPORT_FILE | sed 's/"/\\"/g')\"}"
```

---

## 第六部分：完整实战项目 — 自动化代码质量守卫

将 Hooks、Print 模式和 Agent SDK 结合，构建一个完整的代码质量守卫系统。

### 6.1 项目结构

```
project/
├── .claude/
│   ├── settings.json          # Hook 配置
│   └── hooks/
│       ├── protect-bash.sh    # 危险命令拦截
│       ├── protect-files.sh   # 敏感文件保护
│       └── auto-format.sh     # 自动格式化
├── scripts/
│   ├── batch-review.ts        # 批量审查脚本
│   └── health-check.ts        # 健康巡检脚本
├── .github/workflows/
│   └── claude-review.yml      # CI 审查
└── reports/                   # 报告输出目录
```

### 6.2 完整 Hook 配置

```json
{
  "hooks": {
    "PreToolUse": [
      {
        "matcher": "Bash",
        "hooks": [
          {
            "type": "command",
            "command": ".claude/hooks/protect-bash.sh",
            "timeout": 5
          }
        ]
      },
      {
        "matcher": "Edit|Write",
        "hooks": [
          {
            "type": "command",
            "command": ".claude/hooks/protect-files.sh",
            "timeout": 5
          }
        ]
      }
    ],
    "PostToolUse": [
      {
        "matcher": "Edit|Write",
        "hooks": [
          {
            "type": "command",
            "command": "FILE=$(cat | jq -r '.tool_input.file_path'); case \"$FILE\" in *.ts|*.tsx) npx prettier --write \"$FILE\" 2>/dev/null;; *.py) black \"$FILE\" 2>/dev/null;; esac; exit 0"
          }
        ]
      }
    ],
    "Stop": [
      {
        "hooks": [
          {
            "type": "agent",
            "prompt": "验证修改是否完整：运行 npm test，检查 TypeScript 编译（npx tsc --noEmit），报告结果。如果测试失败，说明失败原因。",
            "timeout": 120
          }
        ]
      }
    ],
    "SessionStart": [
      {
        "matcher": "compact",
        "hooks": [
          {
            "type": "command",
            "command": "echo '项目规则：使用 pnpm 而非 npm。所有 API 必须有错误处理。提交前运行 pnpm test。'"
          }
        ]
      }
    ],
    "Notification": [
      {
        "matcher": "permission_prompt",
        "hooks": [
          {
            "type": "command",
            "command": "osascript -e 'display notification \"Claude Code 需要输入\" with title \"Claude Code\"' 2>/dev/null; exit 0"
          }
        ]
      }
    ]
  }
}
```

### 6.3 批量审查脚本

```typescript
// scripts/batch-review.ts
import { claude } from "@anthropic-ai/claude-code";
import { readdir, writeFile, mkdir } from "fs/promises";
import pLimit from "p-limit";

const limit = pLimit(3);

async function main() {
  const srcDir = "./src";
  const files = (await readdir(srcDir, { recursive: true }))
    .filter((f) => String(f).endsWith(".ts"))
    .map((f) => `${srcDir}/${f}`);

  console.log(`发现 ${files.length} 个 TypeScript 文件`);

  const tasks = files.map((file) =>
    limit(async () => {
      const result = await claude({
        prompt: `对 ${file} 进行代码审查。评分 1-10。输出格式：
          ## 文件: ${file}
          ### 评分: X/10
          ### 问题列表
          - [严重] 问题描述
          ### 建议
          - 改进建议`,
        options: {
          maxTurns: 5,
          model: "claude-haiku-4-5",
          allowedTools: ["Read"],
        },
      });
      return { file, review: result.text, cost: result.cost.totalCost };
    })
  );

  const results = await Promise.all(tasks);

  await mkdir("./reports", { recursive: true });

  const report = results
    .map((r) => r.review)
    .join("\n\n---\n\n");

  await writeFile("./reports/code-review.md", report);

  const totalCost = results.reduce((sum, r) => sum + r.cost, 0);
  console.log(`审查完成。总成本: $${totalCost.toFixed(4)}`);
}

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

运行：

```bash
npx tsx scripts/batch-review.ts
```

### 6.4 健康巡检脚本

```typescript
// scripts/health-check.ts
import { claude } from "@anthropic-ai/claude-code";
import { writeFile } from "fs/promises";

async function main() {
  const result = await claude({
    prompt: `执行代码库健康检查，输出 Markdown 报告：
1. ## 依赖安全 (npm audit 结果摘要)
2. ## 代码标记 (TODO/FIXME/HACK 数量和分布)
3. ## 文件体积 (超过 300 行的文件列表)
4. ## 复杂度热点 (圈复杂度高的函数)
5. ## 测试健康 (测试文件/源文件比例)
6. ## 改进建议 (Top 5 优先级最高的改进项)`,
    options: {
      maxTurns: 25,
      model: "claude-sonnet-4-6",
      permissionMode: "acceptEdits",
    },
  });

  const date = new Date().toISOString().split("T")[0];
  await writeFile(`./reports/health-${date}.md`, result.text);
  console.log(`报告已生成: reports/health-${date}.md`);
  console.log(`成本: $${result.cost.totalCost.toFixed(4)}`);
}

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

### 6.5 工作流全景

```mermaid
flowchart TB
    subgraph 开发阶段
        DEV[开发者提交代码] --> PRE[Git Pre-commit Hook]
        PRE --> |AI检查| PASS{通过?}
        PASS --> |是| COMMIT[提交成功]
        PASS --> |否| REJECT[拒绝提交]
    end

    subgraph CI阶段
        PUSH[Push 到 PR] --> GHA[GitHub Actions]
        GHA --> CLAUDE[Claude Print 模式审查]
        CLAUDE --> COMMENT[评论到 PR]
    end

    subgraph 交互阶段
        INTER[开发者使用 Claude Code] --> HOOKS[Hooks 触发]
        HOOKS --> PRE_HOOK[PreToolUse: 安全检查]
        HOOKS --> POST_HOOK[PostToolUse: 自动格式化]
        HOOKS --> STOP_HOOK[Stop: 自动测试]
    end

    subgraph 巡检阶段
        CRON[每日 Cron] --> HEALTH[健康巡检脚本]
        HEALTH --> REPORT[生成报告]
        REPORT --> SLACK[通知团队]
    end

    COMMIT --> PUSH
```

---

## 延伸阅读

- [Claude Code Headless 官方文档](https://code.claude.com/docs/en/headless) — Print 模式完整参考
- [Claude Code Hooks 官方参考](https://code.claude.com/docs/en/hooks) — 全部 Hook 事件和配置 Schema
- [Claude Code Hooks 实战指南](https://code.claude.com/docs/en/hooks-guide) — 官方 Hooks 教程
- [Claude Agent SDK GitHub](https://github.com/anthropics/claude-agent-sdk-typescript) — TypeScript SDK 源码和文档
- [Claude Agent SDK API 文档](https://docs.claude.com/en/api/agent-sdk/overview) — 官方 SDK API 参考

## 训练营适用性评估

| 维度 | 评估 |
|------|------|
| 适合训练营类型 | 企业 AI 工程化培训、DevOps 自动化进阶、AI Agent 开发实战 |
| 学员基础要求 | TypeScript 基础、Shell 脚本能力、Claude Code 使用经验 |
| 预计教学时长 | 4-6 小时（含动手实验） |
| 实验环境要求 | 每人一台有 Node.js 18+ 和 Claude Code 的开发机，ANTHROPIC_API_KEY |
| 建议分节 | Part 1-2（2h）→ Part 3-4（2h）→ Part 5-6（2h） |

---

## 参考来源

1. [Run Claude Code programmatically - Claude Code Docs](https://code.claude.com/docs/en/headless) — Anthropic 官方 Headless/Print 模式文档，涵盖所有 CLI 标志和输出格式
2. [Hooks reference - Claude Code Docs](https://code.claude.com/docs/en/hooks) — Anthropic 官方 Hooks 事件参考，包含完整 JSON Schema 和退出码定义
3. [Claude Agent SDK - GitHub](https://github.com/anthropics/claude-agent-sdk-typescript) — Anthropic 官方 Agent SDK TypeScript 源码仓库，含安装和基础示例
4. [Claude Code Hooks: Complete Guide with 20+ Examples](https://aiorg.dev/blog/claude-code-hooks) — 社区整理的 20+ 个可复制 Hook 配置实例
5. [Claude Code stream-json 详解](https://backgroundclaude.com/blog/stream-json) — 深度解析 stream-json 输出格式的事件类型和消费者实现

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