学习目标:掌握 Claude Code Skills 的完整开发流程——从理解 Skill 架构、编写 SKILL.md、打包测试到社区发布。读完本教程,你将独立创建一个功能完整、可分发、带测试验证的自定义 Skill,并深入理解 Skill 的触发机制、渐进加载与最佳实践。
适用人群:已安装 Claude Code CLI 并有基本使用经验的开发者,希望将重复性工作流封装为可复用的自动化指令包。
| 条件 | 说明 |
|---|---|
| Claude Code CLI | v2.1.145+(支持 /run-skill-generator、动态上下文注入等新特性) |
| Node.js 18+ | Claude Code 运行环境 |
| 基础终端操作 | mkdir、cat、文件编辑等 |
| Git | Skill 版本管理和发布的基础 |
| 一个 Git 仓库 | 用于实战演练 |
安装验证:
claude --version
# 确保输出 >= 2.1.145
在动手写代码之前,先理解 Skill 的工作原理。这是写出高质量 Skill 的基础。
Skill 不是插件,不是 MCP 服务器,也不是脚本。它是一份结构化指令文档,告诉 Claude 在特定场景下应该如何行动。核心文件只有一个:SKILL.md。
Skill 的运行机制遵循渐进加载(Progressive Disclosure)原则:
graph TD
A[用户输入 / 提问] --> B{Claude 检查可用 Skills 列表}
B -->|description 匹配| C[加载 Skill 元数据<br/>name + description ~100 tokens]
C --> D[读取 SKILL.md 正文<br/>执行指令]
D -->|需要参考文件| E[按需加载 references/<br/>scripts/ 等资源]
D -->|任务简单| F[直接执行并返回结果]
E --> G[使用完整资源完成任务]
F --> H[输出结果]
G --> H
style C fill:#22d3ee,stroke:#0e7490,color:#000
style D fill:#34d399,stroke:#047857,color:#000
style E fill:#a78bfa,stroke:#6d28d9,color:#fff
| 层级 | 内容 | 加载时机 | Token 成本 |
|---|---|---|---|
| 元数据层 | name + description | 始终在上下文中 | ~100 tokens(极低) |
| 指令层 | SKILL.md 正文 | Skill 被触发时 | 保持在上下文中直到会话结束 |
| 资源层 | references/、scripts/、assets/ | 按需读取 | 仅使用时产生开销 |
这个设计的核心优势:一个 2000 行的参考文档在 Skill 未被触发时零开销。
graph LR
subgraph 优先级从高到低
E[Enterprise<br/>企业管理配置]
P[Personal<br/>~/.claude/skills/]
R[Project<br/>.claude/skills/]
PL[Plugin<br/>插件内 skills/]
end
E --> P --> R --> PL
style E fill:#fb7185,stroke:#be123c,color:#fff
style P fill:#fbbf24,stroke:#92400e,color:#000
style R fill:#34d399,stroke:#047857,color:#000
style PL fill:#94a3b8,stroke:#334155,color:#fff
| 位置 | 路径 | 作用域 |
|---|---|---|
| 企业级 | 管理后台配置 | 全组织所有用户 |
| 个人级 | ~/.claude/skills/<skill-name>/SKILL.md |
你所有项目 |
| 项目级 | <project>/.claude/skills/<skill-name>/SKILL.md |
仅当前项目 |
| 插件级 | <plugin>/skills/<skill-name>/SKILL.md |
插件启用时 |
同名 Skill 的优先级:Enterprise > Personal > Project > Plugin。插件级 Skill 使用 plugin-name:skill-name 命名空间,不会冲突。
my-skill/
├── SKILL.md # 主指令文件(必须)
├── template.md # 模板文件(可选)
├── examples/
│ └── sample.md # 示例输出(可选)
├── scripts/
│ └── validate.sh # 可执行脚本(可选)
├── references/
│ ├── api-guide.md # 参考资料(可选)
│ └── best-practices.md
└── assets/
└── logo.svg # 静态资源(可选)
关键规则:只有 SKILL.md 是必须的,其他所有目录和文件都是可选的。
SKILL.md 由两部分组成:YAML 前置元数据(--- 包裹)和 Markdown 正文。
---
# === 基础字段 ===
name: my-skill # 显示名,省略则用目录名
description: | # 核心字段:Claude 据此判断是否触发
一句话说明做什么。触发词:X、Y、Z。
当用户需要 A、B、C 时使用此技能。
# === 触发控制 ===
when_to_use: | # 补充触发上下文(计入 1536 字符上限)
用户说"帮我部署"、"发布到生产"时触发。
disable-model-invocation: true # true = 禁止 Claude 自动触发,仅 /手动调用
user-invocable: true # false = 从 / 菜单隐藏(背景知识型)
# === 参数 ===
argument-hint: "[issue-number]" # 自动补全时显示的参数提示
arguments: "issue-number" # 命名参数,可在正文中用 $issue-number 引用
# === 执行控制 ===
context: fork # 在子 Agent 中运行(隔离上下文)
agent: general-purpose # 子 Agent 类型(需 context: fork)
model: claude-sonnet-4-6 # 指定运行模型
effort: high # 努力级别:low/medium/high/xhigh/max
allowed-tools: "Read Grep Bash" # 预授权工具列表
# === 路径过滤 ===
paths: "src/**/*.py,tests/**/*.py" # 仅在匹配路径时激活
# === 其他 ===
shell: bash # shell 类型(bash 或 powershell)
---
最关键的字段是 description——它是 Claude 决定是否触发 Skill 的唯一依据。字符上限 1536,每个字符都要精打细算。
在 SKILL.md 正文中,可以使用以下变量:
| 变量 | 说明 | 示例 |
|---|---|---|
$ARGUMENTS |
用户传入的全部参数 | /my-skill hello world → hello world |
$ARGUMENTS[0] / $0 |
第一个参数 | hello |
$ARGUMENTS[1] / $1 |
第二个参数 | world |
# frontmatter 中定义命名参数
arguments: "filename format"
<!-- 正文中使用 -->
处理文件 $filename,输出格式为 $format。
这是 Skill 最强大的特性之一——在 Skill 加载时执行命令并将输出嵌入到指令中:
## 当前变更
!\`git diff HEAD\`
## 当前分支
!\`git branch --show-current\`
## 文件列表
\`\`\`!
ls -la src/
\`\`\`
!command`` 形式:Claude Code 在加载 Skill 时执行命令,将输出替换到对应位置。这意味着 Skill 指令中包含的是实时数据,而非静态文本。
现在动手创建一个完整的 Skill:api-doc-gen——自动扫描代码中的 API 路由,生成标准化 API 文档。
| 需求项 | 说明 |
|---|---|
| 核心功能 | 扫描项目中的 API 路由定义,生成 Markdown 格式的 API 文档 |
| 支持框架 | Express.js、Fastify、Koa |
| 输出格式 | 带目录、分组的 Markdown 文件 |
| 触发方式 | /api-doc-gen 或自动识别 API 文档生成需求 |
| 附加功能 | 检测缺失的参数校验和安全标记 |
# 创建个人级 Skill
mkdir -p ~/.claude/skills/api-doc-gen/references
mkdir -p ~/.claude/skills/api-doc-gen/templates
---
name: api-doc-gen
description: |
扫描项目 API 路由并生成标准化 Markdown API 文档。
触发词:"生成 API 文档"、"API 文档"、"接口文档"、"接口文档生成"、"API reference"。
当用户需要生成、更新或审查 API 文档时使用此技能。
支持扫描 Express.js、Fastify、Koa 路由定义。
argument-hint: "[output-path]"
arguments: "output-path"
disable-model-invocation: false
---
接下来是正文部分:
# API 文档生成技能
## 角色定义
你是一位专业的 API 文档工程师。根据项目源代码中的路由定义,自动生成结构清晰、信息完整的 API 文档。
## 工作流程
### Step 1:识别框架
扫描项目的 `package.json`,判断使用的 Web 框架:
- 包含 `express` → Express.js 模式
- 包含 `fastify` → Fastify 模式
- 包含 `koa` / `@koa/router` → Koa 模式
- 无法识别 → 询问用户确认
### Step 2:发现路由文件
使用 Glob 查找路由定义文件:
- `src/routes/**/*.{js,ts}`
- `src/**/*route*.{js,ts}`
- `src/**/*controller*.{js,ts}`
- `app.{js,ts}`(根路由注册)
### Step 3:提取路由信息
对每个路由文件,提取以下信息:
1. HTTP 方法(GET/POST/PUT/DELETE/PATCH)
2. 路径(含路径参数,如 `/users/:id`)
3. 中间件链(认证、校验等)
4. 请求参数(query、body、params)
5. 响应格式(从 res.json 推断)
6. 描述注释(JSDoc @description 或行上注释)
### Step 4:生成文档
按照 `templates/api-doc-template.md` 的格式生成文档。
### Step 5:安全审查
在文档末尾附加安全审查清单:
- 标记缺少认证中间件的路由
- 标记缺少输入校验的 POST/PUT/PATCH 路由
- 标记可能存在 SQL 注入风险的查询拼接
## 输出路径
- 如果用户提供了 `$output-path`,保存到指定位置
- 否则保存到 `docs/api-reference.md`
## 参考资源
框架特定的路由模式识别规则,见 `references/framework-patterns.md`。
references/framework-patterns.md:
# 框架路由模式参考
## Express.js 路由模式
```javascript
// 模式 1:app 直接挂载
app.get('/users', handler)
app.post('/users', handler)
// 模式 2:Router 模块
const router = express.Router()
router.get('/:id', handler)
app.use('/users', router)
// 模式 3:路由文件导出
module.exports = (app) => {
app.route('/items')
.get(handler)
.post(handler)
}
// 模式 1:直接注册
fastify.get('/users', { schema: {...} }, handler)
// 模式 2:插件模式
module.exports = async (fastify) => {
fastify.post('/users', handler)
}
// @koa/router
const router = new Router()
router.get('/users', handler)
router.post('/users/:id', handler)
app.use(router.routes())
### 4.5 创建输出模板
`templates/api-doc-template.md`:
````markdown
# API Reference
> 自动生成于 {date} | 框架:{framework} | 路由总数:{count}
## 目录
- [认证](#authentication)
- {group-toc}
## 认证
{authentication-section}
---
{group-sections}
---
## 安全审查
| 路由 | 问题 | 严重程度 |
|------|------|----------|
| {security-findings} |
````
### 4.6 最终目录结构
api-doc-gen/ ├── SKILL.md # 主指令文件 ├── references/ │ └── framework-patterns.md # 框架路由识别模式 └── templates/ └── api-doc-template.md # 输出文档模板
---
## 五、测试与调试
### 5.1 即时生效机制
Claude Code 实时监控 Skill 目录变更。**创建或编辑 Skill 后无需重启**,下一个对话轮次即可生效。
```bash
# 创建 Skill 后直接测试
claude
# 在对话中输入:
> /api-doc-gen
# 或触发自动匹配:
> 帮我生成这个项目的 API 文档
flowchart LR
A[用户输入] --> B{包含 /skill-name?}
B -->|是| C[直接加载 SKILL.md<br/>100% 触发]
B -->|否| D{description 匹配?}
D -->|是| E[Claude 决定是否加载]
D -->|否| F[不触发]
E -->|任务复杂| G[加载并执行]
E -->|任务简单<br/>Claude 能独立完成| H[不加载<br/>直接用内置能力处理]
style C fill:#34d399,stroke:#047857,color:#000
style G fill:#34d399,stroke:#047857,color:#000
style H fill:#fbbf24,stroke:#92400e,color:#000
关键洞察:Claude 只在自身无法轻松完成任务时才咨询 Skill。简单的单步查询即使 description 完美匹配也不会触发。
如果 Skill 没有被触发,检查以下几点:
| 问题 | 排查方向 |
|---|---|
/ 菜单看不到 |
检查 user-invocable 是否为 false;检查目录名是否包含空格或特殊字符 |
| 不自动触发 | description 是否包含足够的触发词和场景描述?任务是否足够复杂? |
| 触发太频繁 | 添加更精确的 paths 限制或 disable-model-invocation: true |
| description 被截断 | 总长度(description + when_to_use)超过 1536 字符会被截断 |
对于耗时较长的任务,可以让 Skill 在独立的子 Agent 中运行:
---
name: deep-analysis
description: 深度代码分析,生成架构报告。
context: fork
agent: general-purpose
effort: high
---
context: fork 的效果:
- Skill 在独立子进程中运行
- 不消耗主对话上下文窗口
- 结果返回到主对话
可以为 Skill 绑定生命周期钩子,实现更精细的控制:
---
name: deploy-check
hooks:
PreToolUse:
- match: "Bash"
command: "echo 'Deploy skill activated'"
PostToolUse:
- match: "Bash"
command: "echo 'Command completed'"
---
---
name: quick-refactor
model: claude-sonnet-4-6 # 使用更快的模型
effort: low # 快速响应模式
allowed-tools: "Read Edit Grep Bash" # 预授权工具,无需逐一确认
---
allowed-tools 特别适合 CI/CD 集成场景——预授权工具后,Skill 执行过程中不会弹出权限确认。
---
name: python-style
paths: "src/**/*.py,tests/**/*.py,*.py"
---
设置 paths 后,只有当操作涉及匹配文件时 Skill 才会激活。这对于多语言项目中的语言专属 Skill 非常实用。
graph TB
subgraph "Claude Code 扩展体系"
SK[Skill<br/>指令文档]
MCP[MCP Server<br/>工具服务器]
SUB[Subagent<br/>独立 Agent]
CMD[CLAUDE.md<br/>项目配置]
end
SK -->|"复杂度低<br/>纯文本指令"| MCP
SK -->|"需要隔离<br/>可 fork 为"| SUB
CMD -->|"增长为流程<br/>可提取为"| SK
style SK fill:#fbbf24,stroke:#92400e,color:#000
style MCP fill:#a78bfa,stroke:#6d28d9,color:#fff
style SUB fill:#22d3ee,stroke:#0e7490,color:#000
style CMD fill:#94a3b8,stroke:#334155,color:#fff
| 维度 | Skill | MCP Server | Subagent | CLAUDE.md |
|---|---|---|---|---|
| 本质 | 文本指令 | 外部工具服务器 | 独立 Agent 进程 | 项目配置文件 |
| 复杂度 | 低(写 Markdown) | 中高(写服务器代码) | 低(配置 fork) | 低(写 Markdown) |
| Token 开销 | 按需加载 | 无(工具调用) | 隔离上下文 | 始终加载 |
| 适合场景 | 标准化流程、知识注入 | 外部 API 集成、数据获取 | 耗时任务、并行处理 | 项目约定和上下文 |
| 何时选用 | 重复性工作流、专家知识 | 需要外部工具能力 | 需要上下文隔离 | 项目级全局配置 |
选择决策树:如果一个流程在 CLAUDE.md 中已经很长(>50 行),且不是每次对话都需要,就适合提取为 Skill。如果需要调用外部 API 或操作外部系统,用 MCP。如果任务耗时且可以并行,用 Subagent。
.skill 文件使用 Anthropic 提供的打包工具:
# 如果有 skill-creator 插件
python -m scripts.package_skill ~/.claude/skills/api-doc-gen
# 输出:api-doc-gen.skill
.skill 文件是一个自包含的压缩包,包含整个 Skill 目录。
最常见的方式——将 Skill 放在 Git 仓库中,用户通过 --add-dir 引入:
# 克隆 Skill 仓库
git clone https://github.com/yourname/claude-skills ~/my-skills
# 启动 Claude Code 时引入
claude --add-dir ~/my-skills
--add-dir 目录下的 .claude/skills/ 会被自动发现和加载。
对于高质量的 Skill,可以封装为 Claude Code 插件:
package.json 中声明 claude-code 插件元数据skills/ 目录下通过企业管理控制台统一配置,推送给组织内所有用户:
多个 Skill 可以协同工作——一个 Skill 的输出触发另一个 Skill:
sequenceDiagram
participant U as 用户
participant C as Claude Code
participant S1 as Skill A: 代码扫描
participant S2 as Skill B: 报告生成
U->>C: /scan-and-report src/
C->>S1: 触发代码扫描 Skill
S1->>S1: 扫描路由、依赖、安全风险
S1-->>C: 返回结构化分析数据
C->>S2: 触发报告生成 Skill
S2->>S2: 将分析数据格式化为 HTML 报告
S2-->>C: 输出 report.html
C-->>U: 扫描完成,报告已生成
Skill 提供指令和流程,MCP 提供工具能力:
Skill (指令) → "调用 GitHub MCP 获取 PR 列表" → MCP Server (执行) → 结果返回 → Skill 继续处理
将大型参考文档按领域拆分到 references/ 下,Skill 正文保持精简:
<!-- SKILL.md 正文 -->
## 框架特定规则
读取 `references/express.md` 获取 Express.js 路由模式。
读取 `references/fastify.md` 获取 Fastify 路由模式。
仅在使用对应框架时才读取相应文件。
这样做的好处:只有实际需要的参考文件才被加载到上下文中,大幅节省 Token。
description 是触发机制的唯一依据,必须精心编写:
# 差:过于宽泛
description: "Helps with API documentation."
# 好:具体且有触发词
description: |
扫描项目源代码中的 API 路由定义,自动生成标准化 Markdown API 文档。
触发词:"生成 API 文档"、"接口文档"、"API reference"、"文档化接口"。
当用户提到 API 文档、接口文档、路由文档时使用。
支持识别 Express.js、Fastify、Koa 框架路由。
关键技巧: - 首句说明做什么 - 包含用户可能使用的各种表达方式(中文/英文/缩写) - description 稍微"强势"一些——宁可多触发也不要漏触发
每多一行,就在每次触发时多消耗 Token。遵循以下策略:
- 核心流程写在 SKILL.md 正文中
- 详细参考放在 references/ 下按需加载
- 模板放在 templates/ 下
# 差:命令式
MUST scan all files. MUST use Express pattern. MUST check security.
# 好:解释原因
扫描所有路由文件以确保文档完整性——遗漏的路由意味着消费者无法发现该接口。
优先识别 Express 模式因为这是项目的主要框架。
安全审查帮助团队在部署前发现潜在风险。
LLM 足够聪明——解释背后的原因比堆砌强制性指令更有效。
# 实时获取当前状态
!\`git diff HEAD --name-only\`
!\`cat package.json | grep -E "express|fastify|koa"\`
# 根据实时数据决策,而非让 Claude 去猜
如果多个测试用例中 Claude 都独立编写了类似的辅助脚本(如解析路由、格式化输出),这就是信号——应该将脚本提取到 scripts/ 目录中预置。
按以下步骤操作,你将拥有一个可运行的 Skill:
graph TD
A["1. mkdir -p ~/.claude/skills/api-doc-gen"] --> B["2. 编写 SKILL.md"]
B --> C["3. 创建 references/ 参考文件"]
C --> D["4. 创建 templates/ 模板文件"]
D --> E["5. 在任意 Express 项目中测试"]
E --> F["6. 输入 /api-doc-gen 触发"]
F --> G["7. 检查生成的 docs/api-reference.md"]
G --> H["8. 迭代优化 description 触发词"]
H --> I["9. 添加路径过滤 paths 字段"]
I --> J["10. 打包发布"]
style A fill:#22d3ee,stroke:#0e7490,color:#000
style F fill:#fbbf24,stroke:#92400e,color:#000
style J fill:#34d399,stroke:#047857,color:#000
| 步骤 | 命令 | 验证 |
|---|---|---|
| 1. 创建目录 | mkdir -p ~/.claude/skills/api-doc-gen/{references,templates} |
ls ~/.claude/skills/api-doc-gen/ |
| 2. 编写 SKILL.md | 按第四节内容创建文件 | 文件存在且 YAML 格式正确 |
| 3. 添加参考文件 | 创建 references/framework-patterns.md |
文件存在 |
| 4. 添加模板 | 创建 templates/api-doc-template.md |
文件存在 |
| 5. 测试 | 在 Express 项目中运行 claude |
输入 /api-doc-gen 能触发 |
| 6. 自动触发测试 | 输入"帮我生成 API 文档" | 无需 / 前缀即可触发 |
| 7. 输出验证 | 检查生成的 Markdown | 包含路由列表、安全审查 |
| 8. 迭代 | 调整 description 触发词 | 非相关提问不触发 |
/ 菜单看不到原因:目录名或 name 字段包含大写字母、空格或特殊字符。
解决:目录名只使用小写字母、数字和连字符。
原因:description 不够具体,或任务太简单 Claude 认为自己能处理。
解决:
1. 在 description 中增加更多触发场景和同义词
2. 让 description 更"强势"——明确列出应该触发的场景
3. 如果是 CI/CD 场景,考虑使用 claude -p 管道模式直接调用
原因:description 过于宽泛,匹配了不该匹配的场景。
解决:
1. 添加 paths 字段限制激活范围
2. 设置 disable-model-invocation: true 改为纯手动触发
3. 缩小 description 的覆盖面
原因:SKILL.md 正文过长,或参考文件被无条件加载。
解决:
1. SKILL.md 控制在 500 行以内
2. 大型参考文档放在 references/ 下,正文中明确说明"仅在需要时读取"
3. 使用 context: fork 在子 Agent 中运行
.claude/commands/ 怎么办.claude/commands/ 中的命令继续正常工作,与 Skill 共享 / 命名空间。如果同名,Skill 优先。建议逐步迁移到 Skill 格式以获得更多功能(目录支持、frontmatter 控制等)。
| 维度 | 评估 |
|---|---|
| 适合训练营类型 | AI 工具链训练营、开发效能提升营、团队标准化训练营 |
| 预计教学时长 | 2-3 小时(含动手实操) |
| 难度级别 | 中级(需 Claude Code 基础使用经验) |
| 实操占比 | 70%(核心是动手创建和调试 Skill) |
| 交付物 | 每人完成一个可运行的自定义 Skill |
| 建议分组 | 按技术栈分组(前端/后端/DevOps),各组创建不同领域的 Skill |
| 扩展任务 | 将 Skill 打包为插件发布、创建团队共享 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 等场景全覆盖。
