☰
Claude Code Skill开发实战:从50个失败案例到高效SKILL.md设计
2026/10/2 5:32:48 网站建设 项目流程

1. 从50个Skill里爬出来的血泪教训

先交代背景。过去几个月我一直在折腾 Claude Code 的 Skill 系统,前前后后写了差不多50个,覆盖代码生成、接口调试、数据库迁移、文档整理、测试用例补全这些日常场景。写到最后我回头复盘,发现一个很扎心的事实:前30个基本等于白写。不是不能用,而是用起来别扭、维护成本高、复用率低,很多Skill写完之后我自己都不怎么调用。

这篇文章就是把这50个Skill的踩坑过程摊开讲。如果你正在用 Claude Code,或者准备给自己的团队搭一套 Skill 体系,又或者你只是好奇 SKILL.md 到底该怎么写才不浪费生命,那这篇内容应该能帮你少走至少两个月的弯路。我会从整体设计思路讲到具体文件结构,再到实操步骤和排查技巧,尽量把每个“为什么”都讲透。

核心关键词先摆出来:Claude Code、Skill、SKILL.md、MCP、Spring Boot。这几个词基本构成了我整套工作流的骨架。Claude Code 负责调度和推理,Skill 负责把领域知识固化下来,SKILL.md 是载体,MCP 负责打通外部工具和数据源,Spring Boot 则是我主要服务的技术栈场景。

先说结论性的判断:Skill 不是提示词模板,不是写给人看的文档,也不是越详细越好。它更像是一份“给AI看的操作手册”,核心目标是让模型在特定场景下做出稳定、可预期、可复现的行为。前30个Skill之所以白写,根本原因就是我把它当成了“知识堆砌”,而不是“行为约束”。

2. 前30个Skill为什么白写了

2.1 把Skill当文档写,信息密度高但可执行性差

我最早写的Skill,典型结构是这样的:一段背景介绍,一段技术栈说明,然后罗列一堆注意事项,最后附上几个示例。看起来很像一份合格的技术文档,但问题在于——Claude Code 读完之后不知道该“做什么”。它知道了很多事实,但没有明确的行为指令。

举个例子,我写过一个“Spring Boot 接口开发规范”的Skill,里面详细描述了 Controller 层要怎么写、Service 层要怎么分层、DTO 要怎么转换。结果实际调用的时候,模型还是会按它自己的习惯来,因为我的描述是“陈述性”的,不是“指令性”的。后来我改成明确的步骤式指令,比如“生成 Controller 时必须包含以下注解”“参数校验必须使用 @Valid”“返回值必须包装成统一响应体”,效果立刻不一样。

提示:Skill 里的每一句话都要问自己——这是在告诉模型“是什么”,还是在告诉模型“怎么做”?前者价值有限,后者才是核心。

2.2 粒度失控,要么太泛要么太碎

第二个大坑是粒度。我写过那种“万能Skill”,一个文件里塞了代码生成、代码审查、测试补全、文档输出四件事,结果模型每次调用都要在脑子里做一次任务分类,准确率反而下降。也写过那种“超细Skill”,比如“生成一个带分页的查询接口”单独成一个Skill,导致Skill数量爆炸,维护起来想死。

实测下来比较合理的粒度是:一个Skill对应一类明确的任务场景,场景内部可以有分支,但分支之间必须共享同一套上下文和约束。比如“Spring Boot CRUD接口生成”可以是一个Skill,里面区分单表、多表关联、分页查询几种情况,但不要把“接口生成”和“接口文档输出”混在一起。

2.3 忽略MCP的协同,Skill孤军奋战

前30个Skill里,我几乎没有考虑 MCP 的配合。MCP 是模型和外部工具之间的桥梁,它能让 Claude Code 真正去读数据库、调接口、查日志、操作文件系统。我早期写的Skill全是“纯文本指令”,模型只能靠自己的知识来回答,没法验证、没法落地。

后来我把 MCP 接进来之后,整个玩法变了。比如我写一个“数据库迁移检查”的Skill,里面明确要求模型通过 MCP 去读取当前表结构,对比目标结构,再生成迁移脚本。这样出来的结果是有事实依据的,不是模型瞎编的。再比如“接口联调”场景,Skill 里要求模型通过 MCP 调用本地服务,拿到真实响应之后再判断是否符合预期。

2.4 没有版本管理和回归测试

这个坑最隐蔽。我早期改Skill很随意,今天加一条规则,明天删一条规则,改完之后也不记录。结果某天发现某个Skill突然不好用了,回头查根本不知道是哪次改动导致的。后来我养成了习惯:每个Skill都带版本号,每次修改都写变更说明,并且准备一组固定的测试用例,改完就跑一遍。

下面这张表是我总结的前30个Skill的典型问题分布,你可以对照看看自己有没有中招。

问题类型出现频次典型表现修复方向
陈述性描述过多高频模型知道事实但不执行改成指令式步骤
粒度失控高频太泛导致分类困难,太碎导致维护爆炸按任务场景划分
忽略MCP协同中频结果无法验证,容易幻觉接入外部工具做事实校验
无版本管理中频改动后无法回溯加版本号和变更日志
缺少边界条件中频异常场景处理混乱补充失败分支和兜底逻辑
示例过于理想化低频实际输入不匹配增加真实脏数据示例

3. SKILL.md 的正确打开方式

3.1 文件结构:从“给人看”转向“给模型看”

一个能打的 SKILL.md,结构应该非常清晰,而且每一部分都有明确目的。我现在的标准结构是这样的:

# Skill 名称 ## 适用场景 ## 前置条件 ## 执行步骤 ## 输出格式 ## 异常处理 ## 示例 ## 版本记录

看起来简单,但每一部分的写法都有讲究。“适用场景”要写清楚什么时候该用这个Skill,什么时候不该用,这是给模型做路由判断用的。“前置条件”要列出执行前必须满足的状态,比如需要哪些MCP工具可用、需要哪些环境变量。“执行步骤”是核心,必须是指令式的,一步一步来。“输出格式”要明确到字段级别,避免模型自由发挥。“异常处理”要覆盖常见失败情况。“示例”要给真实输入输出,不要给理想化的假数据。

3.2 指令式写法:把“应该”换成“必须”

这是最关键的转变。对比一下两种写法:

陈述式:“在Spring Boot项目中,Controller层通常需要处理参数校验,建议使用@Valid注解。”

指令式:“生成Controller方法时,必须在请求体参数前添加@Valid注解。如果参数校验失败,必须返回统一错误响应,HTTP状态码为400。”

后者模型执行起来几乎没有歧义。我实测下来,指令式写法的Skill,输出稳定性比陈述式高出至少一个档次。原因很简单:模型在生成内容时是在做概率选择,约束越明确,可选空间越小,结果越可控。

3.3 用MCP做事实锚点

Skill里凡是涉及外部状态的判断,都应该通过MCP去获取真实数据,而不是让模型凭记忆回答。比如:

  • 判断某个接口是否存在,通过MCP去读项目源码或接口文档
  • 判断数据库表结构,通过MCP去查information_schema
  • 判断依赖版本,通过MCP去读pom.xml或build.gradle
  • 判断服务是否运行,通过MCP去调健康检查接口

这样做的好处是,Skill的输出有了事实基础,不会出现“模型以为是这样,实际不是”的情况。我在Spring Boot项目里大量使用了这种方式,尤其是接口联调和数据库迁移场景,效果非常明显。

3.4 版本记录不能省

每个SKILL.md末尾我都会加一段版本记录,格式如下:

## 版本记录 - v1.3 (2025-01-15): 增加分页查询场景,补充异常处理分支 - v1.2 (2025-01-08): 修正输出格式,统一响应体字段 - v1.1 (2024-12-30): 增加MCP前置条件检查 - v1.0 (2024-12-20): 初始版本

别小看这几行字,排查问题的时候能救命。有一次某个Skill突然输出格式不对,我翻版本记录发现是前一天改了一条输出规则,回滚之后立刻恢复正常。

4. 实操:从零写一个能打的Skill

4.1 场景选择:Spring Boot 接口生成

我拿一个真实场景来演示:给 Spring Boot 项目生成标准的 CRUD 接口。这个场景足够典型,涉及代码生成、规范约束、MCP协同、异常处理,能把前面讲的要点全部串起来。

先明确目标:输入一个实体类名和字段定义,输出完整的 Controller、Service、Mapper、DTO 代码,并且符合项目现有规范。要求模型通过 MCP 读取项目现有的代码风格和依赖版本,确保生成结果能直接编译通过。

4.2 前置条件与MCP配置

前置条件要写清楚:

  • 项目根目录存在 pom.xml 或 build.gradle
  • 存在统一的响应体类,比如 Result
  • 存在统一异常处理类
  • MCP 文件系统工具可用,能读取项目源码
  • MCP 数据库工具可用,能查询表结构(可选)

MCP 配置这块,我用的是文件系统访问加数据库查询两个工具。文件系统工具让模型能读项目结构、读现有代码、读配置文件;数据库工具让模型能查表结构、查索引、查字段类型。这两个工具配合起来,基本能覆盖接口生成所需的全部上下文。

注意:MCP 工具的权限要控制好,只开放必要的读写范围。我一般只给读权限,写操作由模型生成代码后人工确认再落盘。

4.3 执行步骤的写法

执行步骤是整个Skill的核心,我把它拆成明确的阶段:

## 执行步骤 ### 第一步:读取项目上下文 1. 通过MCP读取项目根目录的pom.xml,提取Spring Boot版本和关键依赖版本 2. 通过MCP读取现有Controller目录,分析代码风格(注解使用、命名规范、包结构) 3. 通过MCP读取统一响应体类和异常处理类,记录其包路径和方法签名 ### 第二步:确认实体信息 1. 如果用户提供了实体类,通过MCP读取该实体类的字段定义 2. 如果用户只提供了表名,通过MCP查询数据库表结构,推导实体字段 3. 输出字段清单,包含字段名、类型、是否必填、校验规则 ### 第三步:生成代码 1. 生成DTO类,包含请求DTO和响应DTO 2. 生成Mapper接口,包含基础CRUD方法 3. 生成Service接口和实现类,包含业务逻辑 4. 生成Controller类,包含RESTful接口 5. 所有生成代码必须符合第一步读取到的项目规范 ### 第四步:自检 1. 检查所有注解是否完整 2. 检查包路径是否正确 3. 检查响应体是否统一 4. 检查异常处理是否覆盖 5. 输出自检报告

这种写法模型执行起来非常顺,每一步都有明确的输入和输出,不会跑偏。

4.4 输出格式与异常处理

输出格式要精确到文件级别:

## 输出格式 按以下顺序输出文件: 1. `{EntityName}RequestDTO.java` - 请求参数 2. `{EntityName}ResponseDTO.java` - 响应数据 3. `{EntityName}Mapper.java` - 数据访问 4. `{EntityName}Service.java` - 服务接口 5. `{EntityName}ServiceImpl.java` - 服务实现 6. `{EntityName}Controller.java` - 接口层 每个文件必须包含: - 完整的package声明 - 完整的import列表 - 类级别注释 - 方法级别注释

异常处理要覆盖这些情况:

异常场景处理方式
项目结构读取失败终止执行,提示检查MCP配置
实体类不存在提示用户确认实体名或表名
依赖版本不兼容输出兼容性警告,建议调整版本
代码风格冲突以项目现有风格为准,输出冲突说明
数据库连接失败跳过表结构查询,要求用户手动提供字段

4.5 实测效果与调优记录

这个Skill写完第一版之后,我拿三个真实项目做了测试。第一个项目是标准的分层架构,生成结果直接能用,编译通过率100%。第二个项目用了自定义的响应体包装,模型通过MCP读到了这个类,生成结果也正确。第三个项目用了多模块结构,模型一开始把包路径搞错了,后来我在前置条件里加了“必须读取模块划分”这一条,问题解决。

调优过程中最大的收获是:MCP读取的上下文越充分,生成结果越准确。我后来把“读取项目上下文”这一步从3个子项扩展到7个子项,包括读取配置文件、读取工具类、读取常量定义,生成准确率从70%左右提升到95%以上。

5. 常见问题与排查技巧实录

5.1 Skill不生效或效果不稳定

这是最常见的问题。排查思路按以下顺序来:

  1. 检查SKILL.md是否被正确加载,路径和命名是否符合规范
  2. 检查Skill的“适用场景”是否写得太宽泛,导致模型路由错误
  3. 检查执行步骤是否指令式,有没有模糊表述
  4. 检查是否有冲突的Skill同时生效
  5. 检查MCP工具是否可用,前置条件是否满足

我遇到过一次典型情况:两个Skill的适用场景都写了“代码生成”,结果模型每次调用都随机选一个,输出自然不稳定。后来把场景描述改得更具体,一个写“Spring Boot接口生成”,一个写“单元测试生成”,问题就解决了。

5.2 MCP调用失败

MCP调用失败的原因比较多,我整理了一张速查表:

现象可能原因解决方法
工具列表为空MCP服务未启动检查服务进程和端口
调用超时网络或服务响应慢增加超时配置,检查服务负载
权限拒绝工具权限配置过严调整权限范围,开放必要路径
返回数据格式错误工具实现有bug检查工具输出格式,修复解析逻辑
间歇性失败连接池或并发问题检查连接配置,增加重试机制

提示:MCP调用失败时,Skill里要有兜底逻辑。比如数据库查询失败时,不要直接报错终止,而是提示用户手动提供信息,继续执行后续步骤。

5.3 生成结果不符合项目规范

这个问题通常是因为Skill里没有强制要求读取项目上下文。我的做法是在执行步骤第一步就明确要求通过MCP读取现有代码,提取规范。如果项目本身规范不统一,那就以最近修改的文件为准,或者让用户指定参考文件。

还有一个技巧:在Skill里加一段“规范冲突处理”逻辑,当模型发现项目内存在多种风格时,输出冲突清单,让用户选择。这样既保证了生成质量,又避免了模型自作主张。

5.4 Skill维护成本高

Skill数量多了之后,维护确实是个问题。我的经验是:

  • 建立Skill索引文件,记录每个Skill的用途、版本、依赖关系
  • 定期清理不再使用的Skill,别舍不得删
  • 把公共约束抽出来,比如代码风格、响应格式,做成共享片段
  • 每次修改都跑回归测试,确保没有破坏现有功能

我现在维护的Skill大概20个左右,比巅峰期的50个少了一半多,但实际使用频率和效果反而更好。少即是多,这句话在Skill管理上特别成立。

6. 我现在的Skill体系长什么样

经过这一轮大浪淘沙,我现在的Skill体系大概分四类:

第一类是代码生成类,包括接口生成、实体生成、测试生成,这类Skill依赖MCP读取项目上下文,输出可直接使用的代码。

第二类是代码审查类,包括规范检查、安全扫描、性能分析,这类Skill依赖MCP读取源码,输出问题清单和修复建议。

第三类是运维操作类,包括日志查询、服务健康检查、配置对比,这类Skill依赖MCP调用外部服务,输出操作结果。

第四类是文档类,包括接口文档生成、变更记录整理、知识库更新,这类Skill依赖MCP读取代码和提交记录,输出结构化文档。

每一类下面大概3到5个Skill,每个Skill都有明确的适用场景、前置条件、执行步骤、输出格式、异常处理和版本记录。整套体系跑下来,日常开发效率提升非常明显,尤其是接口开发和联调环节,以前要半天的工作现在半小时能搞定。

最后分享一个我踩过的最大的坑:不要为了写Skill而写Skill。我前30个Skill里有一半是“觉得应该有用”而写的,实际根本用不上。真正有价值的Skill,都是从真实痛点里长出来的。你先手动做一件事做烦了,再把它固化成Skill,这样的Skill才有生命力。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询