本教程带你从零开发一个名为 dep-checker 的 Claude Code 自定义 Skill。它会扫描项目里的依赖清单(package.json / requirements.txt / go.mod),一键产出"过期依赖 + 已知漏洞 + 推荐升级版本"的报告。学完你能掌握 Skill 的完整解剖结构、frontmatter 16 个字段的核心用法、渐进式披露(progressive disclosure)设计、捆绑脚本技巧以及三种安装作用域。适合已经能跑通 Claude Code、想把重复工作固化成可复用能力的开发者,预计动手时长 90 分钟。
npm)或 Python(含 pip)或 Go 的机器,用于跑依赖审计命令package.json、requirements.txt 或 go.modSkill 不是一段魔法,它就是一个约定好结构的目录。Claude Code 启动时会扫描特定路径下的目录,只要里面有 SKILL.md,就把它注册成一个能力。最小化结构如下:
dep-checker/
├── SKILL.md # 必须 — 机器可读的指令,是 Skill 的"大脑"
├── scripts/
│ └── audit.sh # 可选 — 捆绑的可执行脚本,干脏活累活
└── references/
└── severity.md # 可选 — 参考数据,按需加载,省 token
三个层级的职责要分清:
description。npm audit --json、解析 JSON、按严重度排序)固化成脚本。Claude 调脚本比让模型自己一行行推理稳得多,也省 token。references/severity.md"时,Claude 才会在需要时读它。这就是渐进式披露:默认只把 SKILL.md 塞进上下文,详情懒加载。一句话记忆:frontmatter 决定"何时上桌",正文决定"怎么做菜",scripts 负责"切菜",references 是"菜谱附录"。
动手前先把范围圈死,否则 Skill 会越写越臃肿。我们定三条边界:
不做的事也要写进文档:不自动改 lock 文件、不提交 PR、不联网下载补丁包。这些约束会写进 SKILL.md 的"禁止行为"段,防止模型自作主张。
在个人技能目录下建结构。个人目录路径是 ~/.claude/skills/:
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 能稳定地按名引用。
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 等,日常用上面七个足够。
写法如下:
---
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 最值钱的一行,三条写法原则:
frontmatter 之下就是正文。最佳实践是"角色 → 输入 → 步骤 → 输出 → 错误处理"五段式。下面是 dep-checker 的正文骨架:
你是一名依赖供应链安全专家,擅长审计 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,但漏洞数据每天都在变,必须让脚本去拉实时数据。
scripts/audit.sh 负责所有不确定性高、容易出错的工作。它接收一个类型参数,调对应工具,吐 JSON:
#!/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
为什么一定要把逻辑放进脚本而不是写在正文里让模型执行?四个理由:
bash scripts/audit.sh npm 顶替几十行工具调用。osv-scanner)只改脚本,SKILL.md 一字不动。记得给脚本加可执行权限:chmod +x ~/.claude/skills/dep-checker/scripts/audit.sh。
references/severity.md 放严重度分级标准,SKILL.md 正文只在需要判级时才引用它:
# 漏洞严重度分级速查
- **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 最容易翻车的不是写错代码,而是触发不了或乱触发。三步排查:
/dep-checker(因为 user-invocable 默认开),看流程能否跑通。description 的触发词。disable-model-invocation: true 临时关自动触发)下跑一遍,对比报告质量。常见问题速查:
description 太抽象。改成"动词 + 对象 + 何时用"。description 关键词太宽(比如写了"检查")。收窄触发词,或加 paths 限制文件条件。chmod +x,或 Windows 下没装 bash。准备一个真实的 package.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 汇总成报告。输出大致长这样:
## 依赖体检报告
### 漏洞清单(按严重度)
| 包名 | 当前版本 | 修复版本 | 严重度 | 建议 |
|------|----------|----------|--------|------|
| lodash | 4.17.4 | 4.17.21 | High | `npm i [email protected]` |
| axios | 0.18.0 | 1.7.x | Critical | 主版本升级,注意 API 变更 |
### 过期依赖清单
| 包名 | 当前版本 | 最新版本 | 落后主版本 |
|------|----------|----------|------------|
| react | 17.0.0 | 19.x | 2 |
### 行动建议
先升 lodash(同版本内修复,零风险),再评估 axios 主版本升级的破坏性,react 跨两个大版本需配合迁移指南。
整个过程你只说了一句话——这就是把重复劳动固化成 Skill 的回报。
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 自身的目录结构与加载层级:
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[角色 / 流程 / 输出 / 禁止行为]
/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-creator 插件半自动生成骨架并跑触发率评测hooks,在审计前后自动跑格式化或告警agent 字段把审计委托给专门的只读子代理,进一步隔离权限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 等场景全覆盖。
