本教程面向已装通 Claude Code、想掌握 Skills 开发全流程的开发者。你将从零创建一个Mock 数据生成 Skill——输入一个数据结构描述,Claude 自动产出符合约束的假数据(姓名、身份证、手机号、订单、嵌套对象、数组),并学会 SKILL.md frontmatter 的触发词设计、渐进披露(progressive disclosure)、脚本捆绑、权限收敛、触发准确性测试与团队分享。学完你能把任意重复性工作封装成"一句话触发"的能力,而不是每次都重写提示词。
claude 命令可用,版本 ≥ 1.0.x,2026 年版)claude 进入交互模式很多人把 Skill、MCP、子代理(Subagent)混为一谈。一张表区分清楚:
| 能力载体 | 本质 | 何时加载 | 适合做什么 |
|---|---|---|---|
| Skill | 一个目录 + SKILL.md 指令包(可带脚本) |
触发时才读正文(渐进披露) | 教 Claude "怎么做某类事"的流程与约定 |
| MCP 服务器 | 独立进程,暴露 tools/resources | 始终连接 | 给 Claude 新的"手"(外部 API、数据库) |
| Subagent | 独立上下文的代理实例 | 委派时启动 | 隔离上下文、并行处理大任务 |
Skill 最轻、最适合"把团队规范 / 重复套路固化下来"。它的杀手锏是渐进披露:
flowchart LR
A["启动会话"] --> B["仅加载所有 Skill 的<br/>name + description"]
B --> C{"用户输入<br/>是否匹配某 Skill?"}
C -->|匹配| D["读取该 Skill 的 SKILL.md 正文"]
C -->|不匹配| E["不加载,省 token"]
D --> F{"正文是否引用<br/>脚本/参考文档?"}
F -->|引用| G["按需读取 scripts/ references/"]
F -->|不引用| H["直接执行"]
G --> H
这意味着你的 Skill 可以塞进几千字的详细规则和几十个脚本,而日常会话零开销——因为正文只在被触发时才进上下文。理解这一点,你就不会再把所有规则堆进 CLAUDE.md 把全局上下文撑爆了。
Skill 存放位置有两种作用域:
~/.claude/skills/<skill-name>/SKILL.md —— 跨所有项目可用<project>/.claude/skills/<skill-name>/SKILL.md —— 跟随仓库,团队共享(建议提交到 git)Claude Code 内置了 skill-creator 能力。最稳的起手式是直接让它帮你生成目录骨架,而不是手敲。
操作:在 Claude Code 交互模式里输入
/skill-creator 帮我创建一个名为 mock-data 的 Skill,作用是根据用户描述的数据结构生成贴近真实的 Mock 测试数据
预期结果:Claude 会在 .claude/skills/mock-data/ 下生成:
.claude/skills/mock-data/
├── SKILL.md # 主指令文件(含 frontmatter)
├── references/ # 可选:详细参考文档
└── scripts/ # 可选:可执行脚本
└── gen_mock.py
常见问题:生成的
description太笼统(如 "生成 mock 数据"),导致触发不准。这正是下一步要重写的重点。
frontmatter 不是装饰,它是 Claude 判断"要不要触发这个 Skill"的唯一依据(正文此时还没加载)。把 description 写废了,Skill 就永远沉睡。
打开 SKILL.md,把 frontmatter 改成:
---
name: mock-data
description: Generate realistic mock/test data (Chinese names, IDs, phone numbers, addresses, nested JSON, arrays) from a data structure description. Use when the user needs fake sample data, test fixtures, seed data, dummy JSON for API development, or asks to "造点测试数据/生成假数据/mock 一下". Outputs deterministic, constraint-respecting data.
---
设计 description 的四条铁律:
常见问题:"description 写得越详细越好吗?"——错。description 是给触发路由器看的,控制在 3-5 句。详细规则写进正文,正文不会参与初始匹配。
正文是触发后才加载的"操作手册"。风格要像给一个聪明但不知情的新同事写的 SOP:直接、可执行、带例子。
# Mock Data Generation
You generate realistic mock data that respects the user's stated constraints.
Do NOT hallucinate fields the user didn't ask for. When a field type is
ambiguous, ask one clarifying question, then proceed.
## Workflow
1. Parse the user's data structure description into a field list.
2. For each field, pick the most realistic generator (see references/field-types.md).
3. Respect constraints: count, uniqueness, value ranges, locale, format.
4. Output as the requested format (JSON / CSV / SQL INSERT / Python dict).
5. If count > 50, stream the output to a file instead of printing inline.
## Realism rules
- Chinese names: real-style surnames + given names, not "张三"/"李四" repeats.
- Phone numbers: start with valid Chinese prefixes (13x/15x/17x/18x/19x).
- ID numbers: valid checksum (use scripts/gen_mock.py --id to compute).
- Dates: spread across a plausible range, not all "2026-01-01".
- Money: realistic magnitude per domain (salary 5k–50k, not 999999).
## When to stop and ask
- If the user requests a field you cannot map to any generator.
- If two constraints conflict (e.g., "age between 0-3 AND employed").
- If output would exceed 200 rows — confirm the file path first.
注意几点: - 祈使句开头:"Parse…", "Respect…", "Output…",不要写 "你应该尽量…" - 给边界:"count > 50 就写文件"、"冲突就停下来问",把判断权显式化 - 反例约束:"不要重复张三李四"、"不要把日期都设成同一天"——告诉它不要做什么,比告诉它做什么更省事
光靠 Claude 生成 ID 号的校验位很容易算错。把确定性的活交给脚本,Claude 只负责编排。在 scripts/gen_mock.py 写一个零依赖生成器:
#!/usr/bin/env python3
"""Mock data generator. Zero external deps.
Usage: gen_mock.py --field id --count 5
gen_mock.py --field phone --count 3
"""
import argparse, json, random, sys
SURNAME = list("王李张刘陈杨黄赵吴周徐孙马朱胡郭何高林罗")
GIVEN = ["伟","芳","娜","秀英","敏","静","丽","强","磊","洋",
"艳","勇","军","杰","涛","明","超","秀兰","霞","平"]
PHONE_PREFIX = ["133","135","137","150","159","170","180","188","199"]
def gen_id():
# Simplified 18-digit ID with valid-ish region + checksum
region = random.choice(["110101","310115","440305","510107"])
birth = f"{random.randint(1960,2008)}{random.randint(1,12):02d}{random.randint(1,28):02d}"
seq = f"{random.randint(0,999):03d}"
base = region + birth + seq
# Weighted checksum (GB 11643-1999)
w = [7,9,10,5,8,4,2,1,6,3,7,9,10,5,8,4,2]
code = "10X98765432"
s = sum(int(d)*wi for d, wi in zip(base, w))
return base + code[s % 11]
def gen_name():
return random.choice(SURNAME) + "".join(random.sample(GIVEN, random.randint(1,2)))
def gen_phone():
return random.choice(PHONE_PREFIX) + "".join(str(random.randint(0,9)) for _ in range(8))
GENERATORS = {"id": gen_id, "name": gen_name, "phone": gen_phone}
if __name__ == "__main__":
p = argparse.ArgumentParser()
p.add_argument("--field", required=True)
p.add_argument("--count", type=int, default=1)
args = p.parse_args()
fn = GENERATORS.get(args.field)
if not fn:
sys.exit(f"unknown field: {args.field}")
print(json.dumps([fn() for _ in range(args.count)], ensure_ascii=False))
然后在 SKILL.md 正文里告诉 Claude 怎么用:
## Using the bundled script
For ID numbers, phone numbers, and names, prefer calling the bundled script
to guarantee format validity:
python3 scripts/gen_mock.py --field id --count 10
python3 scripts/gen_mock.py --field phone --count 5
Compose the script's output into the larger structure the user asked for.
Do NOT hand-compute ID checksums — always delegate to the script.
这是 Skill 区别于普通提示词的核心价值:把确定性的、容易出错的计算固化成代码,把语义理解交给模型。
常见问题:脚本路径用相对还是绝对?SKILL.md 里写相对路径(
scripts/gen_mock.py),Claude 运行时会解析到 Skill 目录下,团队 clone 仓库后无需改路径。
正文保持精炼,把"各字段怎么生成"的查表式细节挪进 references/field-types.md,只在需要时加载:
# references/field-types.md
| 字段语义 | 生成策略 | 示例 |
|---------|---------|------|
| email | 拼音名+域名,域名随机自 gmail/qq/163 | `[email protected]` |
| address | 省+市+区+随机街道门牌 | `广东省深圳市南山区科技园路1号` |
| company | 行业词+公司类型 | `星河科技有限公司` |
| price | 按商品类目量级 | 电子产品 99–9999,生鲜 1–200 |
| timestamp | 最近 N 天内随机 ISO8601 | `2026-06-14T03:21:00Z` |
| boolean | 0.3–0.7 比例 True | `true` |
| enum | 从用户给的候选集随机 | `["active","pending","closed"]` |
正文里引用:
For the full field-type mapping table, consult references/field-types.md
when you encounter a field type not covered in the realism rules above.
这就是渐进披露的二层结构:frontmatter(总在)→ SKILL.md 正文(触发时在)→ references(按需在)。上下文成本随深度递减,能力却随深度递增。
Skill 写完不算完,必须验证它在该触发时触发、不该触发时安静。开新会话,跑正反例:
应当触发的输入(期望命中): - "帮我 mock 10 条用户数据,要有姓名手机号身份证" - "造点测试数据,订单表,50 行" - "generate 5 fake user records with nested address" - "接口联调缺数据,给我点假的 JSON"
不应触发的输入(期望不命中): - "解释一下这段代码"(代码理解,无关) - "帮我写个单元测试"(已有专门的单测 Skill) - "mock 一下这个类"("mock" 在这里是测试替身,不是数据——若误触发,回到 description 加否定词:"Do NOT trigger for test doubles / mocking classes / mock objects in unit tests; this skill only generates fake DATA.")
常见问题:调试触发最有效的办法——直接问 Claude:"刚才那条输入,你为什么没/为什么用了 mock-data Skill?" 它会复述自己匹配到的关键词,据此微调 description。
如果这个 Skill 只需要读描述、跑脚本、写文件,就别让它碰别的。在 frontmatter 加:
---
name: mock-data
description: ...
allowed-tools: Read, Write, Bash(python3 scripts/gen_mock.py:*)
---
Bash(python3 scripts/gen_mock.py:*) 是关键——只允许执行这一个脚本及其任意参数,杜绝 Skill 顺手跑别的命令。这把"教 Claude 怎么做"和"限定它能做什么"结合,遵循最小权限原则。
最终目录结构:
.claude/skills/mock-data/
├── SKILL.md
├── references/
│ └── field-types.md
└── scripts/
└── gen_mock.py
在新会话里输入一句话:
给我 1000 条订单测试数据,字段:订单号、买家姓名、手机、收货地址、商品名、单价、数量、下单时间(近 30 天)、状态(paid/shipped/done)。输出 JSON 数组存到 orders.json。
Claude 的执行路径:
sequenceDiagram
participant U as 用户
participant C as Claude Code
participant S as mock-data Skill
participant P as gen_mock.py
U->>C: 一句话需求
C->>S: 命中 mock-data 触发词<br/>加载 SKILL.md
S->>C: 返回 workflow + 调用规则
C->>P: Bash: gen_mock.py --field phone --count 1000
P-->>C: 返回合规手机号数组
C->>P: Bash: gen_mock.py --field id --count 1000
P-->>C: 返回合规身份证数组
C->>C: 组装商品/地址/时间/状态<br/>(查 references/field-types.md)
C->>U: 写入 orders.json (1000 行)
C->>U: 汇总:字段、约束、行数
预期产出(截取):
[
{"order_id":"ORD-20260710-0001","buyer":"陈艳霞","phone":"137xxxx2841",
"address":"广东省深圳市南山区科苑南路8号","item":"无线蓝牙耳机",
"unit_price":199,"qty":2,"ts":"2026-06-22T11:03:00Z","status":"paid"},
{"order_id":"ORD-20260710-0002","buyer":"林涛","phone":"188xxxx7710",
"address":"北京市海淀区中关村大街1号","item":"机械键盘",
"unit_price":459,"qty":1,"ts":"2026-07-01T08:45:00Z","status":"shipped"}
]
对比"不写 Skill、每次手动提示":以前你要反复说明字段格式、手机号规则、价格量级,现在一句话搞定,且身份证/手机号格式由脚本保证永远合规。这就是 Skill 的复利——写一次,用无数次,每次质量稳定。
.claude/skills/mock-data/ 提交到仓库,队友 clone 即生效;或打包成 plugin 放进 .claude/plugins/ 供跨项目安装。version: 1.0.0,变更时升版本号并在 references/ 留 changelog。https://code.claude.com/docs/en/skills —— frontmatter 字段、发现规则、调用机制的权威定义https://duet.so/guides/claude-code-skills-complete-guide —— 何时该用哪种扩展方式https://allahabadi.dev/blogs/ai/claude-code-skills-frontmatter-complete-guide/ —— 十五个支持字段的逐项说明https://techsy.io/en/blog/claude-skills-tutorial —— 从零构建首个 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 等场景全覆盖。
