AI 编程圈最近讨论最多的一个词是 skills。这里的 skills 不是招聘网站上的加分项,而是给 AI 编程智能体(agent)使用的技能包,用来解决一个非常现实的问题:模型确实能写代码,但写出来的东西经常是"能跑但不改没法看"的屎山代码——变量名随意、逻辑重复、风格混乱、注释要么没有要么全是废话。
GitHub 上这个方向的热度已经很明显,21 万星、超过 1400 万次下载量,都是这个趋势的注脚。背后其实是一个共识:靠对话式提示词已经很难稳定约束 AI 的输出质量,大家需要一种更结构化、更可复用的方式,把"怎么写代码、按什么标准写"教给模型。skills 就是在这样的背景下被推到前台的。
这篇文章适合两类人。一类是正在用 Cursor、Codex、Claude Code 这类工具,但觉得 AI 生成代码质量不稳定的开发者;另一类是团队想统一 AI 编码规范,不希望每个成员调出来的 agent 行为都不一样。
我会按实际落地的顺序拆:先弄明白 skills 到底是什么、解决什么问题,然后讲怎么装、怎么写、怎么验证,最后给出一套排查思路。文章不堆功能列表,也不只讲概念,尽量让你看完能自己动手跑一遍。
1. 先确认它到底解决的是提示词、插件还是代码规范问题
1.1 为什么提示词写了一大堆,模型还是写不好代码
很多人以为 AI 写屎山代码,是因为提示词不够长、不够细。于是把几十条规则塞进 system prompt,结果模型照单全收,真正写的时候还是经常跑偏。
原因不复杂。普通对话式提示词是线性的,你告诉模型"代码要规范、变量命名要清晰、要考虑边界情况",它理解了,但执行过程中缺少结构化约束。长提示词还有一个问题:随着上下文变长,模型对前面要求的注意力会逐渐衰减,尤其是任务本身复杂时,规则更容易被任务内容淹没。
skills 的解题思路不一样。它把"如何处理一类任务"的完整知识打包成一个独立单元,包含说明文档、示例、脚本和参考文件,通过显式的描述和触发机制让模型在合适的时候主动加载。模型不是靠记忆遵守规则,而是靠"当前任务匹配到了哪个技能包"来决定行为。
这个切换很关键。前者是"你告诉我该怎么做",后者是"我有一套针对这类任务的完整操作手册,遇到同类问题就加载它"。后者带来的改变不是让模型更听话,而是让模型的执行过程更稳定。
1.2 skills 和普通插件、代码模板的区别
我经常被问到:skills 跟插件、模板、脚手架有什么不同?
插件是代码层面的扩展,它给编辑器或命令行工具增加功能,比如补全、lint、调试。skills 是给模型看的"操作手册",它不直接改变工具能力,而是改变模型执行任务的方式。
代码模板解决的是初始化问题。你想建一个新的前端项目,用模板把目录和基础文件生成好。skills 解决的是持续执行问题。你让 AI 处理一个已有的、包含大量历史代码的仓库时,它能不能稳定按照团队规范来改代码。
这句话可以当作判断标准:skills 解决的不是"能不能生成代码",而是"生成的代码是否符合预期标准"。这也是为什么很多团队引入 skills 后,第一反应是代码风格统一了,而不是生成速度变快了。
如果看到某个技能包号称"让 AI 自动完成所有开发任务",你要降低预期。技能包能约束行为和流程,但做不到凭空提升模型的理解能力。它有边界,这个边界越早认清越好。
2. 从最小使用场景开始:先装一个现成技能包
2.1 常见 AI 编码工具的 skills 入口
目前主流 AI 编程工具基本都支持 skills 或类似能力,但入口和格式略有差异。我用过一次之后发现,最容易被绕晕的就是文件放哪里。
常见入口情况可以这样理解:
| 工具 | 技能入口特点 | 使用建议 |
|---|---|---|
| Claude Code / Claude 桌面端 | 有专门的 skills 目录,使用 SKILL.md 组织技能 | 按官方文档确认目录结构,不要自己改路径 |
| Cursor | 支持项目级规则与指令,新版本逐步兼容技能格式 | 把技能放到项目统一的配置里,避免每个成员各自配置 |
| Codex、OpenCode 等 CLI 工具 | 通过配置文件或命令声明技能路径 | 先查看工具的配置命令,确认语法要求 |
我第一次接触时犯过一个错:把技能包直接扔到项目根目录,以为工具会自动扫描。实际上很多工具只扫描固定目录。所以第一步不要去找"通用路径",而是看当前工具版本支持哪些目录,按官方推荐的位置放。
如果你用的工具没有完全开放技能能力,但支持自定义规则或 agent 指令,也可以把技能文件的内容放到对应的规则目录中。原理一样,只是入口名字不同。
2.2 从社区热门技能包开始测试
社区里现在能搜到很多现成的技能包集合,比如 Superpowers、Nature、Matt Pocock 整理的 skills 集,还有一些专门面向前端开发、测试、学术研究和文案创作的包。搜索时直接搜 agent skills、skills 推荐、find skills 这类关键词,能找到不少社区整理好的清单。
使用顺序我建议这样:
- 先选一个跟自己工作最相关的技能包。日常主要写前端,就选前端开发技能包;日常做测试,就选测试类技能包。
- 装完后不要急着跑大任务。先用一个简单的小任务测试,比如"帮我审查这个组件""帮我生成一份接口测试用例"。
- 观察模型是否选择了这个技能、选择后行为是否发生变化、输出是否符合技能里描述的规范。
- 如果行为没有变化,先检查技能描述是否写清楚了触发条件、路径是否正确、模型版本是否支持。
有些技能包会附带自己的测试样例,这个很值得利用。跑样例相当于做回归测试:如果样例都不能通过,说明技能包跟当前工具或模型版本存在兼容问题。
社区技能包质量参差不齐。看到"一键装完所有技能"这种方案时,不建议直接照搬。技能包装得越多,模型触发时越容易犹豫或选错。通常 5 到 10 个高质量技能包就够用了。
3. 自己动手写第一个 skill:从最小可运行版本开始
3.1 skill 的标准结构:SKILL.md 加资源文件
一个最小可用的 skill,只要一个 SKILL.md 文件就够了。它通常包含两部分:frontmatter 元数据和正文。
frontmatter 里最关键的是 name 和 description。name 是技能的唯一标识,description 是模型判断何时使用该技能的入口。描述写不好,模型根本不会触发这个技能。
我写 description 时有一个习惯:不写形容词,只写条件和边界。比如"当用户要求审查前端组件代码、检查 React 组件性能问题、评估 CSS 可维护性时使用",比"帮助用户写出更好的前端代码"有效得多。原因在于,模型做技能匹配时依赖关键词和意图识别,描述越具体,匹配越稳定。
正文部分要包含执行步骤、技术要求、输出格式和常见禁忌。执行步骤应当按顺序编号,让模型可以逐步执行,而不是给它一堆并列要点。如果技能涉及脚本或参考文件,还要在 SKILL.md 里明确引用方式和路径。
为什么要用 Markdown 而不是直接写在提示词里?因为 Markdown 的结构化特性让模型更容易识别标题、列表、代码块和注意事项。同样一段文字,用无序列表平铺和用编号步骤分节,模型执行后的稳定性差别很大。
3.2 一个前端代码审查技能的例子
用实际场景来演示:写一个前端代码审查 skill。
先创建目录和文件:
mkdir -p ~/.claude/skills/frontend-review touch ~/.claude/skills/frontend-review/SKILL.mdSKILL.md 内容可以这样组织:
--- name: frontend-review description: 当用户要求审查前端代码、评估 React 组件性能、 检查 CSS 可维护性或需要前端代码走查时使用。 --- # 前端代码审查 ## 执行步骤 1. 先读取目标文件,确认文件类型和依赖。 2. 检查组件拆分是否合理,是否存在超过 300 行的组件。 3. 检查状态管理是否集中,是否避免了不必要的 prop drilling。 4. 检查样式是否遵循项目现有规范,是否使用了硬编码值。 5. 给出可执行修改建议,每条建议需附带影响范围。 ## 输出格式 使用 Markdown 表格输出:文件路径、问题等级、问题描述、修改建议。 ## 禁忌 - 不要只给建议而不给位置。 - 不要在不确定时虚构性能数据。 - 不要为了追求简洁而忽略可读性。写完后,用一句"帮我审查一下这个组件"来触发。如果模型没有加载这个技能,查看日志和工具输出;如果加载了但结果仍然很泛,说明正文里的步骤还不够细。
这个例子看起来简单,但已经覆盖了技能的核心要素:触发描述、执行步骤、输出约束。实际项目里可以把脚本、规则文件、示例代码都挂到技能目录下,让模型在执行时能访问完整上下文。
4. 让技能真正可用的关键参数和取舍
4.1 描述、粒度、结构化,三个最容易被忽略的点
很多人刚写 skill 时会犯同一个错误:把技能写成了"提示词大全"。洋洋洒洒几千字,模型执行起来依然没有章法。我建议关注三个细节。
第一个是步骤粒度。每个步骤应该是模型可以独立执行的动作,而不是一个大段描述。比如"分析项目的 package.json,找出依赖中版本过旧的包并评估升级风险",这是可执行步骤;"优化项目依赖"就不是。模型面对模糊步骤时,会按自己的理解补全,而补全出来的行为往往不稳定。
第二个是边界条件。明确告诉模型哪些情况不应该使用这个技能,哪些情况应该停止并询问用户。比如代码审查技能里写"如果文件超过 500 行,先拆分成多个片段再审查",比让模型硬读整个文件更稳定。边界条件能防止模型在错误场景下强行执行技能。
第三个是示例。如果条件允许,在技能里放一个简短的输入输出示例,模型的执行质量会明显提升。示例是给模型最直接的参考,相当于把抽象规则转成具体样例。
4.2 技能的长度和覆盖范围怎么取舍
我见过两个极端:一个技能只写两句话,另一个把整个团队规范都塞进去。
两句话的技能起不到约束作用,模型只是把这两句话当成普通提示,行为很难有实质改变。整体规范塞进一个技能又会造成触发不精准,模型加载后要解析大量内容,容易抓不住重点。
我的建议是:一个技能只解决一类任务。前端代码审查是一个技能,后端接口设计建议是另一个技能,数据迁移脚本生成又是一个技能。如果发现一个技能里还能再拆出多个独立场景,说明粒度还需要再调。
技能正文控制在 300 到 800 字的描述性内容,配合必要的示例和脚本,通常效果最稳定。超过这个长度时,优先考虑拆分,而不是继续往里面堆内容。
参数层面可以理解成三个数值需要权衡:触发命中率、执行稳定度、维护成本。技能描述越精准,触发命中率越高;正文步骤越清晰,执行稳定度越高;但每个技能都需要维护,数量越多,维护成本越高。适合自己的平衡点,需要跑几轮测试才能定下来。
5. 团队使用和生产化:技能库管理、验证和迭代
5.1 把 skills 当成代码来管理
单个开发者使用 skills,随便放目录就行。但团队要统一使用,就必须把它当成代码来管理。
首先要有一个统一的技能仓库。团队约定一个 git 仓库专门存放所有技能包,每个技能一个独立目录,SKILL.md 必须有明确的版本和变更记录。新手入组时一键拉取,而不是靠人肉复制。
其次要建立技能与职责的映射。前端组、后端组、测试组常用的技能不一样。可以在各自的开发环境里只加载本组相关技能,减少模型误触发。技能库统一管理,每个环境按需加载,这才是更合理的组合。
最后要处理更新问题。技能的描述和正文会随着团队规范变化,需要定期 review 和更新。更新时注意兼容性:改一个技能名会导致旧任务无法再触发,尽量保持 name 稳定,只改正文内容。description 的变化也要谨慎,它直接影响触发行为。
5.2 如何验证一个技能包真的有效
验证技能包有没有用,不能只看一次生成结果。一套可复现的验证流程会更可靠:
- 准备一组固定测试任务,覆盖技能的核心场景和边界场景。
- 用同一模型在开和不开技能两种情况下各跑一遍。
- 对比输出质量、代码风格、错误率和修改返工次数。
- 记录模型是否成功触发技能、触发后是否有加载日志。
- 连续跑多次,确认结果不是偶然。
很多人会跳过第三步。其实"对比开和不开"才是关键,它能证明技能的增量价值,而不是模型本身能力带来的提升。如果开和不开没差异,那这个技能本质上只是多了一个没被使用的文件,不如删掉或者重写。
如果测试结果不稳定,优先检查是否多个技能描述了相近场景,导致模型随机选择。把重叠的场景收敛到一个技能里,触发稳定性会明显提升。
6. 常见坑和排查链路
6.1 模型不触发技能,按这个顺序查
技能没触发是最常见的问题。它不一定是技能写错了,很可能是以下几个原因。
先看输入。你的请求里有没有包含技能描述中的关键词或同义意图?如果描述写的是"前端代码审查",你问的是"这段代码行吗",模型可能不触发。描述里要覆盖常见说法,但又不能写得太宽泛。
再看路径。技能文件是否放在工具指定的目录中?目录层级是否正确?很多工具要求技能目录下直接放 SKILL.md,不能多套一层无关目录。多一层,模型就扫描不到。
再看描述。description 是否太宽泛,导致多个技能都能匹配,然后模型随机选了一个?把描述收窄,增加条件词,比如"仅当用户明确提到审查或走查时使用"。
最后看工具版本。老版本工具可能不支持新格式的 skills。如果其他技能能触发,只有某一个不能,重点检查这个技能的 frontmatter 格式和字段名。
6.2 输出效果差,问题通常出在正文而不是元数据
技能已经触发了,但输出效果仍然不好。这时要换一个排查方向,重点检查正文。
第一看执行步骤是否足够具体。模型遇到模糊步骤就会按自己的理解发挥,所以步骤要写到"能独立执行"的程度。
第二看是否缺少终止条件和输出格式。没有终止条件,模型会一直扩展;没有输出格式,模型会输出一堆不必要的内容。比如审查技能里要求"每条建议附带影响范围和修改难度",输出就会比自由发挥更可控。
第三看资源文件是否真的被加载。有些技能包引用了脚本或参考文件,如果路径配置错误,模型在技能里看到的只是 SKILL.md,而不是完整上下文。这时要检查引用路径和文件权限。
我个人的排查顺序一般是这样:初始请求、目录路径、frontmatter、加载日志、正文步骤、输出格式。按照这个顺序走一遍,大多数问题都能定位到具体环节。
下面这个表可以作为快速判断入口:
| 现象 | 最先查的地方 | 再往深查 |
|---|---|---|
| 技能完全没触发 | 输入请求是否包含触发意图 | description 是否够具体、路径是否正确 |
| 多个技能触发混乱 | description 是否覆盖太多场景 | 是否与其他技能描述重叠 |
| 输出去泛 | 正文步骤粒度 | 是否缺少输出格式和边界条件 |
6.3 还有几个容易被忽略的边界
skills 并不是万能的。它不能替代