最近我让 AI 帮我写一个批量文件重命名脚本,它一次成功;半个月后当我想加一个排除目录的功能,打开代码却开始怀疑人生。变量名是 a、b、c,逻辑全堆在 main 里,错误处理为零,日志也没留。改一行,我都不敢确定会不会影响别处,最后选择重写。这个场景让我意识到:单次生成能力再强,也挡不住长期维护的失控。也正是在这前后,GitHub 上“skills”这个概念开始频繁出现,一个标题里甚至写着 21 万星、超过 1400 万次下载这种量级。
如果把 skills 这件事只看成“又一批可以帮助 AI 干活的脚本”,那就低估它了。我更愿意把它理解成一个信号:AI 辅助写代码这件事,正在从“比谁生成得快”进入“比谁生成的代码能维护”的阶段。这篇文章不打算复述 skills 的定义,而是想认真聊几个问题:AI 为什么容易写出“屎山”?skills 到底改变了哪个环节?你上手时最容易踩的坑在哪里?
1. 先想清楚:skills 真正解决的问题不是生成速度
1.1 一个 skill 就像一份给 AI 的交接文档
如果你去搜 skills 相关内容,会看到各种实现版本:有的是一组文件,有的是一整个目录,有的里面塞了示例代码、检查清单、甚至是配套测试。不同工具对它的叫法也不一样,有的叫 skills,有的叫 agent skill,有的叫指令包,但核心机制是一致的:把某个任务所需的知识、规范、步骤和边界打包成一个可加载的单元,让 AI 在动手之前先读一遍,再开始干活。
这个机制解决的不是“AI 能不能写”,而是“AI 按什么标准写”。
我习惯把 AI 理解为一个很聪明的实习生。它基础扎实,你给它一个明确任务,它能很快完成;但它刚进项目时,对团队规则一无所知。你不告诉它命名规范、目录结构、错误处理要求、代码评审关注点,它就会按训练数据里最常见、最普通的方式来写。运气好的时候能跑,运气不好的时候就是一篇只有自己能看懂的代码。一个老员工把任务交接给实习生时,通常会准备一份说明文档:目标、步骤、常见坑、质量标准、不能做的事。skills 就是这样一份给 AI 的交接文档。
它不是把提示词换个地方存。提示词是“对话里的口头交代”,skill 是“可复用、可审查、可迭代的项目资料”。它真正改变的,是上下文管理方式。
1.2 和普通提示词相比,区别在“可管理”
过去我们让 AI 遵守规范,通常是在聊天气泡里写一大段要求。问题很明显:第一,很难复用到下一个任务;第二,每次都要复制粘贴,改一处要全部更新;第三,没有人会对一段聊天记录做 review、做测试、做版本管理。
skills 把这件事从“对话”搬到了“文件系统”。一个技能包可以有说明、有规则、有示例、有否定清单,甚至可以配套测试用例。它可以被放进代码仓库,可以被团队成员 review,可以随项目版本演进,也可以在多个任务间复用。关键是它变成了工程资产,而不是一次性输出。
它和检索增强(RAG)也不完全是一回事。RAG 解决的是“AI 不知道某个信息”,skills 更多解决“AI 不知道怎么按你们项目的规矩做”。一个偏知识检索,一个偏行为约束。概念上容易混淆,实践中却可以配合使用。
我的建议是:决定“要不要上 skills”之前,先别急着找仓库、装技能包。先判断你当前的问题到底是上下文缺失、规则缺失,还是模型能力不够。skills 对“规则缺失”这一类问题有直接帮助。
2. 为什么过去 AI 代码越写越像“屎山”
2.1 代码之所以烂,不是因为模型笨,而是因为约束缺失
很多人把 AI 生成代码质量差归因于模型能力弱。但从工程经验看,大多数“屎山”不是写不出来,而是缺少足够约束。
模型在生成代码时,目标函数是“生成一段看起来合理的代码”,而不是“生成一段符合你们项目规范、半年后还能被同事接手维护的代码”。它是单次生成,没有经过 code review,没有看过项目历史,不知道你的项目里哪些函数是稳定接口、哪些目录不允许改动、哪些风格被团队明令禁止。训练数据里那些不好的编码习惯,在这种缺少约束的环境下就会自然冒出来。
换句话说,AI 不是故意写烂代码,是它根本不知道你的代码评审标准长什么样。你不能要求一个不知道标准的实习生,第一次写出来的代码就正好符合你们团队的审美。
2.2 传统 prompt 的三个结构性问题
如果我们在 prompt 里写清楚规则,问题能解决一部分,但很有限。因为传统 prompt 有三个结构性问题。
第一,规则不可复用。你今天给 AI 的规则,明天换个任务还得再写一遍。项目规范更新了,你很难确保所有 prompt 同步更新。规则分散在无数个对话里,最后变成“每个对话都带了一段规矩,但每段规矩都不完整”。
第二,规则不可验证。你告诉 AI“注意错误处理”,它可能真的加了 try-catch,但 catch 住之后只打了一行 log 就继续跑,这种“形式上的遵守”在评审里依然不合格。为什么?因为你的规范里没有写清楚错误处理的具体行为:是返回默认值,还是抛出异常,还是记录上下文并重试。没有可验证的输出契约,AI 只能猜。
第三,规则不可迭代。一次任务做完了,你发现 AI 有的地方写得好,有的地方需要纠正。这个过程通常只存在于你的记忆里,不会沉淀成团队资产。下一次遇到类似任务,同样的问题还会再犯。这就是很多人反复觉得“AI 写代码像开盲盒”的根本原因。
skills 等于把三个问题一次性搬上手术台:规则从对话里抽出来,放到文件里;输出从“看着合理”变成“对照清单检查”;经验从一次性修正变成可版本化迭代。
3. 上手之前,先判断你是不是真的需要 skills
3.1 适合 skill 的任务和不适合的任务
skills 并不是把 AI 变强的万能开关。它更适合一些特定形态的任务。我习惯按两个维度判断:任务是否重复出现、质量是否有明确标准。
| 类型 | 适合做 skill | 不适合做 skill |
|---|---|---|
| 任务重复度 | 每周都会重复,比如生成新组件、写单元测试、修复某类 bug | 一次性探索,比如设计一个全新系统架构 |
| 规则明确度 | 有明确规范,比如命名、目录、错误处理、日志格式 | 规则还在变化,需求边界模糊 |
| 可验证性 | 输出可以通过 lint、单测或清单验收 | 输出依赖主观审美和创造,比如文案创意 |
| 稳定性 | 项目标准已经稳定 | 项目还在快速重构,规范一周一变 |
一个反直觉的事实是:越“简单、重复、规则清楚”的任务,越值得做成 skill;越“复杂、开放、需要创造”的任务,越不适合。复杂任务如果硬做成 skill,往往会把一堆互相冲突的规则塞在一起,效果反而更差。比如“写一个支付服务的设计文档”这种任务,就算做成 skill,也很难覆盖架构决策背后的复杂取舍;但“按团队规范生成一个标准 API 错误响应结构”就非常适合。
3.2 一个最小可用 skill 的六要素
当你确认某类任务适合之后,不要一上来模仿网上那种几百行的“超级技能包”。先做一个最小可用版本。我建议至少包含六部分:
- 名称与触发条件:这个 skill 负责什么,AI 在什么情况下应该加载它。
- 任务目标:输入是什么,最终输出长什么样。
- 输入输出约定:边界是什么,哪些文件能读,哪些不能动。
- 执行步骤:从开始到结束,按什么顺序做。
- 质量检查清单:输出交付前必须满足哪些条件。
- 禁止事项:哪些行为是绝对不允许的。
这六项不需要写得多漂亮,但每一项都得有可操作性。比如“注意错误处理”不是好的清单项,“若读取文件失败,返回错误码并记录上下文,不抛未处理的异常”才是。清单写得越具体,AI 的生成结果就越稳定。
3.3 先跑通、再批量、最后沉淀
我见过很多人第一次接触 skills,兴奋地找了一堆开源技能包装上去,结果效果不如预期。问题往往不在技能包质量,而在没有经过适配。
建议走一个“先跑通、再批量、最后沉淀”的三步路径:
- 先用一条任务验证。输入、输出、日志全部确认正常,再考虑推广。
- 用三到五个变体任务做小规模测试,观察边界和异常。
- 稳定后把技能包提交进仓库,配一个版本号,作为项目资产固化下来。
不要一上来就加载十几个 skill,或者把所有任务一次性交出去。技能包的复杂度,应该跟着你已验证的场景走,而不是跟着热度走。
4. 写技能包,别从整理提示词开始
4.1 第一步:先积累一批真实任务样本
写 skill 最忌讳的一件事,是坐在电脑前凭感觉写“AI 应该遵守哪些规则”。这样写出来的规则往往是从网上抄来的通用规范,而不是你项目里的真实约束。
更好的做法是先做记录。把过去一两周里让 AI 做过、并且质量不满足要求的任务找出来,列一个清单。看这些任务主要集中在哪几类,是组件生成、测试编写、还是 bug 修复。再从这些失败样本里找出共同点:是命名风格不一致,还是错误处理缺失,还是没有遵守目录结构。
这些真实失败样本才是技能包的原材料。没有它们,你写出来的规则会假大空。如果你想让技能包真正贴近项目,就不能只参考网上的通用范例。
4.2 第二步:把规则抽出来,写成独立文件
找到样本后,把规则从对话里抽出来。不是复制粘贴,而是重新整理成结构化文件。一个常见的目录结构可能长这样:
my-skill/ ├── SKILL.md ├── rules.md ├── examples/ │ ├── good.md │ └── bad.md └── checklist.mdSKILL.md 负责说明任务的触发条件和目标;rules.md 放具体规则;examples 里放对的和不对的示例;checklist.md 放验收清单。这是一个示意结构,具体工具和目录名可能不同,但思路是一致的:把“描述”“规则”“示例”“验收”四类信息分开,而不是混成一个长 prompt。
这样拆开的理由很简单:AI 在处理不同类型信息时,需要更明确的结构,而不是读一篇议论文。人 review 时也能一眼看到规则改动,而不是在一大段描述里找差异。技能包本质上也是一种代码,它需要结构清晰、职责单一、可评审。
4.3 第三步:给每个技能包配一张质量验收单
技能包不能只写“怎么做”,还要写“怎么算做完”。质量验收单应该对应项目里真实发生的检查环节。
举例来说,如果你做的是前端组件生成技能,验收单可以包含:是否遵循团队命名规范、是否包含空态处理、是否使用项目已有的设计变量、是否避免引入新依赖、是否不需要人工清理无用代码。这些项目越具体越有用。
我第一次做这类技能包时,只写了任务描述和步骤,没有写验收单,结果生成结果看起来像那么回事,但细节处全是问题。后来把验收单补齐,让 AI 输出前自己检查一遍,质量才明显稳下来。这不是玄学,是把人工 review 时的关注点前置到了生成阶段。
5. 最容易踩坑的三个位置
5.1 一个技能包里塞了太多目标
很多人会忍不住把一个技能包写得无所不能,又要写组件,又要写测试,又要做国际化,又要考虑性能优化。结果规则之间互相制约,AI 不知道以哪个为准,输出会变得顾此失彼。
技能包应该保持单一职责。一个 skill 只解决一类任务,规则最多覆盖到这一类的必守底线。如果任务范围太大,优先拆成几个小技能包,再在任务层面组合使用。比如把“前端组件生成”和“单元测试生成”分开,而不是塞进同一个技能包。
一个简单的判断标准:如果你写 skill 时发现“这里还得补充一下”“那边也要说明一下”,说明边界已经开始模糊了。停下来,把超出职责的部分拆出去。
5.2 只写“要做什么”,没写“不要做什么”
在 AI 协作里,“禁止事项”比“正向指令”更能决定质量。因为正向指令描述理想状态,禁止事项划定不可逾越的边界。
例如,给 AI 的规则里写“请使用统一的错误处理”,它可能在所有地方都加 try-catch,但从未考虑哪些异常应该向上抛。更有效的写法是同时写明“不要吞掉异常;不要用 print 代替日志;不要修改公共 API 签名”。这些看似消极的规则,实际是质量兜底。
我更喜欢把禁止事项看成安全围栏。没有围栏时,AI 并不知道自己走到哪里算越界;有了明确边界,它才能在范围里自信地发挥。
5.3 技能包没有版本,也没有回归样例
技能包会随着项目演进而失真。项目规范改了,技能包如果不同步更新,就是一份过期的交接文档,甚至比没有更危险。
解决方式是把它当代码管理:每次改动都提交变更记录,最好配一两个最小回归样例。比如生成一个组件,跑一遍,输出如果全部符合验收单才算通过。这样,下次有人更新规则时,就能知道改坏了什么。
另一个常见坑是只看“格式对不对”,不看“行为对不对”。技能包的质量不能只看 AI 是否遵守了文件名或缩进格式,更应该关注它是否真的避免了已知的反模式。所以回归样例要覆盖不止一个正常用例,还要覆盖至少一个边界用例。
6. 代码质量还是不稳定?按这个链路排查
6.1 先确认输入和上下文完整
如果 AI 生成结果仍然差,先别急着改 skill。第一件事是检查任务描述是否完整:你有没有告诉它涉及的模块、约束、依赖和验收标准?上下文是否包含了必要的文件内容?很多情况下,AI 写出偏离预期的代码,只是因为它不知道你心里已经预设了项目背景。
任务描述不是越短越好。一个有效的任务描述至少应该包含:你要达成什么目标、项目里哪些文件是相关参考、有哪些必须遵守的限制、最终输出应该在哪里生效。缺少任何一项,AI 只能靠猜,而猜就会带来偏差。
6.2 再确认技能包确实被加载了
不同工具加载 skills 的方式差异很大,有的靠目录约定,有的需要手动指定,有的要在任务里声明。要查看实际运行的会话记录,确认这次任务确实读到了技能包。如果你发现输出里完全没有技能包的痕迹,大概率是加载没有生效,而不是规则写得不够好。
一个简单的验证方式:在任务里让 AI 复述技能包中的核心规则,看它能不能准确说出来。如果它说不出来,说明加载链路有问题;如果它能说出来但没做到,才需要继续往下排查规则本身。
6.3 然后检查规则之间是否冲突
技能包多了以后,规则冲突是最隐蔽的问题。A 技能要求用函数式风格,B 技能要求沿用现有类结构,同一段生成结果被两边同时影响,输出就会来回跳。这时要检查同一任务下加载了哪些技能包,看它们之间是否存在互斥规则,以及是否有优先级定义。
这个问题在大型项目里尤其明显。不同历史阶段的规范会同时存在,新技能包和旧技能包如果都写得不够克制,就会让 AI 无所适从。规则不在多,而在于一致。
6.4 最后直面模型和能力边界
如果前几层都没问题,输出质量还是不稳定,就要承认可能不是 skills 的问题,而是任务本身超出了当前模型的稳定能力范围。
技能包能改变的是“按什么标准写”,不能改变的是“推理能力到底够不够”。对于高难度的架构设计、复杂算法实现或需要大量领域知识的任务,把任务拆小、分步验证,比继续堆规则更有效。技能包是工程手段,不是魔法。
| 现象 | 优先排查方向 | 常见处理 |
|---|---|---|
| 输出明显跑题 | 任务描述与上下文 | 补充背景,明确输入输出 |
| 规则好像没生效 | 技能包加载链路 | 检查目录、配置、运行日志 |
| 满足一部分规则漏另一部分 | 技能包范围 | 拆小,保持单一职责 |
| 多个技能包互相干扰 | 规则冲突与优先级 | 排查冲突,明确优先级 |
| 结果不稳定且改规则无效 | 模型能力边界 | 拆任务、换工具或人工介入 |
7. 让它成为一个成长系统,而不是一次性配置
7.1 每次代码评审,都是一次技能包更新机会
技能包不是写完就结束的静态文件。真正让它起作用的,是持续的迭代习惯。
我建议把每次人工 review 当成一次训练素材采集。当你在 AI 生成的代码里发现一个坏味道,不要只是手动改掉,而是问一句:这个坏味道能不能写进技能包,让下次不再出现?如果能,就把它补充到 rules 或禁止事项里;如果不能,说明这个场景还不稳定,不适合让 AI 全权处理。
这个循环看起来笨拙,却是技能包真正变得有价值的地方。它让 AI 的质量改进不再依赖一次性的“这轮 prompt 好不好”,而是变成了一个可以持续累积的工程资产。
7.2 一个小型回归集,守住技能包底线
随着技能包迭代,你一定会遇到“改好一个问题又引入另一个问题”的情况。这时候,一组最小回归样例比任何口头约定都管用。
不用很多,三到五个就够。一个正常用例,一个边界用例,一个异常用例。每次更新技能包,先跑一遍回归,确认旧场景没有劣化,再合并变更。如果回归没过,说明新规则和旧规则冲突了,重新整理优先级。
这套方法相当于给技能包做 CI。没有它,技能包就会随改动而腐烂;有了它,你才能放心地把越来越复杂的规则加进去。
与其说 skills 让 AI 不再写“屎山”代码,不如说它给了我们一个把工程纪律带到 AI 协作里的机会。单次生成能力的上限没有变,但“能不能稳定生成符合项目规范的代码”,变得可以被管理了。
如果你现在还在观望,我的建议很直接:不要急着去收藏一堆热门技能包。先挑一个你每周至少会重复三次的任务,按前面说的最小六要素写一个最简技能包,跑通一条真实任务,再用真实失败的案例去迭代它。等你发现某个任务不再需要反复人工改代码时,才算真正找到了 skills 的感觉。