<!-- title: 构建代码影响面分析Skill -->

## 概述

本教程带你从零构建一个名为 `impact-analyze` 的自定义 Claude Code Skill，专门做**改动影响面分析（blast-radius analysis）**：给定一个函数、类或文件，它自动定位所有调用方、定义点、相关测试，产出带风险评级的影响报告、建议的回归测试范围，以及一张 Mermaid 调用关系图。在构建过程中，你会一次性掌握 2026 年 Skill 体系的全部核心能力——`SKILL.md` 结构、YAML frontmatter、可执行脚本封装、动态上下文注入（`!`command``）、渐进披露（progressive disclosure）、参数替换、`allowed-tools` 权限预授与、`paths` 路径触发，以及 description 的触发调优。

适用人群：已经能用 Claude Code 完成日常编码、想从「粘贴提示词」升级到「沉淀可复用工作流」的开发者；尤其适合重构频繁、担心改动波及面的大型代码库维护者。

## 前置条件

- 已安装 Claude Code（v2.1.145 或更高，本教程用到的 `paths`、动态注入等特性在该版本已稳定）。
- 命令行环境，`git` 与 `rg`（ripgrep）可用。若没有 ripgrep，可改用 `grep -rn`，但速度差异明显，建议装上。
- 一个真实的代码仓库作为练手对象（任何语言均可，本教程示例以多语言通用为主）。

---

## 一、为什么是「影响面分析」——Skill 选型方法论

在动手前，先回答一个问题：**什么样的工作流值得封装成 Skill？** 官方文档给了一个清晰的标准——

> Create a skill when you keep pasting the same instructions, checklist, or multi-step procedure into chat, or when a section of CLAUDE.md has grown into a procedure rather than a fact.

提炼成三条判据：

1. **重复性**：你反复把同一套步骤粘贴进对话。
2. **多步骤**：它不是一句话事实，而是一段「先做 A，再做 B，再做 C」的过程。
3. **按需加载**：内容很长，但只在特定场景才用——这正是 Skill 相对 `CLAUDE.md` 的核心优势：`CLAUDE.md` 常驻上下文，Skill 只在触发时加载。

「改动影响面分析」完美命中这三条：每次重构前你都得找调用方、判断风险、圈定测试范围；它天然是多步骤（查引用 → 分类 → 评级 → 出图）；而它的判定规则（什么算高风险、如何打分）属于「长参考材料」，平时不需要，重构时才用。选它做教学样本，是因为它能**自然地逼出 Skill 的所有特性**：需要脚本（grep 引用）、需要动态注入（把实时引用结果喂给模型）、需要渐进披露（风险评判规则独立成文件）、需要参数化（传入符号名）。

### 这个 Skill 不做什么

为避免膨胀，明确边界——它**不负责**：跨语言类型推断（交给 LLM 判断即可）、自动改代码（只做分析，不写 patch）、CI 集成（那是 hooks 的活）。Skill 越聚焦，description 越精准，触发越可靠。

---

## 二、Skill 的目录结构与生命周期（2026 版准确事实）

动手前，先对齐几个容易被旧教程带偏的事实。

### 存放位置决定作用域

| 级别 | 路径 | 作用范围 |
|:--|:--|:--|
| 个人级 | `~/.claude/skills/<name>/SKILL.md` | 你的所有项目 |
| 项目级 | `.claude/skills/<name>/SKILL.md` | 仅当前项目 |
| 插件级 | `<plugin>/skills/<name>/SKILL.md` | 启用该插件处 |

同名时，个人级覆盖项目级；插件级带 `plugin-name:` 命名空间，不会冲突。

### 一个目录就是「一个 Skill」

`SKILL.md` 是唯一必需的入口，其余文件按需放入，形成渐进披露结构：

```text
impact-analyze/
├── SKILL.md              # 主指令（必需，建议 < 500 行）
├── risk-rubric.md        # 风险评判标准（按需加载）
├── report-template.md    # 输出模板（按需加载）
└── scripts/
    └── find-refs.sh      # 可执行脚本（被执行，而非读入上下文）
```

关键区别：`reference.md` 这类文件是**被读入上下文**的（Claude 需要时主动 Read），`scripts/` 下的脚本是**被执行**的（输出结果喂给 Claude，源码不进上下文）。后者省 token，适合任何「机械、确定、量大」的工作。

### 生命周期：热加载 + 常驻

- **热加载**：在已存在的 skills 目录里增删改 `SKILL.md`，当前会话即时生效，无需重启。注意：仅 `SKILL.md` 文本走热加载；若该目录同时是插件，`hooks/`、`.mcp.json` 等改动需 `/reload-plugins`。
- **常驻机制**：一旦被调用，渲染后的 `SKILL.md` 内容作为单条消息进入对话并**停留整个会话**。压缩（auto-compaction）时会保留每个 Skill 最近一次调用的前 5,000 token，多个被调用 Skill 共享 25,000 token 预算，从最近调用的开始填。这意味着：**Skill 正文每多一行都是反复的 token 成本**——保持精简。

---

## 三、动手：创建 `impact-analyze` Skill

### 步骤 1：创建目录

个人级（跨项目复用）：

```bash
mkdir -p ~/.claude/skills/impact-analyze/scripts
```

如果是项目专属，改用仓库根目录下的 `.claude/skills/impact-analyze/scripts`。

### 步骤 2：编写「引用查找」脚本

把机械的 grep 工作交给脚本，让 LLM 只做它擅长的「分类与判断」。新建 `~/.claude/skills/impact-analyze/scripts/find-refs.sh`：

```bash
#!/usr/bin/env bash
# find-refs.sh — locate references to a symbol across the repo
# Usage: find-refs.sh <symbol-or-path>
set -euo pipefail

SYMBOL="${1:-}"
if [[ -z "$SYMBOL" ]]; then
  echo "ERR: no symbol provided"; exit 1
fi

ROOT="$(git rev-parse --show-toplevel 2>/dev/null || pwd)"
echo "# Target: $SYMBOL"
echo "# Repo root: $ROOT"
echo

# 1. 文件级命中清单（用于判断波及面广度）
echo "## Files referencing '$SYMBOL'"
rg -l --no-heading "$SYMBOL" "$ROOT" 2>/dev/null | head -50 || true
echo

# 2. 命中密度 Top20（密度高 = 可能是核心调用点）
echo "## Match density (top 20 by file)"
rg -c --no-heading "$SYMBOL" "$ROOT" 2>/dev/null \
   | sort -t: -k2 -rn | head -20 || true
echo

# 3. 疑似定义点（多语言常见定义关键字）
echo "## Candidate definitions"
rg -n --no-heading \
   "(def |function |func |class |const |export (default )?function |interface )" \
   "$ROOT" 2>/dev/null \
   | rg "\b${SYMBOL}\b" | head -20 || true
echo

# 4. 命中该符号的测试文件（回归测试范围线索）
echo "## Test files touching '$SYMBOL'"
rg -l --no-heading "$SYMBOL" "$ROOT" \
   -g '*test*' -g '*spec*' -g '*.test.*' 2>/dev/null | head -20 || true
```

赋予执行权限：

```bash
chmod +x ~/.claude/skills/impact-analyze/scripts/find-refs.sh
```

**预期结果**：在任意 git 仓库里运行 `~/.claude/skills/impact-analyze/scripts/find-refs.sh checkoutSession`，会打印四段结构化文本——文件清单、密度排序、定义点候选、测试文件清单。这四段正是后续 LLM 评级所需的全部原始素材。

**常见问题**：
- `rg: command not found` → `brew install ripgrep` 或 `apt install ripgrep`；实在没有把 `rg` 换成 `grep -rn`（性能下降）。
- 仓库太大、命中上万行 → 脚本已用 `head` 截断，但若密度图被截断可放宽到 50。

### 步骤 3：编写 `SKILL.md`（frontmatter + 动态注入）

新建 `~/.claude/skills/impact-analyze/SKILL.md`：

```yaml
---
description: Analyze the blast-radius of a code change. Use when the user asks "who calls X", "what will this affect", "is it safe to change/rename/delete X", or before any refactor / rename / delete of a function, class, method, or constant. Produces a risk-rated impact report plus a Mermaid call graph.
argument-hint: <symbol or file path>
allowed-tools: Read Grep Glob Bash
---

## References to "$1"

!`${CLAUDE_SKILL_DIR}/scripts/find-refs.sh "$1"`

## Instructions

You are performing a **change-impact (blast-radius) analysis** of the symbol
above. Work through these steps, then produce the report.

1. **Identify the definition.** From "Candidate definitions", pick the real
   definition site(s). Read 1-2 of them to confirm signature & visibility.
2. **Classify references** into: direct callers, indirect/transitive callers,
   re-exports, and tests. Use "Match density" to spot hotspots.
3. **Rate the risk** of *changing/renaming/deleting* this symbol using the
   rubric in risk-rubric.md — load it: see [risk-rubric.md](risk-rubric.md).
4. **Recommend regression scope** — list the test files that must pass, and any
   caller that has no test coverage (a gap that itself is a risk).
5. **Draw a Mermaid call graph** of the top callers → target → top callees.

## Output format

Follow [report-template.md](report-template.md) exactly:
definition location, risk level (low/medium/high) with one-line reason,
caller table, recommended tests, and a fenced ```mermaid graph.

Keep prose tight. Tables > paragraphs.
```

这里用到了四个 2026 关键特性：

- **`argument-hint`**：在 `/` 自动补全里显示 `<symbol or file path>`，降低误用。
- **动态上下文注入** `!`${CLAUDE_SKILL_DIR}/scripts/find-refs.sh "$1"``：Claude Code 会在把内容交给模型**之前**先执行这行命令，把输出原地替换进去。于是模型看到的不是「请去查引用」，而是「引用已经在这里了」。`${CLAUDE_SKILL_DIR}` 解析为该 Skill 目录的绝对路径，保证脚本在任何 cwd 下都能找到。`$1` 是位置参数替换，展开为用户传入的第一个参数。
- **`allowed-tools`**：预授这些工具权限，免去逐次确认弹窗。注意：它**只授权、不限制**——未列出的工具仍可调用，受全局权限规则约束。
- **渐进披露链接**：`[risk-rubric.md](risk-rubric.md)` 与 `[report-template.md](report-template.md)` 告诉模型「需要时去读」，常驻正文只保留主线，省 token。

> **关于 `$1` 在注入块内的展开**：字符串替换（`$1`、`$ARGUMENTS`、`${CLAUDE_SKILL_DIR}`）作用于整段 Skill 内容，因此注入块里的 `$1` 会被先替换、再执行。如果你的版本对注入块内参数替换支持不一致，最稳妥的写法是 `/impact-analyze checkoutSession`（符号作为第一个词），脚本从 `$1` 读取；或退化为在正文里用一行 `Bash` 工具调用 `find-refs.sh`，效果一致。

### 步骤 4：渐进披露——拆出「风险评判标准」

新建 `risk-rubric.md`：

```markdown
# Risk rubric for blast-radius

Rate the risk of changing/renaming/deleting the target symbol:

- **High** — exported public API / entry point / called by >5 files / part of
  an interface or base class / has no direct test.
- **Medium** — internal helper used by 2-5 files, or public but well-tested.
- **Low** — single-file local, private, fully covered by tests.

Tie-breakers: any "no test coverage on a caller" bumps the level up one notch.
```

新建 `report-template.md`：

```markdown
# Impact report: <symbol>

**Definition:** `path/to/file.py:42` (visibility)
**Risk: HIGH | MEDIUM | LOW** — <one-line reason>

## Callers (top)
| Caller | File | Has test? |
|:--|:--|:--|

## Regression scope
- Must pass: <test files>
- Coverage gaps (risk): <callers without tests>

## Call graph
```mermaid
graph LR
  A[Caller] --> T[Target]
  T --> C[Callee]
```
```

这两个文件故意不塞进 `SKILL.md` 正文——它们只在「评级」和「排版」两步才需要，常驻是浪费。

### 步骤 5：验证热加载

由于目录已存在，**无需重启**。在仓库里启动 `claude`，输入 `/` 应能看到 `impact-analyze`（带 argument-hint）。

---

## 四、三种调用方式与效果验证

1. **显式调用**：`/impact-analyze checkoutSession`
2. **自然语言触发**（靠 description 命中）：直接问「我把 `checkoutSession` 的返回值从对象改成 Promise，会影响哪些地方？」
3. **带引号的多词参数**：`/impact-analyze "processOrder"` —— 若符号含特殊字符，用 shell 风格引号包起来。

预期：模型先呈现「References to ...」段（即脚本实时输出），再按 `report-template.md` 给出定义位置、风险评级、调用方表格、回归测试范围，最后一张 Mermaid 图。

---

## 五、进阶配置

### `paths`：只在改相关文件时触发

若你希望这个 Skill 只在用户编辑源码时自动激活（而非写文档时），加 frontmatter：

```yaml
paths: "**/*.{ts,js,py,go,java,rs,c,cpp}"
```

设置后，Claude 仅在操作匹配文件时才考虑自动加载它，降低误触发与无关 token。

### `disable-model-invocation` vs `user-invocable`

| frontmatter | 你能调用 | 模型能调用 | 上下文加载 |
|:--|:--|:--|:--|
| 默认 | 是 | 是 | description 常驻，调用时加载全文 |
| `disable-model-invocation: true` | 是 | 否 | description 不进上下文，你 `/` 时才加载 |
| `user-invocable: false` | 否 | 是 | description 常驻，模型按需加载 |

对 `impact-analyze`，默认即可——它无副作用（只读分析），适合让模型在「用户说要重构」时自动调用。若是 `/deploy` 这类有副作用的，务必 `disable-model-invocation: true`。

### 安全提示

`allowed-tools` 让 Skill 自授工具权限。**项目级 Skill 的 `allowed-tools` 在你接受工作区信任对话框后才生效**——评审别人的仓库前，先扫一眼 `.claude/skills/` 里有没有可疑的 `allowed-tools` 自授。

---

## 六、实战案例：对真实函数做影响面分析

场景：一个 Node 服务，准备把 `checkoutSession(sessionId: string)` 的返回值从 `Session` 改为 `Promise<Session>`。

```
> /impact-analyze checkoutSession
```

模型产出（节选）：

```markdown
# Impact report: checkoutSession

**Definition:** src/auth/session.ts:88 (exported, public)
**Risk: HIGH** — exported public API, called by 7 files, 3 callers lack tests.

## Callers (top)
| Caller                       | File                        | Has test? |
|:--|:--|:--|
| handleCheckout               | src/routes/checkout.ts:21   | yes       |
| refreshIfNeeded              | src/middleware/auth.ts:54   | yes       |
| adminForceCheckout           | src/admin/sessions.ts:33    | no        |
| ...                          | ...                         | ...       |

## Regression scope
- Must pass: tests/routes/checkout.test.ts, tests/middleware/auth.test.ts
- Coverage gaps (risk): src/admin/sessions.ts (no test — bump risk)

## Call graph
```mermaid
graph LR
  R[checkout route] --> T[checkoutSession]
  M[auth middleware] --> T
  A[admin tool] --> T
  T --> S[(Session store)]
```

随后模型给出建议：先给 `adminForceCheckout` 补测试，再改签名，最后在迁移期提供临时包装以保持同步调用方不立即报错。

这正是「把改动从凭感觉变成有数据支撑」的价值。

---

## 七、调优与避坑

1. **不触发？** 多半是 `description` 没把关键用例放最前。description 与 when_to_use 合计在 Skill 列表里**截断到 1,536 字符**，且「第一个用例」权重最高。把「who calls / what will this affect / safe to rename」放在句首。
2. **触发后行为漂移？** Skill 内容会跨多轮常驻，若多轮后模型「忘了」，多半是上下文太长被压缩稀释——强化 description 与指令，或用 hooks 强制；必要时在后续轮次重新 `/impact-analyze` 一次恢复全文。
3. **正文别太长。** 每行都是反复成本。把长规则挪进 `reference.md`，正文只留「做什么 + 何时读哪个文件」。
4. **脚本路径用 `${CLAUDE_SKILL_DIR}`**，别写死相对路径——否则换 cwd 就 404。
5. **`SKILL.md` 控制 < 500 行**是官方建议的舒适区。

---

## 八、整体工作流（Mermaid）

Skill 加载与运行时数据流：

```text
flowchart TD
  U[用户: /impact-analyze checkoutSession] --> RND[渲染 SKILL.md]
  RND --> SUB[字符串替换: $1, $ARGUMENTS, ${CLAUDE_SKILL_DIR}]
  SUB --> INJ[动态注入: 执行 find-refs.sh]
  INJ --> CTX[实时引用结果 进入正文]
  CTX --> M[Claude 接到 含数据的指令]
  M --> S1[确认定义点 Read]
  M --> S2[分类调用方 Grep]
  S2 --> S3[读 risk-rubric.md 评级]
  S3 --> S4[套 report-template.md]
  S4 --> OUT[影响报告 + Mermaid 调用图]

  style INJ fill:#fde68a,stroke:#b45309
  style CTX fill:#bbf7d0,stroke:#15803d
```

---

## 延伸阅读

- 官方 Skill 文档（本教程权威依据）：[Extend Claude with skills — Claude Code Docs](https://code.claude.com/docs/en/skills)
- Skill 选型决策（CLAUDE.md vs Skill vs Subagent）：[Claude Code Customization Guide (2026)](https://alexop.dev/posts/claude-code-customization-guide-claudemd-skills-subagents/)
- 跨工具通用标准：[Agent Skills 开放标准](https://agentskills.io)
- 构建完整指南（PDF）：[The Complete Guide to Building Skills for Claude (Anthropic)](https://resources.anthropic.com/hubfs/The-Complete-Guide-to-Building-Skill-for-Claude.pdf?hsLang=en)
- Skills 实战合集：[337 Claude Code Skills & Agents (GitHub)](https://github.com/alirezarezvani/claude-skills)

---

## 训练营适用性评估

- **适合类型**：进阶开发训练营、AI 辅助工程实战营、重构与质量保障专题。建议学员已能独立使用 Claude Code 完成日常任务。
- **教学时长**：约 90–120 分钟。其中原理（第二、七节）30 分钟，动手（第三、四节）45 分钟，进阶与实战（第五、六节）30 分钟，讨论调优 15 分钟。
- **可裁剪**：若时长紧张，跳过 `paths` 与 `disable-model-invocation` 对照表，保留「脚本 + 动态注入 + 渐进披露」主线即可。
- **作业建议**：让学员把 `impact-analyze` 适配到自己的语言栈（如 Go 的 `func`、Java 的 `public`），并提交一次真实重构前的影响分析报告。
- **延伸练习**：把输出格式从 Markdown 改为 JSON，再写一个消费该 JSON 的 `/impact-test` Skill（生成回归测试骨架），形成 Skill 编排雏形。

---

## 参考来源

1. [Extend Claude with skills — Claude Code Docs](https://code.claude.com/docs/en/skills) — 官方权威文档，覆盖 frontmatter 全字段、动态注入、渐进披露、生命周期与热加载，本教程所有特性描述以此为准。
2. [Claude Code Customization Guide (2026): CLAUDE.md vs Skills vs Subagents — alexop.dev](https://alexop.dev/posts/claude-code-customization-guide-claudemd-skills-subagents/) — 选型决策框架，回答「何时用 Skill 而非 CLAUDE.md / 子 Agent」。
3. [The Complete Guide to Building Skills for Claude (Anthropic PDF)](https://resources.anthropic.com/hubfs/The-Complete-Guide-to-Building-Skill-for-Claude.pdf?hsLang=en) — Anthropic 官方构建完整指南，含规划、结构化与发布实践。
4. [Agent Skills 开放标准](https://agentskills.io) — Skill 跨工具通用规范，说明 `name + description + markdown` 的跨平台兼容性。
5. [Claude Code Skills: The Complete Guide (2026) — duet.so](https://duet.so/guides/claude-code-skills-complete-guide) — 第三方完整指南，补充 Skill 与命令合并、插件分发的工程化视角。

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