<!-- title: 造依赖体检Skill秒出漏洞升级榜 -->

# 造依赖体检Skill：从零搭一个会扫漏洞的私有能力

## 概述

本教程带你从零开发一个名为 `dep-checker` 的 Claude Code 自定义 Skill。它会扫描项目里的依赖清单（`package.json` / `requirements.txt` / `go.mod`），一键产出"过期依赖 + 已知漏洞 + 推荐升级版本"的报告。学完你能掌握 Skill 的完整解剖结构、frontmatter 16 个字段的核心用法、渐进式披露（progressive disclosure）设计、捆绑脚本技巧以及三种安装作用域。适合已经能跑通 Claude Code、想把重复工作固化成可复用能力的开发者，预计动手时长 90 分钟。

## 前置条件

- Claude Code 已安装并跑通过至少一个项目（CLI 版本建议 2025 年 6 月之后的发行版）
- 一台装了 Node.js（含 `npm`）或 Python（含 `pip`）或 Go 的机器，用于跑依赖审计命令
- 一个真实的测试仓库，里面至少有一个 `package.json`、`requirements.txt` 或 `go.mod`
- 会用命令行创建目录、写文件、看 diff

## 正文

### 步骤一：先搞懂一个 Skill 到底由什么组成

Skill 不是一段魔法，它就是一个**约定好结构的目录**。Claude Code 启动时会扫描特定路径下的目录，只要里面有 `SKILL.md`，就把它注册成一个能力。最小化结构如下：

```
dep-checker/
├── SKILL.md            # 必须 — 机器可读的指令，是 Skill 的"大脑"
├── scripts/
│   └── audit.sh        # 可选 — 捆绑的可执行脚本，干脏活累活
└── references/
    └── severity.md     # 可选 — 参考数据，按需加载，省 token
```

三个层级的职责要分清：

- **SKILL.md**：永远只放"做什么、怎么做"的指令，以及一段告诉 Claude 何时触发自己的 `description`。
- **scripts/**：把确定性的、容易出错的逻辑（比如调 `npm audit --json`、解析 JSON、按严重度排序）固化成脚本。Claude 调脚本比让模型自己一行行推理稳得多，也省 token。
- **references/**：放参考资料。关键设计是**按需加载**——只有当 SKILL.md 正文里显式说"去看 `references/severity.md`"时，Claude 才会在需要时读它。这就是渐进式披露：默认只把 SKILL.md 塞进上下文，详情懒加载。

> 一句话记忆：**frontmatter 决定"何时上桌"，正文决定"怎么做菜"，scripts 负责"切菜"，references 是"菜谱附录"**。

### 步骤二：规划 dep-checker 的能力边界

动手前先把范围圈死，否则 Skill 会越写越臃肿。我们定三条边界：

1. **输入**：项目根目录，自动识别依赖清单类型（npm / pip / go 三选一）。
2. **处理**：调用对应审计工具拉取漏洞数据，再比对最新版本算出"过期清单"。
3. **输出**：一份 Markdown 表格报告，按"严重 > 高 > 中 > 低"排序，每条给出当前版本、修复版本、升级命令。

不做的事也要写进文档：不自动改 lock 文件、不提交 PR、不联网下载补丁包。这些约束会写进 SKILL.md 的"禁止行为"段，防止模型自作主张。

### 步骤三：搭目录骨架

在个人技能目录下建结构。个人目录路径是 `~/.claude/skills/`：

```bash
mkdir -p ~/.claude/skills/dep-checker/scripts
mkdir -p ~/.claude/skills/dep-checker/references
touch ~/.claude/skills/dep-checker/SKILL.md
```

命名规范要遵守：目录名和 frontmatter 的 `name` 字段一律 kebab-case（连字符小写），脚本用 snake_case，参考文件也用 kebab-case 加 `.md`。这套约定保证 Claude 能稳定地按名引用。

### 步骤四：写 frontmatter——这是触发器的总开关

`SKILL.md` 顶部是一段 YAML frontmatter，用 `---` 包起来。官方支持的字段比网上老教程多得多，下面这张表是 dep-checker 会用到的核心字段：

| 字段 | 必填 | dep-checker 的取值与理由 |
|------|------|--------------------------|
| `name` | 否（默认取目录名） | `dep-checker`，显式写更稳 |
| `description` | 推荐 | 触发判定的唯一依据，必须写清"做什么 + 何时用" |
| `argument-hint` | 否 | `[项目路径]`，自动补全时提示用户可传参 |
| `allowed-tools` | 否 | `Read Bash Grep`，限定本 Skill 只能用这三个工具 |
| `disallowed-tools` | 否 | `Write Edit`，明确禁止改文件，做安全围栏 |
| `disable-model-invocation` | 否 | `false`，我们希望它能被自动触发 |
| `paths` | 否 | `**/package.json, **/requirements.txt, **/go.mod`，只在有依赖清单时才激活 |

完整的官方字段还有 `arguments`（命名位置参数）、`user-invocable`（是否能用 `/` 触发）、`model`（临时切模型）、`effort`（思考强度）、`context`、`agent`（委托子代理）、`hooks`（绑定生命周期钩子）、`shell`、`metadata` 等，日常用上面七个足够。

写法如下：

```yaml
---
name: dep-checker
description: 扫描项目的依赖清单（package.json / requirements.txt / go.mod），跑依赖审计并产出按严重度排序的漏洞与过期依赖升级报告。当用户提到"依赖体检""查漏洞""依赖是不是过期""supply chain""npm audit""pip-audit""govulncheck""升级依赖"时使用。
argument-hint: "[可选：项目路径，默认当前目录]"
allowed-tools: Read Bash Grep
disallowed-tools: Write Edit
paths: "**/package.json, **/requirements.txt, **/go.mod"
---
```

`description` 是整个 Skill 最值钱的一行，三条写法原则：

1. **先写能力，再写触发词**：模型先理解"这玩意能干嘛"，再匹配关键词。
2. **塞具体动词和名词**：写"扫描依赖清单跑审计出报告"，别写"帮助处理依赖问题"。
3. **列举同义触发词**：把用户可能说的中英文说法都列上，命中率明显提升。

### 步骤五：写正文指令——给模型一份可执行的菜谱

frontmatter 之下就是正文。最佳实践是"角色 → 输入 → 步骤 → 输出 → 错误处理"五段式。下面是 dep-checker 的正文骨架：

```markdown
你是一名依赖供应链安全专家，擅长审计 Node / Python / Go 项目的第三方依赖。

## 输入
- 用户可传入项目路径，省略时默认为当前工作目录。
- 调用 `Glob` 探测存在哪些依赖清单。

## 处理流程
1. 探测清单类型：有 package.json 走 npm 分支；有 requirements.txt 走 pip 分支；有 go.mod 走 go 分支。可多选。
2. 对每个分支，调用捆绑脚本 `scripts/audit.sh <type>` 拿到结构化结果。不要自己逐行推理漏洞。
3. 若想判断严重度分级标准，按需读取 `references/severity.md`（不要一开始就加载）。
4. 把脚本输出的 JSON 汇总成人类可读的表格。

## 输出格式
输出一段 Markdown，包含三张表：
- 漏洞清单（按 Critical/High/Medium/Low 排序，列：包名、当前版本、修复版本、CVE、升级命令）
- 过期依赖清单（列：包名、当前版本、最新版本、落后主版本数）
- 一句行动建议（先升哪个、有哪些破坏性升级风险）

## 禁止行为
- 绝不修改 package.json / lock 文件 / requirements.txt / go.mod。
- 绝不运行 `npm install` / `pip install` 之外会改变环境的命令。
- 发现高危漏洞时只报告，不自动打补丁。
```

注意第 2 步那句"不要自己逐行推理漏洞"——这是刻意写的**反模式刹车**。模型很喜欢自己脑补 CVE，但漏洞数据每天都在变，必须让脚本去拉实时数据。

### 步骤六：捆绑 audit 脚本——这是 Skill 真正的肌肉

`scripts/audit.sh` 负责所有不确定性高、容易出错的工作。它接收一个类型参数，调对应工具，吐 JSON：

```bash
#!/usr/bin/env bash
# scripts/audit.sh — 依赖审计统一入口
set -euo pipefail
TYPE="${1:-}"
ROOT="${2:-.}"

case "$TYPE" in
  npm)
    cd "$ROOT"
    # 过期依赖：outdated 转 JSON；漏洞：audit 转 JSON
    npm outdated --json 2>/dev/null > /tmp/dc_outdated.json || true
    npm audit --json 2>/dev/null > /tmp/dc_audit.json || true
    echo "{\"type\":\"npm\",\"outdated\":$(cat /tmp/dc_outdated.json),\"audit\":$(cat /tmp/dc_audit.json)}"
    ;;
  pip)
    # 优先用 pip-audit，没有则提示
    if ! command -v pip-audit >/dev/null 2>&1; then
      echo "{\"type\":\"pip\",\"error\":\"pip-audit 未安装，请运行 pip install pip-audit\"}"
      exit 0
    fi
    pip-audit -r "$ROOT/requirements.txt" -f json 2>/dev/null || echo "{\"type\":\"pip\",\"error\":\"审计失败\"}"
    ;;
  go)
    if ! command -v govulncheck >/dev/null 2>&1; then
      echo "{\"type\":\"go\",\"error\":\"govulncheck 未安装，请运行 go install golang.org/x/vuln/cmd/govulncheck@latest\"}"
      exit 0
    fi
    (cd "$ROOT" && govulncheck -json ./... 2>/dev/null) || echo "{\"type\":\"go\",\"error\":\"审计失败\"}"
    ;;
  *)
    echo "{\"error\":\"未知类型 $TYPE，支持 npm/pip/go\"}"
    exit 1
    ;;
esac
```

为什么一定要把逻辑放进脚本而不是写在正文里让模型执行？四个理由：

1. **可复现**：脚本每次行为一致，模型推理每次都可能飘。
2. **省 token**：一行 `bash scripts/audit.sh npm` 顶替几十行工具调用。
3. **好测试**：脚本能脱离 Claude 单独跑、单独写单测。
4. **好升级**：换底层工具（比如 npm audit 改用 `osv-scanner`）只改脚本，SKILL.md 一字不动。

记得给脚本加可执行权限：`chmod +x ~/.claude/skills/dep-checker/scripts/audit.sh`。

### 步骤七：参考数据按需加载

`references/severity.md` 放严重度分级标准，SKILL.md 正文只在需要判级时才引用它：

```markdown
# 漏洞严重度分级速查

- **Critical**：远程代码执行、认证绕过、可直接拿 shell。当天必须修。
- **High**：敏感信息泄露、权限提升、可导致数据被改。本周内修。
- **Medium**：需要特定条件触发的漏洞、DoS。排进迭代。
- **Low**：信息泄露有限、影响面小。可批量处理。
```

这正是渐进式披露的体现：Claude 默认只加载 SKILL.md（几十行），遇到判级需求才把这份附录拉进上下文。一个 Skill 越复杂，省下的 token 越可观。

### 步骤八：安装与三种作用域

Skill 有三种摆放位置，决定了它的可见范围：

| 作用域 | 路径 | 谁能用 |
|--------|------|--------|
| 个人 | `~/.claude/skills/dep-checker/` | 只有你这台机器上的所有项目 |
| 项目 | `<repo>/.claude/skills/dep-checker/` | 任何 clone 这个仓库的人（提交进 Git 即团队共享） |
| 插件 | 通过 plugin marketplace 分发 | 所有装了该插件的用户 |

个人级适合放你自己的私有习惯；项目级适合团队对齐（比如"全组都用这套依赖体检流程"），记得把目录提交进仓库；插件级适合做成产品分发。dep-checker 这种和项目强相关的，**推荐放项目级**，跟着仓库走。

放好后无需重启——Claude Code 会在下个会话自动发现。用 `/help` 或在对话里说"列出我的 skills"可以确认是否注册成功。

### 步骤九：测试与调试三连

新 Skill 最容易翻车的不是写错代码，而是**触发不了**或**乱触发**。三步排查：

1. **显式触发**：直接打 `/dep-checker`（因为 `user-invocable` 默认开），看流程能否跑通。
2. **隐式触发**：换个说法，比如"帮我看看这个项目的依赖有没有过期"，看模型会不会自动调用。不中就回去打磨 `description` 的触发词。
3. **对比测试**：同一个项目，分别在"有 Skill"和"禁用 Skill"（加 `disable-model-invocation: true` 临时关自动触发）下跑一遍，对比报告质量。

常见问题速查：

- **不触发**：`description` 太抽象。改成"动词 + 对象 + 何时用"。
- **乱触发**：`description` 关键词太宽（比如写了"检查"）。收窄触发词，或加 `paths` 限制文件条件。
- **脚本权限错**：忘了 `chmod +x`，或 Windows 下没装 bash。
- **结果飘**：模型没调脚本自己在编。检查正文是否写了"必须调用 scripts/audit.sh"。

## 实战案例：在一个老 React 项目上跑通

准备一个真实的 `package.json`，故意留两个过期包和一个已知漏洞依赖，例如：

```json
{
  "name": "demo-app",
  "dependencies": {
    "lodash": "4.17.4",
    "axios": "0.18.0",
    "react": "17.0.0"
  }
}
```

在项目根目录启动 Claude Code，输入：

> 帮我体检这个项目的依赖，看看有没有过期和漏洞。

预期行为：Claude 探测到 `package.json` → 触发 dep-checker → 调 `scripts/audit.sh npm` → 把 JSON 汇总成报告。输出大致长这样：

```markdown
## 依赖体检报告

### 漏洞清单（按严重度）
| 包名 | 当前版本 | 修复版本 | 严重度 | 建议 |
|------|----------|----------|--------|------|
| lodash | 4.17.4 | 4.17.21 | High | `npm i lodash@4.17.21` |
| axios | 0.18.0 | 1.7.x | Critical | 主版本升级，注意 API 变更 |

### 过期依赖清单
| 包名 | 当前版本 | 最新版本 | 落后主版本 |
|------|----------|----------|------------|
| react | 17.0.0 | 19.x | 2 |

### 行动建议
先升 lodash（同版本内修复，零风险），再评估 axios 主版本升级的破坏性，react 跨两个大版本需配合迁移指南。
```

整个过程你只说了一句话——这就是把重复劳动固化成 Skill 的回报。

## 工作流程图

```mermaid
flowchart TD
    A[用户：体检依赖] --> B{Claude 扫描 skills}
    B -->|description 命中| C[加载 dep-checker 的 SKILL.md]
    C --> D[Glob 探测清单类型]
    D --> E{哪种清单?}
    E -->|package.json| F1[调 audit.sh npm]
    E -->|requirements.txt| F2[调 audit.sh pip]
    E -->|go.mod| F3[调 audit.sh go]
    F1 --> G[拿回 JSON]
    F2 --> G
    F3 --> G
    G --> H{需要判级?}
    H -->|是| I[懒加载 references/severity.md]
    H -->|否| J[汇总成 Markdown 报告]
    I --> J
    J --> K[输出表格 + 行动建议]
```

Skill 自身的目录结构与加载层级：

```mermaid
graph LR
    L1[~/.claude/skills/dep-checker/] --> L2[SKILL.md 默认全量加载]
    L1 --> L3[scripts/audit.sh 按需调用]
    L1 --> L4[references/severity.md 按需懒加载]
    L2 -.frontmatter.-> L5[name / description / allowed-tools / paths]
    L2 -.正文.-> L6[角色 / 流程 / 输出 / 禁止行为]
```

## 常见问题与排坑

- **Skill 注册了但 `/dep-checker` 没反应**：确认 `SKILL.md` 的 frontmatter 没有语法错（`---` 必须独占一行、YAML 缩进一致）。官方文档明确：frontmatter 损坏时 Claude 会以空元数据加载，`/skill-name` 仍能用但触发判定失效。
- **想让它只在某些项目生效**：用 `paths` 字段限定，比如 `**/package.json`，没有依赖清单的项目根本不会激活它。
- **担心它乱改文件**：`disallowed-tools: Write Edit` 是硬围栏，模型在 Skill 激活期间拿不到这两个工具。
- **想做只读巡检、绝不自动跑**：加 `disable-model-invocation: true`，强制只能由人手动 `/dep-checker` 触发，避免在 CI 里被自动调起。
- **多人协作要共享**：把 `dep-checker/` 整个目录提交到仓库的 `.claude/skills/` 下，队友 pull 下来即用。

## 延伸阅读

- 把 Skill 打包成插件分发，走 plugin marketplace：官方《Create plugins》文档
- 用 `skill-creator` 插件半自动生成骨架并跑触发率评测
- 给 Skill 绑定 `hooks`，在审计前后自动跑格式化或告警
- 用 `agent` 字段把审计委托给专门的只读子代理，进一步隔离权限

## 参考来源

1. [Extend Claude with skills — Claude Code Docs](https://code.claude.com/docs/en/skills) — 官方权威，涵盖 frontmatter 全字段、三种作用域与渐进式披露机制
2. [Skill Anatomy — claude-code-skills](https://github.com/Rushik-Ghuntala/claude-code-skills/blob/main/docs/skill-anatomy.md) — 社区整理的目录结构与命名规范速查，含字段对照表
3. [Claude Code Skill Frontmatter: Every YAML Option Explained](https://allahabadi.dev/blogs/ai/claude-code-skills-frontmatter-complete-guide/) — 逐字段拆解 name/description/allowed-tools/disable-model-invocation 的实战含义
4. [Claude Code Skills: The Complete Guide (2026)](https://designrevision.com/blog/claude-code-skills) — 含"有/无 Skill 对比测试"与 skill-creator 评测流程
5. [How to Install Skills in Claude Code: 3 Methods](https://dev.to/samuel_rose_b30991db2b25b/how-to-install-skills-in-claude-code-3-methods-2ofl) — 个人级 / 项目级 / 插件级三种安装路径与取舍

## 训练营适用性评估

- **适合的训练营类型**：面向在职开发者的"工程效能"或"AI 辅助开发"中级训练营；也适合企业内部平台团队做 Skill 体系建设的入门实操课。
- **不适合**：完全零基础的"AI 启蒙"营（需要先跑通过 Claude Code 基础流程）；纯算法/数据结构营（与主题无关）。
- **预计教学时长**：讲授 30 分钟 + 动手 60 分钟 = 90 分钟一个完整模块。建议作为"Skill 开发"系列的第一课，后续可衔接"打包成插件""绑定 hooks""子代理委派"三节进阶课。
- **考核点**：学员能独立产出一个触发率达标（隐式触发命中 ≥ 80%）、带捆绑脚本、有安全围栏（`disallowed-tools`）的可用 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)
