1. 从“装完就吃灰”说起:为什么Skill才是Claude Code的真正分水岭
我大概是在Claude Code刚开放那阵子就开始折腾的。最开始那几周,我的用法跟大多数人一样——打开终端,敲一句需求,等它吐代码,复制粘贴,跑一下,报错,再贴回去让它改。循环往复,效率确实比纯手写高,但总觉得哪里不对劲。直到有一次,我让它帮我处理一个跨了七八个文件的TypeScript重构,它改到第三个文件就开始“失忆”,把前面定好的接口命名规则全忘了,我才意识到问题的根源:它没有一套稳定的、可复用的“工作记忆”和“操作规范”。
后来我开始认真研究Skill这套机制,前前后后给自己的环境里塞了四十来个Skill,覆盖代码审查、文档生成、数据库迁移、前端组件规范、测试用例补全、日志排查等场景。装完之后回头看,之前那种“裸用”Claude Code的方式,基本等于把一台数控机床当锤子使。这篇文章就把我这段时间的踩坑经验、Skill的设计逻辑、以及怎么避免“装了四十个结果一个都用不上”的尴尬,完整地聊一遍。
先给完全没接触过的朋友一个最直白的定义:Skill就是一份写给AI看的“岗位操作手册”。它通常是一个Markdown文件,里面写清楚了在什么场景下、按照什么步骤、遵守什么约束、输出什么格式。Claude Code在启动时会读取这些Skill,当你的请求匹配到某个Skill的描述时,它就会按照手册里的流程来执行,而不是每次即兴发挥。
这跟CLAUDE.md的区别在哪?CLAUDE.md更像是“公司员工手册”,全局生效,讲的是项目背景、代码风格、通用禁忌。而Skill是“岗位SOP”,针对具体任务类型,颗粒度更细,可以按需加载。MCP则是另一层——它解决的是“AI能调用哪些外部工具”的问题,比如读写数据库、操作浏览器、调用设计稿接口。三者是叠加关系,不是替代关系。我见过太多人把这三个概念搅在一起,结果配置写得一团乱,最后怪工具不好用。
适合读这篇的人:已经在用Claude Code但感觉效率没拉满的开发者、正在搭建团队AI工作流的Tech Lead、以及想搞清楚Agent和Skill到底怎么配合的进阶用户。如果你还没装过Claude Code,建议先把基础跑通再回来看,不然容易消化不良。
2. Skill、MCP、Agent三者到底怎么分工
2.1 用一个餐厅类比把三层关系讲透
我习惯用餐厅来类比这套体系。Agent是餐厅经理,负责理解客人(用户)的需求,决定这桌菜该走什么流程,协调后厨和前厅。Skill是菜谱,告诉厨师这道菜先放什么后放什么,火候怎么控,摆盘什么标准。MCP是厨房里的设备接口,比如烤箱、洗碗机、冷藏柜,经理和厨师通过标准接口去调用它们,而不需要关心设备内部怎么运转。
这个类比能解释很多实际困惑。比如有人问“我有了MCP为什么还要Skill”——因为MCP只告诉你“你能用烤箱”,但没告诉你“做舒芙蕾的时候烤箱要预热到多少度、中途不能开门”。Skill补的就是这层操作知识。反过来,只有Skill没有MCP,就像有菜谱但没有烤箱,很多需要外部数据或操作的动作做不了。
再往细说,Agent的决策逻辑是动态的,它根据当前上下文决定调用哪个Skill、哪个MCP;Skill是静态的知识沉淀,写一次可以反复用;MCP是能力边界,决定了Agent能触达的外部世界有多大。三者配合好了,才是一个完整的自动化闭环。
2.2 为什么Skill的“触发描述”比内容本身还重要
这是我踩过的第一个大坑。最开始我写Skill,把大量精力花在步骤细节上,结果发现Claude Code根本不触发它。后来才明白,Skill的frontmatter里那段description,才是决定它能不能被用上的关键。
Claude Code的机制是:启动时把所有Skill的description加载进上下文,当你的请求进来时,它拿你的话去跟这些description做语义匹配。如果description写得太泛,比如“用于处理代码相关任务”,那它几乎永远不会被精准触发,因为所有任务都跟代码相关。如果写得太窄,比如“用于处理React 18中useEffect的依赖数组排序问题”,那稍微换个场景就匹配不上。
我的经验是,description要写成“场景锚点 + 动作 + 输出物”的结构。举个例子,我那个数据库迁移Skill的description是这样的:“当用户需要对PostgreSQL执行schema变更、新增字段、修改索引或编写migration文件时使用,输出符合项目规范的SQL和回滚脚本”。这样既限定了数据库类型,又限定了操作类型,还说明了产出,匹配精度高很多。
2.3 四十个Skill不是越多越好,而是要分层
我一开始贪多,看到什么Skill都想装,结果启动时上下文被塞得满满当当,反而拖慢了响应速度,而且很多Skill之间职责重叠,Claude Code在匹配时经常选错。后来我做了分层管理,把Skill分成三类:
| 层级 | 类型 | 数量控制 | 典型例子 |
|---|---|---|---|
| 基础层 | 全局通用规范 | 3-5个 | 代码风格、提交信息格式、错误处理约定 |
| 领域层 | 按技术栈划分 | 10-15个 | React组件规范、SQL编写、API设计 |
| 任务层 | 具体操作流程 | 15-20个 | 写测试、排查日志、生成文档、重构 |
基础层常驻,领域层按项目加载,任务层按需触发。这样既保证了覆盖面,又不会让上下文过载。四十个Skill听起来多,但分层之后,单个项目实际激活的通常也就十来个。
3. 从零搭建一套能真正用起来的Skill体系
3.1 目录结构和加载机制
Claude Code读取Skill的位置有几个约定,我一般放在项目根目录的.claude/skills/下面,每个Skill一个子目录,里面放一个SKILL.md。全局通用的放在用户目录的~/.claude/skills/。加载优先级是项目级覆盖全局级,这个设计很合理,方便不同项目做差异化定制。
一个标准的Skill目录长这样:
.claude/ skills/ code-review/ SKILL.md db-migration/ SKILL.md api-design/ SKILL.mdSKILL.md的头部是YAML frontmatter,必须包含name和description两个字段。name用短横线连接的小写英文,description就是前面说的触发锚点。正文部分才是具体的操作指令。
3.2 写一个高质量Skill的五个要素
我总结了五个必备要素,缺一个都会影响效果。
第一,明确的触发条件。在正文开头再强调一遍“什么时候用这个Skill”,因为description可能被截断,正文里的补充能帮Claude Code二次确认。
第二,分步骤的操作流程。不要写成一大段散文,要用有序列表把步骤拆开。每一步说清楚“做什么”和“为什么这么做”。比如“先读取现有schema文件(目的是确认当前字段类型,避免类型冲突)”。
第三,输入输出的格式约定。告诉它产出应该长什么样。是返回一个代码块,还是直接写文件,还是输出一个表格。格式约定越具体,产出越稳定。
第四,约束和禁忌。这部分最容易被忽略,但价值最高。比如“禁止在migration中直接DROP COLUMN,必须先确认无数据依赖”“生成的SQL必须包含事务包裹”。
第五,示例。给一个正例,有条件的话再给一个反例。Claude Code对示例的模仿能力很强,一个好的示例能顶一大段文字说明。
3.3 参数计算与阈值设定:以代码审查Skill为例
拿我那个代码审查Skill来说,里面有个“复杂度阈值”的设定。我一开始没设阈值,结果它把每个函数都批一遍,噪音太大。后来我加了一条规则:圈复杂度超过10的函数才需要拆分建议,超过15的必须拆分。这个数字不是拍脑袋来的,是参考了McCabe复杂度的经典研究,10以下基本可维护,10到15是警戒区,15以上维护成本陡增。
再比如“函数长度”这个维度,我设的是超过50行提示,超过80行强制建议拆分。50行大约是屏幕一屏半,超过这个长度阅读时需要滚动,认知负担明显上升。这些阈值写进Skill之后,审查结果的可操作性提升了一大截,不再是“这个函数有点长”这种模糊反馈。
3.4 实操:手把手写一个“日志排查”Skill
我拿一个实际在用的日志排查Skill来演示完整写法。这个Skill解决的问题是:线上出问题时,我需要快速从一堆日志里定位根因,而不是一条条翻。
--- name: log-troubleshoot description: 当用户提供错误日志、异常堆栈或需要排查线上问题时使用,输出根因分析、影响范围和修复建议 --- ## 触发场景 用户贴出报错信息、异常堆栈,或描述线上故障现象时启用。 ## 操作流程 1. 先提取日志中的关键字段:时间戳、错误级别、错误码、请求ID、堆栈顶层。 2. 按请求ID聚合所有相关日志,还原完整调用链。 3. 定位第一个ERROR级别日志,它通常是根因,后续的往往是连锁反应。 4. 检查该错误前后的WARN日志,往往有前置异常信号。 5. 对照代码库中对应的异常抛出点,确认触发条件。 ## 输出格式 - 根因:一句话说明 - 影响范围:受影响的接口/用户群 - 证据链:按时间顺序列出关键日志行 - 修复建议:具体到文件和函数 ## 约束 - 禁止在没有证据链的情况下下结论 - 如果日志不足以定位,明确说明还需要哪些信息 - 不要建议重启服务这类治标不治本的操作这个Skill写完之后,我排查线上问题的平均时间从二十多分钟降到了五六分钟。关键就在于它强制了一个结构化的排查路径,而不是让AI自由发挥。
4. 那些让我少走弯路的实战经验
4.1 Skill之间的冲突怎么解
装到二十多个的时候,我开始遇到Skill打架的情况。最典型的是代码风格Skill和重构Skill冲突:风格Skill要求“保持现有命名习惯”,重构Skill要求“统一改为驼峰命名”,两个同时触发时,Claude Code会犹豫甚至来回改。
解决办法是建立优先级声明。在每个Skill的frontmatter里加一个priority字段,数字越小优先级越高。重构类Skill优先级设为10,风格类设为20,这样冲突时以重构为准。另外,在description里明确写“本Skill优先级高于通用风格规范”,给Claude Code一个显式提示。
还有一个更隐蔽的冲突:两个Skill的输出格式不兼容。比如A Skill要求输出JSON,B Skill要求输出Markdown表格,同时触发时产出会四不像。我的做法是让任务层Skill尽量不定义输出格式,统一继承基础层的格式约定,减少冲突面。
4.2 MCP配置的常见坑
MCP这块我踩的坑比Skill还多。最常见的是连接超时和权限问题。比如接数据库MCP时,一开始没配连接池参数,查询稍微大一点就超时。后来在配置里加了connectionTimeout和queryTimeout,分别设成5000ms和30000ms,稳定多了。
另一个坑是MCP Server的启动顺序。有些MCP依赖本地服务先起来,如果Claude Code启动时那个服务还没就绪,MCP就会连接失败,而且不会自动重试。我的做法是写一个启动脚本,先检查依赖服务健康状态,确认后再启动Claude Code。
还有个容易忽略的点:MCP返回的数据量。有次接了一个文件系统MCP,让它列目录,结果返回了几万行,直接把上下文撑爆了。后来在Skill里加了约束:“列目录时必须加过滤条件,单次返回不超过100条”。这个教训告诉我,MCP是能力,但怎么用这个能力,还得靠Skill来约束。
4.3 常见问题速查表
| 问题现象 | 可能原因 | 排查方向 | 解决方式 |
|---|---|---|---|
| Skill不触发 | description匹配度低 | 检查description是否含场景锚点 | 重写description,加具体场景词 |
| Skill触发错误 | 多个Skill描述重叠 | 查看启动日志中的匹配记录 | 调整priority或合并Skill |
| 输出格式不稳定 | 格式约定不明确 | 检查Skill是否定义了输出结构 | 补充输出格式示例 |
| MCP连接失败 | 依赖服务未就绪 | 检查MCP Server日志 | 加启动前健康检查 |
| 响应变慢 | Skill数量过多 | 统计激活的Skill数量 | 分层管理,按需加载 |
| 上下文溢出 | MCP返回数据过大 | 检查MCP调用参数 | 在Skill中加数据量约束 |
4.4 一个反直觉的发现:少即是多
装到三十多个的时候,我一度觉得越多越好,直到有次做一个小型重构,Claude Code居然调用了数据库迁移Skill,生成了一堆无关的SQL建议。排查后发现是那个Skill的description里写了“修改字段”,而重构任务里恰好有“修改字段命名”,语义匹配上了。
这件事让我意识到,Skill的精准度比覆盖度更重要。后来我砍掉了几个边界模糊的Skill,把功能合并到更明确的Skill里,整体触发准确率反而上升了。现在我的原则是:宁可一个Skill覆盖三个紧密相关的场景,也不要三个Skill各覆盖一个模糊场景。
5. 进阶玩法:让Skill自己进化
5.1 用反馈循环持续优化Skill
Skill不是写完就完事了。我在每个Skill里加了一个“复盘”段落,每次任务完成后,如果产出不理想,我会把问题记下来,定期回顾并修改Skill。比如代码审查Skill最初漏掉了“空指针检查”这个维度,连续几次审查都没提,我就在Skill里补了一条规则。
更系统一点的做法是建一个skill-feedback.md,记录每次触发的问题、期望产出和实际产出的差异。攒够一批之后集中修改,比零散改效率高。
5.2 Skill与Agent的协同模式
单独用Skill是“一问一答”,配合Agent就是“自主执行”。我现在的用法是:把常用Skill挂到一个自定义Agent上,让Agent根据任务类型自动选择Skill组合。比如一个“后端开发Agent”挂了API设计、数据库迁移、测试补全三个Skill,我只需要描述需求,Agent自己决定先调哪个后调哪个。
这里的关键是Agent的决策提示词要写清楚Skill的调用顺序。比如“先设计API契约,再生成数据库迁移,最后补测试”,这个顺序写进Agent的system prompt里,避免它乱序执行导致返工。
5.3 团队协作中的Skill管理
一个人用Skill和团队用Skill是两回事。团队场景下最大的问题是Skill版本不一致,张三改了Skill没同步,李四用的还是旧版,产出就不一样。我的做法是把Skill目录纳入Git管理,每次修改走PR流程,合并后通知全员拉取。同时在CI里加一个检查,确保Skill的frontmatter格式合法、description不为空。
另外,团队里要有一个人负责Skill的“总控”,定期审查所有Skill是否还有效、是否有重叠、是否需要废弃。这个角色不需要全职,但必须有人担,否则半年后Skill目录就会变成一团乱麻。
6. 我个人的一些真实体会
折腾这四十来个Skill的过程,本质上是在把“我脑子里的隐性知识”变成“AI能执行的显性规则”。每写一个Skill,我都得先问自己:这件事我平时是怎么做的?为什么这么做?有没有更好的做法?这个过程反过来也提升了我的工作规范性。
最大的收获不是效率提升了多少,而是我对自己的开发流程有了更清晰的认识。以前很多操作是凭直觉,写Skill的时候被迫拆解成步骤,才发现有些环节其实是冗余的,有些约束其实一直没遵守。Skill写多了,人会变得更严谨。
如果让我给刚入门的人一个建议,那就是:别急着装四十个,先写三个。一个代码风格规范,一个你最常做的任务流程,一个你最容易出错的环节的检查清单。把这三个打磨到真正好用,再逐步扩展。Skill的价值不在于数量,而在于每一个都能在你需要的时候精准地帮上忙。