<!-- title: 把代码规范固化成Skill：团队Reviewer实战 -->

> 本教程聚焦 Claude Code 2026 版 Skills 能力，演示如何把团队散落在 wiki、聊天记录、口头约定里的代码审查规范，固化成一个**行为一致、可复用、可演进**的 `/team-review` Skill。核心技术组合是 `context: fork` 隔离子代理 + `!`git diff`` 动态注入真实改动 + `paths` 文件类型限定 + severity 分级输出——让审查质量不再随 reviewer 心情波动。

## 概述

学完本教程，你能独立设计并交付一个生产级团队代码审查 Skill，掌握 frontmatter 各字段的工程化取舍、隔离子代理执行、动态上下文注入、分级报告输出、以及用 `skill-creator` 跑量化评测与版本 A/B 对比。适合已跑通 Claude Code 首项目、想从"个人提效"迈向"团队工程化"的中级开发者。

## 前置条件

- Claude Code v2.1.145 及以上（`/run`、`/verify` 及子代理增强特性依赖此版本）
- 一个 git 仓库，至少有 `main` 分支和一条特性分支
- 基础 YAML 与 Markdown 语法
- 已安装 `gh` CLI（实战案例中用于回填审查评论到 PR，可选）

---

## 第一步：明确"为什么要固化成 Skill"

代码审查的常见痛点不是"没人审查"，而是**审查标准漂移**：同一个 `useEffect` 依赖数组问题，A reviewer 标 `blocking`，B reviewer 视而不见。规范写在 Confluence 里没人读，新人上手要靠结对 review 摸索半年。

把规范固化成 Skill 解决三件事：

1. **一致性**——每次审查都跑同一份清单，不依赖记忆
2. **可演进**——规范变更只需改一份 `SKILL.md`，全员立即生效
3. **降门槛**——新人拿到的是团队共识，而非某个资深工程师的个人偏好

关键判断：Skill 适合承载**程序性知识**（怎么做），而 `CLAUDE.md` 适合承载**事实性知识**（是什么）。如果你的 review 规范已经从"项目用 React 19"这种事实，长成了"审查 hooks 依赖时要检查……"这种流程，就该毕业成 Skill。

## 第二步：创建骨架目录

在项目根目录下创建项目级 Skill（随仓库提交，团队共享）：

```bash
mkdir -p .claude/skills/team-review/reference
touch .claude/skills/team-review/SKILL.md
```

目录名 `team-review` 决定了命令名 `/team-review`。最终结构如下：

```text
.claude/skills/team-review/
├── SKILL.md              # 入口，frontmatter + 审查流程
└── reference/
    ├── typescript.md     # TS/React 细则（按需加载）
    ├── python.md         # Python 细则
    └── go.md             # Go 细则
```

**预期结果**：在仓库内会话中输入 `/`，autocomplete 列表出现 `team-review`。

**常见问题**：会话启动后才创建 `.claude/skills/` 顶层目录不会自动被发现，需要重启 Claude Code；但**编辑已存在的** `SKILL.md` 文本会实时生效（live change detection 仅覆盖 `SKILL.md` 文本，插件级的 `hooks/`、`.mcp.json` 改动需要 `/reload-plugins`）。

## 第三步：写 frontmatter——这是 Skill 的"大脑"

frontmatter 字段直接决定 Skill 何时被加载、如何执行、用什么工具。这一步是工程化取舍的核心。

```yaml
---
description: |
  用团队规范审查当前分支相对基线的改动，输出分级（blocking/important/nit）的审查报告。
  Use when: review my changes, 帮我 review 这次提交, pre-merge check, 审查 diff, 合并前检查.
argument-hint: "[base-branch] (默认 main)"
arguments: [base]
disable-model-invocation: true
paths:
  - "**/*.{ts,tsx,js,jsx,py,go,java}"
context: fork
agent: general-purpose
allowed-tools:
  - Read
  - Grep
  - Glob
  - Bash(git diff *)
  - Bash(git log *)
  - Bash(git show *)
  - Bash(npm test *)
  - Bash(go test *)
  - Bash(pytest *)
disallowed-tools:
  - Edit
  - Write
  - NotebookEdit
---
```

逐字段讲解设计意图：

**`description`**：把"最重要的用例"放在第一句。skill 列表会把 `description` + `when_to_use` 合并后**截断到 1536 字符**，关键词放前面才不会被裁掉。`Use when:` 后面列出用户真实会说的话（中英混合，覆盖团队成员的不同表达习惯）。

**`disable-model-invocation: true`**：审查是有明确意图的动作，你不希望 Claude 因为"代码看起来 review 过了"就自动跑。设为 `true` 后只能手动 `/team-review` 触发，且 description 不再常驻上下文。

**`paths`**：限定只有改动了 `ts/tsx/py/go/java` 等文件时才激活。改了个 `README.md` 就不该弹审查 Skill。

**`context: fork` + `agent: general-purpose`**：审查在**隔离的子代理**里跑。好处有三：审查指令不污染你的主对话；主对话里无关的上下文不会干扰审查判断；子代理返回的是"审查报告摘要"而非一堆中间过程。注意 `fork` 只适合有明确任务的 Skill——纯指导性内容（如"用这些 API 约定"）配 `fork` 会让子代理收到准则却无事可做。

**`allowed-tools`**：预批准**只读 + 验证**类工具（`Read`、`Grep`、跑测试），让子代理审查时不必逐次请求权限。重点：这里**不是**白名单，所有工具仍可被调用，`allowed-tools` 只免除审批。真正想"禁止改码"，要靠下面的 `disallowed-tools`。

**`disallowed-tools`**：审查者不该直接改代码（否则就失去 Reviewer 的客观性）。把 `Edit`、`Write`、`NotebookEdit` 列入禁用。**限制在你发送下一条消息后清除**——它是会话级临时约束。

**预期结果**：`/team-review` 后，Claude Code 启动一个隔离子代理，它只有只读 + 测试执行权限，改不了你的代码。

**常见问题**：

- "我设了 `allowed-tools` 为什么还会弹权限？"——项目级 Skill 的 `allowed-tools` 在你**接受 workspace trust 对话框**后才生效。首次启用项目 Skill 会弹信任确认，等价于 `.claude/settings.json` 里的权限规则。
- "frontmatter 写错了会怎样？"——YAML 格式错误时 Claude Code 会用空元数据加载 body，`/team-review` 仍能跑，但 `description` 匹配失效。用 `claude --debug` 启动可看到解析错误。

## 第四步：写 SKILL.md body——动态注入 + 清单 + 分级输出

frontmatter 之外的正文是 Claude 真正执行的指令。控制在 500 行以内，细节下沉到 `reference/`。

````markdown
# 团队代码审查

你是团队的资深 Reviewer。审查当前分支相对基线 `$base`（默认 `main`）的全部改动。
**你只审查、只读，不直接修改代码。** 给出问题清单让作者自己改。

## 待审查内容（已预注入）
相对 `$base` 的变更概览：

```!git diff $base...HEAD --stat
```

## 你的审查流程
1. 用 `git diff $base...HEAD` 拉取完整 diff（你已有权限）
2. 用 `git log $base..HEAD --oneline` 理解这次改动分了几次提交、意图是什么
3. 逐文件按下述清单审查
4. 若改动含 TypeScript/React、Python、Go，先读对应 `reference/*.md` 再下结论
5. 跑一次 `npm test`/`go test`/`pytest` 确认现有用例通过

## 审查清单（按优先级降序）
1. **正确性**：边界条件、空值/null、并发与竞态、错误处理路径
2. **安全**：输入校验、注入风险、敏感信息硬编码、越权
3. **性能**：N+1 查询、不必要的循环、内存泄漏、大对象拷贝
4. **可维护性**：命名是否达意、单一职责、注释解释"为什么"而非"是什么"
5. **复用**：新增工具函数前，先 Grep 项目里是否已有现成实现

## 输出格式
每条问题用 severity 前缀标注，附文件:行号：

- 🔴 `[blocking]` 阻断合并，必须修
- 🟡 `[important]` 应修复，如有异议可讨论
- 🟢 `[nit]` 可选，不阻断

末尾给出总评三选一：✅ 可合并 / 🔄 需修改 / 💬 仅有建议。
再补一句本次改动里你认可的亮点（praise）。

## 详尽细则（按需加载，勿一次性全读）
- TypeScript / React 19 见 [reference/typescript.md](reference/typescript.md)
- Python 见 [reference/python.md](reference/python.md)
- Go 见 [reference/go.md](reference/go.md)
````

两个机制要点：

**动态上下文注入**——`` ```!git diff $base...HEAD --stat ``` `` 这一段。执行顺序是：先做**字符串替换**（`$base` → 实际分支，如 `main`），再**运行 shell 命令**，把输出作为纯文本替换回正文。所以 Claude 收到的是"已经渲染好的、带真实 diff stat 的指令"，而非命令本身。它看到的永远是结果，命令是预处理，不是 Claude 自己执行的。

**渐进式披露**——`reference/*.md` 不会在 Skill 加载时进上下文，只有当 Claude 判断改动涉及对应语言、主动 `Read` 时才读入。这把"语言细则"这种大块参考资料的成本从"每次都付"降到"需要时才付"。

**预期结果**：执行 `/team-review main`，子代理先返回一段带文件统计的概览，再逐文件给出分级问题清单，最后给总评。

**常见问题**：

- "命令注入的 `!` 没生效？"——内联形式 `` !`cmd` `` 仅在 `!` 出现在行首或紧跟空白后时才识别。若写成 `KEY=!`cmd``，会被当字面量。多行命令用 ```` ```! ```` 代码块。
- "我不想让 Skill 跑命令（安全）"——管理员可在 settings 设 `"disableSkillShellExecution": true`，所有非 bundled/managed 的 Skill 的 `!` 注入会被替换成 `[shell command execution disabled by policy]`。

## 第五步：写一份 reference 细则

`reference/typescript.md` 示例（保持精炼，只写团队真正分歧的点）：

```markdown
# TypeScript / React 审查要点

## Hooks
- `useEffect` 依赖数组：列全外部依赖；故意省略要写注释说明理由
- `useState` 派生值：能用 `useMemo`/普通变量算出来就不要再加一个 state
- React 19：优先用 Actions 处理表单提交，避免手写 loading 态

## 类型
- 禁止 `any`，用 `unknown` + 类型守卫
- 公共 API 返回类型必须显式声明，不要靠推导
```

这一步的价值在于：规范变更走 PR 评审，团队对"要不要禁 `any`"的共识沉淀在 git 历史里，而不是某次站会的口头结论。

## 第六步：测试——验证 fork 隔离与只读约束

在特性分支上改两三处代码（故意埋一个 `any`、一个漏掉的 `useEffect` 依赖），然后：

```text
/team-review main
```

**预期结果**：
1. Claude Code 提示启动子代理（fork）
2. 子代理输出概览 + 分级清单，`any` 标 🟡，依赖问题标 🔴
3. 全程未触发"是否允许修改文件"的权限请求（因为 `Edit` 被 disallow）
4. 主对话历史保持干净，只有最终的审查报告

再用"自动触发不该触发"反向验证：在主对话里说"帮我把这个函数重命名一下"，确认 Claude **没有**自作主张跑 `team-review`（因为 `disable-model-invocation: true`）。

**常见问题**：

- "fork 后子代理好像没拿到项目上下文？"——`context: fork` 默认会加载 `CLAUDE.md`，但若指定 `agent: Explore` 或 `agent: Plan`，这两个内置代理会**跳过 CLAUDE.md 和 git status** 以保持上下文精简。审查任务需要项目上下文，所以用 `general-purpose`（或不写 `agent`，默认即它）。
- "审查报告偶尔'失忆'，后续不按 Skill 走了？"——Skill 内容在 invoke 后作为单条消息**常驻到会话结束**，但 auto-compaction 时每个 Skill 只保留最近一次调用的前 5000 token（多个 Skill 共享 25000 token 预算，按最近优先）。审查完别立刻 `/compact`，或审查后如需继续就重新 invoke。

## 第七步：用 skill-creator 跑量化评测

"Skill 触发了"不等于"它做对了"。要分别测两件事：**该触发时是否触发**、**触发后输出是否符合预期**。`skill-creator` 插件把这套对比循环自动化。

```text
/plugin install skill-creator@claude-plugins-official
/reload-plugins
```

若提示找不到插件，先刷新市场：`/plugin marketplace update claude-plugins-official`。安装后让 Claude 跑评测：

```text
用 skill-creator 评估我的 team-review skill，写 5 个测试用例
```

它会：
- 把测试用例（prompt + 期望行为）存进 `evals/evals.json`
- 每个 case 起一个隔离子代理跑，记录 token 和耗时
- 对输出逐条断言打分，写 `grading.json`
- 聚合"有 Skill / 无 Skill"的通过率、耗时、token 到 `benchmark.json`
- 支持**版本 A/B 盲测**——你改了一版 description，先盲测确认是改进再 commit

关键动作：**每个 case 都在全新会话里跑**。因为你写 Skill 时的残留上下文会掩盖指令的缺口，干净会话才能暴露真实触发率。

**预期结果**：拿到一份 HTML 报告，能看到"加了 Skill 后，'帮我 review 这次提交'的触发命中从 40% 提升到 95%，且无 Skill 时完全不会误触发"。

## 第八步：管理可见性与触发精度

Skill 一多，描述会互相争抢上下文预算。预算默认是模型上下文窗口的 1%，超限后**最少用的 Skill 描述先被砍**，导致关键词丢失、触发失灵。

诊断：

```text
/doctor
```

看有多少 Skill 描述被截断或丢弃。应对手段：

- 调高预算：`skillListingBudgetFraction: 0.02`（2%）或环境变量 `SLASH_COMMAND_TOOL_CHAR_BUDGET`
- 给低优先 Skill 设 `"name-only"`（在 `/skills` 菜单里对条目按空格切换状态），只列名不占描述
- 精修 `description`：把关键用例前置，因为每条上限 1536 字符（`maxSkillDescriptionChars` 可调）

`skillOverrides` 写进 `.claude/settings.local.json`，四档状态控制可见性：

| 值 | 给 Claude 列出 | 在 `/` 菜单 |
|:--|:--|:--|
| `"on"` | 名称+描述 | 是 |
| `"name-only"` | 仅名称 | 是 |
| `"user-invocable-only"` | 隐藏 | 是 |
| `"off"` | 隐藏 | 隐藏 |

例如把过时的 `legacy-review` 收成 name-only：`{"skillOverrides": {"legacy-review": "name-only"}}`。

## 第九步：团队共享与安全审查

项目级 Skill 随仓库提交即可分发：

```bash
git add .claude/skills/team-review
git commit -m "Add team-review skill"
```

**安全提醒**：项目 Skill 的 `allowed-tools` 在同事 clone 后、接受 workspace trust 时生效。**reviewer 在信任一个仓库前应先读它的 Skill**——一个 Skill 可以给自己授予很宽的工具权限。对 `team-review` 这种只读审查 Skill，确认它只 grant 只读工具，且没有偷偷用 `context: fork` 之外的副作用。

如果想在组织级统一分发（而非每个仓库各自提交），走 managed settings 部署到全员。

---

## 完整实战案例：`team-review` Skill 全貌

目录树：

```text
.claude/skills/team-review/
├── SKILL.md
└── reference/
    ├── typescript.md
    ├── python.md
    └── go.md
```

`SKILL.md` 完整内容（合并第三、四步）：

````markdown
---
description: |
  用团队规范审查当前分支相对基线的改动，输出分级（blocking/important/nit）的审查报告。
  Use when: review my changes, 帮我 review 这次提交, pre-merge check, 审查 diff, 合并前检查.
argument-hint: "[base-branch] (默认 main)"
arguments: [base]
disable-model-invocation: true
paths:
  - "**/*.{ts,tsx,js,jsx,py,go,java}"
context: fork
agent: general-purpose
allowed-tools:
  - Read
  - Grep
  - Glob
  - Bash(git diff *)
  - Bash(git log *)
  - Bash(git show *)
  - Bash(npm test *)
  - Bash(go test *)
  - Bash(pytest *)
disallowed-tools:
  - Edit
  - Write
  - NotebookEdit
---

# 团队代码审查

你是团队的资深 Reviewer。审查当前分支相对 `$base`（默认 `main`）的全部改动。
**你只审查、只读，不直接修改代码。**

## 待审查内容（已预注入）
相对 `$base` 的变更概览：
```!git diff $base...HEAD --stat
```

## 审查流程
1. `git diff $base...HEAD` 拉完整 diff
2. `git log $base..HEAD --oneline` 理解提交意图
3. 逐文件按下述清单审查
4. 改动含 TS/Python/Go 时，先读对应 `reference/*.md`
5. 跑 `npm test`/`go test`/`pytest` 确认通过

## 审查清单（按优先级降序）
1. 正确性：边界条件、空值/null、并发、错误处理
2. 安全：输入校验、注入、敏感信息、越权
3. 性能：N+1 查询、不必要循环、内存泄漏
4. 可维护性：命名达意、单一职责、注释解释"为什么"
5. 复用：新增前先 Grep 是否已有现成实现

## 输出格式
每条问题用 severity 前缀 + 文件:行号：
- 🔴 `[blocking]` 阻断合并
- 🟡 `[important]` 应修复
- 🟢 `[nit]` 可选
末尾总评三选一：✅ 可合并 / 🔄 需修改 / 💬 仅建议。补一句认可的亮点。

## 细则（按需加载）
- [reference/typescript.md](reference/typescript.md)
- [reference/python.md](reference/python.md)
- [reference/go.md](reference/go.md)
````

跑一次 `/team-review main` 的典型输出片段：

```text
📊 变更概览
 src/hooks/useFetch.ts | 18 ++++++----
 src/api/user.ts       |  5 ++-

🔴 [blocking] src/hooks/useFetch.ts:14
  useEffect 依赖数组缺了 `url`，url 变化时不会重新请求。
🟡 [important] src/api/user.ts:9
  返回类型用了 `any`，请用 `unknown` + 类型守卫。
🟢 [nit] src/hooks/useFetch.ts:3
  变量名 `d` 不达意，建议 `data`。

✅ 亮点：错误处理用 try/catch 包裹 fetch，比之前健壮。
🔄 总评：需修改（1 blocking / 1 important）
```

## 工作流程图

```mermaid
flowchart TD
    A["用户输入 /team-review main"] --> B["Claude Code 解析 frontmatter"]
    B --> C{"disable-model-invocation?"}
    C -->|是 手动触发| D["字符串替换 \$base = main"]
    C -->|否则不自动跑| Z(["结束"])
    D --> E["context: fork 启动隔离子代理"]
    E --> F["shell 注入: git diff main...HEAD --stat"]
    F --> G["子代理拉完整 diff + 读 reference/*"]
    G --> H{"工具调用"}
    H -->|Read/Grep 只读| I["按清单逐文件审查"]
    H -->|Edit/Write| J["被 disallowed-tools 拦截"]
    J --> H
    I --> K["跑 npm test / go test 验证"]
    K --> L["生成分级报告 🔴🟡🟢"]
    L --> M["子代理返回报告摘要"]
    M --> N["主对话收到报告<br/>历史保持干净"]
```

## 延伸阅读

- **Agent Skills 开放标准**（`agentskills.io`）——Skill 跨工具通用的规范，含评测文件格式
- **Skill 编写最佳实践**（`platform.claude.com/docs/.../agent-skills/best-practices`）——跨 Claude 产品的通用写作指南
- **Subagents 文档**（`code.claude.com/docs/en/sub-agents`）——`context: fork`、`agent` 字段、子代理预加载 Skill 的完整说明
- **Hooks 文档**（`code.claude.com/docs/en/hooks`）——用 hooks 在 Skill 生命周期做确定性拦截，弥补"模型偶尔不遵守 Skill"的缺口
- **skill-creator 公告**（`claude.com/blog/improving-skill-creator-...`）——benchmark 与版本对比模式的设计背景

## 训练营适用性评估

**适合的训练营类型**：企业级工程化营、团队提效营、中级 Claude Code 进阶营。不适合纯入门营（需先掌握基础命令与首个项目）。

**教学时长**：建议 4–6 小时。1 小时讲 frontmatter 取舍，1.5 小时动手写 `team-review` + reference，1 小时跑 skill-creator 评测，剩余时间做团队规范梳理与 A/B 优化。

**配套练习**：
1. 把自己团队真实的 review checklist 翻译成一个 Skill
2. 故意埋 3 个 bug，看 Skill 能否稳定抓到（用 skill-creator 量化命中率）
3. 与 `/code-review` 内置 Skill 对比，找出团队 Skill 的差异化价值

**评估标准**：能独立解释 `allowed-tools` 与 `disallowed-tools` 的区别、能设计 `context: fork` 的隔离任务、能用 benchmark 证明一次 Skill 改动确实是改进。

## 参考来源

1. [Extend Claude with skills — Claude Code 官方文档](https://code.claude.com/docs/en/skills) — frontmatter 全字段、动态注入、子代理执行、skill-creator 评测的权威说明
2. [awesome-skills/code-review-skill — GitHub](https://github.com/awesome-skills/code-review-skill) — 生产级代码审查 Skill 参考，severity 分级体系与语言指南结构的来源
3. [Evaluating skill output quality — agentskills.io](https://agentskills.io/skill-creation/evaluating-skills) — Agent Skills 开放标准的评测文件格式与迭代工作流
4. [Claude Code Skills: The Complete Guide (2026) — duet.so](https://duet.so/guides/claude-code-skills-complete-guide) — 社区完整指南，覆盖 SKILL.md 规范与安全控制

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