有一段时间,我在团队里最烦的一件事就是:每次让 AI 辅助做代码审查,都要把审查标准从头到尾再描述一遍。“重点看边界条件、错误处理、日志完整性、SQL 注入风险”,这些话我至少重复了几十次。后来接触到 Claude Code Skills 系统,我才意识到这种重复劳动其实是可以彻底收敛的。Skills 系统的核心思路很简单:把一套完整的工作方法、检查标准、处理步骤,写成一个独立可复用的技能文件,Claude Code 在遇到匹配任务时自动加载并执行这套流程。这篇文章我会从设计思路拆到落地配置,再附上我在某团队项目里实际配置代码审查技能、重构辅助技能的完整过程,以及踩过的坑,希望能给正在折腾 AI 辅助编程的同学一点直接能用的参考。
1. 先搞清楚它解决什么问题:Skills 系统到底比提示词强在哪
1.1 低效场景的根源:上下文每次都从零开始
先说一个很多团队都会遇到的问题。接入 AI 辅助编程之后,模型的能力其实够用,但产出质量极不稳定。今天让它审查一个 Python 接口,它能列出十个细节问题;明天换个人提同样的需求,它可能只给三句泛泛而谈的建议。原因不难理解:每一次对话都是独立的,上下文是冷启动的。你把审查标准写在提示词里,这仅仅对当前这一次对话有效;换一个文件、换一个会话,你又要重新描述一遍。
我见过很多团队的"提示词资产"就是一个共享文档,里面积累了十几页的审查规范。使用的时候靠人肉复制粘贴,粘贴完了还得祈祷模型真的把每条规范都执行到位。这种方式有两个致命问题:一是复制粘贴本身有遗漏风险,二是规范里面那些"I类的边界要重点看""空指针要单独列出来"这种条款,模型在一次长对话里很容易执行着执行着就忘了。Skills 系统把"规范"变成了可以被自动识别、自动加载的程序化文件,从机制上绕开了这两个问题。
1.2 Skills 系统和普通提示词的本质差异
说直白一点,普通提示词是"你这次帮我干这件事,按照我说的做";Skills 系统是"当遇到这件事时,自动用我沉淀好的标准流程来做"。差异不只是形式,而是三个层面。
第一个层面是触发机制。普通提示词靠人肉输入,你漏写了某条规范,模型就不可能按规范执行。Skills 系统靠语义匹配,模型在对话中识别到用户意图和某个技能描述匹配,就会自动加载这个技能的文件内容作为执行依据。
第二个层面是复用单位。提示词以会话为单位,会话结束就没了;技能以文件为单位,写在.skills目录下面,跨会话、跨项目都能复用。我更新一次技能文件,等于所有未来会话的默认行为都变了,这个杠杆效应是提示词给不了的。
第三个层面是组合方式。提示词是一次性的线性描述,而技能可以按任务场景拆分,比如代码审查一个技能、规范校验一个技能、重构辅助一个技能。碰到复合任务时,多个技能可以依次被触发,各管一段,互不干扰。我用一个生活化类比给团队讲过:普通提示词相当于你每次去咖啡店都跟店员说"我要中杯、少糖、不要冰块",技能相当于你提前办了一张会员卡,店员看到卡就知道你要什么,你只需要说一句"还是老样子"。
2. 核心机制拆解:SKILL.md 文件结构与触发链路
2.1 技能文件到底长什么样
Claude Code Skills 系统的实体是一个个独立的技能目录,目录里面放一个SKILL.md文件。我在项目里习惯这样组织目录:
.skills/ python-backend-review/ SKILL.md requirements-analyzer/ SKILL.md refactor-helper/ SKILL.md每个SKILL.md文件分为两部分:头部配置信息和正文内容。头部用 YAML 格式写元数据,正文用 Markdown 写具体的执行流程、检查清单和输出格式。下面是一个简化的示例:
--- name: python-backend-review description: 对 Python 后端服务代码进行系统性审查。适用于新增接口、修改业务逻辑、调整数据库查询语句等场景。当用户提到"审查""检查""Review"且涉及后端代码时优先使用。 --- ## 执行流程 1. 列出改动文件中涉及的函数、接口与调用链。 2. 对每个函数依次检查边界条件、异常处理、日志记录。 3. 对数据库相关代码检查是否存在注入风险。 4. 按严重级别输出问题清单,每条问题附带修复建议。这个文件本身不复杂,复杂的是里面的描述信息和执行流程怎么写。我见过不少人的第一个技能就是随便复制了一段提示词进去,结果该系统识别得一塌糊涂,后面我会详细说描述信息该怎么调。
2.2 触发链路的三个关键环节
从实际运行来看,一个技能从被识别到被执行的完整链路大致可以拆成三步。
第一步是意图识别。用户发起请求后,模型会把当前请求和所有技能description字段做语义匹配。这里要特别注意,模型依据的只有description字段,不是SKILL.md的正文。也就是说,正文写得再详细,如果描述信息写得稀烂,技能也永远不会被触发。
第二步是内容注入。一旦某个技能的描述信息和当前任务匹配,模型就会读取这个技能的SKILL.md文件全文,把内容注入到当前的上下文窗口中。这一步也解释了为什么技能文件不能写得太大,文件越大,注入到上下文里的 token 越多,模型执行时的"注意力"就越分散。
第三步是步骤执行。注入完成之后,模型会按照技能正文里写的流程逐步执行。如果正文里写了"先列调用链再逐函数检查",模型就会遵循这个顺序。如果正文里没写输出格式,模型就会按照自己的偏好自由发挥——这就是很多技能看起来执行了,但结果还是不够好的原因。
2.3 优先级与冲突机制
多技能并存之后,冲突是绕不开的话题。最典型的情况是:你有"代码审查"和"安全检查"两个技能,描述信息都写了"当涉及代码质量问题时激活"。结果模型无法区分,干脆随便选一个,或者两个都触发,输出内容重叠得一塌糊涂。
我在实际操作中总结出的经验是:描述信息里必须写清楚边界约束。比如代码审查技能可以写"不涉及安全漏洞专项排查,该类问题交由 security-scan 技能处理",安全检查技能则写"仅当用户明确提到安全、漏洞、渗透时使用"。这种互斥约束能极大降低误触发的概率。
另外要注意技能目录的命名。name字段在文件头部配置,但它主要起标识作用,模型对技能的理解仍然依赖description。我见过有同学把name写得特别复杂,好像名字越长越精确,实际没必要。名字清晰好认就行,触发判断靠描述。
3. 实操第一步:配置一个代码审查技能
3.1 明确这个技能的服务边界
套用一句老话:一个技能只做一件事。代码审查这个技能,看起来目标明确,但如果边界定义不清,最后很容易演变成"什么都管、什么都管不细"。
我在某团队项目里配置第一个技能时,先问了自己三个问题:审查对象是什么语言、什么类型的项目?审查重点是什么?输出格式是什么?当时的项目是 Python 3.11 的 FastAPI 服务,所以我把技能服务对象限定为 Python 后端代码,审查重点定为边界条件、异常处理、日志关注点和数据库安全,输出格式定为问题列表加严重级别加修复建议。这三个问题想清楚了,技能文件的骨架基本就出来了。
3.2 撰写 SKILL.md 的核心流程
我最终的python-backend-review技能正文比第一节里的示例要细得多,这里展示一个经过多次迭代后的精简版本:
--- name: python-backend-review description: 针对 Python 后端服务代码进行系统性审查。适用于新增接口、修改业务逻辑、调整数据库查询等变更场景。当请求中涉及 FastAPI 路由、SQL 语句、异常处理逻辑时优先触发。不处理前端代码与部署脚本。 --- ## 审查步骤 1. 先列出本次改动涉及的所有文件,按"接口层 / 服务层 / 数据层"分组。 2. 对每个接口函数检查:入参校验是否完整、边界值是否有处理、响应状态码是否合理。 3. 对每个服务函数检查:异常分支是否覆盖、日志是否记录关键入参和异常堆栈、是否有重复代码。 4. 对每个数据库查询检查:是否使用了参数化查询、是否存在 N+1 查询、事务边界是否正确。 5. 汇总输出,按"严重 / 普通 / 建议"三级列出问题,每条必须附带具体行号和修复代码片段。这个版本我在实践中发现比第一版好用的原因有三个:给定了文件分组顺序,模型不会再东看一眼西看一眼;明确了每层检查的具体对象,模型不会只挑最显眼的逻辑错误;指定了输出必须附带行号和修复代码片段,否则模型只会给一句"建议优化性能"这种没用的废话。
3.3 在会话中测试触发的完整过程
配置完技能文件之后,最关键的验证环节来了。我习惯用几句话来测试技能的触发效果,比如直接说"按团队的审查标准检查一下最近几个文件改动"。如果 Claude Code 成功调用了技能,在输出中能明显看到它开始先做文件分组,再逐层检查,最后按三级问题汇总;如果技能没有被触发,它可能直接开始评论代码,完全不按流程走。
第一次测试失败非常正常,我现在的做法是:测试失败先不急着改正文,先去改description字段。把触发场景描述得更具体,把负面约束写清楚。比如"不处理前端代码与部署脚本"这句话就是一次真实踩坑后加进去的,因为当时我只说"审查 Python 代码",结果前端文件也被模型拉进来审了一遍,浪费了大量上下文。
迭代的过程说白了就是不断观察"你希望它触发时不触发、不希望它触发时反而触发"这两类错误,然后调整描述信息。这个过程没有一步到位的捷径,需要耐心。
4. 进阶用法:用多个技能的编排解决复杂任务
4.1 需求梳理技能:把模糊需求变成验收清单
代码审查技能只覆盖了开发后半段。一次完整的需求研发要从一堆含糊描述开始,我为此配了第一个技能,名字就叫requirements-analyzer。
它的核心逻辑是:当对话中出现"需求""想要做一个""客户说"这类关键词时,自动把描述拆解成三部分:业务目标、用户操作流程、异常和边界情况。它会不断追问缺失的信息,直到形成一份结构化的验收清单。
这个技能和代码审查技能的协作方式是这样的:需求梳理技能先产出验收清单,后续的开发、验证任务再引用这份清单。虽然两个技能在文件上相互独立,但在工作流上形成了一种流水线关系。我刻意不让技能之间互相引用文件内容,而是通过输出结果衔接,这样每个技能都可以独立维护、独立测试。
4.2 规范校验技能:和代码审查技能做边界互补
一开始我把规范校验的逻辑也写在代码审查技能里,后来发现不行。规范校验是机械规则,比如命名是否符合项目规范、函数长度是不是超标、依赖是否按顺序排列;而代码审查是逻辑问题,比如边界条件和异常分支。两类问题混在一个技能里,模型经常抓不住重点,有时纠结于缩进格式,却放过了真正的逻辑漏洞。
后来我拆了另一个技能style-enforcer,专门处理格式和规范问题。它的描述信息里明确写了"仅关注代码风格和项目规范,不涉及逻辑正确性"。这样代码审查技能就可以在描述里写"不处理格式问题,格式问题由 style-enforcer 处理"。两个技能形成互补,误触发的冲突也减少了。
4.3 重构辅助技能:小步提交的安全流程
重构是最容易让 AI 模型跑偏的任务之一。上来就说"帮我重构这个模块",模型很可能会大刀阔斧地重写一版,完全不考虑兼容性。我配的refactor-helper技能专门克制这种冲动。
它的流程是:先分析现有代码的调用关系,找出所有依赖点;然后建议先补充测试用例,覆盖当前行为;再执行最小粒度的重构,比如先重命名一个函数,运行测试,确保通过后再继续下一步。我把"每次只允许修改一个独立单元"直接写进了技能正文。这样一来,我只需要说"用重构技能处理这个模块",它就会自动进入小步快走的节奏。
4.4 跨技能协作的边界问题
多个技能同时存在后,最大的问题不是单个技能写得好不好,而是彼此之间的边界是否清晰。我遇到过最头疼的一次情况是:代码审查技能和安全检查技能描述里都写了"审查时关注 SQL 注入",结果模型在同一个请求里反复触发两个技能,输出内容大量重复,上下文窗口被白白消耗。
解决思路是在描述信息里做互斥声明。每个技能在description里明确列出自己管什么、不管什么,并用"该问题交由 XX 技能处理"来引导分流。这套互斥描述我后来当成团队规范执行,每个新增技能都必须写清楚"不处理什么",否则不接受。
5. 参数与配置细节速查:我看过的几种配置模式
5.1 常用配置项对照表
我根据实际项目经验,整理了一份技能配置项对照表,不一定覆盖所有场景,但常见的配置需求基本都在里面了:
| 配置项 | 用途 | 容易踩的坑 |
|---|---|---|
| name | 技能标识,用于区分不同技能 | 命名太随意,多个技能之间难以区分 |
| description | 语义触发判断的唯一依据 | 写得太宽泛等于没写,误触发率高 |
| 正文步骤 | 模型执行任务的具体流程 | 没有验收标准,输出质量无法控制 |
| 输出格式定义 | 规定结果以什么形式呈现 | 不定义就会得到自由发挥的杂乱输出 |
| 例外规则 | 明确不处理哪些内容 | 没有例外规则,容易越界处理无关内容 |
5.2 描述信息的三种写法对比
描述信息写得好不好,是技能能否被正确触发的分水岭。我对比过三种典型写法。
第一种是极简派:"审查 Python 代码。"这种描述最大的问题是触发判断过于宽泛。模型看到任何和 Python 相关的请求,都可能激活这个技能,结果连"帮我解释一下这段 Python 语法"也会被拉进审查流程。
第二种是堆砌派:把正文字段的重要内容全部复制到描述里,写了一大段话。这种描述表面看信息量很大,实际上语义信息重复,模型在匹配时反而抓不住关键触发点,而且浪费上下文。
第三种是我现在用的场景派:用触发场景加约束条件描述。例如"当用户要求对 Python 后端服务进行代码审查、检查接口逻辑或数据库查询时使用。不处理前端代码、不处理格式问题。"这种写法既给了模型具体的触发场景,又划定了边界,误触发率明显下降。
5.3 技能文件的大小控制与拆分配置
技能文件不是越详细越好,这一点我反复栽过跟头。最初写代码审查技能时,我把团队所有的研发规范、代码风格文档都塞了进去,文件长度超过了几千行。结果模型每次触发都会把全文注入上下文,消耗了大量 token,反而因为信息过载,执行重点不突出。
现在我的习惯是:一个技能文件控制在 100 到 200 行左右,只保留最关键的执行步骤和验收标准。额外的细节放在项目根目录的文档里,在技能正文中用一句"细节规范参见项目文档某章"来指路。这样技能文件保持轻量,模型不会迷失在细节里,需要的时候也有依据可以引用。
6. 常见问题与排查技巧实录
6.1 技能完全没有被触发
这个问题通常出在description字段上。排查思路我一般按三步走:先确认技能文件所在目录名和文件位置是否正确;再看description里有没有包含用户请求中可能出现的核心词汇;最后检查是不是有其他技能的描述信息覆盖了当前技能。
遇到过一种很隐蔽的情况:两个技能描述高度相似,系统只触发了其中一个,另一个完全没有尝试加载。原因是模型在语义匹配时选择了那一个更匹配的。解决办法不是删掉另一个技能,而是在两个描述里加互斥约束。
6.2 技能被触发但执行结果不完整
触发成功不等于执行到位。我经常遇到的场景是:模型加载了技能文件,但只执行了其中一半的步骤,然后就直接输出结论。这通常不是模型"偷懒",而是技能正文里步骤本身的驱动性不够。
解决办法是在每个步骤后明确写出该步骤的产出物。比如不写"检查函数入参校验",而是写"列出每个接口函数的入参校验逻辑,并标注缺失校验行号"。产出物定义得越清楚,模型的执行就越完整。
6.3 多个技能的上下文相互污染
在复合任务中,一个请求触发多个技能是正常的,但如果技能之间职责重叠,就容易出现上下文污染。最典型的表现是:技能 A 的检查项出现在技能 B 的输出结果里。
我踩过的一个具体例子是:代码审查技能和需求梳理技能同时被触发,结果代码审查过程的中间分析被并入了验收清单,用户拿到的清单里混入了"某函数缺少异常处理"这种和需求无关的条目。后来我在需求梳理技能的输出格式里加了一条规定:"输出内容只允许包含需求相关条目,禁止混入技术实现层面的代码问题。"上下文污染问题才得到控制。
6.4 一个特别容易踩的坑:试图让技能直接操作文件
初期使用该系统时,很容易把它想象成自动化脚本,想让技能直接修改代码文件并提交。实际操作中我发现,技能更适合做分析、规划、审查这类辅助工作,真正执行修改文件这种高风险操作,最好还是人工确认。我在技能正文里明确要求:"修改代码前必须给出 diff 说明,禁止未经确认直接改动文件内容。"这句限制帮团队避免过至少两次事故。
补充一个安全提示:不要在技能文件里写入任何敏感凭据或内部地址信息。因为技能文件会被注入到模型上下文中,敏感信息一旦进入对话,后续输出的内容都有携带风险。保持技能文件内容"只见规范、不见机密"。
6.5 一次对话中技能被反复触发
最后一个常见问题是同一个技能在一次对话中被触发多次,执行流程也被重复跑了多遍。多发生在用户修改了需求表达方式之后,模型又认为需要重新执行一次技能。
如果重复执行不影响结果,可以容忍;如果影响,我会在技能正文开头加一句"如果本次对话已经执行过本技能,且没有新增输入信息,请直接复用上一次分析结果,不重复执行。"这句约束直接命中痛点,能省下大量上下文。
最后分享一点个人经验
整个 Skills 系统用下来,我最大的体会是:不要把它当成提示词模板的升级版,应该把它当成团队的标准化作业程序来维护。提示词是你和模型之间的临时沟通,技能是你和整个团队长期共识的沉淀。每一条描述、每一个步骤、每一处边界约束,背后都是真实项目里踩过的坑。
在实际使用中,我会把每个技能文件纳入版本管理,和代码放在同一个仓库里。技能文件变更走评审流程,更新之后记录变更原因。这套做法让团队的 AI 辅助效率稳定下来,新成员加入时也不用再从头口述审查标准,直接看技能文件就能上手。
我也建议不要贪多,一开始只配置一两个真正高频使用的技能,跑通之后再慢慢扩展。技能数量上来之后,维护成本是指数级上升的,触发冲突、上下文膨胀、职责重叠,这些都要花时间打磨。先把一个技能打磨到"稳定触发、执行完整、输出可用"的状态,比同时维护十个半成品技能有价值得多。