1. 从“能用”到“好用”:为什么40个Skill是分水岭
我大概是在去年年底开始把 Claude Code 当作日常主力工具的。最开始那两个月,我的用法特别朴素:打开终端,敲一句需求,等它吐代码,复制粘贴,跑一下,报错了再贴回去。能用吗?能用。但用久了总觉得哪里不对劲——每次开新会话,它都像失忆一样,我得重新交代项目结构、代码规范、测试命令、提交格式。一天下来,光“喂背景”就耗掉不少时间。
后来我陆续往里面塞 Skill,从最开始的三五个,到现在的四十个出头。变化不是线性的,是那种“过了某个点突然通了”的感觉。以前我觉得 Skill 就是个提示词模板,现在回头看,这个理解太浅了。Skill 真正解决的是上下文复用和行为约束这两件事。前者让 Claude Code 不用每次从零理解你的项目,后者让它按你团队的规矩干活,而不是按它自己的“审美”干活。
这篇文章不打算写成官方文档的翻译版。我想聊的是:四十个 Skill 装下来,哪些是真有用的,哪些是凑数的,SKILL.md 到底该怎么写,frontmatter 里那几个字段为什么不能乱填,以及我踩过的那些坑。如果你刚开始用 Claude Code,或者装了 Skill 但感觉“没啥效果”,这篇应该能帮你省下不少试错时间。
提示:Skill 的效果高度依赖你的项目结构和团队约定。同一个 Skill,在 A 项目里如鱼得水,在 B 项目里可能完全跑不通。别照搬,要改造。
2. Skill 到底是什么:拆开 SKILL.md 看本质
2.1 一个 Skill 就是一份“带触发条件的说明书”
很多人第一次接触 Skill,会把它和 Agent 搞混。我一开始也糊涂。简单说,Agent 是“谁来干活”,Skill 是“活该怎么干”。Agent 决定用哪个模型、走什么流程、调什么工具;Skill 则是一份静态的、可复用的知识包,告诉 Claude Code 在特定场景下应该遵循什么规则、参考什么资料、输出什么格式。
从文件结构上看,一个 Skill 就是一个目录,里面至少有一个SKILL.md。这个文件分两部分:顶部的 frontmatter(用---包起来的那段),和下面的正文。frontmatter 是元数据,决定这个 Skill 什么时候被加载、叫什么名字、能不能被自动触发;正文才是真正的“说明书内容”。
我见过不少人写 Skill,正文写得洋洋洒洒几千字,frontmatter 就随便填两行。结果就是:Skill 装进去了,但 Claude Code 根本不知道什么时候该用它。这就像你写了一本特别好的操作手册,但封面没写书名,放在书架上没人找得到。
2.2 frontmatter 里那几个字段,一个都不能马虎
frontmatter 的字段不多,但每个都有明确作用。我拿一个实际在用的 Skill 举例:
--- name: vue-component-review description: 审查 Vue 3 组件的 props 定义、响应式使用和模板结构,适用于 .vue 文件 trigger: - "review component" - "检查组件" - "vue review" ---name是 Skill 的唯一标识,建议用短横线连接的小写英文,别用中文,也别用空格。我试过用中文名,在某些终端环境下会出现编码问题,加载失败。
description是最关键的字段。它不只是给人看的,Claude Code 在决定是否加载某个 Skill 时,会读这段描述来判断相关性。所以描述里要包含场景和对象,比如“审查 Vue 3 组件”比“代码审查”精准得多。我一般会写成“动词 + 对象 + 适用条件”的结构。
trigger是可选的,但强烈建议加上。它是一组关键词或短语,当你的输入里出现这些词时,Claude Code 会优先考虑加载这个 Skill。注意,trigger 不是精确匹配,是语义相关的模糊匹配。所以别写太泛的词,比如“代码”“帮我”这种,写了等于没写,还会干扰其他 Skill 的触发。
还有一个字段是version,我一开始觉得没用,后来发现当你有四十个 Skill 的时候,版本管理就很重要了。某个 Skill 改了规则,导致输出格式变了,你得知道是哪个版本改的。我现在的习惯是每次改动都升一个小版本号,配合 git 管理,回滚很方便。
2.3 正文怎么写:少讲道理,多给例子
正文部分我踩过最大的坑就是“写太多”。最开始我恨不得把团队所有的代码规范都塞进去,结果 Skill 加载后,Claude Code 的上下文被占掉一大块,反而影响了它处理实际任务的能力。后来我学乖了,正文只写这个场景下必须知道的东西,通用的规范放到项目根目录的CLAUDE.md里。
正文的结构我一般按这个来:先一句话说明这个 Skill 的目标,然后给 2 到 3 个正例和反例,最后列出检查清单。正反例特别重要,因为 Claude Code 对“示例”的敏感度远高于“规则描述”。你说“props 要定义类型”,它可能理解得模棱两可;但你给一个defineProps<{ title: string }>()的正例,再给一个defineProps(['title'])的反例,它立刻就明白了。
还有一个技巧:正文里可以用##和###做分节,Claude Code 在解析时会把这些标题当作结构线索。但别用太深的层级,三级标题足够了,再深它容易忽略。
3. 四十个 Skill 的选型逻辑:我为什么装这些,不装那些
3.1 按“使用频率”和“出错成本”两个维度筛
装到四十个的时候,我其实砍掉过一批。筛选标准就两个:这个场景我多久遇到一次,以及如果不按规矩来,返工成本有多高。
高频且高成本的,必装。比如“提交信息规范”这个 Skill,我每天要提交七八次,如果格式不对,CI 会卡住,还得重新改。这种 Skill 装上去,收益立竿见影。
低频但高成本的,也装。比如“数据库迁移脚本审查”,一个月可能就两三次,但一旦写错,回滚很麻烦。这种 Skill 平时不触发,关键时刻能兜底。
高频但低成本的,看情况。比如“格式化 JSON”,我随手就能做,装个 Skill 反而增加加载开销,我就没装。
低频且低成本的,坚决不装。纯粹是占位置。
3.2 我实际在用的几类 Skill
按功能分,我的四十个 Skill 大概落在这么几类里:
代码规范类,大概十二个。覆盖 Vue、React、TypeScript、Python、Go 这几个主力语言。每个语言一个主 Skill,再加几个针对特定框架的。比如 Vue 有组件审查、组合式函数检查、路由配置检查三个。
工作流类,大概八个。包括提交信息生成、PR 描述生成、变更日志整理、分支命名检查。这类 Skill 的特点是触发词很明确,基本不会误触发。
文档类,大概六个。比如“给函数补 JSDoc”“生成 API 文档”“更新 README 的变更记录”。这类 Skill 我一般手动触发,不设自动 trigger,因为文档更新时机比较讲究,自动触发容易在不该改的时候改。
排查类,大概五个。比如“分析报错栈”“检查依赖冲突”“定位性能瓶颈”。这类 Skill 的正文里我会放一些常见的排查路径,相当于把经验固化下来。
领域特定类,大概九个。比如数学建模的公式检查、论文引用的格式校验、数据可视化的配色规范。这类 Skill 通用性不强,但在特定项目里价值很高。
剩下的几个是实验性的,还在观察效果,可能过段时间就删了。
3.3 装太多会不会拖慢速度
这是我被问得最多的问题。实测下来,Skill 的数量本身不会显著拖慢响应速度,真正影响速度的是单个 Skill 的正文长度和触发频率。Claude Code 在加载 Skill 时是按需加载的,不是一次性把所有 Skill 都塞进上下文。所以四十个 Skill 里,如果大部分平时不触发,对日常使用几乎没影响。
但有个例外:如果你的 trigger 写得太宽泛,导致每次输入都触发好几个 Skill,那上下文会被迅速占满,响应质量会下降。我踩过这个坑,有个 Skill 的 trigger 里写了“检查”,结果我每次说“检查一下这个函数”,它都会加载,后来我把 trigger 改成了“检查依赖”“检查类型”这种更具体的短语,问题就解决了。
4. 手把手:从零装一个 Skill 并让它真正生效
4.1 目录放哪里,决定了它能不能被找到
Claude Code 查找 Skill 的路径是有优先级的。我一般把项目专用的 Skill 放在项目根目录的.claude/skills/下面,把通用的、跨项目复用的放在用户目录的~/.claude/skills/下面。这样项目级的 Skill 不会污染全局,全局的 Skill 又能在所有项目里用。
目录结构大概长这样:
项目根目录/ ├── .claude/ │ └── skills/ │ ├── vue-component-review/ │ │ └── SKILL.md │ ├── commit-message/ │ │ └── SKILL.md │ └── api-doc-gen/ │ └── SKILL.md ├── CLAUDE.md └── src/注意,每个 Skill 一个独立目录,目录名和 frontmatter 里的name保持一致。我试过目录名和 name 不一致,结果在某些版本里加载会出问题,虽然不报错,但 Skill 就是不生效,排查了半天才发现是这个原因。
4.2 写一个能用的 SKILL.md:完整示例
我拿“提交信息生成”这个 Skill 来演示。这个 Skill 我每天都在用,算是打磨得比较成熟的。
--- name: commit-message description: 根据 git diff 生成符合 Conventional Commits 规范的提交信息,适用于任何需要提交代码的场景 trigger: - "生成提交信息" - "commit message" - "写 commit" version: 1.3.0 ---正文部分:
## 目标 根据当前暂存区的变更,生成一条符合 Conventional Commits 规范的提交信息。 ## 格式要求 提交信息格式为:`<type>(<scope>): <subject>` type 只能是以下之一: - feat:新功能 - fix:修复缺陷 - refactor:重构,不改变外部行为 - docs:文档变更 - test:测试相关 - chore:构建、依赖、配置等杂项 scope 为可选项,用变更涉及的模块名,小写,不加空格。 subject 用中文,不超过 50 个字,结尾不加句号。 ## 正例 feat(user): 增加手机号登录入口 fix(api): 修复分页参数越界导致的 500 错误 refactor(utils): 将日期格式化逻辑抽离为独立函数 ## 反例 更新代码 fix bug feat: 增加了一个新功能,这个功能可以让用户通过手机号登录系统这个 Skill 装上去之后,我每次说“生成提交信息”,它就会先跑git diff --staged,然后按上面的规则输出。实测下来,准确率在九成以上,偶尔 scope 判断得不太准,我手动改一下就行。
4.3 验证 Skill 是否生效的三种方法
装完 Skill 后,别急着用,先验证一下。我一般用这三种方法:
第一种,直接问 Claude Code:“你现在有哪些可用的 Skill?”它会列出当前加载的 Skill 列表。如果新装的没出现,说明路径或 frontmatter 有问题。
第二种,用 trigger 里的关键词触发一次,看它的输出是否符合 Skill 里定义的格式。比如我说“生成提交信息”,如果它输出的格式和 Skill 里写的不一样,说明 Skill 没被加载,或者加载了但被其他 Skill 覆盖了。
第三种,看日志。Claude Code 在加载 Skill 时会有日志输出,具体位置取决于你的安装方式。我一般会在启动时加上--verbose参数,能看到 Skill 的加载过程。这个方法最直接,但日志比较长,适合排查疑难问题。
注意:如果你同时装了多个 Skill,且它们的 trigger 有重叠,Claude Code 可能会加载多个,导致输出混乱。我建议定期检查 trigger 的重叠情况,把不用的 Skill 及时删掉或改 trigger。
5. 那些让我拍大腿的 Skill 设计技巧
5.1 用“检查清单”代替“长篇规则”
我早期写的 Skill,正文动辄两三千字,把团队规范从头到尾抄了一遍。结果 Claude Code 加载后,输出确实规范了,但变得特别死板,稍微超出规范的情况就不会处理了。后来我改成“检查清单”的形式,只列出必须检查的条目,每条一两句话,剩下的交给 Claude Code 自己判断。
比如“Vue 组件审查”这个 Skill,我现在的正文核心就是一张清单:
- props 是否都有类型定义
- 是否使用了
defineProps的泛型形式 - 响应式数据是否用
ref或reactive正确声明 - 模板中是否有未使用的导入
- 事件命名是否用 kebab-case
就这五条,Claude Code 每次审查都会逐条过,输出很稳定。而且因为规则少,它有余力去发现清单之外的问题,反而比之前“死守规则”的效果好。
5.2 把“反例”写进 Skill,比写“正例”还重要
这个技巧是我从一次失败中总结出来的。有个 Skill 我写了很多正例,但 Claude Code 总是输出一些“看起来对但实际不对”的东西。后来我加了几个反例,明确告诉它“这样写是错的”,效果立刻好转。
原因不难理解:正例告诉它“往哪走”,反例告诉它“别往哪走”。只有正例的时候,它可能会走到正例附近的某个“看起来像”的地方;有了反例,边界就清晰了。
我现在的习惯是,每个 Skill 至少配两个反例,反例要写得具体,最好是从实际项目中摘出来的真实错误。
5.3 用version字段做灰度发布
当你有四十个 Skill 的时候,改一个 Skill 可能会影响多个项目。我现在的做法是,改 Skill 时先升version,然后在项目里通过CLAUDE.md指定使用哪个版本。这样新版本可以先在一个项目里试,没问题了再推广到其他项目。
具体做法是在CLAUDE.md里写:
## Skill 版本锁定 - commit-message: 1.3.0 - vue-component-review: 2.1.0Claude Code 在加载 Skill 时会读这个配置,如果版本不匹配就跳过。这个机制不是官方强制的,但我在实际使用中发现它确实能减少“改了一个 Skill,崩了三个项目”的情况。
6. 常见问题与排查实录
6.1 Skill 装了但不生效,怎么查
这是最高频的问题。我整理了一个排查顺序,按这个走,基本能定位到原因:
| 排查步骤 | 检查内容 | 常见问题 |
|---|---|---|
| 1 | 目录路径是否正确 | 放错了层级,比如放到了.claude/skill/而不是.claude/skills/ |
| 2 | frontmatter 格式是否正确 | ---没写全,或者 YAML 缩进错误 |
| 3 | name 是否与目录名一致 | 不一致时部分版本会静默失败 |
| 4 | trigger 是否被其他 Skill 覆盖 | 多个 Skill 的 trigger 重叠,导致加载了错误的那个 |
| 5 | 正文是否过长 | 超过上下文限制时会被截断,导致规则不完整 |
我遇到最多的是第 2 和第 4。第 2 个问题特别隐蔽,因为 YAML 对缩进敏感,多一个空格少一个空格都可能出问题。我的建议是写完 frontmatter 后,用一个 YAML 校验工具过一遍,别靠肉眼。
6.2 多个 Skill 冲突怎么办
冲突的表现是:你触发了一个 Skill,但输出格式是另一个 Skill 的。原因通常是 trigger 重叠。比如“代码审查”和“Vue 组件审查”都写了“审查”这个 trigger,那你说“审查这个组件”时,两个都可能被加载。
解决办法有两个:一是把 trigger 写得更具体,二是用priority字段(如果你的 Claude Code 版本支持)指定优先级。我一般用第一种,因为更直观。把“审查”改成“审查组件”“审查函数”“审查接口”,各管各的,互不干扰。
6.3 Skill 输出不稳定,时好时坏
这个问题我遇到过好几次,最后发现原因通常是 Skill 正文里的规则有歧义。比如我写“函数名要简洁”,什么叫简洁?Claude Code 每次理解都不一样。后来我改成“函数名不超过 20 个字符,用动词开头”,输出立刻就稳定了。
所以,Skill 里的每一条规则,都要可量化、可验证。形容词和模糊表述是稳定性的天敌。
6.4 怎么判断一个 Skill 该不该删
我每个月会做一次 Skill 清理。判断标准很简单:过去一个月里,这个 Skill 触发了几次?如果一次都没触发,而且不是因为场景没出现,而是因为 trigger 写得太偏,那就改 trigger;如果场景本身就没出现,那就删掉。
四十个 Skill 听起来多,但真正高频使用的其实就十来个。剩下的要么是低频兜底,要么是特定项目专用。定期清理能让你对每个 Skill 的状态心里有数,不至于装了一堆自己都忘了的 Skill。
7. 从四十个 Skill 里挑出来的五条硬核经验
第一条,Skill 不是越多越好,是越准越好。我见过有人装了上百个 Skill,结果每次输入都触发一堆,上下文被占满,响应又慢又乱。四十个对我来说是个比较舒服的数字,覆盖了主要场景,又不至于互相干扰。
第二条,frontmatter 的 description 要当 SEO 标题来写。它决定了 Skill 能不能被正确检索到。我现在的写法是“动词 + 对象 + 场景”,比如“审查 Vue 3 组件的 props 和响应式使用”,比“Vue 审查”的命中率高很多。
第三条,正文里多放例子,少讲道理。Claude Code 对示例的敏感度远高于规则描述。一个正例加一个反例,胜过三段文字说明。
第四条,trigger 要具体,别用泛词。“检查”“帮我”“看看”这种词,写了等于没写,还会干扰其他 Skill。用“检查依赖”“帮我生成提交信息”“看看这个组件的 props”这种具体短语。
第五条,定期清理,保持精简。Skill 是有维护成本的,每多一个,就多一份 trigger 冲突的风险和上下文占用的可能。每个月花十分钟过一遍,删掉不用的,改掉不准的,比装新 Skill 的收益还大。
最后分享一个我最近在用的技巧:把 Skill 和CLAUDE.md配合起来用。CLAUDE.md放项目级的通用规范,Skill 放场景级的专项规则。这样 Skill 可以写得很薄,只关注它那个场景,通用的东西不用重复写。我试过把两者合并,结果 Skill 变得特别臃肿,加载慢不说,还容易和其他 Skill 冲突。分开之后,每个 Skill 都清爽了很多,维护起来也轻松。