1. 从"agent-skills"这个标题能读出什么
第一次看到agent-skills这个仓库名,我的直觉是:这不是又一个"提示词大全",而是一套把 AI coding agent 当"新员工"来培养的技能体系。事实也确实如此——它把散落在各种博客、推文、issue 里的 agent 使用经验,收敛成了一套可安装、可复用、可版本管理的 skill 集合,通过一个skillsCLI 分发到 Claude Code 这类 AI coding agent 的工作目录里。
说白了,它解决的是一个很具体的痛点:你每次开一个新会话,agent 都像失忆一样,不知道你的代码规范、不知道你的测试习惯、不知道你踩过哪些坑。你要么每次手动贴一大段上下文,要么写一个巨大的CLAUDE.md把所有东西塞进去,结果就是上下文窗口被静态说明占满,真正干活的空间被压缩。
agent-skills的思路是把"能力"拆成一个个独立的 skill 单元,按需加载。比如test-driven-development这个 skill,只在你要写测试的时候才被激活;code-review只在 review 阶段激活。这跟传统"把所有规则写进系统提示"的做法有本质区别——前者是按需检索,后者是全量注入。
适合谁看这篇?三类人:一是已经在用 Claude Code、但感觉"它不够懂我"的开发者;二是想给自己的团队搭一套统一 agent 工作流的 tech lead;三是纯粹好奇"AI coding agent 的技能到底怎么组织"的技术爱好者。不需要你懂 agent 内部实现,但需要你对命令行和 Git 有基本概念。
2. skills CLI 到底在做什么:把"经验"变成"可加载模块"
2.1 为什么不是简单复制文件
很多人第一反应是:不就是把 markdown 文件拷到~/.claude/skills/目录吗,为什么要搞个 CLI?
我一开始也这么想,直到我手动维护了十几个 skill 之后才发现问题。手动拷贝有三个绕不开的麻烦:
- 版本漂移:你从 A 仓库拷了一份 skill,改了两个字;又从 B 仓库拷了一份同名的,覆盖了。过两周你根本不知道本地这份是哪个版本。
- 路径不一致:Claude Code 在不同平台(macOS、Linux、Windows WSL)的配置目录不一样,手动拷贝很容易放错地方,agent 静默地加载不到,你还以为是 skill 写错了。
- 更新困难:上游 skill 修了个 bug,你得重新走一遍"找到文件、对比、覆盖"的流程。
skillsCLI 把这三件事都收敛了:它知道每个平台的正确安装路径,知道每个 skill 的来源和版本,支持一条命令更新全部。这跟npm、brew的存在逻辑是一样的——当"手动管理"的边际成本超过某个阈值,工具化就是必然。
2.2 安装与首次运行
CLI 本身通常通过包管理器分发。以常见的 Node 生态为例,安装命令大致是这样:
# 全局安装 skills CLI npm install -g @agent-skills/cli # 验证安装 skills --version # 查看可用 skill 列表 skills list # 安装指定 skill 到 Claude Code 目录 skills install test-driven-development注意:具体的包名和命令以仓库 README 为准,不同版本可能有差异。我建议先跑
skills --help看清楚子命令,再动手。
安装完成后,CLI 会把 skill 文件放到 Claude Code 能识别的目录。这里有个很容易踩的坑:Claude Code 读取 skill 的目录是分层的——有全局的(用户级),也有项目级的(仓库内)。全局的对你所有项目生效,项目级的只对当前仓库生效。skills install默认装到全局,如果你希望某个 skill 只在这个项目里用,得加--local之类的参数。
我的建议是:通用能力(比如 TDD、code review)装全局,项目特有的(比如"我们这个仓库的 API 命名规范")装项目级。这样既不会污染其他项目,也不会在新项目里丢失通用能力。
2.3 skill 文件长什么样
一个 skill 本质上是一个带 frontmatter 的 markdown 文件。结构大致如下:
--- name: test-driven-development description: 当用户要求编写新功能或修复 bug 时,先写测试再写实现 trigger: 编写测试、TDD、红绿重构 --- ## 核心原则 1. 先写一个失败的测试 2. 写最少的代码让测试通过 3. 重构,保持测试绿色 ## 具体步骤 ...关键字段是description和trigger。agent 不是把所有 skill 全文读进上下文,而是先读这些元数据,判断当前任务该激活哪个 skill,再加载全文。这就是"按需加载"的实现方式,也是它比"巨型 CLAUDE.md"更省上下文的原因。
理解了这一点,你写自己的 skill 时就知道重点在哪:description要写得让 agent 能准确判断"什么时候该用我",正文才写具体怎么做。很多人把description写成一句废话("这是一个关于测试的 skill"),结果 agent 永远不激活它。
3. test-driven-development 这个 skill 为什么值得单独拎出来讲
3.1 TDD 对 agent 的意义和人类不一样
对人类开发者来说,TDD 是一种设计方法论——先写测试逼你想清楚接口。但对 AI coding agent 来说,TDD 的意义更实际:它是防止 agent "幻觉式完成"的最有效手段。
我踩过太多次这个坑:让 agent 实现一个函数,它洋洋洒洒写了一大段,还自信地说"已完成"。你一跑,报错。或者更糟——它跑通了,但逻辑是错的,因为它偷偷改了你的调用方式去迁就自己的实现。
TDD 把这个过程锁死了:测试是你写的(或者你审核过的),agent 的任务只有一个——让测试变绿。它没有空间去"重新定义什么叫完成"。这就是为什么test-driven-development这个 skill 在 agent 场景下价值极高,它不只是编码习惯,而是一种约束 agent 行为的机制。
3.2 红绿重构在 agent 工作流里的具体落地
标准的红绿重构三步,在 agent 协作里我会这样拆:
第一步:红。你(或 agent 根据你的描述)先写测试,运行,确认它失败。这一步不能省。我见过太多人跳过"确认失败",结果测试写错了(比如断言写反了),一直是绿的,agent 随便写点什么都"通过"。
第二步:绿。让 agent 写实现,只要求测试通过。这时候要明确告诉它:不要过度设计,不要顺手重构别的代码。agent 有个坏习惯,你让它改 A,它觉得 B 也不顺眼,一起改了,然后 B 的测试挂了。
第三步:重构。测试绿了之后再优化结构。这一步可以交给 agent,但前提是测试覆盖足够。重构完必须重跑测试。
在 skill 里,这三步会被写成明确的指令序列,agent 每次激活这个 skill 就按这个流程走。关键价值在于"流程固化"——你不需要每次都在 prompt 里重复这套要求。
3.3 一个真实的对比
我做过一个不太严谨的对比。同一个任务(实现一个带边界检查的日期解析函数),两种方式:
| 方式 | 首次通过率 | 返工次数 | 我的介入次数 |
|---|---|---|---|
| 直接让 agent 实现 | 约 40% | 平均 2.3 次 | 3-4 次 |
| 先写测试再让 agent 实现 | 约 85% | 平均 0.6 次 | 1-2 次 |
数据样本很小,不能当结论,但趋势很明显:前期多花 5 分钟写测试,后期省下的是反复沟通和排查的时间。而且测试写完之后是可以复用的,下次改这个函数,测试还在。
4. 把 agent-skills 接进 Claude Code 的完整链路
4.1 环境准备里最容易被忽略的两件事
第一件是目录权限。skill 文件要放到 Claude Code 能读的目录,如果你用sudo装到了系统目录,普通用户跑 Claude Code 时可能读不到。我建议全部装在用户目录下,避免权限问题。
第二件是确认 Claude Code 真的加载了 skill。很多人装完就以为生效了,其实没有。验证方法很简单:开一个新会话,问 agent "你现在有哪些可用的 skill",或者直接触发一个应该激活 skill 的场景,看它的行为是否符合 skill 描述。如果没反应,八成是路径不对或 frontmatter 格式有问题。
4.2 项目级 vs 全局:怎么选
这个决策我前面提了一句,这里展开说。判断标准是这个 skill 的知识是否跨项目通用。
- 跨项目通用:TDD 流程、code review 清单、commit message 规范、通用调试方法 → 装全局
- 项目特有:这个仓库的目录结构约定、内部 API 用法、特定的构建命令 → 装项目级
项目级的 skill 通常会跟着仓库一起提交到 Git,这样团队每个人 clone 下来就自动有了。这是agent-skills一个很聪明的设计——它让 agent 的"团队知识"可以像代码一样被版本管理。
4.3 和 CLAUDE.md 的分工
这里必须澄清一个常见误解:skill 不是用来替代CLAUDE.md的,两者分工不同。
CLAUDE.md适合放永远需要知道的、简短的、全局的信息,比如"这个项目用 pnpm 不用 npm"、"测试命令是pnpm test"。它是每次会话都会加载的。
skill 适合放特定场景才需要的、较长的、流程性的信息,比如完整的 TDD 步骤、详细的 review 清单。它是按需加载的。
我的经验是:CLAUDE.md控制在 50 行以内,超过的内容就该考虑拆成 skill 了。一个臃肿的 CLAUDE.md 会持续消耗每次会话的上下文预算,而 skill 只在需要时付费。
5. 自己写一个 skill:从踩坑到跑通
5.1 什么样的经验值得写成 skill
不是所有东西都值得 skill 化。我总结了一个简单的判断标准:如果这件事你会反复向 agent 解释,且解释内容基本固定,那就值得写成 skill。
反例:一次性的调试过程、某个具体 bug 的修复方案——这些写进对话就行,写成 skill 反而增加维护负担。
正例:你团队的代码风格、你偏好的重构手法、你要求 agent 遵守的安全检查清单——这些每次都要说,且内容稳定。
5.2 frontmatter 写不好,skill 就是死的
我前面强调过description和trigger的重要性,这里给个具体的写法对比。
差的写法:
description: 关于代码审查的 skill好的写法:
description: 当用户要求审查代码、检查 PR、或提到 code review 时激活。按安全性、可读性、性能三个维度逐项检查,输出结构化问题列表。区别在于:好的写法明确告诉 agent什么时候用(触发条件)和用了之后做什么(行为预期)。agent 判断是否激活 skill,靠的就是这段文字。写得模糊,它就永远不激活,你装了等于没装。
5.3 一个我实际在用的 skill 骨架
以"提交前检查"为例,我的 skill 大致长这样:
--- name: pre-commit-check description: 当用户准备提交代码、或提到 commit、提交前检查时激活。依次运行 lint、类型检查、单元测试,任一失败则阻止提交并报告。 trigger: 提交、commit、pre-commit --- ## 执行顺序 1. 运行 `pnpm lint`,失败则停止 2. 运行 `pnpm typecheck`,失败则停止 3. 运行 `pnpm test`,失败则停止 4. 全部通过后,生成符合规范的 commit message ## 注意事项 - 不要自动执行 `git commit`,只做检查并报告结果 - 如果 lint 有自动修复项,先询问用户是否修复这个 skill 帮我省掉了每次都要打一长串"提交前先跑 lint 再跑测试"的麻烦。注意最后那条"不要自动 commit"——这是安全边界,agent 不应该在没有明确指令的情况下改动 Git 历史。
5.4 调试 skill 不生效的排查链路
skill 装了但没反应,按这个顺序查:
- 文件在不在正确目录:
ls一下 Claude Code 的 skill 目录,确认文件真的在那 - frontmatter 格式对不对:YAML 对缩进敏感,多一个空格都可能解析失败
- description 是否可被匹配:把你的触发词直接说给 agent 听,看它是否激活
- 是否有同名冲突:全局和项目级有同名 skill 时,加载哪个取决于实现,容易出意外
- 重启会话:skill 通常在会话启动时加载,改完文件要开新会话
我遇到最多的是第 2 条。YAML 里description如果包含冒号,必须加引号,否则解析直接失败,而且失败是静默的——agent 不会报错,只是当这个 skill 不存在。
6. 几个绕不开的实操问题
6.1 skill 太多会不会拖慢 agent
会,但影响方式和你想的不一样。skill 的元数据(name、description)会被加载用于匹配,正文不会。所以真正影响性能的是元数据的数量,不是 skill 的总数。
我的经验是:几十个 skill 的元数据开销可以忽略,但如果你装了几百个,匹配准确率会下降——agent 可能激活错误的 skill。定期清理不用的 skill,比无脑囤积更重要。
6.2 团队协作时怎么同步 skill
项目级 skill 跟着 Git 走,这是最省心的方式。但要注意:skill 里不要写死个人偏好。比如"我喜欢用 2 空格缩进"这种,写进团队共享的 skill 会引发争议。团队 skill 只放共识,个人偏好放全局 skill。
另外,skill 的变更应该走 code review。一个改错的 skill 会影响团队所有人的 agent 行为,比改错一行代码影响面更大。
6.3 和第三方模型的兼容性
agent-skills的设计是围绕 Claude Code 的 skill 加载机制来的。如果你用的是其他支持 skill 概念的 agent 工具,目录结构和 frontmatter 格式可能不同,需要做适配。核心思路(元数据匹配 + 按需加载正文)是通用的,但具体文件格式要按目标工具的要求来。
我个人的做法是:把 skill 的内容和格式分离。内容(流程、清单、原则)写在一个中立的 markdown 里,然后用脚本生成各工具需要的格式。这样换工具时不用重写内容。
7. 我用了几个月之后的真实体会
最开始我是抱着"试试看"的心态装的,觉得无非是把 prompt 模板换了个地方放。用了几个月之后,最大的改变不是效率,而是一致性。
以前我让 agent 写代码,质量波动很大——有时候它记得写测试,有时候不记得;有时候它遵守命名规范,有时候乱来。这种波动让我不敢完全信任它,每个输出都要仔细检查。装了 skill 之后,至少在我定义了 skill 的场景里,它的行为是可预期的。可预期比"偶尔惊艳"重要得多,因为可预期才能放心地把任务交出去。
另一个体会是:写 skill 的过程,其实是在逼自己把隐性经验显性化。很多规范我平时是"凭感觉"遵守的,写 skill 时不得不把它拆成明确的步骤,这个过程本身就让我对自己的工作流理解更深了。
如果你刚开始,我的建议是别贪多。先挑一个你最常向 agent 重复解释的场景,写成一个 skill,跑通,用一周。有感觉了再扩展。一上来就装几十个 skill,你根本不知道哪个在起作用,出了问题也无从排查。
最后分享一个小技巧:给每个 skill 加一个"最后更新日期"的注释。skill 是会过期的——你的项目结构变了、工具链升级了,skill 里的命令可能就失效了。有个日期,你至少知道哪些该回头检查了。