我第一次正儿八经用 Claude Code 写项目的时候其实还挺兴奋的——命令行里对话、自动改代码、跑测试感觉像多了个不用休息的结对程序员。但用了一周之后我发现一个特别别扭的问题我每天都在重复同样的话。比如提交信息按 Conventional Commits 规范写不要把测试文件放 src 里数据库迁移脚本要带上回滚方案类似的话几乎每个新会话都要重新啰嗦一遍遇到上下文长一点它还会跑偏。后来我试着把规则写进项目级提示词文件里确实好了一些但那玩意儿是全局习惯不是按需加载一遇到跨领域任务就互相打架。直到我把 Skill 机制完整搞懂并落地之后整个工作流才清爽了。这篇东西就是给同样在 Claude Code 里折腾的新手写的一份完整学习笔记从它到底解决什么问题、目录和文件长什么样、怎么亲手写一个能用的 Skill到测试、调试、避坑、进阶一条线捋下来。你可以把它当成一份可以直接照着做的入门手册也可以当成排查自己那些为什么总是不生效问题的诊断指南。1. 为什么需要 Skill没有技能包的 Claude Code 用起来有多别扭先说个扎心的现象。很多新手把 Claude Code 当成一个更聪明的聊天框有需求就丢一句话进去它也确实能干活。但干得漂不漂亮完全取决于你这次对话里给了多少约束条件。1.1 重复提示词与上下文污染我之前处理过一个模拟项目 X 的文档整理任务要求是给每个 markdown 文件加一个标准的元信息头包含 author、date、tags、status 四个字段日期格式统一用 ISO 8601。第一遍我直接说它做得有模有样。到第三个文件的时候它就开始自作主张把 status 字段写成了draft而不是约定的in-progress。原因很简单我已经在前面写了很多关于目录结构调整、图片压缩、链接校验的话那段关于元信息头的指令被淹没在历史里了模型对早期指令的权重会随时间衰减这就是典型的上下文污染。这种问题靠说得再清楚一点是治标不治本。你总不能每个文件都复制粘贴一遍规范。后来我发现其实可以把这套规范做成一个独立的技能包让 Claude Code 在需要处理文档头部的时候主动去加载这份完整的、结构化的说明而不是靠它从我的对话历史里回忆。1.2 Skill 和普通提示词的本质区别普通提示词是一次性指令你说完就没了作用范围局限在当前这轮对话。Skill 是一个可复用的、按需加载的知识包它被存放在固定的目录结构里拥有自己的描述信息。当 Claude Code 判断当前任务跟某个技能相关时会把技能里的指导内容注入到上下文中相当于把一套该领域的最佳实践手册直接发给模型。我打个生活化的比方普通提示词像你每次出门前都跟导航软件重新说一遍走高速、避开拥堵、不要走收费路段Skill 则像是给导航建立一个通勤路线偏好设置你只要说导航去公司它自动把那一套偏好全部带进来。这样既能保证每次的执行标准一致又不占用你宝贵的上下文窗口去反复交代规则。1.3 用 Skill 能解决掉的几个具体场景固定格式输出比如代码提交信息的生成、周报格式化、发布公告模板化。领域专家指导比如数据库索引审查、Dockerfile 安全加固、前端组件可访问性检查。多步骤流程比如上线前的检查清单、模型训练前的数据清洗流水线。团队规范落地把团队的代码规范、目录规范、命名规范做成技能别人拿到项目也能一键复用。以我个人的体验一旦你有了三四个核心技能写代码的效率提升是很明显的因为 Claude Code 第一次就在正确的前提下思考而不是先给你一版次品再让你去纠偏。2. Skill 的触发逻辑与目录机制它到底是怎么被叫醒的很多新手搞不明白一个问题我建了一个 Skill 目录它什么时候会被自动加载为什么有时候我明显提到了相关需求它却没反应这一节我把底层机制拆开讲清楚。2.1 Skill 的标准目录结构与命名规范在 Claude Code 的项目环境中Skill 被存放在.claude/skills/目录下每个技能一个独立的子目录子目录名字最好全小写、用短横线连接。比如你要做一个数据库迁移生成器技能目录长这样.claude/skills/ └── db-migration-generator/ ├── SKILL.md ├── templates/ │ ├── migration_template.sql │ └── rollback_template.sql ├── scripts/ │ └── generate_migration.py └── references/ └── database_guidelines.md这里最关键的文件是SKILL.md它是技能的核心入口。名字不能改Claude Code 扫描目录时靠的就是这个约定。如果少了它整个技能目录会被当成普通资源目录忽略掉。其余的文件都是辅助资源用来给技能提供更细致的模板、脚本和参考文档这些资源不是必须的但对于复杂技能几乎是必需品。2.2 SKILL.md 的文件格式frontmatter 与正文的配合SKILL.md本质上是一个带元信息的 Markdown 文件。顶部用 YAML 格式写 frontmatter下面是正文内容。我见过的最简可用版长这样--- name: db-migration-generator description: 用于生成数据库结构迁移脚本和回滚脚本。当用户要求创建数据库迁移、修改表结构、添加索引或编写回滚操作时使用。工具示例工具。 allowed-tools: Bash, Read, Write, Edit --- # 数据库迁移生成器 这个技能用于生成安全、可回滚的数据库迁移脚本。 ## 执行步骤 1. 先读取当前数据库 schema 文件确认现有结构。 2. 根据用户需求编写迁移脚本必须包含 up 和 down 两个部分。 3. 为每个迁移脚本生成对等的回滚脚本。 4. 输出文件到 migrations/ 目录文件名遵循 YYYYMMDDHHMMSS_description.sql 格式。 ## 硬性约定 - 所有表结构变更必须显式声明 IF NOT EXISTS 或 IF EXISTS。 - 回滚脚本必须能从迁移后的状态回到迁移前的状态。 - 外键约束变更需要先评估现有数据完整性。我重点解释一下这两块的各自职责。frontmatter里的name是技能的唯一标识description是 Claude Code 判断这个技能该不该出场的依据。它不是给人看的简介而是给模型的匹配信号源。模型读到用户的当前任务会跟所有技能的 description 做语义匹配匹配度高才会把对应的SKILL.md正文加载进上下文。所以description写得越准确、越具体触发成功率越高。正文才是真正干活时的指导手册。这里的执行步骤和硬性约定会作为系统级提示词的一部分被注入相当于模型在做这件事时被强制要求遵守的内部规范而不是可有可无的建议。所有内容都要避免口语化废话每一条都要可执行。2.3 触发机制不是关键词匹配而是语义匹配这里我要专门纠正一个常见误区Skill 不是靠你嘴上念叨某个词才触发的。它用的是语义匹配也就是说即便你完全没有提到技能两个字只要任务意图跟 description 里描述的场景高度相似它就会被加载。反过来也一样如果你把 description 写得特别宽泛比如这个技能与数据库相关时使用那几乎任何数据操作都会触发它反而会造成上下文浪费。我见过有开发者的技能 description 只写了一句用于处理代码结果他每次写代码都加载这个大而全的技能包输出风格被强行带偏得不偿失。想让触发精准我的经验是 description 里写清三件事技能适用的任务类型、核心动作、典型的触发场景。最好再带上一两个比如式的描述帮助模型更快对齐语义。比如上面那个数据库迁移的例子我写了当用户要求创建数据库迁移、修改表结构、添加索引或编写回滚操作时使用这就是典型的高质量描述。2.4 与全局提示词文件的分工全局习惯放哪、按需知识放哪Claude Code 里还有一个常见的配置文件它用于存放你对整个项目的全局偏好和习惯比如代码风格优先使用函数式编程注释用中文测试目录放在 tests/ 下这类无论做什么任务都适用、且你不希望被覆盖的规则。而 Skill 解决的则是某个特定领域、特定流程、特定任务的经验整合问题。我见过太多人把这两者搞混要么把所有规范全塞进全局提示词文件导致每次普通对话都背上几百行规矩要么把每个小任务都做成 Skill技能数量爆炸互相干扰。我的建议是——全局文件负责稳定习惯Skill 负责按需专业能力。一句话总结凡是每次对话都要遵守的放全局凡是只有特定任务才需要的放 Skill。3. 从零构建一个真实 Skill身份证件级手把手流程理论说得再多不如动手写一个。我拿自己最近做过的API 接口文档审查员技能来当例子一步步完整走一遍你照做就能跑通。3.1 先想清楚这个技能要管哪些事做 API 接口文档审查本质上是检查一份接口文档是否符合项目的约束路径命名是否符合规范、参数类型是否完整、响应状态码是否合理、有没有缺字段描述、示例请求响应是否与 schema 一致。如果每次接到审查任务都要在对话里罗列十来个检查点费时且容易遗漏。这个场景非常适合做成 Skill。我定义这个技能的工作目标为输入一份 API 文档文件路径输出一份结构化的审查报告内容包括发现的每个问题的位置、级别严重/一般/建议、修改建议和对应的规范条目编号。这些输出要求我在普通提示词里说三次可能都还会跑偏但写成 Skill 正文之后它每次都会严格遵守。3.2 创建目录与文件的完整命令序列你先在项目根目录下执行# 创建技能目录 mkdir -p .claude/skills/api-reviewer/templates mkdir -p .claude/skills/api-reviewer/references # 先看看创建好的目录结构 find .claude/skills -type f -o -type d | sort然后创建核心文件SKILL.md。我建议用你习惯的编辑器直接写别用echo一行行拼容易出错。写完后用cat .claude/skills/api-reviewer/SKILL.md验证一下文件确实存在且内容完整。3.3 SKILL.md 正文写清楚为什么这么做比写做什么更重要新手写 SKILL.md 最常见的问题是只罗列结论不解释条件。比如写了检查所有 URL 是否使用复数名词但没写为什么要用复数名词。在普通场景这句话没什么问题但在复杂接口里模型无法根据上下文判断哪些资源该用复数、哪些例外。所以我写技能时每个规则至少带一行说明。下面是我那个技能的核心内容节选--- name: api-doc-reviewer description: 用于审查 API 接口文档检查路径规则、参数完整性、响应码合理性、示例一致性。当用户要求审查接口文档、检查 API 规范、评估文档质量时使用。工具示例工具。 allowed-tools: Read, Write, Grep --- # API 接口文档审查 对指定 API 文档进行系统性审查输出结构化问题清单。 ## 审查清单 1. 路径命名 - 资源使用复数名词如 /users 而不是 /user。 - 路径层级不超过三级。 - 避免在 URL 中使用动词改用 POST/GET 等方法表达操作。 2. 参数完整性 - 每个参数必须标注类型、是否必填、默认值、约束范围。 - 分页参数约定为 page 和 page_sizepage 从 1 开始。 - 时间参数统一使用 ISO 8601 格式。 3. 响应码合理性 - 创建操作返回 201删除操作返回 204校验失败返回 422。 - 禁止在成功响应中混杂 200 以外的语义模糊状态码。 4. 示例一致性 - 示例请求体必须与参数定义一致。 - 示例响应必须与响应模型一致不允许出现文档中未定义的字段。 ## 报告输出格式 - 标题接口文档审查报告 - 表格问题位置、级别、问题描述、修改建议 - 结尾列出未检查项或文档中缺失的定义写到这里我想多说一句SKILL.md 的正文不是越长越好但每个规则都需要是可操作的。如果正文里出现检查文档是否规范这种话那等于没写模型不知道该怎么执行。反过来每条都有明确判定标准和输出格式模型执行起来几乎不会跑偏。3.4 辅助资源为什么要拆出来模板与参考文档的价值SKILL.md 本质上是行为的骨架而模板和参考文档相当于肉。比如我这个审查技能我准备了两个辅助资源。第一个是references/api_style_guide.md里面放的是团队 API 规范全文。这样SKILL.md里就不用把所有完整规则都塞进去只需要引用详见风格指南第 3 节路径规范就行。模型的注意力资源有限把细枝末节的示例放在参考文档里需要时再展开效率更高。第二个是templates/review_report_template.md它是报告的结构模板确保每次输出的报告格式一致方便后续自动化处理。辅助资源还有个重要优势维护成本低。当团队规范更新时只改参考文档就行不用动主行为逻辑。如果你把所有规则都堆在 SKILL.md 里改动一次就要重写整个技能文件且容易引入前后不一致的问题。4. 一次真实的测试循环让 Claude Code 自己验证技能是否生效写完之后别急着开心Skill 不是写了就生效的它需要经过真实任务的测试和调优。这一节的流程是很多人跳过的但恰恰是零踩坑的关键。4.1 测试前的环境准备与冷启动策略第一步新建一个干净的临时项目目录在里面重启 Claude Code。为什么要在新目录测试因为旧项目的上下文中可能残留了大量对话历史模型会被之前聊的内容影响干扰对技能的判断。冷启动能让你确认技能本身有没有起作用而不是模型根据历史猜出了你想干什么。在临时目录里我会先执行claude然后输入请审查当前项目中的 api_docs/v1.md 文件输出审查报告。同时观察两个东西一是它的思考过程是否引用了技能中的规则比如提到根据审查清单第 2 条二是输出报告的结构是否符合我在 SKILL.md 里定义的格式。4.2 怎么判断 Skill 确实被加载了一个最简单的验证方法Claude Code 在加载技能时通常会在对话中有迹可循比如它会主动提到我将使用 api-doc-reviewer 技能来处理这个任务或者在回答中出现根据该技能的要求。如果你没有看到任何相关迹象我建议你主动问一句你刚才在处理这个任务时使用了哪个技能加载了 SKILL.md 中的哪些约束让它把使用的技能名和关键约束复述出来。只要它能准确说出技能名和具体规则就证明加载成功了。如果它支支吾吾或者说得跟你的 SKILL.md 对不上那就要检查 description 是否写得太模糊或者文件路径命名是否符合规范。4.3 用构造样例来逼出问题更细致一点的测试方法是构造几个包含明显错误的样例文档让模型去审查看它能不能全部发现。我一般会故意埋几个隐患比如接口路径用了单数名词/user/profile并且层数超过三级。某个请求参数没写page_size的范围。示例响应里多了一个 schema 中未定义的字段。删除操作返回了 200 而不是 204。如果技能正确加载这些错误应该被结构化地列出来而不是只被轻描淡写地提到其中一两个。哪一条没抓出来就说明 SKILL.md 里对应的规则写得不够显眼或者描述中的触发场景没有覆盖到。4.4 调试技巧用最小化修改快速迭代Skill 调优的核心原则是每次只改一个地方。如果你同时改了 description、正文结构和参考文档然后发现结果变好了你是没法确定到底哪一步起作用的。我会先调整 description因为它的命中率问题最常见。比如原来写用于审查接口文档触发可能不精准我改成用于审查 API 接口文档当用户要求检查接口规范、路径设计、参数完整性和响应码合理性时使用。改完跑一轮测试如果触发了再继续优化正文规则。正文的调优我会采用局部替换法保留整体结构每次只对某一条规则进行重写然后再跑测试看这条规则的执行效果。比如发现它对响应码合理性检查不严我就把那一段描述改得更具体给出一张状态码对照表而不是写检查响应码是否合理这种模糊指令。调试过程中我还发现一个小技巧查看完整对话输出时重点看模型有没有自言自语提到规则编号。如果一个技能有 10 条规则而它只提到了前 3 条那大概率是后面的内容写得太长太绕被模型忽略了。这时候就需要把关键规则往前放、加粗、或者单独列为最高优先级。5. 新手最容易踩的坑我见过的和踩过的这一节没有废话全是我实际用下来或者帮别人排查时遇到过的问题。每个坑我都尽量给你说清楚为什么会出现、怎么避免。5.1 description 写得太宽泛或太具体description 太宽泛会导致误触发太具体会导致该触发的时候没触发。最好的状态是把常见场景枚举清楚但不穷举。我们做数据库迁移技能时description 写了数据库、迁移、表结构、索引、回滚基本能覆盖 90% 的场景同时不会在用户只是聊聊数据查询时误触发。5.2 把 SKILL.md 当成说明书而不是操作规范Skill 的正文本质上是一份程序化的操作规程但很多人写成产品说明书充满了背景介绍、设计理念、术语定义。这些东西不是不能用但要放到references/里。SKILL.md的开头必须直入主题第一句话就应该告诉模型这个技能干什么、第一步做什么。模型处理上下文时是有注意力预算的前面 200 个字决定了它对整个任务的框架性理解。5.3 忽略 allowed-tools 的约束frontmatter 里的allowed-tools是很多新手完全忽略的字段。它的作用是限制技能执行时模型可以调用的工具范围。如果不写模型可能会随意读取文件、执行命令虽然灵活但存在风险。比如一个纯文档生成技能如果不限制工具模型可能会尝试去执行 shell 命令这既慢又容易出问题。写清楚这个字段等于给技能套了个防护罩。5.4 把 Skill 目录放在错误的位置Claude Code 对 Skill 目录的扫描范围是有约定的。有人把技能放在了普通文件夹里或者把SKILL.md的名字改成了skill.md系统根本不识别。还有不少人同时存在项目级.claude/skills/和用户级配置目录结果两边同名技能互相覆盖行为不可预测。我建议初次尝试时所有技能先都放在项目级目录里跑通后再考虑提升到更高级别。5.5 没有维护计划写成就扔Skill 和代码一样需要维护。团队规范变了、工具版本升了、或者你发现某条规则执行效果不好都要及时更新。很多人的技能写完之后就再也没动过三个月后用来干新任务输出质量明显下降然后怀疑是模型变笨了其实是技能里的规则已经过时了。我给自己定了个习惯每个月末把常用的三四个技能通读一遍删掉废话补充新踩坑总结出来的规则。5.6 在 Skill 里写死绝对路径或依赖特定环境这也是个很隐蔽的坑。如果你在 SKILL.md 的正文里写了Read /home/某开发者/projects/xxx/guide.md这个技能换一台机器、换一个项目就废了。正确做法是使用相对路径并在正文里先声明所有路径均相对于项目根目录然后统一用.claude/skills/api-reviewer/references/api_style_guide.md这类写法。5.7 试图用 Skill 替代一切Skill 不是万能的。它擅长的是把既定流程执行得更稳定而不是创造出你完全没写过的新流程。如果你对某个任务的理解还很模糊不知道正确的操作步骤是什么那技能写出来必然也是错的。我一般会先用普通对话跑通几次任务确认流程稳定可行再把流程固化成一个 Skill。先用对话探索后用技能固化顺序别反。6. Skill 的进阶玩法与边界思考从单文件技能到专家系统如果前面这些你都玩明白了那恭喜你可以开始琢磨一些更进阶的东西了。这一节讲的是怎么把多个技能组织成一个体系以及 Skill 和其他机制比如外部工具集成、子代理的分工边界。6.1 多技能组织从零散技能到技能库我见过有些开发者手上有十几二十个技能但没有目录结构全部平铺在.claude/skills/下。这会导致两个问题一是 description 之间的语义可能重叠触发的时候打架二是维护的时候根本找不到哪个文件对应哪个技能。我自己的做法是按领域建子目录用前缀区分.claude/skills/ ├── review-api-doc/ ├── review-python-code/ ├── review-sql-query/ ├── gen-db-migration/ ├── gen-commit-message/ └── gen-release-notes/你可以注意到我用review-和gen-前缀把审查类和生成类技能分组。这种命名方式不仅方便人看也方便模型在多个技能之间做选择因为 description 被扫描时前缀本身也提供了很强的语义信号。6.2 动态资源让 Skill 引用项目里的实时数据进阶一点的玩法是让 Skill 在执行时读取项目当前的实时数据。比如我在数据库迁移技能里写了这样一个步骤3. 读取项目根目录下的 schema/models.py 或 schema/schema.sql获取当前表结构。 5. 对比当前结构与目标结构生成差异迁移。这相当于给技能装了一个读项目上下文的步骤让它不只是执行静态规则而是能根据当前项目的实际状态做动态判断。这是从普通技能走向准专家系统的关键一步。6.3 Skill 与外部工具、子代理的分工与边界Claude Code 里还有另外两个常见能力一个是连接外部数据源与外部工具的服务机制另一个是以子代理形式执行特定子任务的能力。新手经常问我它们和 Skill 有什么区别。我用一句话区分Skill解决的是怎么做更专业的问题它改变的是模型完成任务的方式。外部工具服务解决的是能接触什么信息的问题它扩展的是模型获取新数据的通道。子代理解决的是谁来干这活的问题它把任务拆分给独立的执行单元并行处理。举个例子。你要写一个从数据库抽出上个月的订单数据并生成分析报告的技能。Skill 负责定义报告的结构和分析维度外部工具服务负责真正连上数据库把数据拉回来如果你还要同时处理多个数据源那就可能用到子代理并行工作。三者可以组合但各自管的事不一样。6.4 版本管理与团队共享当你把技能做得比较成熟之后可以把它当成团队资产来管理。我一般会把.claude/skills/纳入版本控制把每个技能的变更记录写在提交信息里。团队协作时新成员 clone 项目后技能就自动同步下来了不需要手动分发。这里有个细节值得注意技能文件的变更记录必须写在提交信息中不要依赖技能文件里自己写更新历史。因为模型不会主动去读更新历史但版本控制系统会如实记录每次变更方便人回溯。如果你想把某个技能发布到更广泛的社区记得先处理掉里面可能存在的团队内部信息比如数据库地址、内部命名规则、私有脚本路径。公开技能的核心是方法论共享而不是配置泄露。6.5 后记我的几点真实体会最后说点很主观的东西。Skill 这个东西刚开始写的时候会觉得挺简单不就是写个 Markdown 吗。但真正用一段时间之后你会发现它逼着你把自己的工作流程想清楚。以前我让 Claude Code 干活靠的是一股临场发挥的感觉现在我写技能必须先梳理出这类任务到底分几步、每一步有什么判定标准、什么情况算异常。这个梳理过程本身的价值甚至比技能带来的效率提升还要大。它等于把我脑子里那些模糊的经验沉淀成了一份可以被模型执行、也可以被同事阅读的显性知识。说句实话干技术这行能把这套东西做好的人写文档、带新人、评审方案能力都会跟着上去一截。如果你想开始我的建议是先选一个你日常重复次数最多、且你已经很熟悉的流程把它做成第一个 Skill。别贪多一个就好。跑通它你会得到比看十篇教程更深的体会。