本文系统讲解 Claude Code 三大自动化能力的原理与实战:无头模式(Headless Mode) 通过 -p 标志实现非交互式调用;Hooks 钩子系统 在工具执行前后自动触发自定义逻辑;Agent SDK 将 Claude Code 的完整能力以编程方式嵌入你自己的应用。适合已有 Claude Code 使用经验、希望将其接入 CI/CD、批量处理或构建自定义 AI Agent 的开发者。
学习目标:
- 掌握 claude -p 的全部参数与输出格式控制
- 理解 5 种 Hook 事件的触发时机与配置方法
- 用 TypeScript Agent SDK 编写可编程的自主 Agent
- 组合三大能力构建生产级自动化流水线
适用人群:中高级开发者、DevOps 工程师、AI 应用构建者
| 项目 | 要求 |
|---|---|
| Claude Code | ≥ 2.1.x(claude --version 确认) |
| Node.js | ≥ 18.x(Agent SDK 依赖) |
| TypeScript | ≥ 5.x(Agent SDK 开发) |
| 操作系统 | macOS / Linux / WSL2 |
| Claude 订阅 | Max 计划或 Team/Business 计划 |
| 基础知识 | 熟悉 Shell 脚本、JSON 配置、npm 包管理 |
无头模式让 Claude Code 脱离交互式 REPL 界面,以命令行参数驱动的方式运行。所有工具能力(文件读写、Shell 执行、搜索等)均可使用,但无人值守——输出直接打印到标准输出,适合管道串联和脚本编排。
核心标志:-p 或 --print。
# 最简单的无头调用——输出纯文本
claude -p "解释当前项目的目录结构"
# 管道输入——将文件内容喂给 Claude
cat src/utils.ts | claude -p "为这个文件添加 JSDoc 注释"
# 捕获输出到变量
result=$(claude -p "列出所有 TODO 注释")
echo "$result"
# 输出重定向到文件
claude -p "生成 README.md 的内容" > README.md
无头模式的威力来自丰富的参数组合:
| 参数 | 说明 | 示例 |
|---|---|---|
-p / --print |
启用无头模式 | claude -p "hello" |
--output-format |
输出格式:text、json、stream-json |
--output-format json |
--max-turns |
限制 Agent 循环轮次 | --max-turns 5 |
--allowedTools |
限制可用工具列表 | --allowedTools "Read,Glob,Grep" |
--system-prompt |
自定义系统提示 | --system-prompt "你是代码审查专家" |
--append-system-prompt |
追加系统提示 | --append-system-prompt "用中文回答" |
--resume |
恢复指定会话 | --resume session-abc123 |
--continue |
继续最近一次会话 | --continue |
--model |
指定模型 | --model claude-sonnet-4-6 |
--verbose |
详细输出(调试用) | --verbose |
--permission-mode |
权限模式 | --permission-mode plan |
--output-format json 是自动化场景的基石。JSON 输出结构化数据,便于程序解析:
# JSON 格式输出——提取结构化结果
claude -p "分析 package.json 中的依赖版本是否过时" \
--output-format json
# stream-json 模式——实时流式输出(适合长任务监控)
claude -p "重构整个 src 目录的 import 语句" \
--output-format stream-json \
--max-turns 10
JSON 输出包含的关键字段:
{
"type": "result",
"subtype": "success",
"cost_usd": 0.042,
"duration_ms": 15230,
"duration_api_ms": 12800,
"num_turns": 3,
"result": "已完成所有 import 语句的重构...",
"session_id": "sess_abc123"
}
在自动化场景中,安全是第一要务。通过参数限制 Agent 的行为边界:
# 只读模式——只允许搜索和阅读,不能修改文件
claude -p "审查最近的 git commit 是否有安全漏洞" \
--allowedTools "Read,Glob,Grep,Bash" \
--max-turns 3
# 限制 Bash 命令范围(结合 permission-mode)
claude -p "运行测试并报告结果" \
--permission-mode plan \
--max-turns 5
# 预设系统提示,约束行为
claude -p "分析代码质量" \
--system-prompt "你是一个保守的代码审查员。只报告确定的问题,不要修改任何文件。" \
--allowedTools "Read,Glob,Grep"
| 问题 | 原因 | 解决方案 |
|---|---|---|
| 输出包含 ANSI 转义码 | 终端颜色控制字符 | 加 --output-format json 或设置 NO_COLOR=1 |
| Agent 无限循环 | 无 turn 限制 | 始终设置 --max-turns |
| 权限弹窗阻塞 | 工具需要授权 | 使用 --allowedTools 白名单 + --permission-mode |
| 输出被截断 | Token 上限 | 使用 --output-format stream-json 流式处理 |
| 费用失控 | 无成本感知 | JSON 输出中检查 cost_usd 字段 |
Hooks 是 Claude Code 的"神经系统"——在特定生命周期事件发生时,自动执行你预设的 Shell 命令、HTTP 请求或 LLM 提示。不同于手动编写脚本串联,Hooks 由 Claude Code 引擎在运行时自动触发,零延迟、零遗漏。
Hooks 配置位于 settings.json(项目级 .claude/settings.json 或用户级 ~/.claude/settings.json)。
flowchart TD
A[用户发送消息] --> B[SessionStart]
B --> C[Agent 循环开始]
C --> D{选择工具}
D --> E[PreToolUse]
E --> F{钩子返回}
F -->|批准| G[执行工具]
F -->|阻止| H[跳过工具]
G --> I[PostToolUse]
I --> J{还有工具?}
J -->|是| D
J -->|否| K[Stop]
K --> L[Notification]
style E fill:#ff9800,color:#fff
style I fill:#4caf50,color:#fff
style B fill:#2196f3,color:#fff
style K fill:#f44336,color:#fff
style L fill:#9c27b0,color:#fff
| 事件 | 触发时机 | 典型用途 |
|---|---|---|
| PreToolUse | 工具执行之前 | 安全检查、命令拦截、参数修改 |
| PostToolUse | 工具执行之后 | 自动格式化、通知发送、结果验证 |
| Notification | 任务完成时 | Slack/Discord 通知、日志记录 |
| Stop | Agent 停止时 | 最终检查、生成报告 |
| SessionStart | 会话启动时 | 环境初始化、加载上下文 |
在 .claude/settings.json 中添加 hooks 字段:
{
"hooks": {
"PreToolUse": [
{
"matcher": "Write|Edit",
"hooks": [
{
"type": "command",
"command": "python3 scripts/pre-write-guard.py"
}
]
}
],
"PostToolUse": [
{
"matcher": "Write|Edit",
"hooks": [
{
"type": "command",
"command": "npx prettier --write $CLAUDE_FILE_PATH"
}
]
}
],
"Stop": [
{
"matcher": "",
"hooks": [
{
"type": "command",
"command": "python3 scripts/task-complete-notify.py"
}
]
}
],
"Notification": [
{
"matcher": "",
"hooks": [
{
"type": "command",
"command": "curl -X POST https://hooks.slack.com/services/YOUR/WEBHOOK -H 'Content-type: application/json' -d '{\"text\":\"Claude Code 任务完成\"}'"
}
]
}
]
}
}
每个 Hook 通过 stdin 接收 JSON 输入,通过 stdout 返回 JSON 输出。这是核心协议:
PreToolUse 输入(stdin):
{
"tool_name": "Write",
"tool_input": {
"file_path": "/project/src/config.ts",
"content": "export const API_KEY = '...'"
},
"session_id": "sess_abc123"
}
PreToolUse 输出(stdout)——三种决策:
// 1. 批准执行(无输出或空对象)
{}
// 2. 阻止执行
{"decision": "block", "reason": "不允许写入 .env 文件"}
// 3. 修改参数后执行(仅部分工具支持)
{"decision": "approve", "patch": {"content": "// 已清理敏感信息\nexport const config = {}"}}
PostToolUse 输入(stdin):
{
"tool_name": "Write",
"tool_input": { "file_path": "/project/src/index.ts" },
"tool_output": "File written successfully",
"session_id": "sess_abc123"
}
matcher 字段控制 Hook 的触发范围:
// 匹配单个工具
"matcher": "Write"
// 匹配多个工具(管道分隔)
"matcher": "Write|Edit"
// 匹配所有工具(空字符串)
"matcher": ""
// 使用正则表达式
"matcher": "Write|Edit|NotebookEdit"
阻止 Claude 读写 .env、密钥文件等敏感资源:
#!/usr/bin/env python3
"""pre-write-guard.py — 保护敏感文件不被 Claude 修改"""
import sys, json
PROTECTED_PATTERNS = [
'.env', '.env.local', '.env.production',
'credentials', 'secrets', '.pem', '.key'
]
data = json.loads(sys.stdin.read())
file_path = data.get('tool_input', {}).get('file_path', '')
for pattern in PROTECTED_PATTERNS:
if pattern in file_path:
print(json.dumps({
"decision": "block",
"reason": f"安全策略:禁止修改包含 '{pattern}' 的文件"
}))
sys.exit(0)
# 不阻止
print(json.dumps({}))
每次写入/编辑后自动运行 Prettier:
{
"hooks": {
"PostToolUse": [
{
"matcher": "Write|Edit",
"hooks": [
{
"type": "command",
"command": "npx prettier --write \"$CLAUDE_FILE_PATH\" 2>/dev/null || true"
}
]
}
]
}
}
阻止 rm -rf、sudo 等高危 Bash 命令:
#!/usr/bin/env python3
"""pre-bash-guard.py — 拦截危险 Shell 命令"""
import sys, json, re
DANGEROUS_PATTERNS = [
r'rm\s+-rf\s+/',
r'sudo\s+rm',
r'drop\s+database',
r'DROP\s+TABLE',
r'git\s+push\s+--force',
r':\(\)\{.*;\};' # fork bomb
]
data = json.loads(sys.stdin.read())
command = data.get('tool_input', {}).get('command', '')
for pattern in DANGEROUS_PATTERNS:
if re.search(pattern, command, re.IGNORECASE):
print(json.dumps({
"decision": "block",
"reason": f"安全策略:检测到危险命令模式 '{pattern}'"
}))
sys.exit(0)
print(json.dumps({}))
Agent 停止时发送 Slack 通知:
{
"hooks": {
"Stop": [
{
"matcher": "",
"hooks": [
{
"type": "command",
"command": "python3 scripts/notify-slack.py"
}
]
}
]
}
}
#!/usr/bin/env python3
"""notify-slack.py — 任务完成后发送 Slack 通知"""
import sys, json, urllib.request, os
# 从 Stop Hook 的 stdin 读取会话信息
data = json.loads(sys.stdin.read()) if not sys.stdin.isatty() else {}
session_id = data.get('session_id', 'unknown')
webhook_url = os.environ.get('SLACK_WEBHOOK_URL', '')
if not webhook_url:
sys.exit(0)
payload = {
"text": f"✅ Claude Code 任务完成 | 会话: {session_id} | 目录: {os.getcwd()}"
}
req = urllib.request.Request(
webhook_url,
data=json.dumps(payload).encode(),
headers={'Content-Type': 'application/json'}
)
urllib.request.urlopen(req)
每次文件修改后自动 git add:
{
"hooks": {
"PostToolUse": [
{
"matcher": "Write|Edit",
"hooks": [
{
"type": "command",
"command": "git add \"$CLAUDE_FILE_PATH\" 2>/dev/null || true"
}
]
}
]
}
}
除了 command 类型,Hooks 还支持:
// HTTP Hook —— 调用远程 API
{
"type": "command",
"command": "curl -s -X POST http://localhost:8080/hook -d @-"
}
// Agent SDK 中的 LLM Hook(编程接口)
// 在 Agent SDK 中可以使用 prompt 类型 Hook,
// 让另一个 LLM 判断是否允许操作
# 1. 使用 --verbose 查看 Hook 执行详情
claude -p "测试 hook" --verbose
# 2. 在 Hook 脚本中写调试日志
# 在 Python 脚本中:
import logging
logging.basicConfig(filename='/tmp/claude-hooks.log', level=logging.DEBUG)
# 3. 检查 Hook 退出码
# 退出码 0 = 正常(不阻止)
# 退出码 2 = 阻止操作
# 4. 测试单个 Hook 脚本
echo '{"tool_name":"Write","tool_input":{"file_path":"test.ts"}}' | python3 scripts/pre-write-guard.py
Agent SDK 是 Claude Code 能力的编程接口。claude -p 适合简单脚本,当你需要构建多步骤、有状态、可编排的 Agent 应用时,Agent SDK 是正确选择。
graph LR
A[你的应用] --> B[Agent SDK]
B --> C[Claude Code 引擎]
C --> D[文件系统]
C --> E[Shell 命令]
C --> F[搜索工具]
C --> G[MCP 服务器]
style B fill:#ff6b35,color:#fff
style C fill:#2d3436,color:#fff
# 创建项目
mkdir my-agent && cd my-agent
npm init -y
# 安装 Agent SDK
npm install @anthropic-ai/claude-agent-sdk
# TypeScript 支持
npm install -D typescript @types/node
npx tsc --init
query() 是 Agent SDK 的核心——一次调用就是一个完整的 Agent 循环:
// basic-agent.ts
import { query } from '@anthropic-ai/claude-agent-sdk';
async function main() {
const result = await query({
prompt: '分析当前项目的依赖关系,找出过时的包',
options: {
// 限制工具(安全沙箱)
allowedTools: ['Read', 'Glob', 'Grep', 'Bash'],
// 最大循环轮次
maxTurns: 5,
// 自定义系统提示
systemPrompt: '你是一个保守的依赖分析专家。只报告,不修改。',
},
});
console.log('Agent 结果:', result);
console.log('消耗轮次:', result.numTurns);
console.log('花费:', result.costUsd);
}
main().catch(console.error);
构建多轮对话 Agent:
// multi-turn-agent.ts
import { query, type Message } from '@anthropic-ai/claude-agent-sdk';
async function reviewAndFix() {
// 第一步:代码审查
const reviewResult = await query({
prompt: '审查 src/ 目录下的所有 TypeScript 文件,找出 bug',
options: {
allowedTools: ['Read', 'Glob', 'Grep'],
maxTurns: 5,
},
});
console.log('📋 审查发现:');
console.log(reviewResult.result);
// 第二步:基于审查结果自动修复
const fixResult = await query({
prompt: `根据以下审查结果修复所有 bug:\n\n${reviewResult.result}`,
options: {
allowedTools: ['Read', 'Write', 'Edit', 'Bash', 'Glob', 'Grep'],
maxTurns: 10,
systemPrompt: '修复时保持最小改动原则,每个修复添加注释说明原因。',
},
});
console.log('🔧 修复完成:', fixResult.result);
// 第三步:运行测试验证
const testResult = await query({
prompt: '运行项目测试,确认修复没有引入新问题',
options: {
allowedTools: ['Bash', 'Read'],
maxTurns: 3,
},
});
console.log('✅ 测试结果:', testResult.result);
}
reviewAndFix().catch(console.error);
利用会话持久化实现跨调用上下文保持:
// session-agent.ts
import { query } from '@anthropic-ai/claude-agent-sdk';
async function progressiveDevelopment() {
// 第一次调用——获取 session_id
const step1 = await query({
prompt: '阅读 package.json 和 tsconfig.json,理解项目结构',
options: { maxTurns: 3 },
});
const sessionId = step1.sessionId;
console.log(`会话已建立: ${sessionId}`);
// 继续同一会话——Claude 记得上文
const step2 = await query({
prompt: '基于你对项目的理解,为 src/utils.ts 编写单元测试',
options: {
maxTurns: 8,
continue: sessionId, // 继续指定会话
},
});
console.log('测试已生成:', step2.result);
// 再次继续——三步同上下文
const step3 = await query({
prompt: '运行刚生成的测试,修复任何失败的用例',
options: {
maxTurns: 10,
continue: sessionId,
},
});
console.log('最终结果:', step3.result);
}
progressiveDevelopment().catch(console.error);
在编程接口中,Hooks 通过回调函数实现,比 JSON 配置更灵活:
// sdk-hooks-agent.ts
import { query, type HookContext } from '@anthropic-ai/claude-agent-sdk';
async function agentWithHooks() {
const result = await query({
prompt: '重构 src/ 目录下的代码',
options: {
maxTurns: 10,
hooks: {
// 工具执行前——安全检查
PreToolUse: async (ctx: HookContext) => {
if (ctx.toolName === 'Bash') {
const cmd = ctx.toolInput.command as string;
if (cmd.includes('rm -rf') || cmd.includes('sudo')) {
return {
decision: 'block' as const,
reason: '安全策略:禁止执行危险命令',
};
}
}
if (ctx.toolName === 'Write' || ctx.toolName === 'Edit') {
const filePath = ctx.toolInput.file_path as string;
if (filePath.includes('.env')) {
return {
decision: 'block' as const,
reason: '安全策略:禁止修改环境配置文件',
};
}
}
return { decision: 'approve' as const };
},
// 工具执行后——自动格式化
PostToolUse: async (ctx: HookContext) => {
if (ctx.toolName === 'Write' || ctx.toolName === 'Edit') {
const filePath = ctx.toolInput.file_path as string;
if (filePath.endsWith('.ts') || filePath.endsWith('.js')) {
// 在此处触发格式化
console.log(`[Hook] 自动格式化: ${filePath}`);
}
}
},
// 任务完成——通知
Stop: async (ctx: any) => {
console.log(`[Hook] Agent 已停止,共 ${ctx.numTurns} 轮`);
},
},
},
});
return result;
}
agentWithHooks().catch(console.error);
Agent SDK 原生支持连接 MCP 服务器,扩展工具能力:
// mcp-agent.ts
import { query } from '@anthropic-ai/claude-agent-sdk';
async function agentWithMCP() {
const result = await query({
prompt: '查询 GitHub 上 anthropics 组织的最近 10 个 issue',
options: {
maxTurns: 8,
mcpServers: {
// 连接 GitHub MCP 服务器
github: {
command: 'npx',
args: ['-y', '@modelcontextprotocol/server-github'],
env: {
GITHUB_PERSONAL_ACCESS_TOKEN: process.env.GITHUB_TOKEN!,
},
},
// 连接文件系统 MCP 服务器
filesystem: {
command: 'npx',
args: ['-y', '@modelcontextprotocol/server-filesystem', '/workspace'],
},
},
},
});
console.log(result.result);
}
agentWithMCP().catch(console.error);
Claude Code 内置的 /batch 命令用于大规模代码变更——对多个文件应用相同的转换逻辑,比逐个文件调用快最多 10 倍:
# 交互式使用 /batch
# 在 Claude Code REPL 中输入:
> /batch "为所有 src/**/*.ts 文件添加 @author 注释"
结合 claude -p 的经典批量处理模式:
#!/bin/bash
# batch-add-tests.sh —— 批量为所有模块生成测试
set -euo pipefail
FILES=$(find src -name "*.ts" -not -name "*.test.ts" -not -path "*/node_modules/*")
TOTAL=$(echo "$FILES" | wc -l)
CURRENT=0
for file in $FILES; do
CURRENT=$((CURRENT + 1))
echo "[$CURRENT/$TOTAL] 处理: $file"
# 为每个文件生成测试
claude -p "为以下文件编写完整的单元测试:$(cat $file)" \
--output-format json \
--max-turns 5 \
--allowedTools "Read,Write,Glob,Grep" \
> "/tmp/test-result-$(basename $file).json"
# 检查是否成功
if command -v jq &>/dev/null; then
STATUS=$(jq -r '.subtype' "/tmp/test-result-$(basename $file).json" 2>/dev/null || echo "unknown")
echo " 状态: $STATUS"
fi
done
echo "✅ 批量处理完成!共处理 $TOTAL 个文件"
对于更复杂的批量任务,Python 提供更好的并发控制和错误处理:
#!/usr/bin/env python3
"""batch_processor.py —— Claude Code 批处理框架"""
import subprocess
import json
import os
import sys
import time
from pathlib import Path
from concurrent.futures import ThreadPoolExecutor, as_completed
def run_claude_task(prompt: str, cwd: str, max_turns: int = 5) -> dict:
"""执行单个 Claude Code 无头任务"""
cmd = [
'claude', '-p', prompt,
'--output-format', 'json',
'--max-turns', str(max_turns),
]
try:
result = subprocess.run(
cmd,
capture_output=True,
text=True,
cwd=cwd,
timeout=300, # 5分钟超时
)
# 解析 JSON 输出
try:
return json.loads(result.stdout)
except json.JSONDecodeError:
return {
'subtype': 'error',
'result': result.stdout,
'stderr': result.stderr,
}
except subprocess.TimeoutExpired:
return {'subtype': 'error', 'result': '任务超时'}
except Exception as e:
return {'subtype': 'error', 'result': str(e)}
def batch_process(
tasks: list[dict],
max_workers: int = 3,
delay_seconds: float = 2.0,
):
"""并发执行批量任务"""
results = []
with ThreadPoolExecutor(max_workers=max_workers) as executor:
futures = {}
for i, task in enumerate(tasks):
future = executor.submit(
run_claude_task,
task['prompt'],
task.get('cwd', os.getcwd()),
task.get('max_turns', 5),
)
futures[future] = (i, task)
time.sleep(delay_seconds) # 避免并发冲击
for future in as_completed(futures):
idx, task = futures[future]
result = future.result()
results.append({
'index': idx,
'task': task['prompt'][:80],
'status': result.get('subtype', 'unknown'),
'cost': result.get('cost_usd', 0),
'turns': result.get('num_turns', 0),
})
print(f"[{idx+1}/{len(tasks)}] "
f"状态: {result.get('subtype', '?')} | "
f"费用: ${result.get('cost_usd', 0):.4f}")
# 输出汇总报告
total_cost = sum(r['cost'] for r in results)
success_count = sum(1 for r in results if r['status'] == 'success')
print(f"\n{'='*60}")
print(f"批量处理完成")
print(f"总任务: {len(tasks)}")
print(f"成功: {success_count} | 失败: {len(tasks) - success_count}")
print(f"总费用: ${total_cost:.4f}")
print(f"{'='*60}")
return results
# 使用示例
if __name__ == '__main__':
tasks = [
{'prompt': '审查 src/auth.ts 的安全性', 'cwd': '/my-project'},
{'prompt': '审查 src/api.ts 的安全性', 'cwd': '/my-project'},
{'prompt': '审查 src/db.ts 的安全性', 'cwd': '/my-project'},
{'prompt': '审查 src/utils.ts 的安全性', 'cwd': '/my-project'},
]
batch_process(tasks, max_workers=2, delay_seconds=3.0)
利用 --continue 实现多步 Agent 流水线:
#!/bin/bash
# pipeline.sh —— 多步自动化流水线
PROJECT_DIR="/path/to/project"
cd "$PROJECT_DIR"
echo "🚀 启动自动化流水线..."
# 步骤 1:代码审查
echo "📋 步骤 1/4: 代码审查..."
STEP1=$(claude -p "审查 git diff HEAD~5 的所有变更,列出安全问题和 bug" \
--allowedTools "Read,Bash,Glob,Grep" \
--max-turns 5 \
--output-format json)
SESSION_ID=$(echo "$STEP1" | jq -r '.session_id')
REVIEW_TEXT=$(echo "$STEP1" | jq -r '.result')
echo "审查完成,会话: $SESSION_ID"
# 步骤 2:自动修复(继续同一会话)
echo "🔧 步骤 2/4: 自动修复..."
claude -p "根据审查结果修复所有严重问题: $REVIEW_TEXT" \
--continue "$SESSION_ID" \
--max-turns 10 \
--output-format json
# 步骤 3:运行测试
echo "🧪 步骤 3/4: 运行测试..."
claude -p "运行所有测试并报告结果" \
--continue "$SESSION_ID" \
--allowedTools "Bash,Read" \
--max-turns 5 \
--output-format json
# 步骤 4:生成变更报告
echo "📊 步骤 4/4: 生成报告..."
claude -p "总结本次所有变更,生成变更日志" \
--continue "$SESSION_ID" \
--max-turns 3 \
--output-format text
echo "✅ 流水线完成!"
flowchart TB
subgraph 触发层
T1[Git Push Hook]
T2[CI/CD Pipeline]
T3[Cron 定时任务]
T4[手动触发]
end
subgraph 编排层
O1[Shell 脚本]
O2[Python 框架]
O3[Agent SDK]
end
subgraph 执行层
E1[claude -p 无头模式]
E2[Hooks 安全守卫]
E3[会话管理]
end
subgraph 输出层
R1[JSON 结构化结果]
R2[Git Diff 变更]
R3[Slack 通知]
R4[测试报告]
end
T1 --> O1
T2 --> O2
T3 --> O1
T4 --> O3
O1 --> E1
O2 --> E1
O3 --> E1
E1 --> E2
E2 --> E3
E3 --> R1
E3 --> R2
E1 --> R3
E1 --> R4
style 触发层 fill:#e3f2fd
style 编排层 fill:#fff3e0
style 执行层 fill:#e8f5e9
style 输出层 fill:#fce4ec
构建一个完整的自动化系统,在每次 Git Push 时自动执行:代码审查 → 安全扫描 → 自动修复 → 测试验证 → 通知汇报。
claude-guardian/
├── .claude/
│ ├── settings.json # Hooks 配置
│ └── CLAUDE.md # 项目上下文
├── scripts/
│ ├── pre-push-guard.py # PreToolUse Hook
│ ├── auto-format.py # PostToolUse Hook
│ ├── notify.py # Notification Hook
│ └── pipeline.sh # 主流水线脚本
├── package.json
└── tsconfig.json
// .claude/settings.json
{
"hooks": {
"PreToolUse": [
{
"matcher": "Bash",
"hooks": [
{
"type": "command",
"command": "python3 scripts/pre-push-guard.py"
}
]
},
{
"matcher": "Write|Edit",
"hooks": [
{
"type": "command",
"command": "python3 scripts/pre-push-guard.py"
}
]
}
],
"PostToolUse": [
{
"matcher": "Write|Edit",
"hooks": [
{
"type": "command",
"command": "python3 scripts/auto-format.py"
}
]
}
],
"Notification": [
{
"matcher": "",
"hooks": [
{
"type": "command",
"command": "python3 scripts/notify.py"
}
]
}
]
},
"permissions": {
"allow": [
"Bash(npm test)",
"Bash(git diff*)",
"Bash(npx prettier*)",
"Read",
"Write",
"Edit",
"Glob",
"Grep"
]
}
}
#!/usr/bin/env python3
"""scripts/pre-push-guard.py — 统一安全守卫"""
import sys, json, re, os
BLOCKED_FILE_PATTERNS = [
r'\.env($|\.)', r'credentials', r'\.pem$', r'\.key$',
r'id_rsa', r'id_ed25519', r'secrets?\.json'
]
DANGEROUS_COMMANDS = [
r'rm\s+-rf\s+/(?!\w)', r'sudo\s+', r'chmod\s+777',
r'git\s+push\s+--force', r'drop\s+database',
r'>\s*/dev/sd', r'mkfs', r'dd\s+if=',
]
def check_file_path(file_path: str) -> dict | None:
for pattern in BLOCKED_FILE_PATTERNS:
if re.search(pattern, file_path, re.IGNORECASE):
return {
"decision": "block",
"reason": f"⛔ 安全策略:禁止访问匹配 '{pattern}' 的文件"
}
return None
def check_command(command: str) -> dict | None:
for pattern in DANGEROUS_COMMANDS:
if re.search(pattern, command, re.IGNORECASE):
return {
"decision": "block",
"reason": f"⛔ 安全策略:检测到危险命令模式"
}
return None
def main():
data = json.loads(sys.stdin.read())
tool_name = data.get('tool_name', '')
tool_input = data.get('tool_input', {})
# 检查文件路径类工具
if tool_name in ('Write', 'Edit', 'Read'):
file_path = tool_input.get('file_path', '')
result = check_file_path(file_path)
if result:
print(json.dumps(result))
return
# 检查 Bash 命令
if tool_name == 'Bash':
command = tool_input.get('command', '')
result = check_command(command)
if result:
print(json.dumps(result))
return
# 默认放行
print(json.dumps({}))
if __name__ == '__main__':
main()
#!/usr/bin/env python3
"""scripts/auto-format.py — 文件写入后自动格式化"""
import sys, json, subprocess, os
def main():
data = json.loads(sys.stdin.read())
tool_name = data.get('tool_name', '')
tool_input = data.get('tool_input', {})
file_path = tool_input.get('file_path', '')
if not file_path:
return
ext = os.path.splitext(file_path)[1]
# TypeScript / JavaScript → Prettier
if ext in ('.ts', '.tsx', '.js', '.jsx'):
subprocess.run(
['npx', 'prettier', '--write', file_path],
capture_output=True, timeout=30
)
# Python → Black
elif ext == '.py':
subprocess.run(
['black', file_path],
capture_output=True, timeout=30
)
# Go → gofmt
elif ext == '.go':
subprocess.run(
['gofmt', '-w', file_path],
capture_output=True, timeout=30
)
if __name__ == '__main__':
main()
#!/bin/bash
# scripts/pipeline.sh — 代码质量守护流水线
set -euo pipefail
PROJECT_DIR="$(cd "$(dirname "$0")/.." && pwd)"
cd "$PROJECT_DIR"
LOG_FILE="/tmp/claude-guardian-$(date +%Y%m%d-%H%M%S).log"
log() { echo "[$(date '+%H:%M:%S')] $1" | tee -a "$LOG_FILE"; }
log "🚀 启动代码质量守护流水线"
# ========== 阶段 1: 差异分析 ==========
log "📋 阶段 1/4: 分析变更..."
DIFF_SUMMARY=$(claude -p "分析 git diff HEAD~1 的变更,分类为:功能修改、测试修改、配置修改、文档修改。输出 JSON 格式。" \
--allowedTools "Bash,Read,Glob,Grep" \
--max-turns 3 \
--output-format json)
SESSION=$(echo "$DIFF_SUMMARY" | jq -r '.session_id')
log " 会话: $SESSION"
# ========== 阶段 2: 安全审查 ==========
log "🔒 阶段 2/4: 安全审查..."
SEC_REVIEW=$(claude -p "对本次变更进行安全审查:SQL注入、XSS、硬编码密钥、不安全的依赖。输出问题列表和严重等级。" \
--continue "$SESSION" \
--allowedTools "Bash,Read,Glob,Grep" \
--max-turns 5 \
--output-format json)
SEC_ISSUES=$(echo "$SEC_REVIEW" | jq -r '.result' | grep -c "严重\|high\|critical" || echo "0")
if [ "$SEC_ISSUES" -gt 0 ]; then
log "⚠️ 发现 $SEC_ISSUES 个严重安全问题!"
fi
# ========== 阶段 3: 测试验证 ==========
log "🧪 阶段 3/4: 运行测试..."
TEST_RESULT=$(claude -p "运行项目测试套件。如果有测试失败,分析原因并尝试修复,然后重新运行。" \
--continue "$SESSION" \
--allowedTools "Bash,Read,Write,Edit,Glob,Grep" \
--max-turns 8 \
--output-format json)
TEST_STATUS=$(echo "$TEST_RESULT" | jq -r '.subtype')
log " 测试状态: $TEST_STATUS"
# ========== 阶段 4: 生成报告 ==========
log "📊 阶段 4/4: 生成报告..."
REPORT=$(claude -p "基于以上所有分析,生成一份结构化的代码质量报告,包含:变更摘要、安全发现、测试结果、改进建议。" \
--continue "$SESSION" \
--max-turns 3 \
--output-format text)
echo "$REPORT" > "$PROJECT_DIR/quality-report-$(date +%Y%m%d).md"
log "✅ 报告已生成: quality-report-$(date +%Y%m%d).md"
# 输出汇总
TOTAL_COST=$(echo "$DIFF_SUMMARY $SEC_REVIEW $TEST_RESULT" | jq -s '[.[].cost_usd // 0] | add')
log "💰 总费用: \$$TOTAL_COST"
log "🏁 流水线完成!"
将流水线接入 Git Hook,实现 Push 前自动检查:
#!/bin/bash
# .git/hooks/pre-push —— Push 前自动质量检查
echo "🔍 执行 Claude Code 质量检查..."
# 快速检查(不超过 2 分钟)
RESULT=$(claude -p "快速检查即将 push 的 commit:是否有明显的安全漏洞或语法错误?" \
--allowedTools "Bash,Read,Glob,Grep" \
--max-turns 3 \
--output-format json)
STATUS=$(echo "$RESULT" | jq -r '.subtype')
if [ "$STATUS" = "success" ]; then
echo "✅ 检查通过,允许 Push"
exit 0
else
echo "❌ 检查未通过:"
echo "$RESULT" | jq -r '.result'
echo ""
read -p "是否仍要 Push?(y/N) " -n 1 -r
echo
[[ $REPLY =~ ^[Yy]$ ]] && exit 0 || exit 1
fi
# 1. 分级模型策略——简单任务用快模型
claude -p "格式化这个文件" \
--model claude-haiku-4-5-20251001 \
--max-turns 1
# 复杂任务用强模型
claude -p "重构认证模块,支持 OAuth2.0" \
--model claude-opus-4-8 \
--max-turns 15
# 2. 设置 max-turns 防止无限循环
# 简单查询: 1-3 轮
# 代码审查: 3-5 轮
# 重构任务: 5-10 轮
# 大规模变更: 10-20 轮
# 3. 使用只读工具降低风险和成本
claude -p "分析代码" --allowedTools "Read,Glob,Grep"
# retry-agent.py —— 带重试的 Claude Code 调用
import subprocess, json, time
def claude_with_retry(prompt: str, max_retries: int = 3, **kwargs) -> dict:
"""带指数退避重试的 Claude Code 调用"""
cmd = ['claude', '-p', prompt, '--output-format', 'json']
if 'max_turns' in kwargs:
cmd.extend(['--max-turns', str(kwargs['max_turns'])])
if 'allowed_tools' in kwargs:
cmd.extend(['--allowedTools', ','.join(kwargs['allowed_tools'])])
if 'model' in kwargs:
cmd.extend(['--model', kwargs['model']])
for attempt in range(max_retries):
try:
result = subprocess.run(
cmd, capture_output=True, text=True, timeout=600
)
data = json.loads(result.stdout)
if data.get('subtype') == 'success':
return data
else:
print(f"尝试 {attempt+1} 失败: {data.get('result', '')[:100]}")
except subprocess.TimeoutExpired:
print(f"尝试 {attempt+1} 超时")
except json.JSONDecodeError as e:
print(f"尝试 {attempt+1} JSON 解析失败: {e}")
if attempt < max_retries - 1:
wait = 2 ** attempt # 指数退避: 1s, 2s, 4s
print(f"等待 {wait}s 后重试...")
time.sleep(wait)
raise RuntimeError(f"任务在 {max_retries} 次尝试后仍然失败")
# 使用
result = claude_with_retry(
"审查并修复 src/api.ts 中的安全问题",
max_retries=3,
max_turns=8,
allowed_tools=["Read", "Write", "Edit", "Bash", "Glob", "Grep"]
)
使用 Agent SDK 构建并行 Agent 系统:
// parallel-agents.ts
import { query } from '@anthropic-ai/claude-agent-sdk';
interface TaskResult {
task: string;
status: string;
result: string;
cost: number;
}
async function runParallelAgents(): Promise<TaskResult[]> {
const tasks = [
{
task: '安全性审查',
prompt: '审查项目中所有认证相关代码的安全漏洞',
tools: ['Read', 'Glob', 'Grep'] as const,
},
{
task: '性能分析',
prompt: '分析项目中的性能瓶颈和优化机会',
tools: ['Read', 'Glob', 'Grep', 'Bash'] as const,
},
{
task: '代码质量',
prompt: '评估代码质量:重复代码、过长函数、圈复杂度',
tools: ['Read', 'Glob', 'Grep'] as const,
},
{
task: '依赖审查',
prompt: '检查 package.json 中的依赖是否有已知漏洞或废弃包',
tools: ['Read', 'Bash', 'Glob'] as const,
},
];
// 并行执行所有任务
const results = await Promise.all(
tasks.map(async (task) => {
try {
const result = await query({
prompt: task.prompt,
options: {
allowedTools: [...task.tools],
maxTurns: 5,
systemPrompt: '输出简洁的结构化报告。',
},
});
return {
task: task.task,
status: 'success',
result: (result as any).result || '',
cost: (result as any).costUsd || 0,
};
} catch (error: any) {
return {
task: task.task,
status: 'error',
result: error.message,
cost: 0,
};
}
})
);
// 汇总报告
const totalCost = results.reduce((sum, r) => sum + r.cost, 0);
console.log(`\n${'='.repeat(60)}`);
console.log('并行 Agent 执行完毕');
console.log(`总费用: $${totalCost.toFixed(4)}`);
console.log(`${'='.repeat(60)}\n`);
for (const r of results) {
console.log(`【${r.task}】${r.status === 'success' ? '✅' : '❌'}`);
console.log(r.result.substring(0, 200) + '...\n');
}
return results;
}
runParallelAgents().catch(console.error);
# ===== 基础调用 =====
claude -p "提示文本" # 最简调用
cat file.txt | claude -p "分析这段代码" # 管道输入
# ===== 输出控制 =====
claude -p "..." --output-format json # JSON 结构化输出
claude -p "..." --output-format stream-json # 流式 JSON
claude -p "..." --output-format text # 纯文本(默认)
# ===== 安全控制 =====
claude -p "..." --allowedTools "Read,Glob" # 只读工具白名单
claude -p "..." --max-turns 5 # 限制循环轮次
claude -p "..." --permission-mode plan # 计划模式(不执行)
# ===== 会话管理 =====
claude -p "..." --continue # 继续最近会话
claude -p "..." --resume SESSION_ID # 恢复指定会话
# ===== 模型选择 =====
claude -p "..." --model claude-opus-4-8 # Opus(最强)
claude -p "..." --model claude-sonnet-4-6 # Sonnet(平衡)
claude -p "..." --model claude-haiku-4-5-20251001 # Haiku(最快)
# ===== 提示词控制 =====
claude -p "..." --system-prompt "..." # 自定义系统提示
claude -p "..." --append-system-prompt "..." # 追加系统提示
| 问题 | 答案 |
|---|---|
-p 模式和交互模式费用一样吗? |
是的,计费标准相同。但可通过 --max-turns 和 --model 控制成本 |
| Hook 脚本超时怎么办? | 默认超时 60 秒,确保脚本快速返回;长时间任务建议异步处理 |
| Agent SDK 能在浏览器运行吗? | 不能,Agent SDK 需要 Node.js 运行时和文件系统访问 |
| 并行调用有速率限制吗? | 有,Anthropic API 有 RPM/TPM 限制,建议并发 ≤ 3-5 |
| 如何在 Docker 中使用无头模式? | 安装 Claude Code CLI,设置 ANTHROPIC_API_KEY 环境变量即可 |
--continue 的会话有效期? |
会话存储在本地 .claude/ 目录,除非手动清理,长期有效 |
-p 标志全部参数/batch 命令与无头批量处理实战训练营适用性评估:本教程适合 进阶训练营(Day 2-3),学员应已有 Claude Code 基础使用经验。建议教学时长 4-5 小时(含实操),其中无头模式 1h、Hooks 1.5h、Agent SDK 1.5h、综合实战 1h。可配合提供预配置的项目模板,让学员专注在 Hook 脚本编写和 Agent 编排上。
[!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 等场景全覆盖。
