
1. 从 50 个 Skill 里爬出来的血泪教训我在过去几个月里陆续写了 50 个 Claude Code Skill从最开始照着文档瞎摸索到后来慢慢摸出一些门道中间踩的坑实在太多了。最扎心的一个感受就是前 30 个基本白写了。不是功能跑不通而是写完之后发现根本没人用包括我自己——因为触发时机不对、描述写得含糊、结构设计得太复杂导致 Claude 压根不知道什么时候该调用它。这篇文章不是官方文档的复述也不是什么“保姆级教程”。我想做的是把“为什么前 30 个白写了”这件事拆开讲清楚 Skill 到底该怎么设计、SKILL.md 该怎么写、触发条件怎么设、和 MCP 怎么配合、以及那些只有真正写过几十个 Skill 之后才会明白的细节。如果你正在用 Claude Code或者准备给自己的项目加 Skill又或者你只是好奇“Skill 和 MCP 到底有什么区别”那这篇内容应该能帮你少走不少弯路。先给一个最直观的结论Skill 的核心不是“写代码”而是“写触发条件”和“写上下文约束”。很多人包括前 30 个的我把 Skill 当成一个函数来写觉得只要逻辑对就行。但 Claude Code 的 Skill 本质上是一个“给模型看的说明书”它需要让模型在正确的时机、用正确的方式、拿正确的上下文去执行一件事。逻辑只是其中一部分甚至不是最重要的那部分。下面我会从整体设计思路开始拆然后逐层深入到 SKILL.md 的结构、触发条件的写法、和 MCP 的配合方式、常见报错和排查技巧最后再聊几个我实际在用的 Skill 案例。内容会比较长但如果你真的想写出“能被用起来”的 Skill这些细节都值得过一遍。2. Skill 到底是什么和 MCP 有什么区别2.1 用一句话说清楚 Skill 的定位Claude Code 的 Skill 可以理解成“给 Claude 预设的一套操作手册”。你写一个 SKILL.md里面描述这个 Skill 是干什么的、什么时候该用、用了之后按什么步骤执行、需要哪些参数、输出什么格式。Claude 在对话过程中会根据你的描述来判断是否触发这个 Skill。它和 MCP 最大的区别在于MCP 是“能力扩展”Skill 是“行为约束”。MCP 解决的是“Claude 能不能访问某个外部系统”的问题比如能不能读数据库、能不能调某个 API、能不能操作某个工具。Skill 解决的是“Claude 在某个场景下应该怎么做”的问题比如“当用户要求生成周报时按固定格式整理本周 commit 记录并输出”。打个比方MCP 像是给 Claude 装了一双手让它能去够到外面的东西Skill 像是给 Claude 一本操作手册告诉它“够到东西之后该怎么处理”。两者不是替代关系而是配合关系。我见过不少人一上来就想用 Skill 去实现 MCP 的功能结果写出来的东西又臃肿又难维护。2.2 为什么前 30 个 Skill 会白写回头看我最早写的那些 Skill问题基本集中在三个地方第一描述写得太抽象。比如我写过一个“代码审查 Skill”描述是“用于审查代码质量”。这个描述对 Claude 来说几乎没有信息量因为“审查代码质量”这件事在任何编程对话里都可能发生Claude 根本不知道什么时候该触发它。后来我改成“当用户提交了一个 Pull Request 链接或者明确说‘帮我看看这段代码有没有问题’时按以下清单逐项检查”触发率立刻上来了。第二步骤写得太细但缺少判断逻辑。我早期喜欢把每一步都写死比如“第一步读取文件第二步提取函数名第三步检查命名规范”。但实际场景里用户给的东西千奇百怪写死的步骤很容易在第二步就卡住。后来我学会在关键节点加“如果……则……否则……”的分支判断让 Skill 有一定的弹性。第三没有考虑上下文长度。有些 Skill 我塞了大量示例和规则进去结果 SKILL.md 本身就有好几千字。Claude 在触发这个 Skill 的时候光读描述就消耗了大量上下文真正执行的时候反而没空间了。后来我学会把非核心内容拆到单独的参考文件里SKILL.md 只保留最关键的触发条件和执行框架。这三个问题加起来导致我前 30 个 Skill 里有不少是“写完了但从来没被触发过”或者“触发了但执行到一半就偏了”。真正好用的 Skill往往不是功能最复杂的而是触发条件最清晰、执行路径最短的那些。2.3 一个 Skill 的最小可用结构一个能跑起来的 Skill最少需要包含这几个部分名称简短、唯一、能一眼看出用途。触发描述什么情况下该用这个 Skill。这是最重要的部分。执行步骤触发之后按什么顺序做什么事。输入输出约定需要用户提供什么最终产出什么格式。边界条件什么情况下不该用这个 Skill或者需要额外确认。这五个部分里触发描述和执行步骤是核心输入输出和边界条件是加分项。我后来写 Skill 的时候会先花一半时间想触发描述剩下时间才去写具体步骤。因为触发描述写不好后面写得再漂亮也没用。3. SKILL.md 的结构设计与触发条件写法3.1 SKILL.md 的推荐结构我现在写 SKILL.md 基本遵循一个固定骨架虽然不同场景会微调但整体结构比较稳定# Skill 名称 ## 何时使用 描述触发条件越具体越好 ## 前置条件 需要哪些环境、文件、权限 ## 执行步骤 分步骤描述关键节点加判断 ## 输出格式 最终产出什么用什么格式 ## 注意事项 容易出错的地方、边界情况这个结构看起来简单但每个部分都有讲究。比如“何时使用”这一节我一般会写三到五条具体的触发场景而不是一句抽象的描述。“前置条件”是为了让 Claude 在触发之前先确认环境是否满足避免执行到一半发现缺东西。“执行步骤”里我会刻意留一些“如果……则……”的分支让 Skill 有应对变化的能力。3.2 触发条件到底该怎么写触发条件是 Skill 的灵魂。我总结了一个原则用“用户会说的话”来写触发条件而不是用“技术术语”来写。举个例子我写过一个“生成接口文档”的 Skill。最早的触发描述是“当需要生成 API 文档时使用”。这个描述的问题在于用户很少会说“我需要生成 API 文档”他们更可能说“帮我把这几个接口整理一下”、“这个 Controller 能不能输出成文档”、“我要给前端写接口说明”。后来我把触发描述改成当用户提到“整理接口”、“输出接口说明”、“生成 API 文档”时触发。当用户提供了一个 Controller 文件或一组接口定义并要求“说明每个接口的用途”时触发。当用户说“给前端写一份接口对接说明”时触发。改完之后这个 Skill 的触发率明显提升。原因很简单Claude 在判断是否触发时是在匹配用户的实际表达而不是在匹配你脑子里的技术分类。还有一个技巧是在触发描述里加入“反例”。比如“当用户只是询问某个接口的参数含义时不要触发这个 Skill直接回答即可”。这样能避免 Skill 在不该触发的时候被触发减少干扰。3.3 执行步骤的粒度控制执行步骤写多细我的经验是写到“一个刚入行的开发者能照着做”的程度就够了不要写到“每一步的每个按键”。太粗了 Claude 会自由发挥太细了又容易卡死。我一般会把一个 Skill 拆成 5 到 8 个步骤每个步骤用一句话描述目标必要时加一个判断分支。比如读取用户指定的文件或目录确认文件类型和数量。如果文件数量超过 10 个先输出文件清单让用户确认再继续。逐个提取关键信息按统一格式整理。如果遇到无法解析的内容记录到“待确认”列表不要中断流程。汇总输出并在末尾附上“待确认”列表。这种写法既给了 Claude 明确的路径又留了处理异常的余地。实测下来比那种“第一步做什么、第二步做什么、第三步做什么”的机械写法要稳得多。3.4 一个实际案例Spring Boot 接口整理 Skill我拿一个实际在用的 Skill 来举例。这个 Skill 的作用是当用户给出一个 Spring Boot 项目的 Controller 目录时自动整理出所有对外接口的清单包括路径、方法、参数、返回值说明。触发描述我写的是当用户提供 Spring Boot 项目的 Controller 文件或目录并要求“整理接口”、“输出接口清单”、“生成接口文档”时触发。当用户说“帮我看看这个项目有哪些对外接口”时触发。当用户要求“给第三方写接口说明”时触发。执行步骤大致是扫描用户指定的目录找出所有带RestController或Controller注解的类。对每个类提取类级别的RequestMapping路径。对每个方法提取GetMapping、PostMapping等注解拼接完整路径。提取方法参数和返回值类型如果参数是自定义对象尝试读取该对象的字段定义。按“路径 | 方法 | 参数 | 返回值 | 说明”的格式输出表格。如果某个接口的说明不明确标注“待补充”不要自行编造。这个 Skill 我用了大概两个月触发率很高输出也比较稳定。关键就在于触发描述里用了“整理接口”、“输出接口清单”这些用户实际会说的词而不是“生成 API 文档”这种技术术语。4. Skill 和 MCP 的配合方式4.1 什么时候该用 Skill什么时候该用 MCP这个问题我被问过很多次。我的判断标准很简单如果这件事需要访问 Claude 本身访问不到的外部系统用 MCP如果这件事只是对已有信息做处理用 Skill。比如你要让 Claude 读取本地数据库里的数据这需要 MCP因为 Claude 本身没有数据库连接能力。但你要让 Claude 把读取到的数据按某个格式整理成报告这用 Skill 就够了。再比如你要让 Claude 调用某个内部 API 获取用户信息这需要 MCP。但你要让 Claude 根据用户信息生成一封通知邮件这用 Skill 就行。实际场景里两者经常是配合使用的。MCP 负责“拿到数据”Skill 负责“处理数据”。我现在的做法是先用 MCP 把外部能力接进来然后针对常见的数据处理场景写对应的 Skill。这样 Claude 在拿到数据之后能自动按预设的方式处理不需要用户每次都重复描述。4.2 MCP 工具流式输出到文件的 Skill 设计有一个场景我印象比较深用 MCP 工具获取数据后需要把结果流式写入文件。这个场景如果只靠 MCP每次都要用户手动指定输出路径和格式如果只靠 Skill又拿不到数据。所以我把两者结合起来。Skill 的触发描述写的是当用户要求“把 MCP 工具的输出保存到文件”时触发。当用户说“把刚才查到的内容写到某个文件里”时触发。执行步骤是确认用户指定的输出文件路径和格式。调用对应的 MCP 工具获取数据。如果数据是流式的按块读取并追加写入文件。写入完成后输出文件路径和总行数/总大小。如果写入过程中出现错误保留已写入部分并输出错误信息。这个 Skill 的关键在于“流式写入”的处理。如果一次性把数据全部读进内存再写入遇到大数据量时容易出问题。所以我在步骤里明确写了“按块读取并追加写入”让 Claude 知道要用流式方式处理。4.3 MCP 协议在 Skill 里的角色MCP 协议本身对 Skill 来说是透明的。Skill 不需要知道 MCP 底层是怎么通信的它只需要知道“调用哪个工具、传什么参数、拿什么结果”。所以我在写 Skill 的时候会把 MCP 工具当成一个普通的函数来引用不会去描述协议细节。但有一个点需要注意MCP 工具的返回格式可能不稳定。有些工具返回 JSON有些返回纯文本有些返回结构化对象。如果 Skill 里写死了“假设返回 JSON”遇到纯文本返回时就会出错。所以我现在会在 Skill 里加一步“先判断返回格式再决定怎么解析”。5. 实操从零写一个能用的 Skill5.1 准备工作明确场景和边界在动手写之前先问自己三个问题这个 Skill 解决的是什么场景下的什么问题用户在这个场景下通常会说什么话这个 Skill 不该在什么情况下被触发这三个问题的答案基本就构成了 SKILL.md 的触发描述和边界条件。我早期跳过这一步直接开始写步骤结果就是写出来的 Skill 触发条件模糊经常在不该触发的时候被触发。5.2 编写 SKILL.md 的完整流程我现在的流程大概是先写“何时使用”列出三到五条具体触发场景再加一到两条反例。再写“前置条件”确认需要哪些环境、文件、权限。然后写“执行步骤”控制在 5 到 8 步关键节点加判断。接着写“输出格式”明确最终产出是什么。最后写“注意事项”把容易出错的地方列出来。写完之后我会自己模拟几个用户输入看看触发描述是否能覆盖这些输入。如果某个输入无法被触发描述覆盖就补充进去如果某个输入不该触发但被覆盖了就加反例。5.3 参数计算与选择过程有些 Skill 涉及参数计算比如“根据文件数量决定是否分批处理”。这种时候我会在 Skill 里写清楚计算逻辑而不是让 Claude 自己猜。比如我写过一个“批量处理文件”的 Skill里面有一段如果文件数量小于等于 5一次性处理。如果文件数量在 6 到 20 之间分两批处理每批不超过 10 个。如果文件数量超过 20先输出文件清单让用户确认再决定分批策略。这种明确的阈值设定比“根据文件数量决定”这种模糊描述要可靠得多。Claude 不需要自己判断“多少算多”它只需要按你给的阈值执行就行。5.4 实操现场记录一个 Skill 的调试过程我拿最近写的一个“代码变更摘要”Skill 来举例。这个 Skill 的作用是当用户提供一组 git commit 记录时自动生成一份变更摘要按模块分类并标注影响范围。第一版触发描述写的是“当用户提供 commit 记录时触发”。测试的时候发现用户只是贴了一行 commit message 问“这是什么意思”也会触发这个 Skill明显过度触发了。第二版改成“当用户提供三条以上 commit 记录并要求‘总结’、‘整理’、‘生成摘要’时触发”。这次触发准确多了但遇到用户说“帮我看看这些改动”时又没触发。第三版改成“当用户提供多条 commit 记录并要求‘总结’、‘整理’、‘生成摘要’、‘看看这些改动’时触发”。同时加了一条反例“当用户只提供一条 commit 记录时不要触发”。这一版跑了两周触发准确率明显提升。整个过程让我意识到触发描述不是一次写好的而是需要根据实际使用情况不断调整。6. 常见问题与排查技巧实录6.1 Skill 不触发怎么办这是最常见的问题。排查思路按顺序来第一检查触发描述是否用了用户实际会说的词。如果你写的是“生成 API 文档”但用户说的是“整理接口”那大概率不会触发。解决办法是把用户可能的表达方式都列进去。第二检查是否有反例写得太宽。比如你写了“当用户只是询问参数含义时不要触发”但用户的实际输入可能被判定为“询问参数含义”导致该触发的时候没触发。解决办法是把反例写得更具体。第三检查 SKILL.md 是否太长。如果描述部分超过一定长度Claude 可能在读取阶段就消耗了太多上下文导致触发判断变弱。解决办法是把非核心内容拆到单独文件里。6.2 Skill 触发了但执行偏了怎么办执行偏了通常是因为步骤描述不够明确或者缺少判断分支。排查思路第一检查步骤里是否有“如果……则……”的分支。如果没有Claude 遇到异常情况时容易自由发挥。第二检查是否有“不要自行编造”这类约束。有些 Skill 需要严格按输入处理不允许 Claude 补充不存在的信息。这种约束要写清楚。第三检查输出格式是否明确。如果只写“输出一份报告”Claude 可能会用各种格式。如果写“输出 Markdown 表格列为路径、方法、参数、返回值”就会稳定很多。6.3 常见问题速查表问题现象可能原因解决办法Skill 完全不触发触发描述用了技术术语而非用户表达改用用户实际会说的词Skill 过度触发触发描述太宽泛缺少反例加具体反例缩小触发范围执行到一半卡住步骤缺少异常处理分支在关键节点加“如果……则……”输出格式不稳定输出格式描述不明确明确指定格式和字段上下文不够用SKILL.md 太长拆分非核心内容到单独文件MCP 返回解析失败假设了固定返回格式先判断格式再解析6.4 几个容易忽略的细节第一个细节Skill 名称不要用缩写。我早期写过一个叫“CR Skill”的本意是 Code Review但 Claude 在判断时经常把它和“Create”、“Convert”混淆。后来改成“代码审查与问题清单”触发准确率立刻上来了。第二个细节前置条件要写清楚。比如“需要用户提供文件路径”、“需要项目使用 Maven 构建”。如果前置条件不满足Skill 应该先提示用户而不是直接开始执行。第三个细节输出里加一个“待确认”列表。有些信息在输入里不明确Claude 不应该自行编造而应该记录到“待确认”列表里让用户后续补充。这个习惯能大幅减少输出错误。7. 几个我实际在用的 Skill 案例7.1 Spring Boot 接口清单整理这个前面提过是我用得最频繁的 Skill 之一。触发描述里包含了“整理接口”、“输出接口清单”、“生成接口文档”、“给第三方写接口说明”等表达。执行步骤里加了“如果参数是自定义对象尝试读取字段定义”和“如果说明不明确标注待补充”。实测下来这个 Skill 在处理中等规模项目10 到 30 个接口时表现最好。接口太多的时候输出会很长需要分批处理。7.2 代码变更摘要生成这个 Skill 用于把一组 commit 记录整理成变更摘要。触发描述里写了“提供多条 commit 记录”和“要求总结、整理、生成摘要”。执行步骤里按模块分类并标注影响范围。有一个细节我特意加进去了如果 commit message 里包含“fix”或“修复”归到“问题修复”类别如果包含“feat”或“新增”归到“功能新增”类别。这样分类更稳定。7.3 配置文件对比与差异说明这个 Skill 用于对比两个配置文件输出差异说明。触发描述里写了“对比配置文件”、“找出配置差异”、“说明改了什么”。执行步骤里先解析两个文件再逐项对比最后按“新增、删除、修改”三类输出。这个 Skill 的关键在于处理嵌套结构。如果配置文件是 YAML 或 JSON需要递归对比。我在步骤里写了“如果遇到嵌套结构递归对比并在输出里用缩进表示层级”。7.4 项目依赖检查与版本对齐这个 Skill 用于检查项目依赖找出版本不一致的地方。触发描述里写了“检查依赖版本”、“对齐依赖”、“看看有没有版本冲突”。执行步骤里先读取依赖文件再提取版本号最后输出不一致的项。这个 Skill 我一般配合 MCP 使用先用 MCP 读取依赖文件再用 Skill 做对比分析。8. 写 Skill 这件事我踩过的坑和总结的经验写到现在我最大的感受是Skill 的质量不取决于你写了多少行而取决于触发描述有多准、执行路径有多短、异常处理有多全。前 30 个 Skill 白写本质上是因为我把精力花在了“功能实现”上而忽略了“触发时机”和“上下文约束”。如果让我给刚开始写 Skill 的人一条建议我会说先花时间想清楚“用户会在什么情况下说哪些话”然后再动手写步骤。触发描述写好了Skill 就成功了一半。另外不要追求一次写完美。我现在的习惯是先写一个最小可用的版本跑一周根据实际触发情况调整触发描述和步骤。大部分 Skill 都是在第二版或第三版才真正好用的。最后分享一个小技巧在 SKILL.md 里加一段“如果用户输入不明确先提问确认不要直接执行”。这一句话能避免很多因为输入模糊导致的执行偏差。我后来写的每个 Skill 里都有这句话实测下来非常有用。