Claude Code Skills 开发实战:从零构建可复用技能包与 MCP 协同
1. 从技能仓库到能力装配线awesome-claude-skills 到底在解决什么第一次看到awesome-claude-skills这个仓库名很多人的第一反应是又一个 awesome 列表。但真正把 Claude Code 用进日常工作流的人会明白它解决的是一个非常具体的痛点模型本身的能力是通用的而真实任务需要的是专用能力。这两者之间的鸿沟靠反复写提示词是填不平的。举个我自己的例子。我早期用 Claude Code 做前端重构每次都要在对话开头粘贴一大段请遵循以下代码规范、请使用 TypeScript 严格模式、请优先复用现有组件、请写单元测试……。这段提示词写了三十多遍之后我意识到问题不在模型而在我——我把本该固化成技能的东西当成了每次都要重新交代的临时指令。awesome-claude-skills这类仓库的价值就是把这些可复用的能力沉淀成结构化的 skill 包让 Claude Code 在需要的时候自动加载而不是靠人肉复述。所以这篇文章不是带你逛仓库而是带你理解skills 这套机制的设计逻辑以及如何从零构建、调试、组合自己的技能集。关键词里的claude code、mcp、codex、skills 开发、agent skills 测试本质上都指向同一件事如何让 AI 编程助手从通用聊天进化成专用工具链。适合读这篇的人有三类一是已经在用 Claude Code 但还在靠长提示词硬撑的开发者二是想给团队沉淀标准化 AI 工作流的技术负责人三是好奇 agent skills 底层机制、想自己动手写 skill 的工程师。如果你属于这三类中的任何一类下面的内容会帮你少走至少两周弯路。需要先说明一点awesome-claude-skills本身是一个社区维护的技能索引它不提供运行时真正执行 skill 的是 Claude Code 或兼容的 agent 运行时。理解这个分层很重要否则你会误以为装了这个仓库就万事大吉。2. Skill 不是提示词模板拆开一个技能包的内部构造2.1 一个 skill 的最小组成单元很多人把 skill 等同于一段写好的提示词这是最大的误解。一个可用的 skill 至少包含四个部分触发描述description、执行指令instructions、依赖声明dependencies、以及可选的资源文件resources。触发描述决定了 agent 在什么场景下会想起这个技能执行指令是技能被激活后真正注入上下文的内容依赖声明告诉运行时需要哪些工具或 MCP 服务资源文件则是脚本、模板、参考文档等静态资产。我用一个真实场景来说明。假设我要做一个提交信息规范化的 skill它的结构大致是这样name: conventional-commit description: 当用户要求生成 git commit message或需要规范化提交信息时使用 dependencies: - git instructions: | 生成符合 Conventional Commits 规范的提交信息。 格式type(scope): subject type 取值范围feat, fix, docs, style, refactor, test, chore subject 使用中文不超过 50 字不以句号结尾。 如果变更涉及多个模块优先选择影响最大的 scope。注意description的写法。它不是给人看的说明而是给 agent 做语义匹配用的。写得越具体、越贴近真实触发场景被正确调用的概率越高。我见过太多 skill 的 description 写成一个有用的工具结果 agent 永远想不起来用它。2.2 为什么是渐进式加载而不是全量注入这是 skills 机制最精妙的地方也是它区别于把提示词全塞进 system prompt的关键。如果所有技能都常驻上下文token 消耗会爆炸而且模型注意力会被稀释。skills 采用的是渐进式披露progressive disclosure平时只加载每个 skill 的 name 和 description几十个 token只有当 agent 判断当前任务匹配某个 skill 时才把完整的 instructions 注入进来。这个设计带来的直接好处是你可以同时挂载几十个技能而不会显著增加基础开销。代价是匹配准确率变得极其关键——如果 description 写得模糊agent 要么该用的时候不用要么不该用的时候乱用。我在实际调试中发现description 里包含具体的动作动词 对象 场景限定匹配效果最好。比如生成 commit message就比处理 git 相关任务精准得多。2.3 skill 与 MCP 的边界在哪里热词里mcp出现频率极高很多人搞不清 skill 和 MCP 的关系。用一句话概括MCP 解决能不能做skill 解决怎么做。MCPModel Context Protocol是一套让模型访问外部工具和数据的协议它把数据库、文件系统、第三方 API 暴露成模型可调用的能力。而 skill 是编排这些能力的知识。打个比方MCP 像是给工人配了一套电动工具skill 则是老师傅留下的什么活儿用哪个工具、按什么顺序、注意什么的操作手册。一个 skill 的 dependencies 里可以声明它需要哪些 MCP server运行时就会确保这些能力可用。所以你在设计 skill 时先问自己这个任务需要外部能力吗需要的话先确认对应的 MCP 是否就绪再写 skill 去编排它。提示不要试图用 skill 去实现本该由 MCP 承担的功能。skill 里写请读取数据库是没用的除非有对应的 MCP server 提供数据库访问能力。职责分清调试才不会抓瞎。3. 从零写一个能跑起来的 skill完整实操链路3.1 目录结构与放置位置的选择skill 的物理形态就是一个目录里面至少有一个描述文件通常是SKILL.md或带 frontmatter 的 markdown。放置位置决定了它的作用域这一点很多人第一次配会踩坑。常见的有三个层级位置作用域适用场景项目内.claude/skills/仅当前项目项目专属规范、团队约定用户级~/.claude/skills/当前用户所有项目个人通用习惯、跨项目工具插件/仓库分发安装者可见社区共享、团队统一分发我的建议是先放项目级稳定后再提升到用户级。因为项目级 skill 的调试反馈最快改完立刻能在当前项目验证。等一个 skill 在三个以上项目里都验证有效再考虑抽到用户级或打包分发。我早期犯的错就是把一堆半成品 skill 塞进用户级目录结果在某个项目里触发了不该触发的技能排查了半天才发现是全局 skill 在捣乱。3.2 写 description 的三条硬规则前面强调过 description 的重要性这里给出我总结的三条可执行规则包含明确的触发动词。用生成转换检查重构分析这类动作词开头而不是关于……的说明。写清楚适用对象和边界。比如当用户提供 SQL 查询并要求优化性能时使用比SQL 相关精确十倍。避免和已有 skill 语义重叠。如果你有两个 skill 都声称处理代码审查agent 会随机选一个。要么合并要么用更细的限定词区分如安全审查vs风格审查。我实测下来把 description 控制在 30 到 60 个字之间信息密度和匹配准确率最平衡。太短信息不足太长反而引入噪声。3.3 instructions 的写法给流程不给结论instructions 部分最容易写歪。新手常犯的错是写成知识科普比如把 React 的所有最佳实践都堆进去。正确的做法是写成可执行的流程第一步做什么第二步判断什么遇到什么情况走哪个分支。举个例子一个API 接口设计审查的 skillinstructions 应该长这样1. 检查接口路径是否符合 RESTful 命名资源用名词复数动作用 HTTP 方法表达。 2. 检查请求体是否有明确的字段类型和必填标记。 3. 检查响应结构是否统一包装如 { code, data, message }。 4. 检查错误码是否覆盖参数错误、权限不足、资源不存在、服务异常。 5. 对每个不符合项给出具体的修改建议和示例代码。这种写法的好处是可验证——你能明确判断 agent 有没有按步骤执行。而请遵循 RESTful 最佳实践这种写法你根本无法判断它到底做了什么。3.4 本地调试怎么知道 skill 真的被触发了写完 skill 最抓狂的时刻是你不确定它到底有没有生效。我的调试方法分三步。第一步在对话里显式提及 skill 的名字看它是否被加载第二步故意构造一个应该触发它的场景观察输出是否符合 instructions 的流程第三步构造一个不该触发的场景确认它没有误触发。如果 skill 没被触发九成是 description 的问题。这时候不要急着改 instructions先把 description 改得更贴近你的实际提问方式。我有个习惯把平时真实说过的、希望触发这个 skill 的话原样抄进 description 的触发场景里。这招屡试不爽。注意不同版本的 Claude Code 对 skill 的加载时机和匹配策略可能有差异。如果你发现某个 skill 在 A 项目能触发、B 项目不能先检查两个项目的 skill 目录配置是否一致再怀疑匹配逻辑。4. 技能组合与冲突当多个 skill 同时想接管任务4.1 技能叠加的两种模式单个 skill 好用之后你自然会想组合它们。组合有两种模式串行编排和并行叠加。串行编排是指一个任务的输出作为下一个任务的输入比如先做代码审查再生成 commit message。并行叠加是指多个 skill 同时为同一个任务提供约束比如代码规范 skill和安全审查 skill同时作用于一次重构。串行编排相对安全因为职责清晰。并行叠加则容易出问题——如果两个 skill 的 instructions 互相矛盾agent 会陷入两难。我遇到过最典型的冲突是一个 skill 要求所有函数必须写 JSDoc另一个 skill 要求保持代码简洁避免冗余注释。结果 agent 在两者之间反复横跳输出质量反而下降。4.2 冲突排查的完整链路当你怀疑 skill 冲突时按这个顺序排查列出当前可能被触发的所有 skill包括项目级和用户级的。逐个禁用二分定位。先禁用一半看问题是否消失逐步缩小范围。对比冲突 skill 的 instructions找出语义矛盾的具体条款。决定合并还是分层。如果两个 skill 本质是同一件事的不同侧面合并成一个如果是不同优先级用优先级声明或条件触发来分层。我在实际项目里总结出一个原则同一时刻作用于同一类任务的 skill 不超过两个。超过两个冲突概率急剧上升而且调试成本远超收益。4.3 用命名空间避免语义打架一个实用的技巧是给 skill 加命名空间前缀。比如frontend-lint、frontend-a11y、backend-api-review。这样在 description 里就能自然地用前端后端做限定减少跨领域误触发。我见过一个团队把所有 skill 都平铺命名结果代码审查这个 skill 在写文档时也被触发非常尴尬。命名空间还有一个隐性好处便于团队协作。当多人往同一个仓库贡献 skill 时前缀能快速表明归属和领域review 的时候一眼就能看出这个 skill 该由谁维护。5. 把 skill 接进真实工作流几个高价值场景5.1 前端开发从组件生成到样式规范前端是 skills 收益最明显的领域之一因为前端有大量约定大于配置的规范。我给自己配了一套前端 skill 组合component-scaffold按团队模板生成组件骨架、style-guard检查是否使用了设计系统的 token 而非硬编码颜色、a11y-check无障碍属性检查。这三个 skill 的 description 分别锚定不同的触发场景互不干扰。实测下来新组件从手写半小时变成生成后微调五分钟。关键在于component-scaffold的 instructions 里写死了团队的目录结构和命名约定agent 不需要每次问我要放哪里。5.2 后端接口把接口规范变成可执行检查后端场景里我把接口设计规范做成了 skill。它的价值不在于生成接口而在于审查接口。每次写完一个接口我会让 agent 跑一遍这个 skill它会逐条对照规范给出修改建议。这比人工 review 快得多而且不会漏项。这里有个经验把规范拆成必须和建议两档。instructions 里明确标注哪些是硬性要求违反必须改哪些是优化建议可选。这样 agent 的输出有优先级你 review 的时候也能快速抓住重点。5.3 与 MCP 协同让 skill 真正动手纯文本的 skill 只能说要让它做就得接 MCP。比如一个数据库迁移审查的 skill如果配合文件系统 MCP它就能直接读取迁移脚本文件配合数据库 MCP它甚至能检查迁移是否与当前 schema 冲突。我的做法是skill 负责判断逻辑MCP 负责数据获取和执行。skill 的 instructions 里写读取迁移目录下的所有脚本检查是否有破坏性变更具体怎么读、读哪里交给 MCP 的能力去完成。这种分工让 skill 保持轻量也更容易复用。提示在 skill 的 dependencies 里声明 MCP 依赖时写清楚需要的能力类型而非具体实现。这样当底层 MCP server 更换时skill 不需要改。6. 踩过的坑与调试心得6.1 description 写得太聪明反而失效我早期喜欢在 description 里用一些高级表述比如赋能开发流程的智能化编排。结果 agent 完全不知道什么时候该用它。后来改成大白话当用户要求批量重命名文件时使用立刻就能触发了。description 是给机器做匹配的不是给人做宣传的越直白越好。6.2 instructions 太长导致后半段被忽略有一次我写了一个 800 字的 instructions结果 agent 只执行了前 200 字的内容。排查后发现过长的 instructions 在注入时可能被截断或者模型注意力集中在开头。解决办法是把长流程拆成多个 skill或者用步骤清单 详细说明分离的结构让核心步骤始终在前。6.3 忘记清理废弃 skill 导致误触发项目迭代过程中有些 skill 会过时。如果忘记删除它们仍然会被加载和匹配造成莫名其妙的触发。我现在养成的习惯是每个季度 review 一次 skill 目录把三个月没用过的 skill 归档。宁可少而精不要多而乱。6.4 跨项目复用时的路径陷阱把 skill 从项目级提升到用户级时最容易踩的坑是硬编码路径。项目级 skill 里写./src/components没问题但提升到用户级后这个相对路径在不同项目里指向完全不同的地方。解决办法是instructions 里用描述性语言项目的组件目录把具体路径交给 agent 结合当前上下文判断或者通过 MCP 动态获取。7. 关于技能生态的一点个人判断awesome-claude-skills这类仓库的真正价值不在于它收录了多少个 skill而在于它展示了一种能力沉淀的范式。过去我们把经验写在文档里人读了才能用现在我们把经验写成 skillagent 读了就能执行。这个转变的意义比多了一个工具大得多。我自己现在的做法是任何重复三次以上的操作就考虑写成 skill。写的时候不追求完美先跑通再迭代。一个粗糙但能用的 skill价值远高于一个精致但躺在草稿箱里的设想。至于社区里那些现成的 skill我的建议是先读懂再抄——直接拿来用往往因为场景不匹配而效果打折理解它的 description 和 instructions 设计思路再改造成适合自己工作流的版本才是正确姿势。最后分享一个我最近在用的技巧给每个 skill 配一个反例说明即在 instructions 末尾加一句以下情况不要使用本技能……。这能显著降低误触发率尤其是在 skill 数量变多之后。这个细节在大多数教程里都不会提但实测非常有效。