<!-- title: 造接口契约Skill：扫路由秒出文档 -->

## 概述

本教程带你从零亲手打造一个名为 `api-contract-doc` 的 Claude Code Skill——它能扫描项目里的路由/控制器代码，自动反向工程出一份符合 OpenAPI 3.0 规范的接口契约文档。通过这个实战案例，你将掌握 Skill 的底层机制（目录结构、SKILL.md、渐进式披露、脚本挂载）、`skill-creator` 加速器、frontmatter 的触发调优，以及调试发布全流程。适合已跑通 Claude Code、想让 AI 按团队规范重复执行复杂任务的后端开发者与工程效率工程师。

## 前置条件

- 已安装并跑通 Claude Code（能在终端执行 `claude` 进入会话）
- 一台装了 Node.js 18+ 的机器（实战案例的扫描脚本用 Node 写）
- 一个带 HTTP 路由的测试项目（Express / Koa / Fastify 任一即可，没有也行，本教程会给出示例代码）
- 基础的命令行与 Markdown 常识

## Step 1：先把 Skill 的本质看透

很多人把 Skill 想得很神秘，其实它就是一个**带约定结构的文件夹**。Claude Code 启动时会把三个位置的 Skill 注册进会话：

| 级别 | 路径 | 适用场景 |
|------|------|----------|
| 个人级 | `~/.claude/skills/<name>/SKILL.md` | 跨项目复用，比如你的 commit 规范 |
| 项目级 | `<project>/.claude/skills/<name>/SKILL.md` | 团队共享，随仓库走 |
| 插件级 | 通过 plugin marketplace 安装 | 第三方能力 |

一个 Skill 的标准目录长这样：

```
api-contract-doc/
├── SKILL.md              # 唯一必需：入口文件
├── scripts/              # 可选：可执行脚本
│   └── extract-endpoints.js
└── reference/            # 可选：按需加载的详细资料
    ├── openapi-conventions.md
    └── team-api-style.md
```

**核心机制是"渐进式披露"（Progressive Disclosure）**：Claude 启动时只读取每个 Skill 的 `SKILL.md`（理想控制在 500 行以内），把 token 成本压到最低；只有当判断出某个 Skill 与当前任务相关、且需要更深细节时，才会去 `Read` reference 子目录里的文件。这就是为什么你能塞进几千行规范文档而不爆上下文。

```mermaid
flowchart TD
    A[Claude Code 启动] --> B[扫描三个位置的 skills 目录]
    B --> C[只读每个 SKILL.md 的<br/>frontmatter + 正文摘要]
    C --> D{当前任务是否匹配某 Skill?}
    D -->|否| E[跳过该 Skill 不占上下文]
    D -->|是| F[加载完整 SKILL.md 正文]
    F --> G{需要更深细节?}
    G -->|是| H[按需 Read reference 文件]
    G -->|需要执行确定性操作| I[Bash 调用 scripts 脚本]
    H --> J[按规范产出结果]
    I --> J
```

## Step 2：用 skill-creator 一键生成骨架（对比手工）

Claude Code 自带一个 `skill-creator` 官方 Skill，专门帮你生产新 Skill。两种起步方式：

**方式 A：加速器（推荐新手）**

直接在会话里说：

```
/skill-creator 帮我创建一个叫 api-contract-doc 的 skill，
功能是扫描项目路由代码生成 OpenAPI 3.0 接口文档
```

`skill-creator` 会问你几个澄清问题，然后自动生成目录结构、frontmatter 草稿和正文框架。它的价值在于保证文件结构、字段名符合规范，免去查文档。

**方式 B：纯手工（本教程采用，便于讲透每一处）**

```bash
mkdir -p ~/.claude/skills/api-contract-doc/scripts
mkdir -p ~/.claude/skills/api-contract-doc/reference
touch ~/.claude/skills/api-contract-doc/SKILL.md
```

手工的好处是你完全掌控每一行。下面的步骤都基于手工方式推进。

## Step 3：写 frontmatter——Skill 的"命门"

`SKILL.md` 顶部是一段 YAML frontmatter，用 `---` 包裹。其中**只有 `description` 决定 Skill 会不会被触发**，这是新手最容易踩的坑。

```yaml
---
name: api-contract-doc
description: 扫描项目路由或控制器源码，反向工程生成符合 OpenAPI 3.0 规范的接口契约文档（YAML/JSON）。当用户要"生成接口文档""出 API 文档""补接口说明""把代码转成 OpenAPI/Swagger""整理接口契约"时使用。支持 Express/Koa/Fastify 风格路由。
---
```

编写 `description` 的三条铁律：

1. **第一句写"做什么"**：让 Claude 在做意图匹配时有清晰锚点。
2. **铺满触发关键词**：把用户真实会说出口的词都塞进去——"生成接口文档""API 文档""OpenAPI""Swagger""接口契约"。Claude 靠语义相似度判断，关键词越准召回越高。
3. **点明适用范围**：列出支持的框架（Express/Koa/Fastify），既帮召回，也防止跨语言误触发。

> **常见问题**：Skill 写好却从不自动触发？99% 是 `description` 没写出用户嘴里的词。改 description，不需要重启，下一次会话即生效。

可选字段还有 `allowed-tools`（限制该 Skill 只能用哪些工具，如 `Read, Bash`）、`version`。本案例暂不限制，让 Claude 自由组合工具。

## Step 4：写正文——把"专家心法"写成可执行流程

frontmatter 负责"何时用"，正文负责"怎么用"。正文要写得像给一个聪明但不了解你项目的新同事的操作手册：明确步骤、明确分支、明确产出格式。

```markdown
# 接口契约文档生成

## 何时使用
当用户希望从现有路由/控制器代码反向生成接口文档时激活本 Skill。

## 工作流程

1. **定位路由**：先用 Grep/Glob 找到项目的路由定义文件。
   - Express：搜索 `app\.(get|post|put|delete|patch)\(` 或 `router\.(get|post)`
   - Koa：搜索 `router\.(get|post)` 或 `\.ctx\.`
   - 若用户指定了目录，优先扫该目录。

2. **粗扫出端点清单**：调用本 Skill 的脚本生成机器可读草稿：
   ```bash
   node ~/.claude/skills/api-contract-doc/scripts/extract-endpoints.js <路由文件或目录>
   ```
   脚本会输出 JSON 数组，每项含 method、path、handlerName。

3. **补全语义信息**：脚本只能给出骨架，请求/响应 schema、描述、示例需要你阅读
   handler 函数体与相关 model 定义后补全。

4. **套用团队规范**：补全时务必遵循 reference/team-api-style.md 的命名与错误码约定；
   OpenAPI 字段写法遵循 reference/openapi-conventions.md。

5. **产出**：默认输出 openapi.yaml 到项目根目录，并打印一段摘要给用户确认。

## 注意
- 路径参数（如 /users/:id）要转成 OpenAPI 的 {id} 写法。
- 遇到无法静态推断的字段，标注 TODO 而非编造。
```

注意第 2 步和第 4 步：**把"机械活"交给脚本，把"判断活"留给模型**。这是高质量 Skill 的设计哲学——确定性的事情用代码保证一致，需要语义理解的事情交给 LLM。

## Step 5：用 reference/ 实现"按需深潜"

把几百行的 OpenAPI 规范要点和团队接口规范塞进 `SKILL.md` 会撑爆日常上下文。把它们拆到 reference 子目录，正文只在用到时点名引用。

**reference/openapi-conventions.md**（节选）：

```markdown
# OpenAPI 3.0 字段约定

- paths 下每个操作必填：summary、operationId、responses
- operationId 用 camelCase，全局唯一
- 响应体统一走 components/schemas 复用，避免内联
- 错误响应统一引用 ProblemDetails（RFC 7807）结构
- 字段 description 必填，用中文，一句话讲清用途
```

**reference/team-api-style.md**（节选）：

```markdown
# 团队接口风格

- URL 一律小写，单词用连字符分隔：/user-profiles 而非 /userProfiles
- 列表接口必须支持 page、pageSize 分页参数
- 时间字段用 ISO 8601 字符串，字段名以 At 结尾：createdAt、updatedAt
- 业务错误码 5 位数字，前两位标识模块
```

为什么这样组织？因为这两份资料只在"补全语义信息"那一步才需要。Claude 平时根本不读它们，只有在执行该 Skill 且走到第 4 步时，才会按正文指引 `Read` 这两个文件。一个 Skill 配 2000 行资料，日常启动成本几乎为零。

## Step 6：用 scripts/ 挂载确定性脚本

这是本 Skill 区别于"纯提示词 Skill"的关键。脚本用 Node 写，扫描 Express 路由生成端点骨架。

**scripts/extract-endpoints.js**（完整可运行）：

```javascript
#!/usr/bin/env node
// 从 Express/Koa 路由文件中静态提取端点骨架，输出 JSON
const fs = require('fs');
const path = require('path');

const target = process.argv[2];
if (!target) {
  console.error('用法: extract-endpoints.js <文件或目录>');
  process.exit(1);
}

const files = [];
function collect(p) {
  const stat = fs.statSync(p);
  if (stat.isFile() && /\.(js|ts)$/.test(p)) files.push(p);
  else if (stat.isDirectory()) {
    for (const f of fs.readdirSync(p)) collect(path.join(p, f));
  }
}
collect(path.resolve(target));

// 匹配 app.get('/x', ...) / router.post('/y', ...)
const routeRe = /\.(get|post|put|delete|patch)\(\s*['"`]([^'"`]+)['"`]/g;
const paramRe = /:([A-Za-z_]\w*)/g;

const endpoints = [];
for (const file of files) {
  const src = fs.readFileSync(file, 'utf8');
  let m;
  while ((m = routeRe.exec(src)) !== null) {
    const method = m[1].toUpperCase();
    const rawPath = m[2];
    // Express :id -> OpenAPI {id}
    const openapiPath = rawPath.replace(paramRe, '{$1}');
    endpoints.push({
      method,
      path: openapiPath,
      sourceFile: path.relative(process.cwd(), file),
      handlerName: null, // 由模型阅读函数体补全
    });
  }
}

console.log(JSON.stringify({ count: endpoints.length, endpoints }, null, 2));
```

赋可执行权限：

```bash
chmod +x ~/.claude/skills/api-contract-doc/scripts/extract-endpoints.js
```

**预期结果**：对一个含 `router.get('/users/:id', getUser)` 和 `router.post('/orders', createOrder)` 的文件运行，输出：

```json
{
  "count": 2,
  "endpoints": [
    { "method": "GET", "path": "/users/{id}", "sourceFile": "routes/users.js", "handlerName": null },
    { "method": "POST", "path": "/orders", "sourceFile": "routes/orders.js", "handlerName": null }
  ]
}
```

> **常见问题**：脚本在会话里报"permission denied"？记得 `chmod +x`；Windows 下用 `node scripts/extract-endpoints.js` 显式调用解释器即可。

## Step 7：安装、触发与调试

**安装**：因为是个人级路径（`~/.claude/skills/`），无需额外安装命令，新开会话即自动注册。项目级 Skill 同理，把目录放进 `<project>/.claude/skills/` 即可。

**触发**有两种方式：

1. **自动触发**（设计目标）：直接说"帮我把这个项目的接口整理成 OpenAPI 文档"，Claude 读到 description 里的关键词自动激活。
2. **显式触发**：在会话里输入 `/api-contract-doc`（斜杠 + Skill 名）强制调用，用于验证 Skill 是否注册成功。

**调试三连**：

- **看是否注册**：会话里输入 `/` 触发斜杠菜单，找 `api-contract-doc` 是否在列。
- **看是否被加载**：在 prompt 里加一句"请确认你是否知道 api-contract-doc 这个 skill 并简述其工作流"，让 Claude 复述正文，验证加载无误。
- **定位不触发**：若自动触发失败，几乎都是 description 关键词与你的说法对不上。把用户原话里的动词塞进 description 重试。

## 实战案例：跑通一个迷你商城项目

准备一个最小 Express 项目 `mini-shop/routes/orders.js`：

```javascript
const router = require('express').Router();

// 创建订单
router.post('/orders', (req, res) => {
  const { userId, amount } = req.body;
  res.json({ id: 1001, userId, amount, createdAt: '2026-07-12T08:00:00Z' });
});

// 查询订单详情
router.get('/orders/:id', (req, res) => {
  res.json({ id: req.params.id, status: 'paid' });
});

module.exports = router;
```

在项目根目录启动 Claude Code，只说一句话：

> 帮我把 mini-shop 的接口整理成 OpenAPI 文档，放到根目录 openapi.yaml。

预期发生的事：

1. Claude 激活 `api-contract-doc`，Grep 定位到 `routes/orders.js`。
2. Bash 调 `extract-endpoints.js mini-shop/routes` 拿到端点骨架。
3. `Read` 两份 reference 文件套用规范。
4. 阅读两个 handler 补全 schema，产出 `openapi.yaml`：

```yaml
openapi: 3.0.3
info:
  title: Mini Shop API
  version: 1.0.0
paths:
  /orders:
    post:
      summary: 创建订单
      operationId: createOrder
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              properties:
                userId: { type: integer, description: 下单用户ID }
                amount: { type: number, description: 订单金额（元） }
      responses:
        '200':
          description: 创建成功
          content:
            application/json:
              schema:
                type: object
                properties:
                  id: { type: integer }
                  userId: { type: integer }
                  amount: { type: number }
                  createdAt: { type: string, format: date-time, description: 创建时间 }
  /orders/{id}:
    get:
      summary: 查询订单详情
      operationId: getOrderById
      parameters:
        - in: path
          name: id
          required: true
          schema: { type: integer }
      responses:
        '200':
          description: 查询成功
          content:
            application/json:
              schema:
                type: object
                properties:
                  id: { type: integer }
                  status: { type: string, description: 订单状态 }
```

整个过程你只说了一句话，规范、命名、错误码全部对齐团队风格——这就是 Skill 把"重复教 AI"的成本一次性摊销掉的威力。

## 进阶：评估、发布与协同

**评估**：用 `skill-creator` 的 eval 能力，准备 5-10 条真实 prompt（不同说法请求接口文档），跑一遍看触发率与产出质量。description 改一轮、脚本正则补一轮，指标就能稳定上升。

**发布**：项目级 Skill 直接提交进仓库 `.claude/skills/`，团队 clone 即用；要跨组织共享，可封装成 plugin 发布到 marketplace。

**与 CLAUDE.md / Hooks 协同**：把"接口变更必须同步更新 openapi.yaml"写进项目 `CLAUDE.md`，再用一个 PostToolUse Hook 在检测到 `routes/` 改动时提示运行本 Skill，就形成了"改接口→自动催更文档"的闭环。

## 延伸阅读

- Claude Code 官方 Skills 文档（中文）：`https://code.claude.com/docs/zh-CN/skills`
- Anthropic Agent Skills 开放标准与渐进式披露设计原论文
- OpenAPI 3.0 规范官方站：`https://swagger.io/specification/`
- 社区 Skills 合集仓库，可参照目录结构最佳实践

## 训练营适用性评估

- **适合类型**：企业内训的"AI 工程效率"方向、3-5 天的 Claude Code 进阶训练营、研发团队的"工程规范自动化"专题工作坊。
- **教学时长**：建议 2 个课时（约 90 分钟）。第 1 课时讲机制 + Step 1-3（动手搭骨架、写 frontmatter）；第 2 课时 Step 4-7 + 实战案例，学员自带项目跑通一遍。
- **前置衔接**：放在"Claude Code 入门"之后、"MCP 服务器开发"之前最为顺滑——Skill 解决"指令复用"，MCP 解决"工具扩展"，两者互补。
- **难度**：中等。会写 Markdown 和简单脚本的开发者即可完成，难点在 description 调优与"脚本/模型分工"的设计判断，需讲师用真实 demo 点透。

## 参考来源

1. [Claude Skills 开发完全指南（GitHub）](https://github.com/sanshao85/claude-skills-guide/blob/main/Claude_Skills_%E5%BC%80%E5%8F%91%E5%AE%8C%E5%85%A8%E6%8C%87%E5%8D%97.md) — 涵盖文件结构、SKILL.md 编写、Scripts、Reference、调试部署与完整示例的中文开发指南。
2. [Claude Code Skills 完全指南：用 SKILL.md 打造自定义工作流](https://www.heyuan110.com/zh/posts/ai/2026-02-28-claude-code-skills-guide/) — 含 SKILL.md 编写方法、即用模板与 Skills/CLAUDE.md/Hooks 协同技巧。
3. [使用 skills 扩展 Claude — Claude Code 官方文档](https://code.claude.com/docs/zh-CN/skills) — 创建、管理与共享 skills 的权威说明，含调用控制与子代理执行机制。
4. [Claude Code Skills 完全指南（2026 最新版）— 知乎](https://zhuanlan.zhihu.com/p/2034659438850750016) — 涵盖手动安装、热门 Skills 推荐与离线部署场景。

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