1. 从"skills"这个热词说起:它到底在解决什么问题
最近一段时间,不管是在技术社区还是开发者群聊里,"skills"这个词出现的频率高得离谱。很多人第一次看到它,会以为是某种新的编程语言或者框架,其实不是。这里的 skills,指的是围绕 AI 编程助手(比如 Claude Code、Codex 这类工具)构建的一套可复用的能力模块。你可以把它理解成给 AI 助手装的"技能包"——装上一个 skill,AI 就多会一件事;装上一套 skills,AI 就能从"能聊天"变成"能干活"。
我最初接触这个概念的时候,也是懵的。因为网上关于 skills 的资料非常零散,有人说是插件,有人说是提示词模板,还有人说是某种配置文件。实际上,skills 的本质更接近于结构化的任务指令集:它把某个具体场景下的操作流程、注意事项、输出格式全部封装好,AI 助手在需要的时候自动加载,然后按照预设的方式完成任务。这跟传统的"每次都要重新写一遍提示词"相比,效率提升是数量级的。
为什么 skills 会突然火起来?核心原因在于,大家发现通用大模型虽然聪明,但在具体任务上经常"不听话"——你让它写代码,它给你写一堆注释;你让它改 bug,它把整个文件重写一遍。skills 的出现,就是给这种"不听话"套上一个约束框架,让 AI 在特定任务上表现得像一个训练有素的专才,而不是一个什么都懂一点但什么都不精的通才。
这篇文章适合谁看?如果你是刚接触 Claude Code 或 Codex 的新手,想搞清楚 skills 到底是什么、怎么装、怎么用,那这篇内容能帮你少走很多弯路。如果你已经用过一段时间,但总觉得效果不稳定,那这里面关于 skill 设计思路和踩坑经验的部分,应该对你有参考价值。我不会讲太多虚的概念,重点放在实际怎么操作、为什么这么操作、以及我踩过的那些坑上。
2. skills 的核心机制:它凭什么能让 AI 变"听话"
2.1 skill 不是插件,但它比插件更轻
很多人第一次听到 skills,会下意识地把它和 VS Code 插件、IDEA 插件类比。这个类比有一半是对的,但另一半会误导你。相同的地方在于,它们都是"扩展能力"的手段;不同的地方在于,插件通常是二进制程序,需要安装、编译、加载,而 skill 本质上就是一组文本文件,通常是 Markdown 或者 YAML 格式,里面写清楚了"什么时候用这个 skill""用的时候要做什么""输出要长什么样"。
这意味着什么?意味着你可以用记事本打开一个 skill,直接改里面的内容,改完保存,AI 下次调用的时候就会用你改过的版本。这种"可读可改"的特性,是 skills 相比传统插件最大的优势。我见过不少团队,把内部代码规范、部署流程、甚至代码审查清单全部写成了 skill,新来的同事只要装上这套 skills,AI 助手就会按照团队的标准来干活,省去了大量口头培训的成本。
从技术实现上看,skill 的加载机制通常是这样的:AI 助手在启动或者执行任务时,会扫描指定的 skills 目录,读取每个 skill 的元数据(比如名称、触发条件、描述),然后根据当前任务的内容,判断是否需要加载某个 skill。如果需要,就把 skill 的完整内容注入到上下文里,让模型按照 skill 的指示来执行。这个过程对用户是透明的,你不需要手动"启用"某个 skill,只要它放在正确的位置,AI 自己会判断。
2.2 触发条件的设计,决定了 skill 好不好用
一个 skill 能不能发挥作用,关键看它的触发条件设计得合不合理。触发条件写得太宽,AI 会在不相关的任务上也加载这个 skill,导致输出跑偏;写得太窄,AI 又经常想不起来用它,等于白装。
我举个例子。假设你写了一个"生成单元测试"的 skill,触发条件如果只写"当用户要求写测试时",那 AI 在你说"帮我给这个函数加个测试"的时候可能会触发,但在你说"这个模块的覆盖率不够"的时候就不会触发。更好的写法是把触发条件写成"当任务涉及测试编写、覆盖率提升、测试用例补充时",这样覆盖面更广,AI 更容易判断出该用这个 skill。
还有一个容易被忽略的点:skill 的优先级。如果你装了很多 skill,它们之间可能会有冲突。比如一个 skill 说"输出代码时要加详细注释",另一个 skill 说"输出代码时要保持简洁",AI 到底听谁的?这时候就需要在 skill 里明确优先级,或者在设计的时候就避免功能重叠。我的经验是,同类功能的 skill 只保留一个,不要装多个功能相似的,否则 AI 会陷入"选择困难",输出质量反而下降。
2.3 skill 的上下文注入方式,影响 token 消耗
skill 被加载的时候,它的内容会被注入到 AI 的上下文窗口里。这意味着 skill 写得越长,消耗的 token 就越多,留给实际任务的空间就越少。我见过有人写了一个 3000 字的 skill,结果 AI 每次执行任务都要先"读"完这 3000 字,真正用来干活的空间被压缩得很厉害。
所以写 skill 的时候,要遵循一个原则:能一句话说清楚的事,不要写一段。比如"输出代码时要遵循 PEP8 规范"这一句就够了,不需要把 PEP8 的每一条规则都抄进去。AI 本身就知道 PEP8 是什么,你只需要告诉它"要遵守"就行。skill 的价值在于告诉 AI 做什么、不做什么,而不是教 AI 知识。
另外,skill 的加载方式也有讲究。有些工具支持"按需加载",就是 AI 判断需要的时候才加载;有些工具是"全部加载",启动时把所有 skill 都读进来。前者省 token,但需要 AI 有较强的判断能力;后者简单直接,但 token 消耗大。选择哪种方式,取决于你用的工具和你的实际需求。如果 skill 不多,全部加载也无所谓;如果 skill 很多,建议用按需加载。
3. 从零开始:skills 的安装与配置实操
3.1 环境准备:不同工具的 skills 目录在哪里
skills 的安装,第一步是找到正确的目录。不同的 AI 编程助手,skills 的存放位置不一样。我整理了一个常见的对照表,你可以根据自己的工具来查:
| 工具 | 默认 skills 目录 | 备注 |
|---|---|---|
| Claude Code | ~/.claude/skills/ | 用户级目录,所有项目共享 |
| Claude Code(项目级) | <项目根目录>/.claude/skills/ | 只对当前项目生效 |
| Codex | ~/.codex/skills/ | 用户级目录 |
| Codex(项目级) | <项目根目录>/.codex/skills/ | 只对当前项目生效 |
| VS Code 插件版 | 插件设置里指定的目录 | 需要在设置里手动配置 |
注意:如果你用的是 Windows 系统,
~代表的是C:\Users\你的用户名\。有些工具在 Windows 上对路径的处理不太一样,建议用绝对路径,避免出现"找不到目录"的问题。
我个人的习惯是,通用 skill 放在用户级目录,项目相关的 skill 放在项目级目录。比如"代码格式化""生成注释"这种走到哪都用得上的,放用户级;"这个项目的部署流程""这个项目的数据库连接方式"这种只跟当前项目有关的,放项目级。这样切换项目的时候,不会因为加载了不相关的 skill 而干扰 AI 的判断。
3.2 安装一个 skill 的完整流程
假设你已经找到了 skills 目录,接下来就是安装。安装一个 skill 通常有三种方式:
方式一:手动创建。直接在 skills 目录下新建一个文件夹,文件夹名就是 skill 的名字,然后在里面放一个SKILL.md文件,写上 skill 的内容。这是最基础的方式,适合自己写 skill。
方式二:从市场安装。有些工具提供了 skill 市场,你可以浏览、搜索、一键安装。这种方式适合新手,省去了自己写的麻烦。但要注意,市场里的 skill 质量参差不齐,装之前最好看一下它的描述和评价。
方式三:从 Git 仓库克隆。很多团队会把内部的 skills 放在 Git 仓库里,你只需要git clone到 skills 目录就行。这种方式适合团队协作,大家用同一套 skill,保证输出一致。
我以手动创建为例,演示一个完整的流程。假设我要创建一个"生成 Git 提交信息"的 skill:
# 进入 skills 目录 cd ~/.claude/skills/ # 创建 skill 文件夹 mkdir git-commit-helper # 创建 SKILL.md 文件 touch git-commit-helper/SKILL.md然后在SKILL.md里写入内容:
--- name: git-commit-helper description: 当用户需要生成 Git 提交信息时使用此 skill trigger: 用户要求写 commit message、提交代码、生成提交信息 --- # Git 提交信息生成规范 生成提交信息时,遵循以下规则: 1. 使用 Conventional Commits 格式:`<type>(<scope>): <subject>` 2. type 可选值:feat、fix、docs、style、refactor、test、chore 3. subject 使用中文,不超过 50 个字符 4. 如果有必要,在 body 里补充详细说明 5. 不要生成 "Generated by AI" 之类的字样 示例: - `feat(user): 添加用户登录功能` - `fix(api): 修复订单查询接口的空指针问题`保存之后,重启 AI 助手(或者重新加载配置),这个 skill 就会生效。下次你让 AI 帮你写提交信息的时候,它就会按照你定义的格式来输出。
3.3 验证 skill 是否生效的几种方法
装完 skill 之后,怎么知道它有没有生效?我常用的方法有三种:
方法一:直接问 AI。你可以问"你现在加载了哪些 skill?",有些工具会列出当前生效的 skill 列表。如果 AI 能说出你刚装的 skill 名字,说明加载成功了。
方法二:触发测试。故意做一个会触发 skill 的操作,看 AI 的输出是否符合 skill 里定义的格式。比如你装了一个"生成提交信息"的 skill,就随便改一行代码,然后让 AI 帮你写提交信息,看它是不是按照 Conventional Commits 格式来的。
方法三:看日志。有些工具在启动时会输出加载日志,你可以在终端里看到"Loaded skill: xxx"之类的信息。如果日志里没有你的 skill,说明路径不对或者格式有问题。
提示:如果 skill 没生效,先检查文件格式。
SKILL.md开头的---包裹的部分是元数据,必须严格按照 YAML 格式写,冒号后面要有空格,缩进要用空格不能用 Tab。这些细节很容易出错,但报错信息往往不明显。
4. 写一个真正好用的 skill:设计思路与实战技巧
4.1 从"我每次都要重复说什么"出发
写 skill 最实用的切入点,是回想一下你每次用 AI 时都要重复交代的那些事。比如你每次让 AI 写代码,都要说"用 TypeScript,不要用 any,函数要有返回类型";每次让 AI 写文档,都要说"用 Markdown,标题不要超过三级,代码块要标注语言"。这些重复的话,就是 skill 的素材。
我把这种思路叫做"重复即 skill"。凡是你说过三遍以上的要求,都应该考虑写成 skill。这样不仅省事,还能保证每次的输出标准一致。我自己的 skills 目录里,有一大半都是这么来的。
具体怎么写?我拿"TypeScript 代码规范"举例。一个基础的 skill 可以这样写:
--- name: typescript-standards description: 生成或修改 TypeScript 代码时使用 trigger: 任务涉及 .ts 或 .tsx 文件的编写、修改、审查 --- # TypeScript 代码规范 - 禁止使用 `any`,不确定的类型用 `unknown` 或泛型 - 所有函数必须显式声明返回类型 - 优先使用 `interface` 定义对象结构,`type` 用于联合类型和工具类型 - 使用 `const` 和 `let`,禁止 `var` - 导入顺序:外部库 → 内部模块 → 相对路径 - 错误处理使用 `try/catch`,不要忽略 catch 块这个 skill 不长,但覆盖了最常见的几个要求。AI 加载之后,生成的代码基本就能符合团队规范,不需要你每次再重复。
4.2 触发条件要"宽进严出"
前面提到触发条件的重要性,这里展开说一下我的经验。触发条件的设计,我总结为四个字:宽进严出。
"宽进"是指触发条件要写得宽泛一些,让 AI 在更多场景下能想到用这个 skill。比如"生成测试"的 skill,触发条件不要只写"用户要求写测试",而要写"任务涉及测试编写、测试补充、覆盖率提升、测试重构"。这样即使你没有明确说"写测试",AI 也能判断出当前任务跟测试有关,从而加载 skill。
"严出"是指 skill 里的执行规则要写得严格、具体。比如不要写"代码要规范",而要写"函数名用 camelCase,类名用 PascalCase,常量用 UPPER_SNAKE_CASE"。规则越具体,AI 执行起来越不容易跑偏。
我见过一个反例:有人写了一个"代码审查"的 skill,触发条件写的是"当用户要求审查代码时",规则写的是"检查代码质量"。结果 AI 要么不触发,要么触发了也不知道该检查什么,输出一堆"代码看起来不错"之类的废话。后来他把触发条件改成"任务涉及代码审查、代码质量检查、PR 评审",规则改成"检查以下五项:命名规范、错误处理、边界条件、性能隐患、安全问题",效果立刻就不一样了。
4.3 用"示例"代替"描述"
AI 对示例的理解能力,远强于对抽象描述的理解能力。你在 skill 里写十句"输出要简洁",不如给一个简洁输出的例子。所以我在写 skill 的时候,能举例就举例。
比如你要定义一个"生成 API 文档"的 skill,与其写"文档要包含接口地址、请求方法、请求参数、响应格式",不如直接给一个示例:
# API 文档格式示例 ## 获取用户信息 - 接口地址:`GET /api/users/{id}` - 请求参数: - `id` (path, required): 用户 ID - 响应示例: ```json { "id": 1, "name": "张三", "email": "zhangsan@example.com" }AI 看到这个示例,就知道你要的文档长什么样,生成的时候会直接套用这个格式。这比任何抽象描述都管用。 ### 4.4 skill 的版本管理:别把 skill 当一次性用品 skill 不是写完就扔的东西,它需要维护。随着项目变化、团队规范调整,skill 也要跟着更新。我建议把 skills 目录纳入 Git 管理,每次修改都提交,这样能追溯"什么时候改了什么、为什么改"。 另外,skill 也要有版本号。在元数据里加一个 `version` 字段,比如 `version: 1.2.0`。当 skill 有重大变更时,升一下版本号,方便团队成员知道"这个 skill 更新了,需要重新拉取"。 我还见过一种做法:把 skill 分成"稳定版"和"实验版"。稳定版放在主目录,实验版放在 `experimental/` 子目录。新写的 skill 先在实验版里跑一段时间,验证没问题了再挪到稳定版。这种做法适合团队规模较大、skill 数量较多的情况。 ## 5. 那些年我踩过的 skills 坑 ### 5.1 skill 冲突:两个 skill 打架,AI 左右为难 最常见的坑就是 skill 冲突。我一开始装了很多 skill,有管代码风格的,有管注释的,有管提交信息的。结果有一次让 AI 改代码,它输出的代码既加了详细注释,又保持了极简风格,看起来非常别扭。后来才发现,是两个 skill 的规则打架了:一个说"注释要详细",一个说"代码要简洁"。 解决这个问题的办法,前面提过,就是**同类 skill 只保留一个**。如果你确实需要多个 skill 协作,那就在 skill 里明确优先级,比如在元数据里加 `priority: 10`,数字越大优先级越高。AI 在冲突时会优先执行高优先级的 skill。 还有一种冲突是"触发条件重叠"。比如你有一个"生成测试"的 skill 和一个"代码审查"的 skill,它们的触发条件都包含"测试"这个词。当你让 AI"审查测试代码"的时候,两个 skill 都会被触发,AI 就不知道该按哪个来。这时候需要把触发条件写得更精确,比如"生成测试"的触发条件限定为"编写新测试","代码审查"的触发条件限定为"审查已有代码"。 ### 5.2 skill 太长:AI 读完了,但没记住 前面提过 token 消耗的问题,这里说一个更隐蔽的坑:**skill 太长会导致 AI"读了后面忘了前面"**。我写过一个 2000 多字的 skill,里面列了十几条规则。结果 AI 执行的时候,只遵守了前几条,后面的全忘了。后来我把这个 skill 拆成了三个小 skill,每个只聚焦一个方面,效果就好多了。 所以写 skill 的时候,**单条 skill 的规则不要超过 7 条**。这是我从实践中总结出来的经验值。超过 7 条,AI 的遵守率就会明显下降。如果确实有很多规则,就拆成多个 skill,每个 skill 管一个方面。 ### 5.3 路径问题:Windows 和 Mac 的差异 跨平台使用 skills 的时候,路径问题很容易踩坑。Mac 和 Linux 用 `/` 分隔路径,Windows 用 `\`。有些工具在 Windows 上对 `~` 的解析也不一样。我建议在 skill 里引用文件路径时,**尽量用相对路径或者环境变量**,不要写死绝对路径。 还有一个坑是**文件编码**。Windows 默认可能是 GBK 编码,而 skill 文件通常是 UTF-8。如果编码不对,中文内容会变成乱码,AI 读到的就是一堆问号。解决办法是在保存文件时明确选择 UTF-8 编码,或者在 skill 里避免使用中文。 ### 5.4 更新 skill 后没生效:缓存问题 有时候你改了 skill 的内容,但 AI 的行为没变化。这通常是缓存问题。很多工具会把 skill 内容缓存在内存里,改了文件之后需要重启工具或者手动刷新缓存才能生效。我一般的做法是:改完 skill 之后,先重启一次工具,确认生效了再继续用。如果重启还不行,就检查一下是不是有多个 skills 目录,改错了地方。 > 注意:有些工具支持热加载,改了 skill 文件会自动生效;有些不支持,必须重启。具体看你用的工具,建议查一下官方文档。 ## 6. 进阶玩法:把 skills 用出花来 ### 6.1 用 skill 固化团队工作流 skills 最有价值的用法之一,是把团队的工作流固化下来。比如你们团队的代码审查流程是"先跑 lint,再看测试覆盖率,最后人工审查",那就可以写一个"代码审查"的 skill,把这三步写进去。AI 在审查代码的时候,就会按照这个流程来,不会漏掉任何一步。 我见过一个团队,把他们的部署流程写成了 skill:先跑测试,再构建镜像,再推送到仓库,最后更新服务。AI 在收到"部署"指令时,会自动按照这个流程执行,每一步都有检查点,出错就停下来报告。这比写一个部署脚本更灵活,因为 AI 可以根据实际情况调整,比如测试失败时自动分析原因。 ### 6.2 用 skill 做知识沉淀 skill 还可以用来沉淀团队知识。比如你们团队踩过一个坑:"数据库连接池不能设置太大,否则会拖垮数据库"。这个经验可以写成一个 skill,触发条件是"任务涉及数据库连接配置",规则是"连接池大小不超过 20,超时时间设置为 30 秒"。这样新来的同事在配置数据库时,AI 就会提醒他注意这个问题,避免重复踩坑。 这种"经验型 skill"的价值,随着时间推移会越来越高。因为团队踩过的坑越多,skill 里积累的经验就越丰富,AI 的表现就越好。我建议每个团队都指定一个人负责维护 skills,定期把新的经验补充进去。 ### 6.3 skill 的组合使用:1+1>2 单个 skill 的能力有限,但多个 skill 组合起来,能产生意想不到的效果。比如你有一个"生成代码"的 skill 和一个"生成测试"的 skill,当你让 AI"实现一个功能并写测试"时,两个 skill 会协同工作:先生成代码,再根据代码生成测试。这种组合使用的方式,能大幅提升开发效率。 组合使用的关键是**skill 之间的接口要清晰**。比如"生成代码"的 skill 输出的是代码文件,"生成测试"的 skill 需要读取代码文件来生成测试。这两个 skill 之间就要约定好:代码文件放在哪个目录、用什么命名规范。约定清楚了,组合起来就很顺畅。 ### 6.4 用 skill 做多语言支持 如果你的项目涉及多种编程语言,可以为每种语言写一个 skill。比如"Python 规范""TypeScript 规范""Go 规范"。AI 在处理不同语言的文件时,会自动加载对应的 skill,按照该语言的规范来输出。这样你就不需要在一个 skill 里写"如果是 Python 就怎样,如果是 TypeScript 就怎样",逻辑更清晰,维护也更方便。 我自己的项目里,前端用 TypeScript,后端用 Go,脚本用 Python。我分别写了三个 skill,每个 skill 只管一种语言。AI 在改前端代码时加载 TypeScript skill,改后端代码时加载 Go skill,互不干扰。这种"分而治之"的思路,比写一个大而全的 skill 要好得多。 ## 7. 关于 skills 的一些个人体会 用了大半年 skills 之后,我最大的感受是:**skill 的质量,取决于你对任务的理解深度**。如果你自己对某个任务的理解就是模糊的,那写出来的 skill 也是模糊的,AI 执行起来自然好不到哪去。反过来,如果你能把一个任务拆解得很清楚,知道每一步要做什么、注意什么,那写出来的 skill 就会很精准,AI 的表现也会很稳定。 另一个体会是,**不要追求一次写出完美的 skill**。skill 是需要迭代的。我最早的几个 skill,现在回头看简直惨不忍睹,但正是通过不断使用、发现问题、修改,才慢慢打磨出了好用的版本。所以我的建议是:先写一个粗糙的版本,用起来,遇到问题就改,改着改着就顺了。 最后说一个容易被忽略的点:**skill 不是越多越好**。我见过有人装了上百个 skill,结果 AI 每次启动都要加载半天,而且经常触发错误的 skill。我的经验是,常用的 skill 保持在 10 个以内,每个都经过验证,比装一堆用不上的要强得多。定期清理 skills 目录,把不再用的删掉,保持精简,AI 的表现反而更稳定。 如果你刚开始接触 skills,我的建议是从一个最简单的开始:找一个你每天都要重复交代的要求,把它写成 skill,用一周,看看效果。有效果就继续加,没效果就调整。这种"小步快跑"的方式,比一上来就搞一套复杂的 skill 体系要靠谱得多。