本教程带你从零造一个名为 endpoint-scaffold 的 Claude Code Skill:输入一句 POST /users 创建用户,它自动产出路由、处理器、单元测试、接口文档四个文件——也就是后端开发最重复的"四件套"。在这个过程中,你会真正吃透 Skills 的三个核心机制:渐进式披露(薄入口 + 引用文件)、命名参数($method、$path、$desc)、动态上下文注入(!命令``)。适合已经用过 Claude Code、想从"复制粘贴提示词"升级到"封装可复用工程资产"的开发者。
${CLAUDE_PROJECT_DIR} 需要该版本)/permissions、/model 等基础命令核心概念速记:一个 Skill 就是一个目录,入口是 SKILL.md。它有两种 YAML 块之外的内容——frontmatter(告诉 Claude"何时用、能用什么工具")和正文(告诉 Claude"怎么做")。与 CLAUDE.md 最大的区别是:Skill 正文只在被调用时才加载,长期参考材料几乎零成本。
很多人写 Skill 的第一步是打开 SKILL.md 开始堆文字,这是反模式。先在纸上画清楚三件事:
对本 Skill 而言,三个答案很清晰:
routes/<name>.js、handlers/<name>.js、tests/<name>.test.js、docs/<name>.md这一步决定了后续所有设计。把第三项里"固定不变的部分"抽成模板文件,"需要动态填充的部分"留给参数——这就是渐进式披露的雏形。
Skills 存放位置决定作用域。个人级放 ~/.claude/skills/,项目级放 .claude/skills/。脚手架类工具强绑定项目,建议放项目级,跟着代码一起进版本库、被团队共享。
mkdir -p .claude/skills/endpoint-scaffold/templates
mkdir -p .claude/skills/endpoint-scaffold/examples
最终结构:
.claude/skills/endpoint-scaffold/
├── SKILL.md # 薄入口:导航 + 流程
├── templates/
│ ├── route.tpl # 路由声明模板
│ ├── handler.tpl # 处理器函数模板
│ ├── test.tpl # 单测模板
│ └── doc.tpl # 接口文档模板
└── examples/
└── one-liner-to-files.md # 一句话→四文件的对照样例
预期结果:Claude Code 监视这些目录,文件改动在当前会话内即时生效,无需重启。若新建的是会话启动时并不存在的顶层目录,才需要重启一次。
常见问题:把模板塞进 SKILL.md 而不是单独文件——结果正文膨胀到几百行,每次调用都把模板原文灌进上下文,token 成本飙升。记住官方建议:SKILL.md 控制在 500 行以内,详情挪到引用文件。
模板是"骨架",用占位符标记"活肉"。占位符命名要和参数一一对应,这里统一用 {{METHOD}}、{{PATH}}、{{DESC}}、{{NAME}}(由路径派生)。注意:{{...}} 是给 Claude 看的"提示性占位",真正的参数替换靠步骤四的 $method 机制。
templates/route.tpl:
// Auto-scaffolded by endpoint-scaffold skill
import { {{NAME}}Handler } from '../handlers/{{NAME}}.js';
router.{{METHOD_LOWER}}('{{PATH}}', {{NAME}}Handler);
templates/handler.tpl:
// {{DESC}}
export async function {{NAME}}Handler(req, res) {
try {
// TODO: implement business logic for {{METHOD}} {{PATH}}
res.status(501).json({ error: 'not implemented' });
} catch (err) {
res.status(500).json({ error: String(err) });
}
}
templates/test.tpl:
import { describe, it, expect } from 'vitest';
// import { {{NAME}}Handler } from '../handlers/{{NAME}}';
describe('{{METHOD}} {{PATH}}', () => {
it('should {{DESC}}', async () => {
// TODO: wire up request mock and assert response
expect(true).toBe(true);
});
});
templates/doc.tpl:
# {{METHOD}} {{PATH}}
{{DESC}}
## Request
TODO
## Response
TODO
预期结果:四个 .tpl 文件躺在 templates/,它们本身不会自动加载进上下文——这正是渐进式披露的好处。只有 SKILL.md 在被调用时进入对话,模板文件是 Claude "按需读取"的资料。
这是全教程的核心。一份 SKILL.md 同时调度命名参数、动态注入、模板引用三种能力。
.claude/skills/endpoint-scaffold/SKILL.md:
---
name: endpoint-scaffold
description: Scaffold a complete API endpoint (route + handler + unit test + API doc) from a one-line spec. Use when the user asks to add/create a new endpoint, generate CRUD scaffolding, or build out a new route with tests and docs.
when_to_use: triggers on phrases like "加个接口", "新建 endpoint", "生成 CRUD", "scaffold a route", "add an API"
argument-hint: [METHOD path description...]
arguments: [method, path, desc]
allowed-tools: Read, Write, Edit, Glob, Bash(ls *), Bash(test *)
---
## Current request
Scaffold the endpoint: **$method $path** — $desc
## Project context (auto-detected)
- Stack hint: !`cat package.json 2>/dev/null | grep -E '"(express|fastify|koa|next|vitest|jest)"' || echo "no package.json or unknown stack"`
- Existing routes: !`ls src/routes 2>/dev/null || ls routes 2>/dev/null || echo "no routes dir yet"`
## Your task
Produce the "四件套" (four files) for the endpoint above.
1. Derive `{{NAME}}` from `$path`: take the last non-param segment, drop a trailing `/:id`, convert to camelCase (e.g. `/api/users/:id` → `users`; `/api/orders/:id/items` → `orderItems`).
2. Lowercase `$method` for the router call (`{{METHOD_LOWER}}`).
3. Read each template file and fill the placeholders, then write the result:
- templates/route.tpl → src/routes/{{NAME}}.js
- templates/handler.tpl → src/handlers/{{NAME}}.js
- templates/test.tpl → tests/{{NAME}}.test.js
- templates/doc.tpl → docs/{{NAME}}.md
4. If `src/routes/index.js` (or equivalent registry) exists, append a registration import for the new route.
5. Print a one-line summary: which files were created and a suggested next command.
Keep generated code minimal and idiomatic to the detected stack. When the stack is unknown, default to plain Express-style handlers and note the assumption in the doc file.
## Resources
- For one worked example of input→output, read [examples/one-liner-to-files.md](examples/one-liner-to-files.md)
- Templates live in [templates/](templates/) — read them on demand, do not assume their contents.
逐行拆解这股力量的来源:
命名参数:frontmatter 的 arguments: [method, path, desc] 把 /endpoint-scaffold POST /users 创建用户 拆成三段,正文里 $method→POST、$path→/users、$desc→创建用户。多词描述要用引号包裹,/endpoint-scaffold POST /users "create a guest user" 才能把第三段当整体。
动态上下文注入:!cat package.json ...` 在正文送达 Claude **之前**执行,命令输出原地替换占位符。Claude 看到的不是命令本身,而是真实的项目栈与已有路由——这正是脚手架能"自适应"的原因。多行命令用 ``! 围栏。
模板引用:结尾的"Resources"列出支持文件,并写明何时该读。Claude 不会预读 templates/,只在执行到第 3 步时按需 Read,把占位符成本降到最低。
allowed-tools:预授权 Read/Write/Edit/Glob 与受限的 Bash(ls *)、Bash(test *),省去逐次确认;但不放开任意 Bash,避免 Skill 自我授权执行危险命令。项目级 Skill 的 allowed-tools 在你接受 workspace trust 对话框后才生效——这是反恶意 Skill 的护栏。
预期结果:保存后无需重启,输入 /endpoint-scaffold 应能在补全菜单看到该 Skill,argument-hint 提示 [METHOD path description...]。
常见问题与解决:
| 现象 | 原因 | 解决 |
|---|---|---|
| 菜单里看不到 Skill | 目录名拼错或 SKILL.md 不在根 |
确认路径为 .claude/skills/endpoint-scaffold/SKILL.md |
$desc 只取到第一个词 |
未加引号 | 多词参数整体加引号 |
| Skill 触发但栈识别错误 | ! 命令输出为空 |
手动检查探测命令能否在项目根跑通 |
| Skill 不被自动触发 | description 不含触发短语 | 把 when_to_use 写满真实触发句 |
examples/one-liner-to-files.md 是渐进式披露的另一关键:给 Claude 一个明确的输入→输出映射,减少自由发挥导致的跑偏。
# Input
/endpoint-scaffold POST /api/orders 创建订单
# Derived
NAME = orders
METHOD_LOWER = post
# Output files
- src/routes/orders.js
- src/handlers/orders.js
- tests/orders.test.js
- docs/orders.md
# Sample handler (filled)
export async function ordersHandler(req, res) {
try {
res.status(501).json({ error: 'not implemented' });
} catch (err) {
res.status(500).json({ error: String(err) });
}
}
有了这份样例,Claude 遇到边界情况(如路径带 /:id)会更倾向遵循既有派生规则,而非自己发明。
在项目根目录启动 Claude Code:
claude
两种调用方式都试一次:
/endpoint-scaffold POST /users 注册新用户
或者用自然语言触发(验证 description 是否生效):
帮我加个接口:GET /products 列出所有商品,要带测试和文档
预期结果:Claude 先读取模板,按派生规则填充占位符,写出四个文件,并在 src/routes 注册新路由,最后给出一行总结。整个过程应可逆——若不满意,删掉生成的文件即可。
验证生成的测试能跑:
npx vitest run tests/users.test.js
Skill 能触发,不等于它做对了。官方推荐的检验法是带基线对照:收集 3–5 条真实请求,分别在"启用 Skill"和"禁用 Skill"的新会话里跑,比较产物。为什么要新会话?因为编写 Skill 时残留的上下文会掩盖正文写得不够好的缺陷。
若触发准确率不稳,优先改 description 与 when_to_use;若触发准但产物差,改正文步骤或补 examples/。更系统的方式是装官方插件:
/plugin install skill-creator@claude-plugins-official
它会为每个测试用例在隔离子代理里跑、记录 token 与耗时、生成 benchmark.json,支持两个 Skill 版本的盲测 A/B——改动是否真的是改进,用数据说话。
假设要给一个电商后端快速铺底。按下面顺序喂同一句式:
/endpoint-scaffold POST /api/orders 创建订单
/endpoint-scaffold GET /api/orders/:id 查询订单详情
/endpoint-scaffold PATCH /api/orders/:id 更新订单状态
/endpoint-scaffold DELETE /api/orders/:id 取消订单
/endpoint-scaffold GET /api/products 商品列表
每次 !ls src/routes` 注入的"已有路由"清单会随轮次增长,Claude 能据此决定是否需要新建注册条目还是复用现有orders` 文件。一轮下来你拿到 20 个文件(5 组四件套),每个 handler 都是可编译的 501 占位实现,测试是可运行的红绿骨架。接下来把精力集中到业务逻辑即可——这正是脚手架类 Skill 的价值:把"从零搭壳"的时间压缩到接近零。
进阶可叠加的能力:在正文里加 ultrathink 触发更深推理,处理复杂派生;或加 context: fork 让 Skill 在隔离子代理里执行,避免污染主会话上下文——后者适合那些需要大段探索的生成任务。但要记住官方警告:context: fork 只适合"有明确任务的 Skill",纯参考类 Skill 放进子代理会因没有可执行任务而无功而返。
flowchart TD
A["用户输入<br/>/endpoint-scaffold POST /users 注册新用户"] --> B{"Claude Code<br/>匹配 description/when_to_use"}
B -->|命中| C["frontmatter 解析<br/>arguments: method path desc"]
C --> D["动态注入预执行<br/>!`cat package.json` → 真实栈<br/>!`ls src/routes` → 已有路由"]
D --> E["SKILL.md 正文进入会话<br/>模板文件尚未加载"]
E --> F["Claude 执行步骤1-2<br/>派生 NAME / METHOD_LOWER"]
F --> G["按需 Read templates/*.tpl<br/>渐进式披露: 只读需要的文件"]
G --> H["Write 四件套<br/>route/handler/test/doc"]
H --> I["注册路由 + 输出总结"]
I --> J["基线对照迭代<br/>skill-creator 跑 benchmark.json"]
B -->|未命中| K["降级为普通对话<br/>或检查 description 触发短语"]
code.claude.com/docs/en/skillsagentskills.iofp8.co/articles/Claude-Code-Skills-Complete-Developer-Guidecontext: fork 子代理执行与 disallowed-tools 自主护栏两个扩展点。[!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 等场景全覆盖。
