1. 从"skills"这个模糊词说起:它到底指什么
第一次看到"skills"这个词作为项目标题,说实话我是有点懵的。这个词太泛了,泛到放在任何语境下都能说得通——招聘网站上的技能标签叫skills,游戏里的技能树叫skills,而最近技术圈里反复被提起的skills,指的其实是Agent Skills,也就是围绕Claude Code、Codex这类AI编程代理构建的一套可复用能力模块体系。
我接触这套东西的契机很偶然。当时我在做一个前端项目,需要反复让AI帮我处理组件拆分、样式规范检查、接口类型对齐这几件事。每次开新会话,我都得把同样的规则重新讲一遍,讲得我自己都烦了。后来有人跟我说,你为什么不把这些规则写成一个skill?我才开始认真研究这套机制。
简单来说,Agent Skills的核心逻辑是:把"你希望AI怎么干活"这件事,从每次对话里的口头交代,变成一份结构化的、可被AI自动识别和加载的文件。这个文件通常叫SKILL.md,放在特定的目录结构下,AI在需要的时候会自己去读它,然后按照里面写的流程和规范来执行任务。
它解决的是什么问题?解决的是重复交代、标准漂移、上下文浪费这三个痛点。你不需要每次都告诉AI"我们团队用TypeScript严格模式,组件必须拆到200行以内,样式用CSS Modules不用styled-components",这些写进skill里,AI自己会看。你也不需要担心这次会话里AI记得规范、下次会话就忘了,因为skill是持久化的文件,不依赖对话上下文。
适合谁来学?我觉得三类人最该关注:一是日常高频使用Claude Code或类似AI编程工具的开发者,二是需要团队协作、希望统一AI输出标准的技术负责人,三是做数学建模、内容创作等需要AI按固定套路输出的人。哪怕你只是偶尔用AI写写脚本,学会写一个简单的skill也能省下大量重复沟通的时间。
接下来我会从skill的文件结构、编写方法、安装配置、实战案例、常见坑这几个角度,把这件事讲透。
2. SKILL.md的文件结构:为什么这样设计
2.1 一个skill的最小组成单元
先看一个最简的skill长什么样。假设我要做一个"前端组件代码审查"的skill,目录结构大概是这样:
skills/ frontend-review/ SKILL.md references/ style-guide.md component-checklist.md核心就是那个SKILL.md。它的内容通常包含几个部分:元信息(name、description)、触发条件、执行步骤、输出格式、参考文件索引。我拿一个真实在用的例子给你看:
--- name: frontend-review description: 审查前端组件代码,检查命名规范、拆分粒度、类型完整性 --- ## 何时使用 当用户要求审查React/Vue组件代码,或提到"组件规范""代码审查"时使用。 ## 执行步骤 1. 读取 references/style-guide.md 中的命名规范 2. 检查组件是否超过200行,超过则建议拆分 3. 检查props/emit是否有完整类型定义 4. 检查是否存在内联样式,有则建议提取 ## 输出格式 按"问题-位置-建议"三段式输出,每条问题标注严重程度。这个结构不是随便定的。name和description放在最前面,是因为AI在判断"要不要加载这个skill"时,最先看的就是这两项。description写得越具体,AI匹配得越准。我见过有人把description写成"一个有用的skill",结果AI根本不知道什么时候该用它,等于白写。
2.2 为什么用Markdown而不是JSON或YAML
这个问题我被问过好几次。用Markdown的好处是AI读起来自然。你想想,skill的本质是给AI看的"操作手册",而AI对Markdown格式的理解能力是最强的——标题层级、列表、代码块,这些结构AI都能准确解析。如果你用JSON写,虽然机器解析没问题,但AI在理解"步骤之间的逻辑关系"时反而容易出错。
另一个原因是人也能读。skill不只是给AI看的,团队成员也要能看懂、能改。Markdown的可读性远超JSON,一个不懂技术的人打开SKILL.md也能大概明白这个skill在干什么。
2.3 references目录的作用与取舍
references目录放的是详细参考资料,比如完整的代码规范文档、检查清单、示例代码。为什么不把这些直接写进SKILL.md?因为上下文是有成本的。SKILL.md本身要尽量精简,让AI快速理解"要做什么";references里的内容只在需要时才被读取,避免一次性塞太多信息把上下文撑爆。
我的经验是:SKILL.md控制在100-200行以内,references可以随便长。如果一个skill的SKILL.md超过300行,基本可以考虑拆成两个skill,或者把细节挪到references里。
注意:references目录不是必须的。简单的skill只有SKILL.md一个文件也完全能用。不要为了"看起来完整"而硬造references。
3. 写一个能用的skill:从需求到落地
3.1 先想清楚"触发场景"再动笔
很多人写skill的第一个错误是:上来就开始写步骤,结果写完发现AI根本不知道什么时候该用。正确的顺序是先定义触发场景。
我一般会问自己三个问题:这个skill在什么情况下该被激活?用户会用什么词来描述这个需求?如果不激活会有什么后果?把这三个问题的答案写进description和"何时使用"部分,AI的匹配准确率会高很多。
举个例子,我写过一个"数学建模论文格式检查"的skill。description我写的是:"检查数学建模竞赛论文的格式规范,包括摘要结构、公式编号、图表标题、参考文献格式。当用户提到'建模论文''格式检查''论文排版'时使用。"这样写之后,我只要在对话里说"帮我看看这篇建模论文的格式",AI就能自动加载这个skill。
3.2 步骤要写成"可执行的动作"而不是"原则"
这是区分新手和老手的关键。新手写步骤喜欢写原则,比如"确保代码质量""注意命名规范";老手写的是可执行动作,比如"检查每个函数名是否以动词开头""检查变量名是否超过30个字符"。
为什么?因为AI执行原则时会产生歧义,而执行具体动作时不会。你写"注意命名规范",AI可能觉得getUserInfo和fetch_user_info都算规范;你写"函数名必须用驼峰命名,且以动词开头",AI就能明确判断。
我自己的做法是:每写一条步骤,就问自己"如果换一个AI来执行,它能不能100%确定该做什么"。如果不能,就继续细化。
3.3 输出格式的约束力比你想的更重要
很多人忽略输出格式这一节,觉得"AI自己会组织语言"。但实际用下来,输出格式是保证结果可用的关键。如果你不约束,AI可能这次给你一段话,下次给你一个列表,再下次给你一个表格,你根本没法做后续处理。
我通常会在输出格式里规定三件事:结构(分几段、每段叫什么)、粒度(每条多长)、标记方式(用什么符号标注严重程度)。比如:
## 输出格式 按以下结构输出: - 【严重】问题描述 | 位置 | 修复建议 - 【建议】问题描述 | 位置 | 优化方向 每条不超过两行,位置精确到行号或函数名。这样约束之后,输出结果可以直接贴进代码审查工具,或者用脚本做二次处理。
3.4 一个完整的skill编写流程
我把自己的编写流程总结成五步:
- 记录痛点:在日常使用中,把"我又要重复交代一遍"的场景记下来
- 提炼规则:把这些交代整理成明确的规则和步骤
- 写SKILL.md:按元信息、触发条件、步骤、输出格式的结构写
- 实测三轮:用三个不同的真实任务测试,看AI是否能正确触发、正确执行
- 迭代description:如果触发不准,优先改description,而不是改步骤
实测三轮这一步不能省。我写过一个"API接口文档生成"的skill,前两轮测试都正常,第三轮遇到一个返回结构特别复杂的接口,AI就懵了。后来我在步骤里加了一条"如果返回结构超过三层嵌套,先画结构树再生成文档",问题才解决。
4. 安装与配置:不同环境下的落地方式
4.1 Claude Code环境下的skill放置位置
Claude Code读取skill的位置通常有两个:项目级目录和用户级目录。项目级的放在项目根目录下的.claude/skills/或skills/里,只对当前项目生效;用户级的放在用户主目录下的配置文件夹里,对所有项目生效。
我的建议是:团队协作的规范类skill放项目级,个人习惯类skill放用户级。比如"组件命名规范"是团队约定,放项目级,跟着代码仓库走;"我个人的代码注释风格"放用户级,换项目也能用。
配置的时候有个细节容易踩坑:目录名必须和skill的name一致。我有一次把skill放在skills/review/目录下,但SKILL.md里的name写的是frontend-review,结果AI死活加载不了。后来改成目录名和name一致就好了。
4.2 从GitHub获取现成skill的正确姿势
网上有很多开源的skill集合,比如一些"superpower skills"仓库。获取方式一般是clone或者下载压缩包,然后放到对应的skills目录下。
但这里有个常见问题:下载下来的skill可能依赖特定的目录结构或额外的工具。我建议拿到一个skill后,先打开SKILL.md看三件事:它依赖哪些references文件?它假设的运行环境是什么?它的输出格式是否符合你的需求?确认没问题再放进去。
另外,如果你用的是Windows环境,注意路径分隔符的问题。有些skill里写死了/路径,在Windows下可能读不到文件。遇到这种情况,把路径改成相对路径或者用path.join的方式处理。
4.3 验证skill是否生效的三种方法
装完skill之后,怎么确认它真的生效了?我用三种方法:
第一种,直接问AI。在对话里问"你现在加载了哪些skill",AI会列出它识别到的skill列表。如果列表里没有你刚装的,说明路径或name有问题。
第二种,触发测试。用description里提到的关键词发起一个请求,看AI是否按照skill里的步骤执行。比如skill里写了"输出按三段式",你就看输出是不是三段式。
第三种,看日志。Claude Code在加载skill时通常会有日志输出,能看到它扫描了哪些目录、加载了哪些文件。如果日志里没有你的skill,就是没被扫描到。
提示:如果skill没生效,排查顺序是——目录名是否匹配name、SKILL.md的frontmatter格式是否正确、文件编码是否是UTF-8。这三个问题占了90%的加载失败原因。
4.4 多skill共存时的优先级问题
当你装了很多skill之后,会遇到一个情况:两个skill的触发条件有重叠,AI不知道该用哪个。这时候description的精确度就决定了优先级。写得越具体的skill越容易被选中。
我的处理方式是:给每个skill的description加上"排他性"描述。比如"当用户明确要求检查组件代码时使用,不用于检查样式文件"。这样AI在匹配时就能区分开。
如果实在冲突严重,可以在项目级目录里放一个"skill索引"文件,明确告诉AI什么场景用什么skill。不过这属于进阶用法,skill数量少于10个的时候一般用不上。
5. 实战场景拆解:skill在不同领域的用法
5.1 前端开发中的skill组合
前端是我用得最多的场景。我目前维护着四个前端相关的skill:组件审查、样式规范检查、接口类型对齐、提交信息生成。它们各自独立,但在实际工作流里会串联使用。
比如我写完一个组件,会先触发"组件审查"skill,它会检查拆分粒度和命名;然后触发"样式规范检查",确认没有内联样式和魔法数字;最后提交前触发"提交信息生成",按约定格式生成commit message。整个过程我不需要重复交代任何规范,AI自己会按skill里的流程走。
这里有个经验:skill之间不要互相调用。我试过让一个skill去触发另一个skill,结果AI在理解调用关系时经常出错。正确做法是让它们保持独立,由我在对话里按顺序触发。
5.2 数学建模比赛中的skill应用
数学建模是我另一个高频使用场景。比赛期间时间紧、任务重,AI辅助的效率直接决定成败。我总结了一套建模skill组合:论文格式检查、公式推导验证、图表规范生成、摘要结构优化。
其中"论文格式检查"这个skill帮我省了最多时间。它内置了国赛和美赛两套格式规范,我只要把论文丢给它,它就会逐项检查摘要字数、公式编号连续性、图表标题位置、参考文献格式。以前这些检查要花我两个小时,现在十分钟搞定。
"公式推导验证"这个skill比较特殊,它的步骤里包含"如果推导结果与预期不符,列出可能的假设错误"。这一条是我踩坑之后加的——有一次AI推导出一个错误结果,但它自己没发现,直接输出给我了。加了这条之后,它会主动做合理性检查。
5.3 内容创作场景的skill设计
除了技术场景,我也用skill来辅助内容创作。比如"AI漫剧脚本生成"这个skill,里面规定了角色对话的风格、分镜的描述格式、每集的时长控制。
内容类skill和技术类skill的最大区别是:技术类skill重规则,内容类skill重风格。技术类skill的步骤要精确到可执行动作,内容类skill的步骤要精确到风格特征。比如"角色对话要口语化,每句不超过20字,避免书面语",这种描述对AI来说就是可执行的风格约束。
5.4 不同AI工具的skill兼容性
目前skill这套机制在Claude Code上支持最好,Codex、opencode等工具也在逐步跟进。但不同工具对SKILL.md的解析方式有差异。我实测下来,frontmatter的格式兼容性最好,正文部分的Markdown结构兼容性次之,references的加载逻辑差异最大。
如果你需要跨工具使用同一个skill,建议把核心逻辑写在SKILL.md正文里,references只放可选的补充材料。这样即使某个工具不支持references加载,skill的核心功能也不受影响。
6. 踩坑记录:那些让我折腾半天的错误
6.1 skill写了但AI不触发
这是最高频的问题。我遇到过至少五次,排查下来原因各不相同:
第一次是description太笼统,写的是"帮助处理代码",AI根本不知道什么时候该用。改成"审查React组件代码,检查命名、拆分、类型"之后就好了。
第二次是frontmatter格式错误,我在---后面多打了一个空格,导致AI解析不了元信息。这种错误很隐蔽,因为文件看起来是正常的。
第三次是目录层级不对,我把skill放在了skills/skills/frontend-review/下面,多了一层目录,AI扫描不到。
第四次是文件编码问题,我用某个编辑器保存成了GBK编码,AI读出来是乱码。
第五次最离谱,skill的name和目录名不一致,而且description里用了中文标点,AI匹配时出了问题。
6.2 触发太频繁,不该用的时候也加载
这个问题和上面正好相反。我写过一个"代码优化"的skill,description写得太宽泛,结果我每次让AI写新代码,它都会触发这个skill,然后开始"优化"我还没写完的代码。
解决办法是在description里加否定条件。比如改成"当用户明确要求优化已有代码时使用,不用于生成新代码"。加了这句之后,误触发率大幅下降。
6.3 skill之间的规则冲突
我同时装了"代码简洁优先"和"代码可读性优先"两个skill,结果AI在执行时经常左右为难。一个说"能一行写完就一行写完",另一个说"每行不超过80字符,逻辑要分段"。
这种冲突没有完美的技术解决方案,只能在规则层面做取舍。我的做法是:把冲突的规则合并到一个skill里,明确优先级。比如"默认简洁优先,但当简洁影响可读性时,可读性优先"。
6.4 更新skill后行为不一致
我改了一个skill的步骤,但AI的行为还是按旧版执行。排查后发现是缓存问题——Claude Code会缓存已加载的skill,改了文件之后需要重启会话或者手动刷新。
这个坑的教训是:改完skill一定要开新会话测试,不要在旧会话里验证。旧会话可能还在用缓存的版本。
6.5 排查skill问题的通用链路
踩了这么多坑之后,我总结了一套排查链路,按顺序走基本能定位问题:
| 步骤 | 检查项 | 常见问题 |
|---|---|---|
| 1 | 目录名与name是否一致 | 不一致导致加载失败 |
| 2 | frontmatter格式 | 多空格、缺分隔符、编码错误 |
| 3 | description精确度 | 太笼统导致不触发,太宽泛导致误触发 |
| 4 | 文件编码 | 非UTF-8导致乱码 |
| 5 | 缓存状态 | 改完未刷新导致行为不一致 |
| 6 | skill间冲突 | 规则重叠导致执行混乱 |
按这个顺序排查,90%的问题能在前三步解决。
7. 让skill真正提升效率的几个心得
7.1 从"最小可用skill"开始迭代
我见过很多人想一次写一个完美的skill,结果写了三天还没写完,最后放弃了。我的建议是先写一个能用的最小版本,哪怕只有五行,先跑起来,然后在实际使用中迭代。
我的第一个skill只有三行:name、description、一条步骤。但它确实解决了我的问题——不用每次重复交代命名规范。后来我根据使用中遇到的情况,慢慢加到了现在的二十多行。
7.2 把"我经常说的话"变成skill
判断一个场景该不该做成skill,有个很简单的标准:这句话我是不是说过三次以上。如果是,就值得做成skill。
我现在的skill库里,大部分都是从"我又要说一遍"的场景里提炼出来的。比如"接口返回要判空""日志要带traceId""异常要分类处理",这些都是我说过无数遍的话,现在都固化在skill里了。
7.3 定期清理不再用的skill
skill装多了会有两个问题:一是AI匹配时容易混淆,二是维护成本上升。我每隔一个月会清理一次skill库,把三个月没用过的删掉或者归档。
清理的标准很简单:如果这个skill的规则已经变成了我的肌肉记忆,或者已经写进了项目的lint配置,那它就可以删了。skill的价值在于弥补人的遗忘和AI的上下文限制,当这个缺口被其他方式补上时,skill就完成了使命。
7.4 团队协作中的skill管理
如果是团队使用,skill的管理需要额外注意几点:版本控制(skill跟着代码仓库走,改动要有记录)、命名规范(团队内统一前缀,比如team-开头)、评审机制(新skill或重大改动要经过评审)。
我们团队现在的做法是:skill放在项目仓库的.claude/skills/目录下,和代码一起做code review。每个skill的description里必须写明负责人,出问题能找到人。
7.5 关于skill的未来演进
从我自己的使用体验来看,skill这套机制还在快速演进。目前比较明显的趋势是:skill的组合使用(多个skill协同完成复杂任务)、skill的动态加载(根据任务类型自动选择skill)、skill的跨工具标准化(同一份SKILL.md在不同AI工具间通用)。
我现在会刻意把skill写得"工具无关"——不依赖特定工具的API,只用标准的Markdown结构。这样即使以后换工具,skill也能直接迁移。
最后分享一个我最近在用的技巧:给skill加一个"自检"步骤。在SKILL.md的最后加一条"执行完成后,检查输出是否符合输出格式要求,不符合则重新生成"。这一条加上之后,输出质量的稳定性明显提升。这个技巧不复杂,但确实管用。