03 · Skill 什么时候该做、怎么做
文字规则不够用时的升级。80% 的工夫在 description。
开场比喻
对前端开发者,Skill 最贴切的类比是 VS Code extension:
- 你不会打开 VS Code 就激活所有插件
- 每个插件有
activationEvents("写 TypeScript 时激活") - 需要时才出来,平时安静在后台
Claude Code 里的 skill 同理——写了不代表每次会话都加载,它有 description 当"激活条件",只在匹配场景被 Claude 主动拉进来。
把前两篇串起来:三层升级路径
| 信息重复度 | 存哪 |
|---|---|
| 说一次 | 对话上下文 |
| 反复说(文字规则够用) | CLAUDE.md / auto-memory |
| 反复说 + 流程复杂 + 上下文重 | Skill(文字规则升级为可调用模块) |
Skill 是文字规则不够用时的下一阶。
三个触发条件(至少满足两个才做)
① 同类任务做过 3 次以上
第一次不做,第二次考虑,第三次必须做。一次性任务写 SKILL.md 的成本 > 重做一次。
② 流程稳定
能用有限步骤枚举清楚。每次做法都不一样 → 做成 skill 只会固化错误。
③ 上下文重
规则展开超过 30 行塞 CLAUDE.md 不合适 → 抽成 skill,CLAUDE.md 保持清爽。
什么时候 不 该做
| 情况 | 为什么 |
|---|---|
| 一次性任务 | 成本 > 收益 |
| 流程不稳定 | 会固化错误 |
| 一句 prompt 就能说清 | 直接说 |
| 每次要自动触发 | 走 hook,不是 skill |
最关键的边界:自动触发 → hook;按需触发 → skill。混淆是新手高频错误(见 06)。
SKILL.md 解剖
标准结构:
---
name: add-region
description: 往项目添加新的 App Store 地区。
当用户说"加个 X 地区"、"support <country>"、"新增 <地区代码>"时触发。
输入:ISO 3166-1 alpha-2 大写代码。
---
# Add Region
## When to use
- 用户明确要给项目新增一个 App Store 地区
- 输入是地区代码(如 `BR`、`DE`)
## Steps
1. 读 `src/constants/regions.ts`,确认目标地区不在
2. 查 Apple App Store 支持列表(`scripts/verify-apple-region.ts`)
3. 追加到 `regions.ts`,按字母序维持
4. 所有 `messages/*.json` 补翻译 key
5. 更新 i18n 测试快照
6. 跑 `pnpm test -- regions` 和 `pnpm build`
7. 输出 commit 建议
## Inputs
- 地区代码(ISO 3166-1 alpha-2 大写)
## Output
- `regions.ts` 新增一行
- 所有语言 JSON 新增翻译
- Commit message 建议
## Do NOT
- 不往 `constants/` 以外的文件硬编码地区
- 不跳过 build 验证三要素:frontmatter(身份证)+ When to use(门牌)+ Steps(剧本)。
description 是生死线
Claude 决定"要不要加载这个 skill" 只看 description。写不好,skill 白做。
好 description 公式:
[做什么] + [什么时候触发] + [输入形态]❌ 太笼统
description: 添加地区到项目Claude 不知道"什么项目"、"什么叫添加地区"。
✅ 精准
description: 往 XX 项目添加新的 App Store 地区。
当用户说"加个 X 地区"、"support <country>"、"新增 <地区代码>"时触发。
输入:ISO 3166-1 alpha-2 大写代码。四个要点
- 项目 / 领域明示——避免别的项目误触发
- 触发短语列全(中英文都列)——用户表达不统一
- 输入格式——让 Claude 能识别"这不是我该干的活"
- 隐性"不做什么"——比如上例没写"删除地区",Claude 不会误用到删除场景
Skill 放哪
<repo>/.claude/skills/<name>/SKILL.md ← 项目级,入 git(团队共享)
~/.claude/skills/<name>/SKILL.md ← 个人全局,跨所有项目判断:
- 项目专属 → 项目级(入 git,团队都能用)
- 跨项目通用(如"从剪贴板生成 kebab-case slug")→ 个人级
加载条件
项目级 skill 能被识别,需要三个条件:
① 目录结构必须精确
<repo>/.claude/skills/<skill-name>/SKILL.md注意三层:
.claude/是项目配置根目录(必须这个名字)skills/子目录(必须这个名字)- 每个 skill 各自一个子目录
- 主文件必须叫
SKILL.md(大小写敏感;Linux / CI 环境需特别注意,macOS 默认不区分大小写,但 CI 通常跑在 Linux 上)
② 项目必须被"信任"
Claude Code 首次进入新仓库时会问:
This directory contains a
.claude/config. Do you trust it?
选 Yes,项目级 skills 才生效。
③ Frontmatter 合法
至少带 name 和 description:
---
name: add-region
description: <一句话,谁 / 什么时候 / 输入啥>
---加载优先级
同名 skill 存在多处时:
项目级 (<repo>/.claude/skills/) > 用户级 (~/.claude/skills/) > 内置项目级覆盖用户级——比如你用户级有个通用 deploy skill,项目里可以放一个同名的覆盖掉。
进阶:索引式 skill
当一个 skill 覆盖大量主题(如"Next.js 最佳实践")时,单文件会膨胀。此时用**"索引 + 分派"模式**:
next-best-practices/
├── SKILL.md ← 4KB 索引(加载门面)
├── async-patterns.md ← 1.7KB
├── bundling.md ← 4.4KB
├── data-patterns.md ← 6.7KB
├── ... 另外 16 个专题 md
└── self-hosting.md ← 8.3KBSKILL.md 本体不教具体知识,只做两件事:
- 声明覆盖哪些领域
- 告诉 Claude 想看 X 去读 X.md
两级触发机制
## Image Optimization
See [image.md](./image.md) for:
- Always use `next/image` over `<img>`
- Remote images configuration
- Responsive `sizes` attribute
- Blur placeholders
- Priority loading for LCP不只给路径,还列了子文件里能找到什么。Claude 加载 SKILL.md 后看清单,不用真的打开 image.md 就能判断现在需不需要读它。
两级过滤:
- 外层 description → Claude 决定要不要拉 SKILL.md
- 内层 bullet list → Claude 决定要不要拉具体子文件
好处
| 问题 | 单文件版 | 索引分派版 |
|---|---|---|
| 触发一次加载多少 | 85KB 全进 | 仅 4KB 索引 |
| Claude 聚焦度 | 差 | 好(按需) |
| 维护成本 | 动巨文件 | 改子文件即可 |
什么时候用
- 主题超过 5 个且彼此独立
- 总内容超过 20KB
- 同一领域有"按场景"分派的自然结构
不适用:单一任务的线性流程(如 add-region)——没必要拆。
字段细节:user-invocable
看到这个字段你可能会愣一下:
user-invocable: false含义:这个 skill 不能被用户直接调用(比如 /next-best-practices),只能由 Claude 自己判断要不要拉进来。
| 字段值 | 含义 | 典型 skill |
|---|---|---|
默认(true) | 用户可输 /xxx 触发 | /review、/security-review |
false | 只能 Claude 自动触发 | 领域规则类(写 Next.js 时被动参考) |
用法判断:
- Skill 是"命令" → 默认(user-invocable)
- Skill 是"被动参考的规则集" →
false
管理纪律
- 一个 skill 一件事——SKILL.md 超过 200 行多半该拆
- 脚本 / 模板放子目录,SKILL.md 保持纯指令
- 定期清理:三个月没触发过的 → 要么删,要么改 description
- 少而精 >>> 多而杂——skill 越多 Claude 选择负担越重
- 子文件 < 1.5KB 考虑合并——加载 overhead 不值
反模式三连
① SKILL.md 当说明书写
前半段"本 skill 介绍 / 设计理念 / 历史背景"——Claude 需要指令,不是背景故事。
② description 写成功能清单
description: 本 skill 可以:添加地区、删除地区、修改地区、查询地区...万能 skill 是触发灾难。一个 skill 一个动作,要删除流程?单开 remove-region。
③ 把 hook 的事做成 skill
"每次提交前跑 tests"——这是 hook。skill 需要主动拉取,不会自动激活。
一句话总结
Skill 是文字规则的升级版:当一条规则需要多步骤 + 脚本 + 验证时,升级成 skill。
写 skill 的 80% 工夫在 description——那是它唯一的生死线。
速查:两种典型形态
| 形态 | 场景 | 结构 |
|---|---|---|
| 单步流程 | add-region、city-card | 单 SKILL.md + scripts/ |
| 索引分派 | next-best-practices、ui-ux-pro-max | 顶层 SKILL.md + 多个主题 md |
| 纯工作流 | /review、/security-review | 单 SKILL.md,user-invocable 默认 |
| 被动参考 | 领域规则集 | 多文件,user-invocable: false |