Claude Code Skill 实战:从50个踩坑到20个高效封装
1. 从 50 个 Skill 里踩出来的血泪教训我在过去几个月里陆续写了 50 个 Claude Code Skill从最开始照着文档瞎写到后来慢慢摸出一些门道中间踩的坑实在太多了。最扎心的一个发现是前 30 个基本等于白写。不是完全没用而是投入产出比极低维护成本高得离谱真正高频调用的没几个。后来我复盘了一下发现问题的根源不在于 Skill 本身难写而在于我对“什么样的任务值得封装成 Skill”这件事判断错了。这篇文章就是把这 50 个 Skill 的实战经验摊开来讲。我会说清楚 Skill 到底是什么、SKILL.md 应该怎么写、哪些场景适合封装、哪些场景纯属给自己找麻烦以及怎么和 MCP、Spring Boot 这类后端服务配合使用。如果你刚开始接触 Claude Code Skill或者已经写了一堆但感觉效果一般这篇内容应该能帮你少走不少弯路。先给不太熟悉的朋友快速对齐一下概念。Claude Code 是 Anthropic 推出的命令行 AI 编程工具它可以在终端里直接读写文件、执行命令、调用工具。而 Skill 是 Claude Code 的一个扩展机制你可以把它理解成“给 AI 写的一份操作手册”——通过一个叫 SKILL.md 的 Markdown 文件告诉 Claude 在特定场景下应该怎么做、按什么步骤做、注意哪些事项。当用户的请求匹配到 Skill 的描述时Claude 会自动加载这份手册按照你定义的流程来执行任务。听起来很简单对吧但问题恰恰出在“看起来简单”这四个字上。我前 30 个 Skill 就是被这种错觉害的。2. 前 30 个 Skill 为什么白写了2.1 最常见的三个致命错误回头看我最早写的那批 Skill问题集中在三个地方。第一个错误是把 Skill 当文档写。我一开始觉得 Skill 就是写一份说明文档于是把某个框架的使用方法从头到尾写了一遍什么安装步骤、API 说明、注意事项洋洋洒洒几千字。结果 Claude 加载之后确实“知道”了这些信息但它并不知道在当前项目里应该怎么用。Skill 不是知识库它更像是一份 SOP标准作业流程核心价值在于“指导行动”而不是“传递知识”。第二个错误是粒度太细。我给每一个小功能都写了一个 Skill比如“创建 Spring Boot Controller”“添加 MyBatis Mapper”“写单元测试”各一个。听起来很模块化很优雅但实际使用的时候Claude 经常不知道该调哪个或者调了一个之后不知道下一步该调另一个。Skill 之间没有编排关系导致体验非常割裂。后来我改成按“任务场景”来划分比如“新增一个完整的 CRUD 接口”作为一个 Skill里面涵盖 Controller、Service、Mapper、测试的完整流程效果好了很多。第三个错误是触发描述写得太模糊。SKILL.md 里有一个关键字段是 description它决定了 Claude 在什么情况下会加载这个 Skill。我早期写的描述都是“帮助用户完成数据库操作”“辅助代码审查”这种大而空的话结果要么永远不触发要么在不该触发的时候乱触发。后来我学乖了description 必须包含具体的触发关键词和使用场景比如“当用户需要新增数据库表对应的增删改查接口时使用关键词CRUD、Mapper、Controller、Service”。2.2 什么样的任务根本不值得封装这是我最想分享的一条经验不是所有重复性工作都值得做成 Skill。我总结了一个简单的判断标准满足以下条件越多的任务越值得封装判断维度值得封装不值得封装执行频率每天多次每周不到一次步骤确定性流程固定步骤明确每次情况不同上下文依赖依赖项目结构但不依赖具体业务高度依赖具体业务逻辑出错成本出错后修复成本高出错了大不了重来团队共享多人需要统一规范只有自己用举个例子“生成 Spring Boot 项目的基础分层结构”非常值得封装因为步骤固定、频率高、团队新人都需要。“根据业务需求设计数据库表结构”就不太值得因为每次的业务需求都不一样Skill 能提供的帮助有限不如直接对话。我前 30 个 Skill 里至少有 15 个属于“不值得封装”的类别。它们不是不能用而是维护成本超过了收益。每次项目结构变了、依赖升级了我都得回去改这些 Skill改完还不一定对。后来我狠心删掉了这些只保留了真正高频且流程固定的那些整体效率反而提升了。2.3 一个反直觉的发现少即是多删掉 20 个 Skill 之后我剩下 30 个。但我继续用了一段时间又发现其中 10 个左右虽然值得封装但写得不够好。于是我又重写了一轮最终稳定在 20 个左右的核心 Skill 上。这 20 个 Skill 覆盖了我日常开发中 80% 以上的重复性场景包括Spring Boot 项目初始化与分层MyBatis 映射文件生成RESTful 接口的标准化实现单元测试模板生成代码审查清单日志与异常处理规范数据库迁移脚本生成API 文档自动生成配置文件管理多环境部署脚本每一个都是经过反复打磨的description 精确、步骤清晰、边界明确。这比 50 个半成品强太多了。3. SKILL.md 到底该怎么写3.1 文件结构与核心字段一个标准的 Skill 就是一个目录里面至少包含一个 SKILL.md 文件。目录结构通常长这样.claude/skills/ my-skill-name/ SKILL.md templates/ template1.java scripts/ helper.shSKILL.md 的头部是 YAML frontmatter用来定义元信息--- name: spring-boot-crud description: 当用户需要为数据库表生成完整的增删改查接口时使用。触发关键词CRUD、增删改查、Mapper、Controller、Service、RESTful ---这里有两个关键点。name要简短且唯一用英文小写加连字符。description是最重要的字段它直接决定了 Skill 的触发准确率。我的经验是 description 要包含三部分什么场景下使用、解决什么问题、触发关键词有哪些。正文部分就是 Markdown 格式的操作指南。我一般会按这个结构来写## 前置检查 - 确认项目使用 Spring Boot 2.3.x 或 2.6.x - 确认已配置 MyBatis 或 MyBatis-Plus - 确认数据库连接可用 ## 执行步骤 1. 读取目标表结构 2. 生成 Entity 类 3. 生成 Mapper 接口和 XML 4. 生成 Service 和 ServiceImpl 5. 生成 Controller 6. 生成单元测试 ## 代码模板 引用 templates 目录下的模板文件 ## 注意事项 - 字段命名遵循驼峰转换规则 - 主键策略默认为自增 - 分页查询统一使用 PageHelper3.2 触发描述的三个层次description 的写法我摸索了很久最终总结出一个“三层描述法”第一层场景定位。用一句话说清楚这个 Skill 是干什么的。比如“为 Spring Boot 项目生成标准化的 CRUD 接口”。第二层触发条件。列出用户可能说什么话、用什么关键词时会触发。比如“当用户提到新增接口、创建 CRUD、生成 Mapper 时”。第三层排除条件。说明什么情况下不应该触发。比如“不适用于非 Spring Boot 项目不适用于 GraphQL 接口”。完整的 description 示例为 Spring Boot MyBatis 项目生成标准化的增删改查接口包括 Entity、Mapper、Service、Controller 和单元测试。当用户需要新增 CRUD 接口、生成 Mapper 映射、创建 RESTful 端点时使用。触发关键词CRUD、增删改查、Mapper、Controller、Service、RESTful、接口生成。不适用于非 Spring Boot 项目或 GraphQL 接口。这样写之后触发准确率从原来的大概 60% 提升到了 90% 以上。3.3 步骤设计的原则Skill 正文的步骤设计我遵循几个原则。原则一每一步都要可执行。不要写“分析代码结构”这种模糊的话要写“读取 src/main/java 目录下的所有 .java 文件提取类名和包路径”。Claude 需要的是明确的动作指令不是思考方向。原则二步骤之间要有依赖关系。好的 Skill 步骤是链式的前一步的输出是后一步的输入。比如先生成 Entity再根据 Entity 生成 Mapper再根据 Mapper 生成 Service。这样 Claude 执行起来有明确的推进感。原则三关键决策点要给出判断规则。比如“如果表中存在 created_at 和 updated_at 字段则在 Entity 中添加对应的自动填充注解否则跳过”。这种条件分支能让 Skill 适应更多情况。原则四留出人工确认的节点。不是所有步骤都让 Claude 自动执行有些关键节点应该暂停让用户确认。比如“生成完 Entity 后展示给用户确认字段映射是否正确确认后再继续生成 Mapper”。4. Skill 与 MCP、Spring Boot 的配合实战4.1 MCP 是什么和 Skill 什么关系MCP 全称 Model Context Protocol是一个让 AI 模型与外部工具、数据源交互的协议。你可以把它理解成“AI 的 USB 接口”——通过统一的协议AI 可以连接数据库、调用 API、操作文件系统等等。Skill 和 MCP 的关系是互补的。Skill 定义的是“怎么做”的流程MCP 提供的是“能做什么”的能力。举个例子你要让 Claude 帮你操作数据库MCP 负责提供数据库连接和查询能力Skill 负责定义“先查表结构、再生成代码、再执行迁移”这个流程。我实际使用中最常见的组合是用 MCP 连接数据库和代码仓库用 Skill 定义开发流程。比如我有一个“数据库迁移”的 Skill它会通过 MCP 读取当前数据库结构对比目标结构生成迁移脚本然后通过 MCP 执行脚本。4.2 一个完整的 Spring Boot CRUD Skill 实战让我用一个具体例子来展示 Skill 怎么写、怎么用。假设我们要为一张user表生成完整的 CRUD 接口。首先Skill 的目录结构.claude/skills/spring-boot-crud/ SKILL.md templates/ entity.java.tpl mapper.java.tpl mapper.xml.tpl service.java.tpl serviceImpl.java.tpl controller.java.tpl test.java.tplSKILL.md 的内容--- name: spring-boot-crud description: 为 Spring Boot MyBatis 项目生成标准化的增删改查接口。当用户需要新增 CRUD 接口、生成 Mapper 映射、创建 RESTful 端点时使用。触发关键词CRUD、增删改查、Mapper、Controller、Service、RESTful、接口生成。不适用于非 Spring Boot 项目或 GraphQL 接口。 --- ## 前置检查 在执行任何生成操作之前先确认以下条件 1. 项目根目录存在 pom.xml 或 build.gradle且包含 spring-boot-starter-web 依赖 2. 项目中存在 MyBatis 或 MyBatis-Plus 依赖 3. 用户已提供目标表名或表结构 如果任一条件不满足停止执行并告知用户缺少什么。 ## 执行步骤 ### 第一步获取表结构 通过 MCP 数据库工具查询目标表的 DDL或者让用户提供建表语句。 需要提取的信息 - 表名 - 所有字段名、类型、是否可空、默认值 - 主键字段 - 索引信息 ### 第二步生成 Entity 类 根据表结构生成 Entity 类放在 src/main/java/{basePackage}/entity/ 目录下。 命名规则 - 类名 表名转为大驼峰如 user_role - UserRole - 字段名 列名转为小驼峰如 created_at - createdAt - 类型映射VARCHAR - String, INT - Integer, BIGINT - Long, DATETIME - LocalDateTime, DECIMAL - BigDecimal 如果表中存在 created_at 和 updated_at 字段添加 TableField(fill FieldFill.INSERT) 和 TableField(fill FieldFill.INSERT_UPDATE) 注解。 生成后展示给用户确认确认后再继续。 ### 第三步生成 Mapper 接口和 XML Mapper 接口放在 src/main/java/{basePackage}/mapper/ 目录下继承 BaseMapperEntity。 Mapper XML 放在 src/main/resources/mapper/ 目录下包含 - resultMap 定义 - 基础 CRUD 语句 - 分页查询语句使用 PageHelper ### 第四步生成 Service 和 ServiceImpl Service 接口放在 src/main/java/{basePackage}/service/ 目录下继承 IServiceEntity。 ServiceImpl 放在 src/main/java/{basePackage}/service/impl/ 目录下继承 ServiceImplMapper, Entity 并实现 Service 接口。 ### 第五步生成 Controller Controller 放在 src/main/java/{basePackage}/controller/ 目录下。 包含以下端点 - GET /api/{resource} - 分页查询 - GET /api/{resource}/{id} - 根据 ID 查询 - POST /api/{resource} - 新增 - PUT /api/{resource}/{id} - 更新 - DELETE /api/{resource}/{id} - 删除 统一返回 ResultT 包装类。 ### 第六步生成单元测试 测试类放在 src/test/java/{basePackage}/ 目录下使用 JUnit 5 Mockito。 覆盖以下场景 - 正常查询 - 分页查询 - 新增成功 - 更新成功 - 删除成功 - 参数校验失败 ## 注意事项 - 所有生成的代码必须符合项目的代码风格检查是否有 checkstyle 或 spotless 配置 - 如果项目使用了 LombokEntity 使用 Data 注解否则手动生成 getter/setter - Controller 的参数校验使用 Valid 注解 - 异常处理统一使用全局异常处理器 - 生成完成后运行 mvn compile 验证编译通过这个 Skill 写完之后我每次新增一张表的 CRUD 接口只需要说一句“帮我为 order 表生成 CRUD 接口”Claude 就会自动走完整个流程。原来手动写这些代码大概需要 30 到 40 分钟现在 3 到 5 分钟就能搞定而且风格统一不会出现这个接口用驼峰那个接口用下划线的情况。4.3 和 MCP 配合的进阶玩法上面这个例子已经用到了 MCP 的数据库查询能力。但 MCP 能做的事情远不止这些。我目前常用的 MCP 工具包括数据库 MCP查询表结构、执行 SQL、生成迁移脚本文件系统 MCP批量读写文件、搜索代码Git MCP查看提交历史、创建分支、生成 commit messageAPI 测试 MCP发送 HTTP 请求、验证接口返回把这些 MCP 工具和 Skill 结合起来能实现很多有意思的自动化流程。比如我有一个“接口联调”的 Skill它会通过文件系统 MCP 读取 Controller 定义通过数据库 MCP 准备测试数据通过 API 测试 MCP 发送请求验证返回结果是否符合预期如果失败通过 Git MCP 查看最近的变更定位问题这个 Skill 帮我省了大量的联调时间尤其是接口多的时候手动一个个测太痛苦了。5. 常见问题与排查技巧实录5.1 Skill 不触发怎么办这是最常见的问题。你写了一个 Skill但 Claude 就是不用它。排查思路如下第一步检查 description 是否包含用户可能说的关键词。如果用户说“帮我建个接口”而你的 description 里只有“CRUD”那大概率不会触发。解决办法是把常见说法都列进去。第二步检查 Skill 目录位置是否正确。Claude Code 默认从.claude/skills/目录加载 Skill如果你放在别的地方需要额外配置。第三步检查 SKILL.md 的 frontmatter 格式。YAML 对缩进和冒号很敏感一个多余的空格都可能导致解析失败。建议用 YAML 校验工具检查一下。第四步用claude --debug模式启动查看 Skill 加载日志。如果 Skill 被加载了但没触发日志里会有匹配过程的记录。5.2 Skill 触发了但执行结果不对这种情况通常是步骤描述不够明确导致的。Claude 在执行 Skill 时会尽量按照你写的步骤来但如果某一步描述有歧义它就会按自己的理解来。解决办法是把模糊的描述改成明确的指令。比如模糊“生成合适的 Entity 类”明确“生成 Entity 类类名使用大驼峰命名字段使用小驼峰命名类型映射关系如下表所示”另外可以在 Skill 里加入验证步骤。比如生成完代码后让 Claude 自己检查一遍“确认所有字段都已映射确认没有遗漏主键注解确认 import 语句完整”。这样能提前发现大部分问题。5.3 多个 Skill 冲突怎么办当你有很多 Skill 时可能会出现两个 Skill 都觉得自己应该触发的情况。比如你有一个“生成 CRUD”的 Skill 和一个“生成 API 文档”的 Skill用户说“帮我生成用户模块的接口和文档”两个 Skill 都可能被触发。解决办法有两个。一是在 description 里明确排除条件比如 CRUD Skill 里写“不适用于仅生成文档的场景”。二是设计 Skill 的层级关系让一个 Skill 可以调用另一个 Skill。比如“生成用户模块”这个 Skill 里明确写了“先生成 CRUD 接口再生成 API 文档”这样就不会冲突了。5.4 常见问题速查表问题现象可能原因解决办法Skill 完全不触发description 关键词不匹配补充常见说法和同义词Skill 触发但报错SKILL.md 格式错误检查 YAML frontmatter 缩进执行结果不符合预期步骤描述有歧义改成明确的动作指令多个 Skill 同时触发description 边界不清添加排除条件或设计层级Skill 执行到一半停了缺少必要的前置条件在开头添加前置检查步骤生成的代码风格不统一没有引用项目规范在 Skill 里加入代码风格检查Skill 加载很慢Skill 文件太大拆分 Skill把模板放到单独文件修改 Skill 后不生效缓存问题重启 Claude Code 或清除缓存5.5 几个我踩过的坑坑一在 Skill 里写死绝对路径。我早期写的 Skill 里用了/Users/myname/project/这样的绝对路径结果换台电脑就废了。后来全部改成相对路径或者用环境变量。坑二Skill 里包含敏感信息。有一次我把数据库密码写在了 Skill 的示例代码里差点提交到仓库。现在我的原则是 Skill 里绝对不出现任何密钥、密码、token需要的话通过环境变量或配置文件读取。坑三过度依赖 Skill 的自动化。有些步骤其实让用户确认一下更好但我为了“全自动”跳过了确认环节结果生成了一堆错误代码还得手动改。现在我一般在关键节点都会加一个“展示给用户确认”的步骤。坑四忘了更新 Skill。项目升级了 Spring Boot 版本但 Skill 里的模板还是老版本的写法生成出来的代码编译不过。现在我养成了习惯每次项目大版本升级后都检查一遍相关 Skill 是否需要更新。6. 我目前稳定在用的 Skill 清单经过反复筛选和打磨我目前稳定在用的 Skill 大概有 20 个。这里列一下最核心的 10 个供参考Skill 名称用途触发频率spring-boot-init初始化 Spring Boot 项目结构每周 1-2 次spring-boot-crud生成完整 CRUD 接口每天多次mybatis-mapper生成 MyBatis 映射文件每天多次unit-test-gen生成单元测试每天多次code-review代码审查清单每天 1-2 次api-doc生成 API 文档每周 2-3 次db-migration数据库迁移脚本每周 1-2 次log-exception日志与异常处理规范每周 2-3 次config-manage配置文件管理每周 1-2 次deploy-script多环境部署脚本每周 1 次这 10 个 Skill 覆盖了我日常开发中绝大部分重复性工作。每个都是经过至少 10 次以上实际使用和迭代的description 精确、步骤清晰、边界明确。写 Skill 这件事我的核心体会就是质量远比数量重要。与其写 50 个半成品不如精心打磨 10 个真正好用的。判断一个 Skill 是否值得保留就看它能不能让你在每次使用时都感到“省事了”。如果用了之后还得花时间检查和修正那这个 Skill 就是负资产。另外Skill 不是一成不变的。项目在变、团队在变、工具在变Skill 也需要跟着迭代。我现在的习惯是每个月花半个小时回顾一下所有 Skill看看哪些需要更新、哪些可以合并、哪些该删了。保持 Skill 库的精简和新鲜比一味地增加新 Skill 重要得多。