不用急着往下翻,先问你一句:你写的那个Skills文件,是真的让AI“会用”,还是只是把你平时用的一段提示词改了个文件名?我说的就是那些放在.cursor/skills、.claude/skills目录里,或者通过GitHub项目分发给别人的、以SKILL.md结尾的“AI技能包”。
说实话,我见过太多打着“Skills开发”旗号的仓库了。打开里面就是一个两三行的描述,加上一段换皮提示词,别说让AI按流程办事了,连让模型理解“什么时候该触发”都费劲。标题说“连及格线都没到”,不是嘲讽,是我真的替这些项目可惜——方向是对的,但写法还停留在“给AI发微信”的阶段。这篇博文我就把话说透:什么才是合格的Skills,怎么从零写出一个能打满分的技能包,以及那些不同工具(Cursor、Claude Code、Codex)之间的坑该怎么填。
1. 先泼盆冷水:什么是不及格的Skills
1.1 你以为写完SKILL.md就算结束了?
我先还原一个特别常见的场景。你可能在某个“awesome claude skills”列表里看到了别人分享的技能包,下载下来发现目录结构很简单,就一个markdown文件。然后你照葫芦画瓢,自己也写了一个,往里面塞了这么几行:
--- name: latex_formatter description: 格式化LaTeX文档 --- 请帮我格式化LaTeX文档,注意排版规范。输出完整结果。写完之后往目录里一放,告诉朋友“我做了一个Skills”。这也太草率了。
真正的问题在于:Skills不是一个指令文件,而是一个给AI的“工作手册”。AI执行的时候,不是把你那段话背下来,而是要根据你的描述去理解“何时用、怎么用、用到什么程度”。我见过最典型的不及格表现,就是description写得像产品说明书——宽泛、模糊、没有触发场景。你写“处理文档”,AI根本不知道该在什么场景下主动调用,最后只能变成用户手动硬塞给它的“高级粘贴板”。
1.2 五个一眼就能看穿的硬伤
我拆过不少别人分享的技能包,也返工过自己早期写的版本。如果你不知道及格线在哪,先对照下面这五条自查:
| 硬伤 | 典型表现 | 后果 |
|---|---|---|
| 描述是凑字数的 | description只有一句“用于帮助用户处理任务” | AI无法判断触发时机,技能基本废掉 |
| 结构就是超长提示词 | 一整篇“请按照以下步骤执行”,无分段无分层 | 模型读取效率低,关键约束容易被忽略 |
| 没有示例 | 从头到尾没有一个输入/输出案例 | 模型只能靠猜,输出风格飘忽不定 |
| 没有边界约束 | 没写“什么情况不要用”“哪些操作禁止” | AI擅自扩大适用范围,越权操作 |
| 不考虑上下文开销 | 文件内容过长,每次对话都全量塞进上下文 | 回答质量下滑,对话成本上升 |
说实话,前两条是新手最容易踩的。尤其是“超长提示词”那种写法,等于你让AI每次用这个技能的时候,都重新读一遍小作文。模型不是不聪明,是真的会“读不完”。你想想一个人面对三千字的操作手册还能条理清晰吗?换到AI身上,表现就是后半段约束经常丢失,输出结果和你的预期差十万八千里。
2. 一个合格的Skills,到底长什么样
2.1 先搞明白Skills的本质:它不是提示词,是“入职手册”
我之前在跟朋友聊Skills脚手架的时候,打过一个比方:你写一个Skills,其实是在给一个能力很强但完全不了解你团队的新人写入职手册。这个新人就是AI模型,他懂得多,但他不知道你的行话、不知道你的流程、不知道你的输出偏好。你的任务不是给他布置任务,而是给他一套“遇到什么情况走什么流程”的决策树。
所以靠谱的SKILL.md,核心不是“请做什么”,而是三个问题的答案:
- 什么时候用:什么样的请求、任务、上下文里,模型应该考虑激活这个技能?
- 怎么用:拿到这个任务之后,分几步走,每一步的输入是什么、产出是什么?
- 用完之后输出什么:最终交付物的格式、长度、检查标准是什么?
把这三个问题回答清楚,一个Skills的骨架就立住了。反过来,你看那些下载量很高的技能包,普遍都有这结构:清晰的角色定义、明确的触发条件、分步骤的执行流程、几个“示例对话”、以及最后的“自检清单”。
2.2 核心结构拆解:标准的SKILL.md骨架
我整理了一个通用的骨架,你可以直接拿去改。这个结构我在Claude Code、Cursor和Codex里都实测过,兼容性很好:
--- name: 技能名称(英文短横线命名,如code_reviewer) description: 用于什么场景、解决什么问题,触发条件写清楚。 --- # 技能名称 ## 角色定位 在这个任务中,你的身份是什么样的专家,遵守什么原则。 ## 工作流程 ### 第一步:输入分析 - 需要收集哪些信息 - 信息不足时如何向用户追问 ### 第二步:方案设计 - 列出候选方案 - 基于什么标准做选择 ### 第三步:执行与输出 - 输出格式、结构、规范 - 必须包含哪些关键部分 ## 约束与边界 - 什么情况禁止使用本技能 - 遇到不确定信息时如何反馈 ## 示例 ### 示例1:典型输入 具体的用户输入示例 ### 示例1:典型输出 期望的模型输出示例 ## 自检清单 - [ ] 输出是否满足格式要求 - [ ] 是否遗漏任何必要步骤注意,我把“示例”单独拎出来了。这东西特别重要,因为现在的大语言模型本质上是“下一个词预测”,你给它几个高质量的输入输出对,它就能模仿出你的口味。你写“输出要专业”,说一百遍都不如一个真实的优秀案例放在它面前。
2.3 命名、目录与分类:这些细节决定你Skills的“存活率”
很多刚开始接触Skills开发的同学,会忽略一个致命细节:AI工具箱里放着几十个技能,模型怎么知道该用哪一个?答案就藏在文件名和description里。如果你的技能名叫skill1.md,description又写得特别泛,那模型大概率会忽略它,或者错误触发另一个技能。所以我在命名时一般遵循三个原则:
- 文件名用动词开头:
generate_report.md、refactor_code.md,让模型一眼看到“这个技能是干嘛的”。 - description里带上触发场景词:比如“当用户要求撰写周报、月报或项目总结文档时”,而不是“帮助处理文本”。
- 目录按职责划分:我习惯建
writing/、coding/、analysis/、conversion/这样的二级目录,每个目录放同类的技能。目录清晰不仅能帮模型定位,也方便自己维护。
还有一个容易踩坑的点是优先级。当用户的需求同时命中多个技能时,模型会冲突。我的解决办法是在每个技能的description里加一句“如果用户同时需要XX功能,优先使用另一个技能”,或者在约束边界里写清楚“本技能仅处理XX,不负责YY”。这些看起来不起眼的句子,能省掉你后面大量的返工时间。
3. 手把手:从零写一个能打的Code Review Skills
3.1 场景定义与目标拆解
说了这么多理论,接下来我带你实战一次。就拿我自己用得最多的场景举例:代码审查。你肯定遇到过这种情况——让AI帮你审查代码,它上来就给你输出一堆“优化建议”,没有重点、没有分级,甚至有些建议根本不适用于当前项目。问题出在哪?出在你没有给它一套审查的“规则”。
我的目标是写一个Skills,让AI在拿到一段代码或一个diff之后,能按照固定的维度去审查:正确性、安全性、性能、可维护性,并且最终输出一份有严重程度分级、有行号定位、有修改建议的审查报告。这不算复杂,但足够演示一个合格Skills的所有要素。
先定义输入输出接口:
- 输入:一段代码片段(含上下文)、一个Git diff、或者一个PR描述。
- 输出:分级审查报告,包括问题列表、风险等级、修复建议。
3.2 SKILL.md源码逐段拆解
这是完整版的SKILL.md,是我目前在用的简化版,去掉了项目特定内容,你可以直接复用:
--- name: code_reviewer description: 当用户要求审查代码质量、检查Pull Request、分析代码潜在缺陷时使用。适用于代码片段、Git diff 或整个文件的审查。主要关注正确性、安全性、性能与可维护性。 --- # Code Reviewer ## 角色定位 你是一名资深代码审查专家,拥有多年的后端、前端与架构设计经验。你的任务不是夸代码写得好,而是诚实地指出问题,给出可落地的改进方案。 ## 工作流程 ### 第一步:理解变更意图 先分析用户提供的代码或diff,判断这段代码是新增功能、Bug修复还是重构。如果没有上下文,主动向用户提问,最多追问两次。不要凭空假设。 ### 第二步:按维度审查 逐个检查以下四个维度: 1. **正确性**:是否存在逻辑错误、边界条件遗漏、并发问题。 2. **安全性**:是否存在注入风险、敏感信息泄露、不安全的反序列化。 3. **性能**:是否有不必要的重复计算、N+1查询、内存泄漏风险。 4. **可维护性**:命名是否清晰、函数是否过长、是否符合项目现有架构风格。 ### 第三步:输出审查报告 报告结构如下: - **总体结论**:一句话概括代码状态(通过/需修改/存在严重问题)。 - **问题列表**:按严重程度降序排列。每条包含:位置(文件名+行号)、问题描述、严重程度(严重/中等/轻微)、修复建议。 - **亮点**:如果确实有写得好、值得保留的设计,简短列出。 ## 约束与边界 - 只审查用户提供的代码,不臆测未给出的上下文。 - 如果代码超过500行,优先聚焦高风险区域,而不是逐行检查。 - 不要修改代码,只输出审查结果。 - 禁止输出模糊的评价,如“代码整体不错”,必须落到具体问题。 ## 示例 ### 输入示例 审查下面的Python函数: def process_user_input(data): result = eval(data) return result ### 输出示例 总体结论:存在严重问题,需修改后再合入。 问题列表: 1. [严重] process_user_input 使用 eval() 处理外部输入,存在代码注入风险。建议改用 ast.literal_eval() 或 JSON 解析。 2. [中等] 函数缺少异常处理,输入格式不合法时会导致程序崩溃,建议增加 try-except。 亮点: - 函数签名简洁,职责单一,后续修改成本低。 ## 自检清单 - [ ] 是否覆盖正确性、安全性、性能、可维护性四个维度 - [ ] 问题描述是否包含具体位置和行号 - [ ] 每一个问题是否给出可执行的修复建议 - [ ] 输出是否有明确的分级这里面我觉得最值得学的不是骨架本身,而是第二步的维度划分和第三步的输出约束。维度划分解决的是“AI只给泛泛建议”的问题;输出约束解决的是“AI滔滔不绝却没结论”的问题。很多不及格的Skills,问题不在没结构,而在输出没有明确的格式标准,导致每次结果都不一样。
3.3 测试与调优:没有跑过三遍以上,别急着发布
代码写完了要跑测试,Skills写完了同样要跑。我的习惯是准备一个专门的测试目录,里面放几种典型输入:一个正常的函数、一个明显有安全漏洞的函数、一个空文件,以及一个残缺的diff。然后挨个触发这个技能,看输出是否稳定。
我第一次测试code_reviewer时就发现一个问题:当代码很短时,AI会过度审查,把一个只有三行的函数拆出五条建议,明显是在硬凑工作量。所以后来我在约束里加了“如果代码少于20行,仅检查高风险的严重问题,不输出轻微建议”。这就是迭代的重要性——你不可能第一次就写出完美的Skills,但你可以通过反复测试把边界条件补齐。
还有一个调优技巧:把你的测试输入输出对记下来。我建了一个test_cases.md,每次测试完把输入和输出都贴进去,下次改技能文件时,可以对照旧输出看是否变坏了。这个习惯帮我避掉了大量“改了一个地方,其他例子全崩”的坑。
4. 跨工具迁移:Cursor、Claude Code、Codex的Skills兼容实战
4.1 三套体系的差异:别指望一份Skills通吃所有工具
做Skills开发时间长了,你一定会遇到这个问题:在Claude Code里跑得好好的技能,放到Cursor里就失效了,或者Codex压根不认这个目录结构。说实话,这三大工具的Skills体系目前还不是完全通用的,底层各有各的约定。
| 工具 | 默认Skills目录 | 特色 | 主要限制 |
|---|---|---|---|
| Cursor | .cursor/skills/ | 与规则文件Rules配合好,支持Agent模式自动调用 | 依赖额外配置,老版本兼容性一般 |
| Claude Code | .claude/skills/ | 生态最丰富,社区仓库多 | description触发有随机性,依赖模型判断 |
| Codex | ~/.codex/skills/或项目级目录 | CLI工具友好,适合自动化流水线 | 配置项偏底层,对新手不友好 |
我在迁移时踩过一个大坑:Claude Code的Skills可以通过文件模板引用其他文件,但Cursor对这个支持很弱。如果你的技能依赖多个辅助文件,在Cursor里表现就是“找不到文件”,然后整个流程崩掉。所以我现在写技能时,会刻意遵循一个原则:核心逻辑全部写在一个SKILL.md里,辅助文件只放数据,不放逻辑。这样即使在兼容性最差的工具里,也能保证主流程跑通。
4.2 一份Skills多处跑的通用做法
那有没有办法让一份Skills最大程度地在几个工具之间复用?我目前的做法是这样:
第一,目录结构遵循通用标准。不要依赖某个工具独有的字段,只用name、description这种全模型都能理解的元信息。第二,在description里写清已知的替代方案。比如我可以加一句“如果无法访问外部工具,使用标准库实现”,这样即使环境限制不同,AI也会自动降级。第三,环境变量和符号链接技巧。我维护了一个Git仓库专门放Skills,然后在各工具的配置目录里用软链接指向仓库里的对应文件夹。这样改一次代码,所有工具都能同步更新。
具体做法是:
# 以Claude Code为例,把仓库里的skills链接到项目目录 ln -s ~/my-skills-repo/code_reviewer .claude/skills/code_reviewer # Cursor同理 ln -s ~/my-skills-repo/code_reviewer .cursor/skills/code_reviewer这招对于同时用Cursor和Claude Code写代码的同学来说极其好用。你再也不用在两个目录里分别拷贝一份文件,改了一处忘了另一处了。
4.3 共享Skills目录的同步方案:Git仓库是唯一解
还有一个进阶话题:多个人共同维护一套Skills库。我在跟团队协作时就发现,大家各写各的,很快就会出现命名冲突、版本不一致、改完找不到人的情况。后来我定了一套规矩:所有Skills统一放在一个Git仓库里,按模块分目录,每个技能的负责人必须在文件头部标注。提交前必须跑一次测试用例。
这套流程跑顺之后,“Codebuddy和Claude Code公用skills目录”这类需求就变得很简单了——只要两边都软链接到同一个Clone出来的仓库目录就行。唯一要注意的是别两个人同时改同一个技能文件不合并,我建议每个技能单独一个分支,测试通过再合并到主分支。别嫌麻烦,这比你手动同步文件省心一百倍。
5. 常见问题与排查技巧实录
5.1 高频翻车现场:这些坑我基本都踩过
写Skills写多了,什么怪问题都能遇到。我整理了一个问题速查表,都是从真实项目里抽出来的,有相同症状的直接对照着查:
| 现象 | 根本原因 | 解决方案 |
|---|---|---|
| 技能从来没有被自动触发 | description太宽泛,或没有触发场景词 | 在description里明确“当用户要求XX时” |
| 触发了但执行到一半停下来 | 工作流步骤不明确,模型不知道该先做哪步 | 拆成“第一步/第二步/第三步”,每步只干一件事 |
| 输出格式每回都不一样 | 缺少输出模板和自检清单 | 在文件里用代码块给出固定输出结构 |
| 模型上下文被技能文件塞满 | SKILL.md内容过长,一次性全量加载 | 精简文件,复杂逻辑拆到引用文件里 |
| 多个技能互相冲突 | 没有写优先级或边界说明 | 在description里写“本技能优先于XX” |
| 换工具后技能直接失效 | 依赖了某个工具独有的配置项 | 只用通用markdown字段,少依赖专有功能 |
这里特别说一下“技能从来没有被自动触发”这个问题。很多人以为是模型傻,其实是你没把description的“触发词”写对。比如你要写一个处理图片的Skills,别只写“用于处理图片”,要写成“当用户上传图片、截图、或要求提取图片中的文字时使用”。这样模型在判断时,会把用户请求里的“截图”和你的description关联起来,触发概率会高很多。
5.2 从提示词到Skills的升级路径:不是把提示词换个壳
我知道很多人写Skills,本质上是把以前用顺手的提示词,原封不动塞进markdown里。这条路走不长。从提示词到Skills,你需要做三件额外的事:
第一,抽象出触发条件。提示词是你主动给AI的,但Skills是AI主动识别的。你必须给AI一个“什么时候掏出这个技能”的信号,这往往比技能内容本身还重要。第二,定义输入接口。提示词可以不关心输入格式,但Skills必须明确“拿到什么样的输入才开工”,否则就会遇到用户给一段乱糟糟的需求,AI不知道该从哪下手。第三,输出结构化。Skills的价值在于可复用,如果你的输出每次都不一样,那就失去了复用的意义。
我有个朋友从提示词迁移到Skills时,花了一整个下午在纠结“工作流程应该写多细”。我的建议是颗粒度适中:既有步骤划分,又不至于详细到每个光标移动都写出来。你要相信模型的推理能力,你的任务是给它划出边界,而不是替它思考。
5.3 最后分享几个写Skills的私房经验
聊到最后,我再多说几个纯经验层面的东西,可能不在任何官方文档里。
第一,Skills也讲究“小步快跑”。不要一上来就想做一个万能技能,覆盖10种场景。我早期写过一个大而全的“文档生成器”,里面又要写周报又要写PRD又要写会议纪要,结果哪样都做得不精。后来我拆成三个独立技能,每个只管一个场景,效果立刻好了。拆开之后,每个技能的description可以写得更精准,模型也不会搞混。
第二,版本管理永远不过时。每次修改SKILL.md,我都顺手在后面加一个## Changelog小节,记录日期和改动内容。这个习惯帮了我大忙——有时候改了某个字段,一个星期后发现效果变差了,还能回头查是哪次改动引入的。
第三,多看优秀项目,但别照抄。GitHub上“awesome claude skills”这类仓库里的项目质量参差不齐,有些写得确实好,有些也就是个换皮提示词。我的学习方法是:重点看那些包含了“示例对话”和“自检清单”的技能,因为这两块是大部分人懒得写但恰恰是最有价值的。看多了你会发现,真正优秀的Skills作者,花在边界约束上的时间比花在正文上的时间还多。
第四,养成“用测试用例跑技能”的习惯。别只在真实场景里试,那样反馈太慢。像我前面说的,准备一套固定的测试输入,每次改完技能文件就跑一遍,看输出是否退化。这套方法听起来土,但在我维护十多个技能包的过程中,帮我提前拦下了至少一半的回归问题。
Skills不是写出来给人看的,是写出来给模型“照着干活”的。所以别再沉浸在“我写了一个Skills”的成就感里了。下次写完,先问自己一个问题:如果今天换一个完全不了解背景的实习生,他能靠这份文档把活儿干对吗?要是答案是否定的,那你的Skills,确实还没及格。