你是不是也有这种感觉:用AI写代码有一段时间了,但每次新开一个会话,都要把项目背景、技术栈、代码规范、输出要求从头说一遍。说少了它理解偏,说多了上下文被占满,真正干活的位置反而不够。我一度以为这是模型的限制,直到我把工作流拆成一个个可复用的“技能包”,也就是现在社区里讨论度很高的Agent Skills,才发现问题根本不在模型,而在我们喂给它的方式。
Skills不是什么玄乎的新框架,它就是把“某个任务到底该怎么做”沉淀成一套结构化文件夹,里面有一份说明文件、若干参考文档,可能还有模板和校验脚本。Claude Code、Codex、Cursor、OpenCode这些主流AI编程工具目前都直接或间接支持这个思路。这篇文章是我过去几个月实测下来的经验总结,包括一个Skill到底应该怎么组织、SKILL.md怎么写才真正有用、怎么让Skill去调用MCP工具,以及前端开发、测试用例、学术研究这几类高频场景中我实际落地的方案。所有内容都来自真实项目里的反复调整,希望能帮你少走一些弯路。
1. 为什么AI编程助手需要Skill:受够了每次重新“教”它
1.1 零散Prompt的瓶颈:一次会话教会,下一会话全忘
早期的AI编程用法,本质上是在“现场教学”。你打开一个新会话,告诉模型你要做什么、项目是什么结构、有哪些约束,然后它开始大段生成代码。这套流程最大的问题不是模型笨,而是每次会话都从零开始。
我自己经历过一个很典型的场景。团队维护一个内部组件库,要求所有新代码必须遵循特定的导出风格、注释规范和测试组织方式。我花了很多时间在新会话里复制粘贴一段很长的“项目规范说明”,但复制过去之后模型生成的效果依然不稳定:第一次它记住了导出的约束,第二次就漏了,第三次把组件文档格式也写错了。后来我统计过,同样的规范说明反复粘贴了不下十次,而每次模型的理解程度都不同。
这里的问题本质是:Prompt是一次性的,它没有任何“记忆”机制,也不会主动去查阅你准备好的参考资料,除非你明确告诉它。而真正复杂的工作流,靠几段话根本交代不清楚。
1.2 Skills和Prompt到底差在哪:它自带执行资源
Skills和普通人理解的“Prompt模板”有个根本区别:Prompt模板只是“一段更有组织的文字”,而Skill是一个“自带资源的目录”。
一个标准Skill通常长这样:
~/.claude/skills/component-generator/ ├── SKILL.md # 技能说明,模型会优先读取 ├── reference/ │ ├── style-guide.md # 组件库风格规范 │ └── api-patterns.md # 常用API写法示例 ├── templates/ │ └── component.tsx # 标准组件模板 └── scripts/ └── validate.py # 生成结果校验脚本模型读取SKILL.md之后,会知道有一个完整的流程可以执行:先读reference里的风格规范,再按templates里的模板生成代码,最后用scripts里的脚本校验结果。每个资源文件都不需要一次性塞进上下文,而是“按需加载”,用到哪一步再打开哪一步。
这就像你给新人发了一本工位手册,而不是站在旁边一遍一遍口述。Prompt是口述,Skill是工位手册。口述的信息量受限于你当时的表达和对方的记性,而手册是结构化的,需要哪个步骤就去翻对应章节。
1.3 当前生态盘点:Claude Code、Codex、Cursor、OpenCode里的Skills实现
过去一年,Skills这个概念从Anthropic的Agent Skills开始快速蔓延到整个AI编程工具链,各家的实现逻辑有一致性,但细节和配置方式差异不小。我直接列一下我实测过的几个工具的情况。
| 工具 | Skills支持方式 | 存放位置 | 我实测的感受 |
|---|---|---|---|
| Claude Code | 官方原生支持Agent Skills | ~/.claude/skills/(个人级)或项目级.claude/skills/ | 最完整的实现,SKILL.md的约定几乎成了社区事实标准 |
| Codex | 通过codex.md/AGENTS.md方式配置项目指令,社区大量Skill以文档库形式被引用 | 项目根目录或全局配置 | 更偏向“项目说明书”,但对Skill的分析类任务支持很好 |
| Cursor | 以Rules和自定义命令形式组织,社区也出现了大量前端Skills合集 | 项目级.cursor/rules/ | 前端场景很顺手,尤其是配合Agent模式使用 |
| OpenCode | 支持自定义Skill目录,兼容类SKILL.md格式 | 配置文件指定 | 开源阵营里做得比较轻量,适合自己改造 |
出现这种“同一条赛道各自跑”的状态,反而是好事。说明“把任务流程外置成可复用文件”这个方向,各家的判断是一致的。你现在花时间学SKILL.md的组织方式,换工具时并不过时,核心思路完全可以平移。
2. 从零开发一个Skill:SKILL.md怎么写才有用
2.1 SKILL.md的标准结构:元信息、使用场景、执行步骤
很多人第一次接触Skills,以为就是写一个Markdown文件然后放进目录里。实际上SKILL.md的门道比看上去要多,一个好的SKILL.md应该同时承担三重角色:告诉模型“什么时候该用我”、告诉模型“用我的时候按什么顺序做什么”、告诉模型“做完了怎么判断质量”。
先说最基础的格式。以我目前在用的一个生成Python单元测试的Skill为例,它的SKILL.md开头长这样:
--- name: "python-unit-test-generator" description: "当用户需要为Python函数或模块生成单元测试时使用。 适用于pytest框架,自动分析函数签名、边界条件和异常路径。 不适用于已有完整测试但需要重构的场景。" --- # Python单元测试生成技能 ## 执行流程 1. 读取目标Python文件,提取所有需要测试的函数签名与默认参数。 2. 对每个函数列出输入边界、类型边界和异常分支。 3. 基于边界分析结果生成测试用例表,先不急着写代码。 4. 将测试用例表映射为pytest代码,使用项目已有的测试风格。 5. 运行测试并修正失败用例。 ## 完成标准 - 每个函数至少覆盖正常路径、边界路径、异常路径三条分支。 - 测试代码通过pytest执行,无语法错误。 - 不修改被测函数的原始行为。这里最关键的是YAML头部的description字段。模型判断“当前任务要不要启用这个Skill”,基本就是靠读这一句话。所以description必须写清楚三件事:什么时候用、能解决什么、什么时候不要用。最后一条很多人会忽略,但它能避免模型在给定目录下所有可用的Skills里选中不相关那一个。
2.2 把“我知道的东西”转成模型能跟着做的步骤
写SKILL.md最需要练习的,是把脑内已经自动化的工作流,重新翻译成模型能逐条执行的步骤。举一个我自己调整过多轮的细节。
最早我写“生成测试用例”这个Skill时,步骤写的是“为每个函数生成充分的测试用例”。结果模型确实生成了,但选择的全是最简单的正例,边界检测基本没有。后来我改成“对每个函数先写出一张边界值表,包含极大值、极小值、空值、错误类型、默认参数覆盖,表通过后再生成代码”。同一套模型,生成质量立刻上了一个台阶。
差别在哪?差别在于“充分”是一个模糊标准,但“列出极大值、极小值、空值”是模型能执行的指令。把隐式的专业经验变成显式执行步骤,是Skill开发最核心的功课。凡是你在心里默认“这步太基础不用写”的东西,最好都考虑要不要显式写出来。模型不会像人类同事那样通过观察你眼神来补全信息。
另外,步骤与步骤之间要有“产物交接”。第2步的产出是“边界值表”,第3步的输入是“这张表”。写步骤时明确说出每一步的输入和输出,模型才不容易跳步或省事。
2.3 配套资源目录:参考文档、模板、校验脚本
SKILL.md负责“流程”,但一个真正可用的Skill大概率还需要配套资源。我的习惯是分成三类。
第一类是reference,放那些“不该塞进SKILL.md但执行时可能用到”的详细资料。比如团队代码风格的完整版规范、历史案例、框架官方文档的重点摘录。SKILL.md里只需要写“阅读reference/style-guide.md来确认组件命名规则”。
第二类是templates,放标准化的起始文件。模型生成代码时,给它一个模板会比让它从头写稳定得多。模板里可以用通配符标注需要替换的位置,配合模型自己根据场景填充。
第三类是scripts,放校验脚本。这是很多人忽略的一层。Skill执行完,模型说自己“做完了”不一定真做完了,给它一个能跑的命令来自检,准确率会有质的提升。比如生成HTML后运行一个检查标签闭合的脚本,生成测试后自动跑一遍pytest。如果你能让模型在Skill的最后一步固定执行scripts里的校验,它的输出质量会朝你期望的方向持续收敛。
3. Skills如何调用MCP工具:打通技能包与外部工具
3.1 Skills和MCP的分工:该谁管任务,该谁管工具
Skills和MCP(Model Context Protocol)这两个概念经常被放在一起讨论,但它们解决的问题完全不同。如果做个类比,Skill是菜谱,MCP是厨房里的厨具和食材供应商。菜谱决定你做番茄炒蛋时需要先切番茄还是先打蛋,供应商决定你拿到的番茄新不新鲜、锅好不好用。
实际落地中,我给它们的职责划分是:Skill负责“任务怎么做”,MCP负责“能力从哪里来”。Skill可以在步骤描述里写明“这里需要调用某个MCP工具来完成特定子任务”,但具体怎么连接、怎么返回结果,交给MCP去实现。
以“分析某段前端代码的运行时性能”为例,这个Skill内部的步骤可以写“调用浏览器调试工具的MCP接口,收集页面性能指标”,真正去启动浏览器、监听网络请求、返回指标数据的,是MCP服务器侧完成的动作。
3.2 声明MCP调用:在SKILL.md里描述工具边界与调用意图
不少人在SKILL.md里写“如果需要,请调用MCP工具”,这种写法太模糊,模型拿不准什么时候该调、调了干什么。我在实测中的经验是,要把工具调用写得像接口文档一样明确:哪个步骤、调用什么工具、传入什么参数、期望拿到什么结果。
下面是我在一个“API接口回归检查”Skill里的写法片段:
## 执行流程 3. 调用MCP工具 `mcp__http-client__post`, 对步骤2列出的每个API端点发送GET请求, 请求参数使用reference/test-cases.json中的示例数据。 4. 接收工具返回的状态码、响应体和耗时。 将状态码不在200-399范围内,或耗时超过500ms的端点记录到issues.md。写清楚之后,模型不需要自己脑补“该不该调”,而是明确知道某一步就要调用指定工具。另外,我还习惯在Skill的目录下建一个mcp-tools.json文件,里面标注这个Skill会用到哪几个MCP服务器、哪个工具,以及工具的简单说明。虽然不是所有工具都会读取这个文件,但这样相当于给Skill做了一份“依赖清单”,排查问题会快很多。
3.3 一个设计稿还原Skill的完整MCP调用链路
这里分享一个我实际在建的“图片还原设计稿给前端开发”的Skill,它能充分说明Skills和MCP是怎么配合的。这个Skill的主要任务是把一张设计稿截图转成可直接运行的前端页面代码,涉及视觉分析、布局提取、组件生成三个环节。
它的MCP调用链路是这样的:先调用图像处理MCP里截取/裁剪图片的工具,把设计稿缩放到适合模型理解的尺寸;再调用浏览器渲染MCP把生成的中间HTML渲染出来,并截图回传给模型做像素级对比;如果发现尺寸、间距不对,再调用图像标注工具在截图上标记差异区域,让模型针对差异修正样式变量。每调一次工具,模型的上下文里就多了一轮真实反馈,而不是靠“猜”来判断页面写没写对。
这个Skill我只跑了几个内部项目,最大的感受是:纯粹靠模型“看一眼设计稿然后写代码”,和“生成后主动截图回放给自己看”,结果质量完全不是一个量级。这就是Skills配合MCP工具带来的增量价值。
4. 三类高频技能包拆解:前端、测试用例、学术研究
4.1 前端领域:图片还原设计稿、组件代码生成
前端是目前社区里Skill数量最多、也最内卷的领域。搜一下“前端开发skills”能看到大量现成方案,比如GitHub上很火的“前端superpower skills”,还有各种针对Cursor的“前端技能包合集”,核心思路都差不多,只是颗粒度不一样。
我自己在用的几个前端Skill里,价值最高的是“设计稿还原”。这个Skill的SKILL.md执行流程很明确:先要求模型用视觉分析能力描述设计稿的整体布局结构,得出一个类似“顶部导航+左侧侧边栏+右内容区,主色为#6366F1,间距基准为8px”的结构化描述;然后根据这个描述生成HTML骨架和CSS变量表;再进入组件生成阶段,按功能区域拆开逐个生成组件代码;最后是自检阶段,核对间距、字号、颜色是否与设计稿标注一致。
移动端的Skill也类似,但要多写一个约束:组件样式必须用响应式单位,并且需要额外生成不同断点下的预览截图。社区里“移动端skills推荐”的话题很热闹,但我的建议是先不用急着囤一堆Skill,选一个适配你技术栈的,跑通一个完整流程再扩展。
4.2 测试领域:从需求描述自动生成边界用例
测试用例是另一个很适合Skill化的场景,因为它本质上非常结构化。我开发“测试用例skills”时的切入点是:很多测试同学发现让模型直接列用例,得到的结果往往温和且重复,真正容易让人翻车的边界用例很少覆盖全。
于是我设计了一个测试用例生成Skill,核心步骤是强制模型先产出“需求歧义清单”,再产出“边界值分析表”,两者都通过了才允许进入用例列表阶段。在边界值分析表里,我会要求模型按字段列出:有效等价类、无效等价类、边界值、越界值、类型错误值、空值。模型基于这张表再生成用例,覆盖质量会好很多。
比如一个“用户注册接口”的需求:正常情况是用户名、密码、邮箱都合法;但Skill会引导模型继续想,用户名为空、密码只有1位、邮箱格式缺少@、内容包含SQL关键字、用户名长度刚好等于边界值等场景。这些用例不一定都会出现在需求文档里,但它们在质量保障里恰恰最容易暴露问题。
4.3 研究领域:文献阅读、结构化笔记与数学建模
学术研究类的Skills,包括热搜里出现的“academic research skills”“数学建模skills”,本质上是让模型按照研究流程来辅助人。我写过一个小Skill,专门用来处理论文PDF:输入一篇PDF,输出一张结构化阅读卡片,卡片里包含研究问题、方法、数据集、基线、主要结论、局限性和可复现性备注。
这个Skill有一个特殊设计:它会把整个PDF拆成章节分片读取,而不是一次性全量塞进上下文。读取“方法”章节时,会让模型同时记录“作者声称做了什么”和“实际上代码或者公式是否支撑了这个说法”两个维度。这样生成的阅读卡片,在写文献综述时直接用,省了非常多的重复阅读时间。
数学建模类Skills我接触过一些公开方案,常见流程是先读题并列出已知条件与约束,然后做问题重述、假设分级、建模思路对比、选模型、求解、验证、报告输出。这套流程天生适合做成Skill,因为建模比赛的每一步都有清晰的输入和输出。
5. 开发Skills踩过的坑:这些细节决定技能包好不好用
5.1 描述写得太宽,模型“以为自己会了”
我最早开发的“代码审查Skill”就栽在这个问题上。SKILL.md里的description写的是“当用户需要代码审查时使用”,结果任何涉及代码的对话都会触发它,而真正执行时又因为目标不明确,输出的审查意见停留在“代码风格不够统一”这种泛泛层面。
后来我把description改成了“当用户要求审查Python函数的安全性和错误处理时使用,重点检查外部输入校验、异常捕获精度、资源释放路径”之后,情况和之前完全不一样——不再误触发,触发后输出的审查点也贴近真实需求。description不是写给人看的,是写给模型做“路由选择”用的,宽度要收敛到“不是这个任务就别碰我”的程度。
5.2 步骤细节和上下文预算的平衡
一开始做Skill时技术文档出身的我很贪心,恨不得把几十页规范全部写进SKILL.md。结果模型读完SKILL.md,上下文已经被吃掉一大半,后面真正生成代码时捉襟见肘。
后来我改用“分层读取”的方式:SKILL.md只保留执行流程和关键判断标准,所有需要展开的细节放到reference目录里,在具体步骤中通过“读取reference/xx.md的xx节”来按需加载。这相当于把一个巨大的Prompt拆成了索引和执行两个层面,上下文利用率高很多。如果你发现一个Skill执行到一半就开始忘记前面的内容,优先检查是不是SKILL.md本身写得太长了。
5.3 MCP工具调用的权限与超时处理
Skill里调用MCP工具,最常遇到的三个问题:工具不可达、调用超时、权限配置不正确。
工具不可达通常发生在刚启动工具或新配置MCP服务器之后,Skill已经按记忆去调了,但MCP侧还没就绪。我在Skill步骤里都会要求模型“先执行一个轻量探测调用,确认工具可响应再进入正式调用”。调用超时则跟网络和任务复杂度有关,比如浏览器渲染MCP在处理大页面时可能跑十几秒才返回,但是MCP客户端默认超时可能是10秒。解决方案是工具侧调大超时阈值,同时Skill步骤里写明“如果调用失败,等待三秒后重试一次,再失败则记录错误并继续后续可用步骤”。
权限这块要特别留意,普通任务尽量不调用具有文件系统写入、命令行执行等高权限的MCP工具。给Skill配一个“允许工具清单”,执行过程中只从这个清单里选工具,能有效避免模型自己脑补出不该用的工具。
5.4 团队共享与版本更新:一个Skill的完整生命周期
Skill的最后一个坑,是把它当成一次性的本地文件用。我自己经历过一个局面:公司的组件库规范更新了,而旧Skill还在按旧规范生成代码,直到有人踩坑才发现。
现在的做法是,所有Skill都进Git仓库管理,变更记录直接写在SKILL.md的YAML区,比如加一个version字段。每次修改规范,都要同步去找依赖这个规范的Skill,更新它对应的reference文档。团队共享时,可以约定一个统一的Skills仓库,各成员本地通过软链或同步脚本拉取。社区里也有一些把Skill做成包管理器分发的实验性项目,但对我来说,放到Git仓库里跑CI校验已经足够顺滑。
最后分享一点我的个人体会
折腾Skills这段时间,我最大的认知转变是:它的本质不是提升模型的“智商”,而是把项目的隐性经验外置成模型可以反复调用的显式流程。过去我们依赖模型“现场听懂”,现在换成我们主动定义“应该怎么做”,产出稳定性提升了一个档次。如果你也想上手,我强烈建议别一开始就追求全功能大而全的Skill,找一个你每周都会重复至少三次的痛点任务,花两小时写一个只有五十行说明的Skill,跑通一次完整流程,再在真实项目中打磨细节。高频场景沉淀成Skill,用时间换取稳定,这件事一旦开始,就停不下来了。