1. 从 50 个 Skill 里踩出来的血泪教训
我在过去几个月里陆陆续续写了 50 个 Claude Code Skill,从最开始照着文档瞎写,到后来慢慢摸出规律,中间踩的坑实在太多了。最扎心的一个发现是:前 30 个基本等于白写。不是功能跑不起来,而是它们要么重复造轮子,要么结构混乱到我自己过两周都看不懂,要么就是把本该放在项目配置里的东西硬塞进 Skill 里。这篇文章就是把这 50 个 Skill 的实战经验完整拆开,告诉你哪些坑可以提前绕过去,哪些设计思路能让你的 Skill 从"能跑"变成"好用"。
如果你正在用 Claude Code,或者刚开始接触 Skill 这个概念,这篇文章会帮你省下大量试错时间。我会从 Skill 的本质讲起,拆解 SKILL.md 的结构、frontmatter 的写法、和 MCP 的配合方式,再给出可以直接抄的模板和排查清单。不管你是刚安装完 Claude Code 的新手,还是已经写过几个 Skill 想进阶的老手,都能从里面找到能直接用的东西。
先说一个最核心的认知:Skill 不是插件,不是脚本,也不是简单的提示词模板。它更像是给 Claude Code 这个"通用助手"装上一套"专业操作手册",让它在特定场景下知道该按什么流程、用什么工具、遵守什么约束来干活。理解这一点,后面所有的设计决策都会顺很多。
2. Skill 到底是什么:先搞清楚定位再动手
2.1 Skill 和普通提示词的本质区别
很多人第一次接触 Skill,会把它当成"存起来的提示词"。我一开始也是这么理解的,结果写出来的东西就是一堆指令堆砌,Claude Code 执行起来时好时坏。后来才明白,Skill 的核心价值不在于"告诉 Claude 做什么",而在于"定义一套可复用的工作流"。
普通提示词是你每次对话时临时给的指令,用完就没了。Skill 则是持久化的、结构化的能力单元,它包含几个关键要素:触发条件(什么时候该用这个 Skill)、执行流程(按什么步骤做)、工具依赖(需要调用哪些工具或 MCP)、输出规范(结果应该长什么样)。这四样东西缺一个,Skill 就会变得不可靠。
举个例子,我早期写过一个"代码审查 Skill",内容就是"请审查以下代码,找出问题并给出建议"。这东西看起来没毛病,但实际用起来效果很差,因为 Claude 每次审查的角度都不一样,有时候关注性能,有时候关注可读性,输出格式也飘忽不定。后来我把它重写成结构化的 Skill,明确定义了审查维度(安全性、性能、可维护性、边界条件)、每个维度的检查清单、以及固定的输出格式,效果立刻稳定了。
2.2 SKILL.md 的文件结构长什么样
一个标准的 Skill 就是一个目录,核心文件是SKILL.md。这个文件分两部分:顶部的 frontmatter 元数据,和下面的正文内容。
frontmatter 用 YAML 格式写在---之间,最关键的字段是name和description。name是 Skill 的唯一标识,description决定了 Claude 什么时候会触发这个 Skill。我见过太多人把 description 写得含糊不清,结果 Skill 要么不触发,要么在不该触发的时候乱触发。
正文部分就是具体的指令内容,可以用 Markdown 组织,支持标题、列表、代码块等。这里有个经验:正文不要写得太长太啰嗦,Claude 的上下文是有限的,Skill 内容越长,留给实际任务的空间就越少。我一般控制在 500 到 1500 字之间,把最关键的流程和约束写清楚就行。
2.3 为什么前 30 个 Skill 会白写
回头看那 30 个失败的 Skill,问题集中在几个方面。第一是定位错误,把本该用 MCP 解决的事情硬写成 Skill,比如需要实时访问外部数据的场景,Skill 根本做不到。第二是粒度过细,一个 Skill 只做一件极小的事,导致需要写几十个 Skill 才能完成一个完整任务,维护成本爆炸。第三是缺乏复用设计,每个 Skill 都是独立的一次性产物,没有考虑参数化和组合。
最典型的一个例子是我写的"生成 commit message"Skill。第一版就是简单的一句"根据 diff 生成规范的 commit message",结果生成的格式五花八门。第二版加了格式约束,好了一点,但还是经常不符合团队规范。直到第三版,我才想明白应该把团队的 commit 规范完整写进去,包括类型前缀、scope 规则、描述长度限制、以及几个正反示例。这一版才真正可用。
3. 写 Skill 前必须想清楚的五件事
3.1 这个需求真的适合用 Skill 吗
不是所有需求都适合做成 Skill。判断标准很简单:如果这个任务需要实时数据、需要复杂的外部 API 调用、或者需要长时间运行的状态管理,那它更适合用 MCP 或者直接写脚本。Skill 最擅长的是"流程性、知识性、规范性的任务",比如代码审查、文档生成、格式转换、按固定流程排查问题。
我踩过的一个坑是写了个"查询数据库"Skill,想让 Claude 能直接查数据。结果发现 Skill 根本没法维持数据库连接,每次都要重新配置,还不如直接用 MCP 封装一个数据库工具。后来我把这个 Skill 删了,改用 MCP 方案,问题立刻解决。
3.2 触发条件怎么设计才精准
description 字段是 Skill 的"门面",它决定了 Claude 在什么情况下会加载这个 Skill。写得太宽泛,Skill 会到处乱触发;写得太窄,又该触发的时候不触发。
我的经验是,description 里要包含三类信息:动作(这个 Skill 做什么)、场景(什么情况下用)、关键词(用户可能提到的词)。比如一个"API 文档生成"Skill 的 description 可以写成:"根据代码中的路由定义和注释,生成符合 OpenAPI 规范的接口文档。当用户需要为后端接口生成文档、更新 API 说明、或检查接口文档完整性时使用。"
这样写的好处是,Claude 能通过"生成文档""API 说明""接口文档"这些关键词准确匹配到场景,不会在无关的时候触发。
3.3 输出格式要不要严格约束
这个问题我纠结了很久。早期我倾向于让 Claude 自由发挥,觉得这样更灵活。但实际用下来发现,输出格式不固定的 Skill 几乎没法用在自动化流程里,因为下游处理没法预期结果长什么样。
后来我改成严格约束输出格式,用模板加示例的方式明确告诉 Claude 应该输出什么结构。比如要求输出 JSON 就给出完整的 schema,要求输出 Markdown 就给出标题层级和字段顺序。这样虽然牺牲了一点灵活性,但换来的是可靠性,值得。
3.4 要不要依赖 MCP
MCP 是 Claude Code 连接外部工具的协议,它让 Claude 能调用文件系统、数据库、浏览器等各种能力。Skill 和 MCP 的关系是:Skill 定义"做什么和怎么做",MCP 提供"用什么工具做"。
我的建议是,如果任务需要访问外部资源,优先考虑 MCP。Skill 里只需要写清楚"调用哪个 MCP 工具、传什么参数、怎么处理返回结果"就行。不要把本该 MCP 做的事硬塞进 Skill,那样只会让 Skill 变得臃肿且不可靠。
3.5 怎么判断 Skill 写得好不好
我总结了一个简单的判断标准:把 Skill 交给一个完全不了解背景的同事,他能不能照着 Skill 的描述,在 Claude Code 里复现出稳定的结果。如果能,说明 Skill 写得合格;如果不能,说明还有模糊地带需要补充。
另一个标准是看 Skill 的复用率。好的 Skill 应该能在多个项目、多个场景下重复使用。如果一个 Skill 只在某个特定项目里用过一次就再也没用过,那它大概率设计得不够通用。
4. 一个高质量 Skill 的完整拆解
4.1 从零写一个代码审查 Skill
我拿一个实际在用的"代码审查"Skill 来完整拆解,这个 Skill 是我迭代了五版之后才稳定下来的。
首先是目录结构,我习惯这样组织:
skills/ code-review/ SKILL.md templates/ review-output.md examples/ good-review.md bad-review.mdSKILL.md是主文件,templates放输出模板,examples放正反示例。这种结构的好处是主文件保持简洁,细节内容按需加载。
4.2 frontmatter 的写法细节
这个 Skill 的 frontmatter 是这样的:
--- name: code-review description: 对代码进行结构化审查,覆盖安全性、性能、可维护性和边界条件四个维度。当用户提交代码片段、文件或 PR 需要审查,或提到"代码审查""review""检查代码"时使用。 ---注意 description 里明确列出了四个审查维度,这样 Claude 在触发时就知道这个 Skill 的覆盖范围。同时列出了触发关键词,提高匹配准确率。
4.3 正文流程的分步设计
正文部分我分成几个明确的步骤,每一步都有具体的操作要求:
第一步是"识别输入类型",判断用户给的是单个文件、代码片段还是整个 PR。不同类型的输入,审查策略不一样。
第二步是"逐维度审查",按照安全性、性能、可维护性、边界条件的顺序,每个维度用固定的检查清单过一遍。这里我会把每个维度的检查项列出来,比如安全性维度包括:输入验证、SQL 注入、XSS、敏感信息泄露、权限检查等。
第三步是"分级标注问题",把发现的问题按严重程度分成 blocker、major、minor 三级。blocker 是必须修复的,major 是建议修复的,minor 是可以忽略的。
第四步是"生成结构化输出",按照模板输出审查结果,包含问题列表、修复建议、以及整体评价。
4.4 输出模板的设计思路
输出模板我放在templates/review-output.md里,内容大致是这样:
## 审查结果 ### 整体评价 [一句话总结代码质量] ### 问题列表 #### Blocker - [文件:行号] 问题描述 - 原因: - 建议: #### Major ... #### Minor ... ### 亮点 [值得肯定的地方]这个模板的好处是结构固定,下游可以直接解析。同时保留了"亮点"部分,避免审查结果全是负面反馈,这在团队协作里很重要。
4.5 正反示例的作用
examples目录里我放了两个示例,一个是好的审查输出,一个是差的。好的示例展示了完整的结构、具体的建议、以及恰当的语气。差的示例展示了常见问题,比如问题描述模糊、建议不可操作、语气过于苛刻。
这两个示例的作用是给 Claude 提供"参照物",让它在生成输出时有个明确的对标。实测下来,加了示例之后,输出质量的稳定性提升非常明显。
5. 那些让我返工的坑和排查方法
5.1 Skill 不触发怎么办
这是最常见的问题。我遇到过好几次写完 Skill 但 Claude 完全不理的情况。排查思路是这样的:
先检查 frontmatter 格式是否正确,YAML 对缩进和符号很敏感,一个多余的空格都可能导致解析失败。然后检查 description 是否包含用户可能提到的关键词,如果用户说"帮我看看这段代码",而你的 description 里只有"代码审查",那可能匹配不上。最后检查 Skill 的存放位置是否正确,不同版本的 Claude Code 对 Skill 目录的要求可能不一样。
我踩过最坑的一次是 frontmatter 里用了中文冒号,看起来没问题,但解析直接失败。这种问题很难发现,建议写完 Skill 后先用一个简单的测试用例验证一下。
5.2 Skill 触发太频繁怎么办
反过来,有些 Skill 会在不该触发的时候乱触发。这通常是 description 写得太宽泛导致的。比如一个"文档生成"Skill,如果 description 只写"生成文档",那用户说"帮我写个 README"时也可能触发。
解决办法是在 description 里加上明确的场景限定,比如"当用户需要为代码生成 API 文档时使用",把范围收窄。同时可以在正文里加一句"如果输入不满足以下条件,请忽略本 Skill",给 Claude 一个主动跳过的选项。
5.3 输出格式不稳定怎么办
这个问题我折腾了很久。即使写了模板,Claude 有时候还是会自由发挥。后来发现几个关键点:
模板要足够具体,不能只说"输出 Markdown 格式",而要给出完整的结构示例。示例要放在正文里,不能只放在单独的文件里,因为 Claude 不一定每次都会去读那些文件。约束要用强指令,比如"必须严格按照以下格式输出,不得增删字段",而不是"建议按照以下格式"。
5.4 Skill 之间冲突怎么办
当你有多个 Skill 时,可能会出现两个 Skill 都想处理同一个请求的情况。我的经验是,在 description 里明确写出"不适用场景",主动排除掉不该触发的范围。比如代码审查 Skill 可以写"不适用于代码生成、重构建议等场景",把边界划清楚。
5.5 常见问题速查表
| 问题现象 | 可能原因 | 排查方法 |
|---|---|---|
| Skill 完全不触发 | frontmatter 格式错误 | 检查 YAML 缩进和符号 |
| Skill 触发但结果不对 | 正文指令模糊 | 补充具体步骤和示例 |
| 输出格式飘忽 | 模板不够具体 | 给出完整结构示例 |
| 多个 Skill 冲突 | description 范围重叠 | 明确写出不适用场景 |
| Skill 加载慢 | 正文内容过长 | 拆分或精简内容 |
| MCP 调用失败 | 工具名或参数错误 | 检查 MCP 配置和工具签名 |
6. 让 Skill 真正好用的进阶技巧
6.1 参数化设计让 Skill 更通用
早期我写的 Skill 都是硬编码的,比如"审查 Python 代码"。后来发现这样复用性太差,改成参数化之后,一个 Skill 能覆盖多种场景。
参数化的做法是在正文里定义变量,比如{{language}}、{{framework}}、{{strictness}},然后在 description 里说明这些参数怎么传。Claude 会根据上下文自动填充这些变量。这样同一个 Skill 就能处理 Python、JavaScript、Go 等多种语言的审查。
6.2 用 MCP 扩展 Skill 的能力边界
Skill 本身只能做"知识性"的工作,要访问外部资源必须靠 MCP。我常用的几个 MCP 组合是:文件系统 MCP 让 Skill 能读写文件,Git MCP 让 Skill 能查看提交历史,浏览器 MCP 让 Skill 能抓取网页内容。
关键是要在 Skill 里明确写出"调用哪个 MCP 工具、传什么参数"。比如"使用 filesystem MCP 的 read_file 工具读取目标文件,参数为文件路径"。这样 Claude 就知道该调用什么,不会瞎猜。
6.3 版本管理和迭代策略
Skill 也是代码,需要版本管理。我的做法是在 Skill 目录里放一个CHANGELOG.md,记录每次修改的原因和内容。同时在 frontmatter 里加一个version字段,方便追踪。
迭代策略上,我建议小步快跑。每次只改一个点,改完立刻测试,确认有效再继续。不要一次性大改,那样出问题很难定位。
6.4 团队协作中的 Skill 规范
如果是团队使用,Skill 需要统一规范。我们团队的做法是:所有 Skill 必须包含 description、正文流程、输出模板、至少一个示例。命名统一用小写加连字符,比如code-review、api-doc-gen。每个 Skill 必须有负责人,负责维护和更新。
另外建议建一个 Skill 索引文档,列出所有 Skill 的名称、用途、负责人、最后更新时间。这样新人能快速了解团队有哪些能力可用。
6.5 实测有效的三个小技巧
第一个技巧是在 Skill 开头加一句"在开始之前,先确认以下前提条件是否满足",让 Claude 先做一次自检,避免在不满足条件的情况下硬执行。
第二个技巧是在 Skill 结尾加一句"完成后,请简要说明执行了哪些步骤",这样你能看到 Claude 的实际执行路径,方便排查问题。
第三个技巧是把常用的 Skill 组合成一个"工作流 Skill",比如"代码提交前检查"可以组合代码审查、测试运行、commit message 生成三个 Skill,一次调用完成整个流程。
7. 我个人的一些体会
写了 50 个 Skill 之后,最大的感受是:Skill 的质量不取决于你写了多少,而取决于你想得有多清楚。前 30 个白写的根本原因,是我在没想清楚需求、场景、输出格式的情况下就急着动手,结果写出来的东西自己都不想用。
现在我写 Skill 的流程固定下来了:先用一句话说清楚这个 Skill 解决什么问题,然后列出触发场景和不适用场景,再设计输出格式,最后才动手写正文。这个顺序看起来慢,但实际上省下了大量返工时间。
另外一点体会是,Skill 不是越多越好。我现在维护的 Skill 只有十几个,但每一个都是经过多次迭代、在多个项目里验证过的。与其写一堆半成品,不如把几个核心 Skill 打磨到真正好用。这个道理说起来简单,但真要做到,需要克制"多写几个"的冲动。