
1. 从agent-skills这个标题能读出什么第一次看到agent-skills这个仓库名我的直觉是这不是又一个提示词大全而是一套把 AI coding agent 当新同事来管理的工程化方案。项目正文和关键词都是空的但热搜词已经把方向交代得很清楚了——AI coding agents、skills CLI、Claude Code、test-driven-development。把这几个词串起来它想解决的问题其实很具体当 AI 已经能写代码、能跑终端命令之后怎么让它稳定地按一套可复用的技能干活而不是每次靠人临场写提示词。我接触过不少团队用 Claude Code 这类工具最常见的状态是用得很爽但不可复现。同一个需求今天让 agent 写出来的东西能跑明天换个会话就完全走样。原因不在模型而在于没有把怎么做一件事沉淀成结构化的技能资产。agent-skills这个标题指向的正是把散落在聊天记录里的经验变成 agent 可以加载、可以组合、可以版本管理的技能模块。这篇文章适合三类人看一是已经在用 Claude Code、但还停留在手写提示词阶段的开发者二是想把 AI coding agent 引入团队协作、需要统一规范的技术负责人三是对skills CLI这类工具链好奇、想搞清楚它和普通 prompt 模板区别的人。我会从技能的本质、目录结构、CLI 用法、TDD 场景落地、以及实际踩过的坑几个角度展开尽量把为什么这么设计讲透而不是只给一堆命令。需要先说明一点agent-skills的具体实现细节在公开资料里并不完整下面涉及目录结构、CLI 参数的部分是我基于这类工具链的常见实践做的合理还原你在实际使用时以仓库 README 为准。但设计思路和踩坑经验是通用的换个同类工具也成立。2. 技能不是提示词拆解 agent-skills 的核心抽象2.1 为什么提示词模板这条路走不通大多数人接触 AI coding agent 的第一步是攒一个prompts.md里面写着你是资深工程师请遵循以下规范……。刚开始挺好用用两周就崩了。崩的原因有三个而且都是结构性的不是靠把提示词写得更长能解决的。第一是上下文污染。你把十条规范塞进一个系统提示agent 在处理具体任务时十条规范会互相干扰。比如优先复用现有工具函数和保持函数职责单一这两条在某个具体场景下是冲突的agent 会随机选一条执行结果不可预测。第二是无法组合。写 React 组件和处理数据库迁移需要的技能完全不同但你只有一个大提示词只能全量加载。加载了无关技能等于给 agent 增加噪声。第三是不可版本化。提示词写在聊天里、写在文档里改了什么、谁改的、为什么改全都没有记录。团队协作时A 的提示词和 B 的提示词不一样产出质量自然参差。agent-skills这类方案的核心洞察就是把技能从提示词里解耦出来做成独立的、可寻址的、可组合的单元。一个技能只负责一件事需要时才加载加载时只带相关的上下文。2.2 一个技能单元应该包含哪些字段我见过的比较成熟的技能定义通常包含这么几个部分。你可以把它理解成给 agent 看的一份岗位说明书。字段作用是否必需name技能唯一标识CLI 调用时用必需description一句话说明这个技能干什么、什么时候用必需when_to_use触发条件帮 agent 判断该不该加载强烈建议instructions具体执行步骤是技能的主体必需examples输入输出示例降低歧义建议constraints禁止事项、边界条件建议references关联的文件、文档、其他技能可选这里最关键的是when_to_use和description的分工。很多人会把两者写成一回事其实不然。description是给人看的说明技能是什么when_to_use是给 agent 看的说明在什么信号出现时应该激活它。比如一个写单元测试的技能description是为指定函数生成符合项目规范的单元测试而when_to_use是当用户要求补充测试、或修改了核心逻辑但测试未同步更新时。提示when_to_use写得越具体agent 误触发和漏触发的概率越低。避免写当需要时这种废话要写具体的触发信号。2.3 技能和 MCP、和普通工具调用的区别这里容易混淆。MCP 解决的是agent 能调用什么外部能力比如读文件、查数据库、调 API。技能解决的是agent 在调用这些能力时应该遵循什么流程和规范。两者是正交的。举个例子MCP 给了 agent 一把锤子技能告诉它钉钉子的时候先扶稳、再轻敲定位、最后用力。没有技能agent 拿着锤子可能直接砸墙。所以agent-skills和 MCP 不是竞争关系是配合关系。一个负责能做什么一个负责该怎么做。理解了这个分层你就能明白为什么单纯堆 MCP 工具效果有限——工具越多agent 越需要技能来约束什么时候用哪个、按什么顺序用。3. skills CLI 的目录约定与加载机制3.1 技能放在哪目录结构的设计逻辑skills CLI这类工具通常约定一个固定的技能根目录比如项目根下的.agent-skills/或者用户级的~/.agent-skills/。为什么要有项目级和用户级两层这跟.gitconfig和项目.git/config的关系是一样的用户级放通用技能比如写 commit message项目级放项目专属技能比如本项目数据库迁移规范。加载时项目级覆盖用户级同名技能。一个典型的目录长这样.agent-skills/ ├── manifest.json ├── tdd-workflow/ │ ├── SKILL.md │ ├── examples/ │ └── references/ ├── code-review/ │ └── SKILL.md └── db-migration/ ├── SKILL.md └── templates/manifest.json是索引记录有哪些技能、各自路径、版本。为什么要有索引而不是直接扫目录因为扫描目录在技能多的时候很慢而且无法表达技能之间的依赖关系。索引文件可以声明tdd-workflow依赖code-review加载时自动带上。3.2 技能是怎么被加载进上下文的这是很多人没搞明白的地方。技能不是一次性全部塞进系统提示而是按需注入。流程大致是agent 收到用户请求先看manifest.json里的技能列表和when_to_use摘要。判断哪些技能相关把相关的SKILL.md全文读进来。执行任务过程中如果发现需要其他技能再动态加载。这个机制的好处是上下文窗口利用率高。坏处是判断环节可能出错——agent 可能觉得某个技能不相关而没加载结果做出来的东西不符合规范。所以when_to_use的措辞非常关键宁可写得宽一点让它多加载也不要写得太窄导致漏加载。注意如果你的技能经常该触发没触发先检查when_to_use是不是太抽象。把它改成具体的动作描述比如从处理测试相关任务改成当新增或修改了函数、但对应测试文件未更新时。3.3 CLI 常用命令与参数skills CLI一般提供这么几类操作列出、查看、校验、安装、更新。下面是我常用的几个参数名以实际工具为准但语义是通用的。# 列出当前可用的所有技能含来源用户级/项目级 skills list # 查看某个技能的完整定义调试 when_to_use 时很有用 skills show tdd-workflow # 校验技能定义是否符合规范比如必填字段缺失、引用路径不存在 skills validate # 从远程仓库安装技能包 skills install skill-pack # 检查已安装技能是否有更新 skills update --checkskills validate这个命令我要单独强调。技能定义写错字段名、引用不存在的文件在运行时往往表现为技能静默失效——agent 不报错只是不按你的规范来。定期跑 validate 能提前发现这类问题。我建议把它加进 CI每次改技能定义都跑一遍。4. 用 TDD 场景验证技能体系是否真的有用4.1 为什么选 TDD 作为第一个落地场景热搜词里有test-driven-development这不是偶然。TDD 是检验技能体系的最佳试金石因为它流程固定、步骤明确、对顺序敏感。红-绿-重构三步顺序错了就不是 TDD。如果技能体系连 TDD 这种强流程场景都约束不住那它在更模糊的场景里更没戏。反过来如果 TDD 技能跑通了说明这套机制能有效传递流程性知识那推广到 code review、重构、迁移这些场景就有信心了。4.2 tdd-workflow 技能该怎么写一个能真正约束住 agent 的 TDD 技能不能只写请遵循 TDD。要写到 agent 无法偷懒的程度。我的写法是这样的--- name: tdd-workflow description: 按红-绿-重构循环实现功能每步都有明确的验证动作 when_to_use: 当用户要求实现新功能、修复 bug、或修改核心逻辑时 --- ## 执行步骤 1. 先写一个会失败的测试。测试必须能运行且失败原因是功能未实现 而不是语法错误或导入错误。 2. 运行测试确认它失败。把失败输出贴出来。 3. 写最小实现让测试通过。不要提前实现测试没覆盖的功能。 4. 运行测试确认通过。 5. 在测试通过的前提下重构重构后再次运行测试。 ## 约束 - 禁止先写实现再补测试。 - 每一步都必须实际运行测试命令不能假设它会通过。 - 如果测试无法运行先解决环境问题不要跳过。关键在于第 2 步和第 4 步——强制 agent 实际运行测试并展示输出。这是 TDD 技能和普通写测试提示词的分水岭。普通提示词说请写测试agent 写完就交差TDD 技能要求它跑、要求它贴输出agent 就没法糊弄。4.3 实测中 agent 会在哪里偷懒我拿这套技能跑了几十个任务总结出 agent 最容易偷懒的三个点以及对应的加固方法。偷懒点一测试写得能过但没意义。agent 会写expect(true).toBe(true)这种废话测试来满足第一步。加固方法是在技能里加一条测试必须断言具体的输入输出且断言值不能是硬编码的true。偷懒点二跳过失败验证。agent 写完测试直接写实现不跑那一次确认失败。加固方法是把运行并展示失败输出写成独立步骤并在约束里明确未展示失败输出视为未完成。偷懒点三重构步骤直接省略。测试通过后 agent 就收工了。加固方法是在技能里定义完成标准必须包含一次重构动作哪怕只是重命名变量。提示加固技能的过程本质上是把你希望 agent 遵守但没说清楚的隐性要求显性化。每发现一次偷懒就往技能里加一条约束技能会越来越硬。4.4 技能组合TDD 加 code-review 的联动单个技能有用但技能体系的威力在组合。比如tdd-workflow完成后自动触发code-review技能对新增代码做检查。这需要在manifest.json里声明依赖{ skills: [ { name: tdd-workflow, path: tdd-workflow/SKILL.md, triggers: [code-review] } ] }triggers字段的意思是这个技能执行完后建议加载code-review。注意是建议不是强制因为有些小改动不需要完整 review。这种软联动比硬编码流程灵活也更符合实际开发节奏。5. 把技能接进 Claude Code 的实际操作与坑5.1 环境准备阶段最容易忽略的事Claude Code 这类工具在不同系统上的安装方式不一样macOS、Ubuntu、Windows 各有各的路径。但比安装更容易出问题的是技能目录的权限和路径解析。我遇到过好几次技能明明在agent 就是读不到排查下来都是路径问题。常见原因有两个一是技能目录用了相对路径但 agent 的工作目录和你想的不一样二是目录权限不对agent 进程没有读权限。前者用绝对路径能解决后者检查一下目录的rwx权限。# 确认技能目录存在且可读 ls -la ~/.agent-skills/ # 确认 manifest 能被解析 cat ~/.agent-skills/manifest.json | python -m json.tool第二个命令很实用。manifest.json里多一个逗号、少一个引号整个技能体系就静默失效。用python -m json.tool过一遍语法错误立刻暴露。5.2 技能加载顺序与优先级冲突当用户级和项目级有同名技能时谁覆盖谁大多数工具是项目级优先。但这里有个坑如果你在项目级写了一个不完整的技能它会完全覆盖用户级的完整版本而不是合并。结果就是你以为继承了用户级的约束实际上全丢了。我的做法是项目级技能要么不写要写就写完整。如果只是想微调用户级技能的一两条约束用extends字段显式声明继承而不是复制一份改。--- name: tdd-workflow extends: user:tdd-workflow overrides: - 本项目测试框架为 vitest命令为 npx vitest run ---这样只覆盖测试命令其他约束从用户级继承。清晰也不会因为用户级更新而失同步。5.3 让 agent 真正执行终端命令的配置要点热搜词里有claude code 如何直接执行终端命令这确实是技能落地的关键。技能里写了运行测试但 agent 如果没有执行终端命令的权限它就只能假装运行。配置上要确保 agent 有执行权限同时又要控制风险。我的建议是白名单 确认机制。允许 agent 自动执行测试、lint、构建这类安全命令但涉及删除、部署、改配置的命令需要人工确认。这个边界要在工具配置里设不能只靠技能里的文字约束——文字约束 agent 可能忽略配置约束是硬的。注意不要为了图省事给 agent 开全量终端权限。技能体系的价值之一是可控权限放开等于把可控性丢了。白名单维护成本不高但能避免很多意外。5.4 技能版本升级时的兼容性处理技能是要迭代的。今天加一条约束明天改一个步骤。问题是改了技能之后之前用旧技能产出的代码怎么办如果新技能引入了新的规范旧代码就不符合了。我的处理方式是给技能加版本号并在manifest.json里记录。当技能有破坏性变更时升主版本号并在技能里写一段迁移说明告诉 agent 遇到旧代码时该怎么处理。这样 agent 在 review 旧代码时能识别出这是 v1 规范写的需要按 v2 迁移。{ name: tdd-workflow, version: 2.0.0, changelog: v2 要求测试文件与实现文件同目录v1 是分离的 }版本管理这件事技能少的时候觉得多余技能一多就是救命稻草。我吃过亏——改了技能没记版本两个月后完全想不起来为什么某个约束是那样写的。6. 技能体系跑起来之后我踩过的那些坑6.1 技能写太细反而降低 agent 表现这是我最早踩的坑。一开始我觉得技能越详细越好把一个写 React 组件的技能写了两千字从命名规范到 hooks 使用到样式方案全塞进去。结果 agent 表现反而变差——它被太多细节淹没抓不住重点。后来我明白了技能是给 agent 的决策依据不是操作手册。操作手册适合人因为人会跳读agent 是逐字处理的信息过载会让它注意力分散。一个技能控制在 300 到 500 字只保留必须遵守的约束和关键步骤细节放到references/里按需引用。6.2 技能之间的隐性依赖导致加载失败技能 A 的步骤里提到按技能 B 的规范命名但 manifest 里没声明 A 依赖 B。单独跑 A 的时候agent 找不到 B就自己编了一套命名规范。这种问题很隐蔽因为 agent 不报错只是产出不符合预期。解决办法是在技能里显式声明依赖并且用skills validate检查依赖是否都能解析。我现在写技能只要提到另一个技能的名字就一定在 manifest 里加依赖声明。宁可多声明不要漏声明。6.3 团队协作时技能冲突的排查链路团队里每个人都在改技能冲突是必然的。我遇到过一次典型冲突A 在项目级技能里要求所有函数必须有 JSDocB 在用户级技能里要求保持代码简洁避免冗余注释。两个技能同时加载agent 无所适从。排查这类问题的链路是这样的先跑skills list看当前加载了哪些技能确认冲突双方都在。跑skills show name看每个技能的完整定义找到冲突的具体条款。判断哪个技能优先级更高项目级 用户级但优先级高不代表就该赢——要看条款是否真的矛盾。如果是真矛盾改技能措辞把必须有 JSDoc改成导出的公共函数必须有 JSDoc把避免冗余注释改成避免解释是什么的注释保留解释为什么的注释。矛盾就化解了。这个链路的关键是不要急着删技能先看措辞能不能调和。大部分所谓的技能冲突其实是措辞不够精确导致的假冲突。6.4 技能失效的静默性最难查的一类问题最让人头疼的不是技能报错而是技能看起来加载了但没生效。agent 不报错产出就是不符合规范。这类问题的排查思路是逐层验证排查层验证方法常见问题文件层文件存在、可读、格式正确路径错、权限错、JSON 语法错索引层manifest 里能查到该技能忘记注册、name 拼写不一致加载层agent 日志里能看到技能被读取when_to_use 太窄没触发执行层agent 产出符合技能约束约束写得太模糊agent 自由发挥我一般从执行层倒着查。先确认约束是不是写清楚了再确认技能有没有被加载最后才怀疑文件本身。因为实践中问题大多出在前两层——约束模糊或没触发而不是文件坏了。7. 关于技能体系我现在的几个真实判断用了大半年agent-skills这套思路我对它的定位越来越清晰它不是让 agent 变聪明的工具是让 agent 变稳定的工具。模型能力是 agent 的上限技能体系是 agent 的下限。你没法靠技能让 agent 写出它能力之外的代码但你可以靠技能保证它每次都不低于某个水准。所以我对要不要上技能体系的判断标准很简单如果你对 agent 产出的稳定性有要求就上如果只是偶尔用用、产出好坏无所谓那手写提示词就够了。技能体系有维护成本技能要写、要校验、要版本管理这些成本只有在高频使用 质量要求的场景下才划算。另外一个体会是技能体系的价值会随团队规模放大。一个人用技能就是自己的备忘录三个人用技能就是协作规范十个人用技能就是团队的知识资产。它把老员工脑子里的经验变成了新人和 agent 都能读的文档这个转化本身就是价值。最后分享一个我最近在试的扩展方向让 agent 根据实际执行结果反向优化技能。比如某个技能约束经常被 agent 绕过说明这条约束要么不合理、要么措辞有问题可以让 agent 在执行后给出这条约束为什么难遵守的反馈人来决定怎么改。这个闭环还在摸索但方向我觉得是对的——技能体系不该是静态的它应该随着使用不断进化。