前阵子我整理电脑里的开发目录,发现自己不知不觉装了七八个AI编程工具。Cursor、Claude Code、Windsurf、GitHub Copilot、Codex CLI……每个工具都很强,但它们的Agent技能体系完全是各说各话。Claude Code的技能放在.claude/skills目录下,用SKILL.md加YAML front matter定义元数据;Cursor靠.rules文件和自定义指令;Windsurf用的是Workflow加Agent Rules;Copilot的custom instructions又是另一套写法。技能本身明明是一种东西——就是你沉淀下来那套“怎么让AI准确干活”的能力,结果却被拆成了四五种方言,散落在各自配置目录的角落里,想复用只能靠复制粘贴,想同步只能靠手动维护,时间一长必然出现“A工具改了三版、B工具还是旧版”的窘境。
Skills Manager这个跨平台桌面中枢项目,核心目标就是把散落在54+个AI编程工具里的Agent技能收拢到一个统一的管理层里,解决“技能标准化、版本管理、跨工具分发、一键迁移”这一整条链路的问题。它更像是一个连接层:上面是你积累的最佳实践,下面是对各个工具技能格式的适配和渲染,中间用一套统一的元数据标准来承载。这篇文章我会把这套系统从抽象层字段设计、桌面端选型、配方适配机制到同步与回滚的完整实现思路都摊开讲,还会附上我在迁移真实技能时踩过的坑。如果你也在多款AI编程工具之间来回切换,或者想给团队搭一套可沉淀、可复用的Agent技能库,这篇文章应该能给你提供一套可以直接参照的落地方案。
1. 当AI Agent技能变成“数字碎片”:我为什么动手做这个中枢
1.1 每个工具都在定义自己的“技能方言”
我在早期其实走过弯路:曾经试图在所有工具里统一用一套规则去写技能,结果发现根本做不到。因为“技能”这个概念在不同工具里的落地形态差距很大,不是简单的文件后缀不同,而是元数据结构、触发机制、上下文注入方式都完全不一样。我把几个主流工具的技能载体做了个粗略对照:
| 工具 | 技能载体 | 元数据格式 | 存放位置 | 触发方式 |
|---|---|---|---|---|
| Claude Code | SKILL.md 目录 | YAML front matter | .claude/skills/ | 子agent按描述自动匹配 |
| Cursor | .rules/ 自定义指令 | 纯文本 + glob规则 | 项目根目录 | 会话开始时注入上下文 |
| Windsurf | Workflow | 自带编辑器内格式 | .windsurf/ | 手动执行 / 规则触发 |
| GitHub Copilot | custom instructions | Markdown/text | 仓库级或全局配置 | 自动注入提示词 |
| Codex CLI | AGENTS.md 指南 | Markdown | 项目文档目录 | 全局上下文读取 |
注意看最后一列,触发方式的不同直接决定了技能内容的写法。Claude Code把技能当成一个“可以被Agent按需拉取的知识模块”,所以要求有明确的描述字段和边界;Cursor的规则是被动注入,技能写得再漂亮,如果开头没有匹配到当前任务就毫无作用;Copilot则更像系统提示词,强调的是指令优先级和上下文约束。这就导致一个问题:一个在Claude Code里运行得很好的技能,直接复制到Cursor里很可能变得既冗长又失效。
我刚开始做技能管理脚本时,用的办法是“每种工具建一个文件夹,里面放对应格式的副本”。这个方案在工具数量少的时候还能凑合,工具一多就彻底失控了。你改了主版本,得手动同步到十几个副本;你想查某个技能在哪些工具里被使用,要一个个目录去翻;最痛苦的是版本回滚,基本只能靠后悔药式的CTRL+Z。构建一个统一中枢的需求,就是这么被逼出来的。
1.2 中枢要管的不是模型,而是“人与工具的连接层”
很多朋友看到“统一管理Agent技能”这几个字,第一反应是“这不就是搞个Prompt仓库吗”。这是最大的误解。一个AI编程工具的Agent技能,承载的信息远不止一段提示词。一份完整的技能通常包含这几个部分:技能的目标描述(什么时候该用)、详细的操作步骤(怎么一步步执行)、约束条件和注意事项(什么不能做)、以及可能附带的小脚本、代码模板、参考文档。这些内容加起来,本质上是一个“可执行的规程文档”,Prompt只是它的表达形式之一。
所以Skills Manager真正管理的是“人和工具之间的经验沉淀层”。这个层的特点是:它跟具体的模型无关(GPT-4、Claude、Gemini都可以用同一套思路),但跟工具的文件格式强相关(Cursor只认自己的规则文件,Claude Code只认自己的SKILL.md)。既然如此,就必须要有一个独立于任何工具的中间表示层来做标准化存储,再通过适配器把标准内容渲染成各工具需要的格式。这个思路其实很像前端领域的“一次编写,到处编译”,只不过编译的目标不是浏览器,而是各种AI工具的技能目录。
2. 技能统一抽象层:把54种格式翻译成一种“普通话”
2.1 一套中间表示(IR)的字段设计
如果要做统一管理,第一件事就是定义中间表示层(Intermediate Representation,以下简称IR)。在设计IR字段时,我的核心原则是:既要保留各工具技能格式的共性,又要能无损容纳它们各自独特的元数据。
我最终采用的IR结构以Markdown为正文载体,用YAML front matter承载结构化元数据。一个标准的技能包大致长这样:
--- name: code-review-checklist description: 对PR进行系统性代码审查,涵盖安全、性能、可读性、兼容性四个维度 version: 2.3.1 tags: [code-review, pr, security] author: dev-team updated: 2025-06-10 applies_to: - claude-code - cursor - windsurf - copilot triggers: - review pr - 代码审查 - pull request constraints: - 不得自动修改代码,只输出审查意见 - 每次审查必须输出阻塞项和优化项两份清单 assets: - scripts/check_security.py - templates/review_report.md --- 正文内容:技能的详细步骤、检查项、输出格式说明。这个设计里有几个字段是我在实际使用中反复调整过的。triggers字段非常重要,因为Claude Code这类工具会拿描述和触发词做语义匹配,而Cursor这类工具更多看路径规则和第一句话的匹配。如果你的技能要在多工具间流转,必须在IR里显式声明触发场景,否则迁移过去之后Agent根本不知道什么时候该用这个技能。constraints字段也是刚需,各工具里最容易翻车的地方就是“AI自由发挥”,写清楚约束能显著降低误操作概率。applies_to字段则是用来做分发过滤的,我不希望某个只有Claude Code能正确执行的技能被分发到其他工具里造成污染。
为什么不用任何一种工具的原生格式直接当标准?我也试过。Claude Code的SKILL.md格式相当成熟,YAML front matter + Markdown正文的结构已经很接近IR了。但问题是,一旦把某种工具的格式定为标准,其他工具的适配逻辑就容易出现“迁就”心态,比如Cursor没有描述字段,就干脆不写描述,最后技能的含义全靠文件名猜。IR必须是一套“中立格式”,不偏向任何单一工具,才能保证从IR到目标格式的渲染是可靠的。
2.2 目录规范:为什么技能必须是“目录+Markdown+清单”三段式
第二种早期方案是把每个技能塞成单个Markdown文件。这个方案在Cueball数量少的时候很清爽,但遇到带脚本、带模板的技能就崩了——你没法在一个文件里既写步骤说明又附带一个Python脚本和一个引用模板。经过几轮重构,我最终把技能包的目录规范定成了“目录 + 主文档 + 资源清单”的三段式:
skills/ └── code-review-checklist/ ├── SKILL.md # IR主文档,含front matter和正文 ├── assets/ # 技能运行需要的资源文件 │ ├── scripts/ │ │ └── check_security.py │ └── templates/ │ └── review_report.md └── manifest.json # 资源清单,声明文件和用途manifest.json是最容易被忽视但最值得设计的文件。它记录了该技能包内的所有资源文件路径、md5校验值、以及每个文件的用途说明。之所以需要校验值,是因为技能包在跨机器传输时经常出现文件损坏或半截同步的问题,有了校验值,Skills Manager在导入技能包时就能自动做完整性验证,发现不匹配直接拒绝导入,避免把坏技能分发到所有工具里。
整体目录规范还有一个额外的好处:它天然兼容“技能包”的打包分发场景。你可以把整个code-review-checklist目录直接打包成一个zip或tar包,发给同事导入到自己的Skills Manager里,所有的元数据都跟着走,不会出现“只有正文没有资源”的残缺状态。
2.3 模板引擎:从IR到目标格式的渲染规则
统一抽象层设计好了,下一步就是怎么把IR渲染成各工具的具体格式。这一步我把它拆成了两层:先是“格式转换层”,负责把IR的front matter字段映射到目标格式的对应字段;然后是“内容适配层”,负责根据目标工具的能力特性调整Markdown正文的结构和引用方式。
举个例子,同一个triggers字段,在Claude Code的SKILL.md里会被渲染成description里的关键词描述,让Agent在语义检索时能匹配到;在Cursor的.rules文件里则会被渲染成文件顶部的匹配规则注释,告诉Cursor这个规则适用于什么场景;在Copilot的custom instructions里则是直接作为段落标题出现。这三者的渲染逻辑完全不同,但数据源是同一个。
再比如正文里的资源引用方式。Claude Code支持Agent读取相对路径下的文件,所以我们可以直接在正文里写请参考 assets/scripts/check_security.py;但Cursor的规则文件是纯文本上下文注入,没能力动态读取相对路径资源,遇到这种情况模板引擎会把资源内容直接内联进Markdown正文,变成一个折叠的代码块。这种“按目标能力降级内联”的机制,是模板引擎里最核心的适配逻辑。它保证了一个技能哪怕在能力最弱的工具里也能完整看到资源内容,而在能力强的工具里则能保持目录结构不被破坏。
3. 跨平台桌面端的技术选型:Tauri、SQLite与文件监听
3.1 为什么不用Electron?桌面中枢的体积与内存账
Skills Manager的定位是桌面应用,因为技能管理涉及大量本地文件操作、目录监听、与各工具配置目录的直接交互,纯Web应用根本没有权限做这些事。桌面框架的选择上,我最终选了Tauri而不是更主流的Electron,核心原因是资源占用差距太悬殊。
Electron打包出来的最小应用体积动辄80MB到150MB,运行时的内存占用轻松超过300MB。这还只是装一个管理工具的代价,如果算上它常驻后台监听技能目录变化的开销,对开发机来说简直是在浪费内存。Tauri用系统自带的WebView渲染前端,用Rust做后端,打包体积能压到5MB到10MB,运行时内存占用通常只有Electron的十分之一左右。对一个“应该安静地待在后台、只在需要你操作时才出现”的桌面中枢来说,这个资源账非常关键。
当然,Tauri不是没有代价。它依赖各平台系统WebView的版本,在Windows上偶尔会遇到老版本WebView导致界面渲染异常的情况,开发时也需要额外处理系统差异。我的应对方案是把核心逻辑尽量下沉到Rust后端,前端只负责展示和事件交互,这样即使前端在某个平台渲染有问题,后端的数据管理和文件操作逻辑依然是可靠且可测试的。这也是桌面应用开发的一个通用经验:重逻辑放本地,轻展示放Web,永远别让UI层承担业务正确性。
3.2 SQLite:本地元数据仓库的取舍
技能库的元数据如果直接在文件系统里续写,用JSON文件存,说实话也能跑,但一旦技能数量上到几十个、单个技能的变更历史又有多个版本时,就非常难受了。JSON文件的读写是整体读、整体写,版本一多,几百KB的JSON反复读写,不仅慢而且容易丢数据。我最后选了SQLite作为本地元数据仓库,理由很务实:单文件、跨平台、支持事务、备份简单。
SQLite在这里承担的核心职责不是存技能正文——正文保持在文件系统里,SQLite存的是索引、版本历史、标签关系、分发状态这些结构性数据。比如“哪个技能在哪个工具里上次分发是什么时候”“某个技能的版本历史是怎么演进的”“哪些技能打了某个标签”这类查询,用SQL做比遍历目录高效得多。这里有个细节:跨平台应用写SQLite时尽量别用需要编译原生扩展的方式,选纯Rust的rusqlite或者带bundled的SQLite库,能避免在Windows/macOS/Linux上分别编译原生依赖的麻烦。
由于元数据是结构化存储,我习惯用DB Browser for SQLite(就是开源的那个DB4S工具)直接打开数据库文件检查数据结构,排查分发记录异常或者同步标记错乱时非常直观。你不需要特意为它写复杂的查询界面,很多调试场景直接用桌面SQLite工具翻表更快。这也呼应了“跨平台工具”的一个通用经验——选型时优先选底层文件格式开放、可以被第三方工具直接检视的方案,能帮你省下大量排查时间。
3.3 文件监听的节流与哈希比对:避免CPU被目录拖垮
桌面中枢有个绕不开的功能:要监听各个工具的技能目录,当外部工具或你自己手改技能文件时,中枢要能检测到变化并更新索引。实现这个功能本身不难,难的是怎么做才不把电脑拖垮。
技术上是这样处理的:Rust端用一个notify库来监听文件系统事件,但不能一收到事件就立刻触发全量扫描。写代码时编辑器保存文件往往一秒钟触发五六次目录变更事件,如果每次事件都扫描一次,CPU和磁盘都会被击穿。解决方案是做一个500ms的节流窗口:事件触发后重置计时器,等连续500ms没有新事件了,才真正开始扫描变更。
光有节流还不够,扫描本身也要做增量处理。我的做法是维护一个文件哈希缓存表,记录每个文件的路径、最后修改时间和内容哈希。扫描时先比较修改时间,只对时间戳变化的文件重新计算哈希,再拿哈希和缓存表比对,哈希没变就跳过,哈希变了才更新索引并触发渲染逻辑。这套机制测试下来很稳,即使技能目录里有几千个文件,日常监控时的CPU占用也基本可以忽略。
哈希缓存表本身也存在SQLite里,可以说SQLite在这套系统里不只是元数据仓库,还是文件监听的“记忆体”。
4. 54+工具的适配策略:配方(Recipe)驱动的插件系统
4.1 别为每个工具写适配器:检测规则+模板生成器双层结构
如果54+个AI编程工具要给每个都写一个独立的适配器模块,这个工程量完全不可持续。而且新工具层出不穷,今天适配了54个,下周可能就冒出来第55个。我的设计方案是做一个“配方(Recipe)”驱动的插件系统:每一个工具对应一个配方文件,里面声明检测规则、目录定位逻辑、模板渲染参数和验证规则。配方本身是声明式的YAML配置,而不是硬编码的Rust代码,这样新增一个工具的适配不需要重新编译主程序,只要把一个新配方文件丢进recipes目录即可。
一个简化版的配方长这样:
--- id: cursor-rules tool: cursor detect: glob: ".cursor/rules/*.mdc" marker: ".cursor" output_dir: ".cursor/rules" render: template: "cursor_rules" naming: "{skill_name}.mdc" validate: required_keys: ["trigger", "description"] ---这里的核心设计是双层结构:第一层是检测规则,用于在文件系统里找到该工具的技能配置目录(比如检测到项目根目录有.cursor文件,就认为这是一个Cursor项目,技能应该放在.cursor/rules下);第二层是模板生成器,用于把统一的IR内容按该工具的能力和格式渲染出来。渲染结果还需要经过validate校验,比如检查必需字段是否存在、格式是否合法,校验不通过时直接报告错误而不是静默写入。
4.2 冲突检测与合并规则
多工具管理最容易遇到的问题就是同一份技能的多个版本发生冲突。举个实际场景:你在Skills Manager里维护了一份“代码审查”技能的主版本,然后某天直接跑到Cursor的手动配置里改了几行规则,没通过Skills Manager同步。由于Cursor目录文件被监听到变化,Skills Manager会把改动识别为“外部修改”,此时就产生了冲突:主仓库里的版本是A,Cursor里的版本是B。
处理这类冲突的策略,我试过“以主仓库为准”的直接覆盖方案,也试过无脑保存外部版本的让别人改方案,最后都在实际使用中翻过车。目前采用的策略是三分支合并的思路:以冲突发生前的共同祖先版本为基线,把主仓库的改动和外部工具的改动分别做diff,两边一致性较高的字段自动合并,真正冲突的字段(比如description或trigger完全对不上)才弹对话框让用户手动选择。自动合并的比例在实际使用中大概能覆盖到70%左右,剩下的30%手工处理,总比直接丢掉一份修改要靠谱得多。
自动合并后的文件会先生成一个.conflict副本保存原始内容,再写入合并结果。这个设计虽然多占一点磁盘空间,但能极大降低手动合并时的心理压力——就算合并错了也有后悔药吃,不会因为一个错误操作把你手动改的半天的内容抹掉。
4.3 配方社区与增量适配
“54+”这个数字在落地时不是一次性写出来的,而是靠配方机制持续演进而来的。我第一版只写了十几个最常用工具的配方,后面每用一个新工具就往recipes目录里加一个对应文件,算法调整过程中不断出现对某个工具机制的新理解,再回头更新配方。这种做法说白了就是“兼容性是一种留痕的工程,而不是一次性冲刺”。
配方机制的另一个好处是天然支持社区共享。配方文件是纯YAML文本,可以放到Git仓库里分享,别人克隆下来放进recipes目录就能用。这不就是最原始的“插件生态”嘛。如果你实际动手做类似的系统,建议一上来就把配方的Schema定义好、做好兼容性说明(比如声明某个配方适配的工具版本范围),否则后续加配方时很容易出现互相覆盖和格式漂移。
5. 技能的迁移、同步与回滚:从“复制粘贴”到版本化
5.1 导出导入的三种格式与跨工具迁移流程
技能管理的核心价值之一是可迁移性。我把“迁移”分为三个层次:单个技能包迁移、全量技能库备份、跨机器环境迁移。单个技能包迁移是最常见的使用方式,比如你写了一个很顺手的技能想分享给同事,Skills Manager会导出一个完整目录包,打包成zip格式,同事直接拖拽导入即可。导入时系统会校验manifest里的文件校验值,校验通过才注册进本地技能库。
全量技能库备份是把整个技能仓库连同SQLite数据库一起导出成一个归档文件,这个主要用于定期备份和个人存档。跨机器环境迁移的流程更复杂一些,因为目标机器上各工具的技能目录位置、工具版本可能不完全一样。我的做法是先导出“与工具无关的技能包集合”,再在目标机器上通过配方逐一渲染分发。这套流程测试下来,一台新机器从装好Skills Manager到所有主流工具的技能全部就位,大概5分钟,而手工迁移动辄半小时起步。
整个迁移过程最重要的一个原则是:优先迁移“标准化之后的资源”,而不是迁移“针对某个工具渲染好的成品”。因为成品到了新工具那就不见得好用,而标准化资源到了任何环境都能重新按照当地规则渲染。
5.2 同步策略与冲突解决
同步是个老话题,我想分享一个踩坑经验:别把技能库目录直接放进网盘的自动同步文件夹里。第一次图省事,我把skills目录丢进了坚果云的同步目录,结果联网状态下多台机器同时打开Skills Manager,各自往SQLite数据库里写变更,直接把库文件锁冲突给干崩了。后来又尝试过用Git仓库做同步,但它的问题是需要处理手动commit和push,不够“自动”。
目前采用的方案是“SQLite作为主状态库”加“文件系统作为真源”的折中:各机器上的技能文件通过任意文件同步工具(自建WebDAV或者局域网同步均可)保持内容一致,SQLite里只存索引和版本记录,同时用文件监听和哈希比对来识别冲突。每次同步前先扫描本地文件的哈希变化,再对比远端同步过来的文件哈希,两边都不一致的位置自动标记为冲突,进入合并流程。简单说就是:内容文件随便同步,冲突检测在本地做。
5.3 事务化回滚:为什么“替换文件”不足以叫回滚
有一类工具的回滚做得不干净,本质上是回滚操作没有原子性和安全性保障——比如替换文件只替换了一半、权限没还原、软链接断了。我在这套系统里把回滚设计成了“事务化回滚”:每次对技能文件做变更前,先把当前的所有相关文件快照存储到SQLite的changes表里,包含每个文件的内容、路径、校验值和变更时间。
执行回滚时,系统不是简单地把文件复制回去,而是走一个完整的事务流程:先在校验值表中确认目标文件当前状态确认为要回滚的状态,防止“想退回B版本,结果文件已经是C版本”导致误覆盖;然后创建当前状态的回滚点快照(以防你连续回滚操作时丢掉了中间状态);最后再执行文件替换,替换完成后重新计算哈希并更新索引表。整个流程任何一个步骤失败都会自动回滚,不会出现“替换了一半、另一半天知道跑哪里去”的不干净回滚。这其实和物理引擎里处理回滚的教训是一样的——回滚必须要基于快照、事务和幂等操作,而不是基于“我都改回原样了”的直觉。
6. 实测案例:把一套“代码审查”技能从 Claude Code 迁到 Cursor 和 Windsurf
6.1 迁移前这几套工具的配置差异
我拿团队里一直在用的一份“代码审查”技能做了完整迁移实验。这份技能原本维护在Claude Code里,是一个标准的.claude/skills/code-review-checklist目录,包含主文档、三个检查脚本和一份输出模板。Claude Code的Agent能通过语义匹配自动加载它,触发词是“review pr”或“代码审查”。
在Skills Manager里导入后,我把它标记为“核心技能”,然后执行分发。Cursor端生成的.cursor/rules/code-review-checklist.mdc文件,由于Cursor不读YAML front matter,模板引擎把描述和触发词转成了中文注释块,把主文档的检查列表拆成了几个分段规则。Windsurf端的生成则是完全另一套格式——它更偏向结构化的规则条目,所以模板引擎把Markdown里的有序列表直接渲染成了Windsurf format支持的checks条目。
迁移过程中最耗时的地方不是导出和渲染,而是本地化调优。同一个技能在Claude Code里能靠Agent自主检索上下文,功能可以写得很简略;分配到Cursor之后,你要手动调整规则文件顶部的匹配优先级,否则它在简单的“帮我看看这个PR”场景下根本不会触发;而在Windsurf里,你还要把步骤拆成Workflow的节点,因为它们更依赖显示步骤驱动而不是语义联想。
6.2 迁移后的效果与需要手工微调的细节
最终迁移完成之后,三个工具里的技能都能跑通,但使用体验有明显差异。在Claude Code里它安静、自主、表现最稳定;在Cursor里它能正确触发,但你要习惯它频繁把审查结果内联成代码注释的问题;在Windsurf里它变成了逐步向导式的审查流程,每一步都要求你输入确认,虽然更繁琐但出错概率很低。
我粗略统计了这次迁移的效率:手工把一份Claude Code技能完整搬到一个工具大概需要四十分钟,其中包含阅读文档、改写格式、反复测试触发词和调优输出格式。用这套系统迁移到三个工具,加上人工微调,总耗时大概一个多小时,其中真正的机械操作时间是几分钟,其余都在打磨“触发词是否精准”“约束描述是否足够强”这类只能靠经验调整的事情。换句话说,工具能把90%的机械劳动去掉,但最后10%的“活用感”还得靠人去调。
7. 给想自己动手的人:关键经验与避坑清单
7.1 五条我在踩坑之后才明白的规则
第一,IR的字段设计要早做,而且要对“新增字段”保持极度克制。每个字段都会被模板引擎、冲突合并器和分发系统引用,加字段不是只改一个模型的事,而是动一串链路。能不加就不要加,宁可用命名规范去表达,也不要用额外字段去表达。
第二,生成的技能必须是幂等的。也就是说,同一份IR内容,在任何时间渲染到某个工具里,输出结果必须完全一致。如果渲染结果里带了时间戳、随机ID这类不稳定因素,会导致哈希比对永远在变化,文件监听和冲突检测的可靠性直接崩盘。我就踩过这个坑,曾经在渲染模板里加了一个generated_at字段,结果每次分发都产生新的哈希,让冲突检测误报不断。
第三,目录扫描一定要排除生成目录和缓存目录。如果Skills Manager自己的输出目录被纳入了监听范围,就会产生“渲染→触发监听→再次渲染→再次触发监听”的死循环。这是做文件监听系统最容易忽略的一个陷阱。
第四,不要把技能文件放到工具自身的配置目录里直接编辑。每个AI编程工具在自身运行期间可能会对配置目录做缓存或者重写,你的辛辛苦苦改的格式可能会被工具的缓存机制覆盖掉。正确做法是:让Skills Manager管理“源技能目录”,工具目录只作为“生成产物目录”,源和产物分离,改动永远在源头上做。
第五,多工具共用技能时,要预判各工具的“编排模型”差异。有的工具Agent能自主规划步骤,有的工具Agent是严格按照规则顺序执行的。一套技能写得太简略,在自主型工具里运行良好,在规则型工具里就会卡壳;写得太死板,则反过来。所以技能内容最好分成“目标层”和“执行层”,目标层突出目的,执行层写清过程,这样两种模型都能各取所需。
7.2 一个可落地的起步方案
如果你看了这篇文章想自己动手做类似的东西,我给你一个最小可行的起步方案。第一阶段先别想着统一54个工具,选一个你最常用的工具和一个你第二常用的工具,写好它们对应的两个配方文件,做一个“IR → 目标格式”的单向渲染命令行工具就够了。第二阶段加入SQLite元数据存储和最简单的版本历史功能。第三阶段再去做文件监听和冲突合并。我自己的开发顺序就是这样,每个阶段都能独立使用,不会出现“做到半路工具没法用”的尴尬。
技能库本身建议从一开始就放Git仓库里,配一个CI脚本做格式校验,校验IR字段是否合法、渲染结果是否幂等。这个东西后期带来的收益远远超出你搭它时花的一个小时。格式校验能在问题流入其他工具之前就拦住它,尤其是多人协作时,这简直是保命必备。
最后再分享一个小技巧:技能的版本号不要只跟着功能变更走,只要改动触发词、约束条件或者依赖的脚本,都建议升一个次版本号。因为这类改动不直接体现在“能跑”上,但深刻影响Agent在不同工具里触发时的实际表现,版本号是你判断“当前各工具里的技能是否同步”的最快速参照。我自己吃到过不少因为只看主版本号、忽略次版本差异导致的“同版本不同行为”的教训。技能管理这种事,做得再细致都不为过。