如果你和我一样,桌面上同时躺着好几个AI编程工具——Claude Code、Codex CLI、Cursor,再装上一个带了Continue插件的VS Code——那你大概率经历过一种说不出的别扭:每个工具都支持Agent技能,但技能的写法、目录约定、加载方式全都不一样。遇到同一个任务,我得在每个工具里重新调教一遍。这种重复劳动攒到某个临界点,就会冒出同一个念头:能不能有一个统一的地方,把这一堆Agent技能管起来?
这个念头落地之后,就是我在维护的项目:Skills Manager。简单来说,它是一个跨平台的桌面中枢,负责统一管理54+ AI编程工具的Agent技能——把散落在各个工具里的提示词、脚本、工作流收拢成标准化技能包,再自动分发回你日常使用的那些工具。这篇文章不打算讲标准教程,我想把当时怎么踩坑、怎么设计、怎么让它真正用起来的过程写清楚,尤其面向那些和我一样在多个Agent工具之间来回切换的开发者。如果你正被"每个工具一套技能语法"这件事折磨,这篇应该能给你一个可以落地的思路。
1. 从散装技能到统一中枢:我在为多套Agent重复写提示词
1.1 桌面上至少有四个Agent,我却只能各写各的
先说日常状态。我主力使用的AI编程工具有四个:Claude Code负责写核心模块,Codex CLI做批量代码审查,Cursor处理日常重构,VS Code里的Continue辅助写测试。听起来很合理,对吧?实际用起来会发现一个绕不开的问题:这四兄弟对"技能"的定义完全是各说各话。
Claude Code用的是.skills目录,里面放SKILL.md文件,靠自然语言描述让Agent理解技能;Codex CLI那一套更偏向用AGENTS.md这种指令文件约束行为;Cursor走的是.rules规则文件,把技能写成项目级的规则片段;Continue则有自己的一套commands命令体系。同一个"检查未处理的异常"技能,在这四个工具里是四份完全不同的文本。我最初还能靠记忆力同步,等到技能数量突破20个,就彻底失控了。
失控的第一个信号是:我改了Claude Code版本的技能,结果忘了Codex CLI那份还停在旧逻辑。第二天用Codex做代码审查,它按老规矩跳过了一个已经被我列入黑名单的错误码,害我多花了半小时手工排查。那一刻我突然意识到,问题不在于我懒,也不在于某款工具做得不好,而在于我把"技能"当成了某个工具的自留地,而不是属于自己的资产。
1.2 重复劳动的代价不是时间,是维护意愿
这里我想说一个容易被忽略的点:重复维护带来的最大损失,其实是维护意愿的持续下降。
技能少的时候,五份就五份,忍一忍还能同步。技能一多,每份之间的细小差异会让你产生"算了,不折腾了"的心态。一旦这种心态出现,技能就开始失效——不是程序崩溃那种失效,而是它慢慢跟不上你真实的工作方式。你明知道某个技能写得不够好,但一想到要在四个工具里各改一遍,就会拖到下周。拖到下周的结果往往是下周也不改,最后这个技能就躺在那里吃灰。
我尝试过几个"缓解方案":用Notion整理一份技能笔记;把提示词模板统一存到一个Markdown文件里;甚至试过用Git子模块去同步不同工具的配置目录。效果都有,但治标不治本。笔记不等于可执行文件,模板文件没法被工具自动加载,Git子模块解决的是版本同步,解决不了格式翻译。我需要的是一个中间层——它既能用一套格式描述技能,又能把手里的技能翻译成每个工具认识的方言。
1.3 统一之后的工作流长什么样
受够了手工同步之后,我给自己定了一个目标工作流:用一个编辑器写技能,一次描述让全局可见,所有工具自动拉取最新版本,任何修改一处生效。听起来很理想化,但实现路径是清晰的。
在这个工作流里,我不再对着Claude Code写Claude Code版技能、对着Cursor写Cursor版技能,而是先写一个中性的技能包,再由Skills Manager在需要时分发给具体工具。正确用法是:你先定义技能本身,然后告诉中枢"这个技能要支持哪些工具",剩下的事交给适配层。对比一下前后的差别:以前是1个技能对应N份配置,现在是1个技能包加N个适配器。后者多了一点点前期设计成本,但长期维护成本直线下降——这个账怎么算都划算。
2. 技能仓库不等于收藏夹:桌面中枢的核心设计逻辑
2.1 技能包的中性格式:换工具不换技能
真要动手做统一,第一个要解决的问题是:用什么格式来描述一个技能?
市面上已经有一些参考,比如Anthropic提到的Agent Skills概念,社区里也有不少关于"skill教程"的讨论。但我的需求更具体:这个格式必须足够中性,不能被任何单一工具绑架。如果我把格式定成Claude Code的SKILL.md变体,那Codex CLI适配起来就会很别扭;如果定成Cursor的rules风格,那通用性又会受限制。
最终我采用了"技能包"的概念,每个技能是一个独立目录,包含三部分:描述文件、参考脚本、引用资源。描述文件负责告诉Agent"这个技能是什么、什么时候用、怎么用",参考脚本负责把模糊需求变成可执行逻辑,引用资源则放清单、模板、示例这类辅助材料。这个结构与大多数工具的加载机制天然兼容,因为所有工具最终都是靠文本与Agent交互——你只要能让技能在恰当的时候以一种它看得懂的方式出现在上下文里,它就能工作。
这个设计思路可以类比成统一充电口:以前每个手机厂商都有自己的充电标准,换个设备就要换根线。技能包就是那个Type-C口,适配器解决的是协议转换,而不是重新发明充电器。
2.2 匹配与分发:为什么需要一个适配层
有了统一的技能包格式,紧接着的问题是:一个技能要怎么落到具体工具里?
这里就是Skills Manager的核心了,我管它叫适配层。适配层要处理三件事:第一,识别你当前在哪个工具语境下;第二,把中性技能包翻译成那个工具能理解的格式;第三,把翻译结果挂到正确的加载位置。整个过程看起来像是"技能分发",实际上更像一个格式编译的过程。
不同工具的适配逻辑差别确实很大,我整理了一张表,基本能反映当时的适配情况:
| 工具类型 | 代表工具 | 技能挂载方式 | 适配重点 |
|---|---|---|---|
| CLI编码代理 | Claude Code / Codex CLI | 目录扫描 / 指令文件 | SKILL.md语法、指令覆盖范围 |
| IDE智能插件 | Cursor / Continue | rules文件 / commands配置 | 规则优先级、项目级vs全局级 |
| 原生Agent工具 | Codex、各类Agent平台 | 平台自带技能格式 | 参数传递方式、上下文截断策略 |
| 通用Agent框架 | LangChain / ADK等 | 工具函数注册 | 把技能转为可调用函数描述 |
这个表格看起来简单,每一条背后都有不少细节。就拿IDE插件来说,Cursor的rules文件和Claude Code的SKILL.md在描述方式上是两套语境,你在技能包里写的when_to_use字段,落到Cursor里可能要转成globs匹配规则。适配层要做的不是简单把文本粘贴过去,而是理解两边语义后做一次"翻译"。这也是为什么我不建议直接把某个工具的技能目录复制到另一个工具。
2.3 它不是什么:既不是收藏夹,也不是文档库
做这个项目的时候,我经常被问到:"这不就是一个技能收藏夹吗?"还真不是。
收藏夹解决的是"东西放在哪"的问题,文档库解决的是"东西是什么"的问题,而Skills Manager解决的是"东西怎么跑起来"的问题。你在收藏夹里存一篇Claude Code的技能教程,下次换到Cursor还是不知道怎么写;你在文档库里整理一套完整的技能说明,Agent并不会自动读到它。Skill不是知识条目,它是"代码+说明+参数"三位一体的可执行单元。
打个比方:收藏夹像一个书架,你需要的书都在上面,但每本书都得自己翻开看;Skills Manager像一个训练有素的助手,你告诉它"按食材清单做饭",它自己就知道先去翻菜谱、再检查冰箱里有什么、最后按步骤执行。所以从第一天起,这个项目的边界就定得很清楚:技能仓库只对可执行的东西负责,那些"仅供参考"的知识资料不进来。
3. 全平台的地基:本地数据、CLI与GUI的分工
3.1 数据存哪:本地优先的取舍
一站式技能管理工具最容易踩的坑,就是一上来就搞云端账号体系。我见过不少类似项目,上来就是"注册、登录、云同步"三件套。但我们的目标用户是天天跟终端打交道的人,他们对本地文件有天然的信任感,对云同步反而充满了不确定性。
我最终选择了本地优先的方案。技能数据保存在本机的~/.skills-manager/目录下,元数据用一个SQLite单文件存储,技能包本身则是普通目录和Markdown文件。这样做的理由很实:离线可用、响应快、隐私可控、迁移方便——搬家就是拷一个目录的事。同步怎么办?我没有自己做云同步,而是把这个能力开放给现有的工具链,你可以直接用Git仓库同步技能包,也可以用一个NAS文件夹定时镜像。本地优先不代表拒绝云,而是让云变成一个可插拔的可选层。
目录结构很简单,一眼能看懂:
~/.skills-manager/ db/ # SQLite元数据库 skills/ # 技能包目录 code-review/ # 自动导入审查技能 semantic-commit/ # 语义化提交信息技能 dependency-check/ # 依赖更新检查技能 templates/ # 公开的技能模板 logs/ # 执行与审计日志SQLite在这个场景里其实比很多重型数据库都合适。单文件、跨平台、支持全文检索,对技能元数据这种量级的数据来说绰绰有余。后期如果技能数量涨到几百个,SQLite依然能撑住,而且你随时可以把数据导出成JSON、CSV,或者直接同步到远程Postgres——它是一个面向未来的起点。
3.2 CLI做核心,GUI做外壳
跨平台桌面应用,很多人第一反应就是必须有个漂亮GUI。但实际上,对Agent技能管理这个场景来说,命令行才是真正的核心。为什么?因为技能管理天然要跟自动化结合:CI流程里要批量更新技能,新机器初始化要一键恢复技能环境,这些场景都需要能被脚本调用的接口。
所以我把Skills Manager设计成"CLI为核心,GUI为外壳"的结构。核心命令基本就这几条:sm list查看所有技能,sm add添加技能包,sm run手动在某个工具里执行技能,sm link把技能关联到指定工具,sm sync从Git仓库拉取最新技能。GUI其实是包了一个Tauri壳,把命令行的输出可视化,方便不熟命令行的队友查看技能状态和审核日志。
我刻意让GUI做得"薄",不承载太多业务逻辑。这是个反直觉的取舍,因为很多桌面应用都在努力让GUI变厚。我的理由是:GUI一旦承担核心逻辑,就意味着所有功能都得等UI完成才能用,而且自动化场景会被锁死。CLI先跑通,GUI只做展示,开发效率和灵活性都最高。
3.3 安全边界:脚本执行前的授权控制
本地优先还有一个绕不开的问题:安全。技能本质上是可以在你机器上执行的脚本,如果不做权限控制,等于把家门钥匙交给了任意提示词。这个风险必须正面处理。
我的做法是给每个技能包声明权限级别:只读、受限读写、完全执行。只读技能只能访问指定目录里的文件,受限读写技能可以修改项目文件但不能触碰系统目录,完全执行技能则不做限制,但必须经过手动确认。所有执行动作都写入审计日志,记录谁在什么时间用了哪个技能、访问了哪些路径。实际使用时,默认所有技能都是只读或受限读写,"完全执行"这个权限落地时会让用户再做一次二次确认。
刚开始有人嫌这个流程烦,但后来一次事故让所有人都闭嘴了:团队里有人写了一个"自动修复依赖冲突"的技能包,权限声明的是完全执行,结果在未确认状态下直接跑了,把环境变量文件改乱了。从那以后,没有人再说权限确认是多此一举。本地工具的灵活性是一把双刃剑,安全边界永远值得前置。
4. 让Agent真正听懂技能:SKILL.md规范与加载机制
4.1 SKILL.md的字段设计
如果只把技能包做成"脚本合集",那和普通工具库没区别。真正让Agent把技能用起来的,是那份SKILL.md描述文件。它的作用不是给人看的README,而是Agent在运行时理解技能的关键上下文。
每个SKILL.md我强制要求六个字段:name是技能的唯一标识,description说明技能的大致用途,when_to_use是本技能的最佳触发时机,params列出需要的输入参数,steps是给Agent的分步执行动作,resources指向脚本和引用文件。六个字段里最容易被忽略、但实际最影响效果的是when_to_use。因为它直接决定了Agent在多技能混用场景下的选择准确率——你可以在描述里写"这个技能只用于处理单元测试覆盖率问题",但如果没写清楚,模型很可能在代码审查任务里也把这个技能拉出来用。
结构上我参考了社区里关于Agent Skill的不少经验帖,但做了一点本地化改良:增加了一个context字段,用来声明该技能对工作目录、项目语言、文件类型的默认假设。这个小字段在后面处理跨工具分发时帮了大忙,因为每个工具对上下文的感知能力不一样,有的工具本身就带着项目全貌,有的工具只能看到当前文件,context字段让适配层能提前判断分发策略。
4.2 一个可直接抄作业的技能包示例
空谈规范太抽象,直接给一个我日常在用的技能包做例子:语义化提交信息生成。这个技能的作用是扫描当前改动,生成符合Conventional Commits规范的提交信息。目录结构长这样:
~/.skills-manager/skills/semantic-commit/ SKILL.md scripts/scan_diff.py references/commit_rules.mdSKILL.md核心内容示例:
--- name: semantic-commit description: 生成遵循约定式提交规范的git commit信息 when_to_use: 在用户准备执行git commit之前,需要生成提交信息时使用 params: target: 要扫描的目录,默认当前项目根目录 steps: - 运行 scripts/scan_diff.py --path {target} - 读取 scan_diff.py 输出的改动摘要 - 参考 references/commit_rules.md 中的提交类型表 - 输出一条符合规范的完整commit信息 resources: - scripts/scan_diff.py - references/commit_rules.md version: 1.2.0我希望读者注意几点:when_to_use写的是"提交信息生成"而不是"代码变更分析",因为一旦这个技能被选中,后面几个步骤全部围绕提交信息展开;params只有一个target字段,避免给模型太多选择空间;resources里的两份文件都是必要的,一个负责执行,一个负责兜底。这个技能包分发到Claude Code里会被扫描进.skills目录,分发到Cursor里会转成rules,但核心动作没有变。
4.3 参数传入与上下文记忆
技能包光有脚本还不够,Agent能不能正确拿到运行参数,直接影响技能的成功率。我一开始把参数写死在SKILL.md里,效果很差,因为不同项目的路径结构、语言环境差异太大。后来改为参数化设计,每个技能都声明自己需要哪些参数,并在执行时把参数嵌入上下文中。参数化本身不复杂,复杂的是让Agent知道参数该从哪来。
这就涉及到Agent记忆的话题了。技能不是每次执行都是"失忆"状态,它会读工作目录里的项目结构,会自动提取一些显式参数,还会通过本地记忆文件记住上次相关任务的处理偏好。比如"semantic-commit"这个技能,首次执行时用户指定了type粒度要用中文注释,这个偏好会被写回记忆,下次执行时Agent会主动参考。
这个机制让我对"技能"的理解往前走了一步:技能不只是描述文件和脚本的堆叠,它还需要一个轻量的上下文状态。Agent在执行技能前会先做一次状态查询,执行完再更新状态。这个状态数据就存在本地SQLite里,不依赖任何外部服务,效果却非常明显——同一技能的第二、三、四轮执行,准确率有明显提升。
5. 实测:在Windows主机上调度54+工具的踩坑记录
5.1 哪些类型的技能复用率最高
项目跑了一段时间后,我统计了所有技能在54+工具上的实际调用频率,结果有些出乎意料。最容易复用的技能不是那些"AI味"很浓的魔法操作,而是四个实用主义类型:
| 技能类型 | 代表场景 | 复用率 | 原因分析 |
|---|---|---|---|
| 代码检查类 | 未处理异常扫描、死代码检测 | 很高 | 任务边界清晰,脚本能处理大部分逻辑 |
| 依赖管理类 | 依赖版本冲突分析、更新建议 | 高 | 规则明确,模型只需读清单做判断 |
| 测试补全类 | 为函数生成测试用例 | 高 | 输入输出明确,参数简单 |
| 提交辅助类 | 生成提交信息、整理变更记录 | 高 | 动作单一,技能说明短但有效 |
观察这些高复用技能,会发现一个共同特征:它们都把一个模糊需求压缩成了明确步骤。比如"扫描未处理异常",模型不用思考"什么叫未处理、什么叫异常",脚本已经把答案按行输出来了,模型只需要解释和汇总。这其实给技能设计提了一个通用原则:尽可能把确定性逻辑下沉到脚本里,让模型只做决策性工作。
5.2 适配各工具时的实际差异
理想很丰满,真实环境里的适配远比预想中碎。在Windows主机上做全量适配时,我撞上了几个真实存在的坑。
第一个坑是路径分隔符。Windows用反斜杠\,脚本输出的路径如果是POSIX风格,某些工具解析时会直接断掉。排查半天发现是技能里的正则表达式没考虑Windows盘符前缀——C:\src\project会被正则当成C:加一个反斜杠分隔符的组合。修复方法很简单:所有路径处理统一走pathlib,禁止手写字符串拼接路径。
第二个坑是编码。Agent运行时经常要读日志文件,但我有一个技能在解析前端构建日志时反复失败,原因是那份日志是日文Shift-JIS编码,脚本按UTF-8去读,全变乱码了。更麻烦的是,当时用的模型并不会主动告诉你编码不对,它只会基于乱码内容给出错误结论。后来我给所有文件读取逻辑加了编码探测层,遇到非UTF-8文件自动转码,这个问题才算根治。
第三个坑是执行超时。某些工具对子进程的运行时长有隐性限制,长一点的脚本会被直接杀掉,而错误信息往往是一个很模糊的"execution terminated due to error"。后来我养成一个习惯:所有技能脚本都做分块执行,每块输出阶段性结果,这样即使超时,也已经拿到了有价值的中间状态。
5.3 误选、失效与技能漂移
比适配更折磨人的,是Agent会"误选"技能。技能库越来越大之后,模型经常在错误的任务里调用错误的技能。我遇到过最离谱的一次:用户明明在做代码重构,Agent却调用了依赖版本检测技能,给出的建议完全牛头不对马嘴。问题的根因出在技能描述太泛,when_to_use写得不够精准。
另外两个高频问题就是技能失效和技能漂移。技能失效往往是因为外部API变化——比如某个依赖工具的CLI版本升级,参数变了,旧脚本直接报废。技能漂移则更隐蔽:技能的作者修了一个边缘问题,顺手改了脚本逻辑,但没更新SKILL.md的描述,于是技能的行为和Agent对它的理解出现了偏差。
这三样问题我最终的解决方案是流程化的:每次技能更新必须同时更新SKILL.md里的版本号和变更说明;每季度做一次全量回归执行,把技能库里所有技能在重点工具上跑一遍;对误选问题,除了加强描述约束,还会在技能之间加"互斥声明"——比如"提交信息生成"和"代码审查"不能同时出现在一次任务里。这套流程跑起来之后,误选率降了一大截。
6. 把技能变成团队资产:共享、评审与版本管理
6.1 技能共享:从个人文件夹到团队仓库
自己用得顺之后,自然想着把它推广到团队。个人技能库和团队技能库之间最大的差异,不是内容,而是质量门槛。个人可以容忍一个粗糙的技能包,团队不行。一个技能万一在关键任务里给错了参数,影响的是整个交付节奏。
我们团队的做法是搞一个共享技能仓库,走PR流程:有人新写一个技能,先提PR,附上样例输出和测试记录,评审人按一份Checklist逐项打分——名字是否清晰、描述是否准确、触发条件是否够窄、示例是否完整、有没有覆盖边界情况。这套流程不是摆设,一开始有人嫌麻烦,但连续几次因为技能质量差导致线上问题之后,大家都默认了规则。现在团队里两百多个技能,质量比最开始下降得慢很多。
6.2 多Agent协作下的技能编排
技能库有了规模之后,另一个价值才真正浮现出来:多Agent协作。现在的AI编程工具早就不是单打独斗了,日常任务往往要多个Agent角色配合。某些技能属于"规划类"Agent,负责拆解任务、生成实现步骤;另一些技能属于"执行类"Agent,负责写代码、跑测试、改文件。
Skills Manager在其中扮演的是路由层的角色:它知道哪个Agent擅长什么,也知道哪个技能适合哪个Agent。任务进来之后,中枢会做一个初步意图识别,把任务拆成若干子步骤,每个子步骤挂对应的技能和Agent。这时候单个技能包就不再是孤立的资产,而是整个多Agent工作流里的一个齿轮。
说实话,这个方向目前还在演进中,但已经能看到明显的优势:单个Agent不需要内置全部能力,AI Agent中台化之后,每个Agent保持小巧、专注,复杂度靠技能编排去承接。这个架构对团队新人也友好,上手时只需要读对应技能的SKILL.md,而不用先啃整个Agent框架的源码。
6.3 沿着这条路线继续改造,我的下一步
项目走到现在,最初的"统一管理技能"目标已经完成了大半,真正的价值反而沉淀在别处:一套统一的技能心智模型。以前团队成员对"技能"的理解千差万别,有人理解成提示词模板,有人理解成脚本工具,现在大家有了共同语言——技能就是"描述+脚本+资源"的包,有版本、有权限、有触发条件。
下一步我想在这个底子上加两个东西。第一个是技能生成器:让Agent根据一个实际任务描述,自动反写出完整的技能包结构。说白了,就是把"把经验固化成技能"这件需要动脑子的事,用模型辅助做掉一半。第二个是技能健康度仪表盘:通过记录每个技能的执行成功率、误选率、更新频率,给每个技能一个健康分,低分的自动进入待评审队列。我更希望让技能库像开源项目一样持续演化,而不是建好之后就变成一堆僵尸文件。
最后交代一句心里话:这个项目算不上什么惊世骇俗的发明,它解决的就是一个日常到不能再日常的痛点——我有N个AI编程工具,而我实在受不了给它们各写一套技能。如果你也有同感,建议别急着再去找第N+1个工具,先把已有技能统一起来,你会有一种"终于不用做重复劳动"的踏实感。