
先说结论我手上现在维护着54个AI编程工具相关的Agent运行环境分布在Windows、macOS、Linux三套系统上每天来回切换这些工具的时候最让我头疼的不是模型选哪个而是技能文件散落各处。Claude Code有它的.claude/skillsCodex有它的AGENTS.mdCursor又有自己的.cursor/rules同一个技能我要在至少三个地方维护三份不同格式的副本改一次就要同步一次技能一多就完全乱套。所以这半年我花了大量周末时间做了个叫Skills Manager的跨平台桌面应用专门用来统一管理这54工具的Agent技能今天把完整设计思路、核心实现和踩坑记录整理成文希望能给同样在折腾Agent技能体系的兄弟们一点参考。这个项目适合三类人经常在多个AI编程工具之间切换的独立开发者想把个人经验沉淀成团队知识库的团队负责人以及研究Agent Skill机制本身、想搞清楚各家格式底层逻辑的人。如果你只是在一个工具里用官方自带技能可能暂时感受不到它的价值但只要你开始自己写SKILL.md开始给Agent喂自定义技能你会发现这个问题迟早会找上你。1. 先说痛点Agent技能正在变成“一次性消耗品”1.1 什么是Agent技能为什么它比提示词更重要很多人刚接触AI编程工具时习惯把一段很长的提示词复制到对话框里让Agent去执行一个复杂任务。这种方式的问题是提示词是一次性的每次都要粘贴、调整、等待而且不同工具对同一条指令的理解方式还不一样。Agent技能Skill就是来解决这个问题的——它本质上是一组结构化的文件用Markdown或YAML描述任务背景、执行步骤、输出规范、依赖资源Agent在读取到这些文件后就像拿到了一本岗位手册知道遇到什么场景该按什么流程干活。拿我自己的经验举例我给Agent写过一个“SQLite数据库迁移”技能里面明确了连接数据库要用什么命令、迁移前要备份、外键约束怎么处理、回滚脚本怎么组织。以前我在Claude Code里要靠手动粘贴一大段提示词来触发后面我把这个技能写进.claude/skills目录只需要告诉Agent“按SQLite迁移技能处理”整个流程它就自动拆解执行了。这就是技能和普通提示词的区别技能是可复用、可版本化、可分享的资产而提示词是消耗品。1.2 54工具的“方言”问题同一个技能三份写法问题出在标准不统一。现在的AI编程工具几乎每家都推出了自己的Agent技能机制但文件格式、存放路径、命名规则完全不一样工具技能目录配置文件格式触发方式Claude Code.claude/skills/SKILL.md frontmatter自然语言/指令引用OpenAI CodexAGENTS.md/skills/Markdown 前置规则块项目上下文自动加载Cursor.cursor/rules/.mdc / .rules规则匹配自动注入Gemini CLI.gemini/skills/SKILL.md 独立资源目录语义检索触发Aider.aider/纯Markdown约定命令参数指定Windsurf.windsurf/内存文件Memory会话上下文Zed.zed/agent/skills.yaml语义检索Trae / Continue / Cline 等各不相同的配置目录JSON / YAML / MD工具内置机制这不是一个简单的文件夹路径不同的问题。你写一个技能Claude Code要求frontmatter里有name和descriptionCusor的规则文件要求globs和applyToCodex又有一套自己的优先级语法。把这些统一起来本质上是在做一次“跨方言翻译”。我在做Skills Manager之前经常是同一个技能在三四个目录里各存一份一不小心改了其中一处另外几处还停留在旧版本调用的效果完全不是同一套逻辑。这种情形持续了大概一个月我才下定决心要做一个统一管理的中枢。1.3 一次真实的崩溃场景让我彻底坐不住的是两个月前的一次跨工具迁移。当时我想把一个写好的“前端组件Review”技能从Claude Code迁到Cursor上用想着无非就是复制粘贴改改路径。结果那是一个带资源文件的技能里面有3个代码模板文件、1个checklist、还有个自动生成测试的辅助脚本全部用相对路径互相引用。我在Cursor里复制完SKILL.md一运行就发现模板找不到、测试脚本路径断裂折腾了两个小时才把所有资源文件重新归位。后来我又在Codex里试了一下它的技能加载规则和前两者又不一样等于同一套逻辑要重写第三遍。这件事让我意识到Agent技能资产正在变成“一次性消耗品”——每次换工具之前积累的经验就基本作废。真正值得做的不是一个技能一个技能地去适配而是一个中枢把这些技能的存储、编辑、转换、分发全部接管让技能和背后的工具解耦。2. 架构设计与技术选型为什么不做一个云端平台2.1 先定边界只做技能资产层不做全家桶做这种工具最容易犯的毛病是边界失控。有人一上来就想做“Workflow编排”、“多Agent协同调度”、“模型路由”最后项目烂尾。我一开始就跟自己定死Skills Manager只做技能资产层也就是技能的存储、编辑、校验、转换、分发坚决不碰以下三个领域第一不内嵌模型调用模型路由和推理交给各家工具自己处理第二不做云端同步和账号体系本地文件才是唯一事实来源云同步可以后续挂WebDAV或Git仓库第三不做一个IDE插件去拦截代码编辑事件技能的分发和更新靠文件系统和CLI触发即可。为什么这样定因为技能的本质是一堆文件最有价值的能力是“把这堆文件管理好”而不是再造一个IDE。如果把精力花在做全家桶上等于同时和Claude Code、Cursor、JetBrains生态对抗我只有一个人做不了这种事。划定边界之后整个项目的复杂度至少降低一半。2.2 Tauri vs Electron跨平台桌面端的最终选择桌面端我是在Tauri和Electron之间二选一。先说结论最终用了Tauri 2.x用Rust做后端核心前端用Vue 3。理由有三点第一安装包体积。Electron打包出来随便就是80MB到110MBTauri的安装包能压在8MB到12MB左右对于这种效率工具来说安装体积直接影响用户是否愿意在第二台机器上装它第二内存占用。Skills Manager要同时监控几十个技能目录Electron的Chromium常驻内存很容易跑到400MB以上Tauri利用系统原生WebView内存一般只有150MB左右第三文件系统密集操作方面Rust的notify和walkdir等库在处理大规模目录扫描、哈希计算、文件监听上性能和稳定性比Node.js底层一票回调要可靠得多。Tauri也有其麻烦之处最大的坑就是系统WebView差异。Windows上WebView2、macOS上WKWebView、Linux上是WebKitGTK渲染表现不完全一致尤其是CSS的某些属性。项目录入了很多长列表和树形控件我在Linux上调试时出现过列表滚动卡顿、焦点样式丢失的问题。解决方案是尽量用标准HTML/CSS功能避免依赖某个浏览器的私有属性复杂的树形视图直接用Canvas绘制或者改用虚拟滚动。2.3 三层架构导入层、归一化层、分发层Skills Manager的核心架构我拆成三条管线导入层负责识别各个工具的原生技能格式把散落在.claude/skills、.cursor/rules等目录中的技能文件读进来归一化层把各家的方言翻译成统一的内部Schema所有编辑、校验、版本比对都在这一层完成分发层再根据目标工具把归一化后的技能生成对应格式写回对应目录。这个设计的核心价值在于“双向转换”。很多人在做这类工具时会想我直接把所有技能都转成Claude的SKILL.md格式用Claude Code作为标准不就行了实际上行不通因为你在用Cursor的时候它读的就是Cursor自己的规则格式不是克劳德的。所以内部统一、对外兼容才是正确解法。所有技能在Skills Manager内部一律以自带Schema存储只有到导出阶段才做格式适配。这样做还有一个额外好处将来有新的AI编程工具出来不需要改动现有技能任何内容只需要为它写一个新的适配器就能把整个库的技能同步过去。3. 归一化Schema与54工具适配器3.1 各家技能格式背后的共同逻辑虽然各家格式不一样但拆开来看几乎所有Agent技能文件都在做同一件事用一段元信息描述技能的名称、用途、适用场景用一段正文描述任务处理的步骤和规范再用若干资源文件承载模板、脚本、示例。这就是我说的“frontmatter 正文 资源”三段式结构。明白了这个底层逻辑就能设计一个足够通用的内部Schema把各家的差异全部放到适配器里去消化而不是让用户去背每个工具的格式规范。比较典型的三类“方言”是Claude Code系用SKILL.mdfrontmatter是YAML格式重点是name、description正文用Markdown分节描述执行流程Codex系用AGENTS.md或在skills目录下放独立Markdown文件它的规则描述更像一套“指令文本”对前置条件和后置条件要求明确Cursor系用.mdc或.rules文件支持globs作用域匹配核心是让规则在特定文件类型或目录下自动注入。这三类方言看似差异巨大但都能映射到统一Schema中。3.2 内部Schema设计我是怎么定义一份技能元数据的归一化Schema是整个系统的心脏它直接决定适配器的复杂度。我设计的时候坚持一个原则“元数据丰富但尽量宽松”。一份技能在Skills Manager内部的形态大概是这个样子的id: sqlite-migration-skill name: sqlite-migration version: 1.3.0 description: 执行SQLite数据库安全迁移包含备份、DDL变更、外键处理、回滚检查 author: dev-team homepage: https://internal.wiki/skills/sqlite-migration category: database tags: [sqlite, migration, ddl, backup] scene: - 当用户提出修改数据库表结构时 - 当Agent识别到破坏性DDL语句时 steps: | 1. 连接数据库前先执行 PRAGMA foreign_keysON; 2. 迁移前必须生成一次完整备份备份文件放入 ./backup/ 3. DDL变更必须包含下行回滚语句 4. 执行完成后运行 integrity_check interaction: read-write input: - 目标数据库路径 - 变更SQL脚本 output: - 迁移报告Markdown - 回滚脚本 resources: - template_backup.sh - rollback_template.sql dependencies: - sqlite3 3.35 permission_notes: 允许读写数据库路径下的文件禁止访问系统目录这里每个字段都不是随便定的。id是技能的全局唯一标识不管它被转换到哪个工具这个id保持不动用于追溯和去重scene是触发场景描述可以同时有多个因为同一个技能在Claude里可能靠语义触发在Cursor里可能靠glob规则匹配场景写清楚后适配器才知道该往哪个字段映射interaction字段标记技能的安全等级只读技能可以放心分发读写技能分发到工具时要给额外提示permission_notes是我自己加的约束描述某些工具不支持权限声明语法但保留这段文字在人工审查时非常有用。3.3 插件化适配器为54工具各写一个翻译员适配器的核心是三个方法detect判断一个目录里存的是不是本工具的技能parse对话原生格式解析成内部Schemagenerate把内部Schema再生成原生格式。我只定义这3个接口每一个工具对应一个适配器增量扩展时就写一个新文件不碰其他逻辑。这里有一个我一开始走了弯路的地方我最初是给每个工具写“完整双向支持”结果发现成本极高。后来我改成了适配器分级A级支持完整双向往返既能读取也能写回B级支持单向导出只把内部Schema转成该工具格式C级只支持只读识别识别目录里有技能能展示但不同步写回。为什么会有B级和C级因为有些工具的技能格式迭代太快正向导出可以保证用户在需要时能用上反向读取如果跟不上改动反而会把错误信息导入到中枢里。分级之后我终于能在大约三周内把54个工具都纳入支持范围虽然有一些只是C级识别。3.4 配置解析的细节两个最容易被忽略的坑配置解析是整个系统里最琐碎、最容易出问题的环节。第一个坑是frontmatter格式不统一。Claude的SKILL.md用的是YAML的frontmatter但Codex的规则文件里Blocks是 txt 包起来的Cursor的.mdc文件也有一套自己的布局有些还带渲染层。我的做法是写一个多态解析器先用启发式判断文件属于哪种模板再调用对应解析器解析失败时保留原始文本不轻易丢弃数据。第二个坑是依赖资源文件的相对路径。很多技能的正文里会引用scripts/backup.sh这样的相对路径一旦从原生目录导出到另一个工具的目录引用链就断了。我的解决方式是在导入时扫描正文中的资源引用把引用的文件复制到中枢的资源库中并在导出时重写路径让它在目标工具下也能正常工作。4. 核心功能与实操记录4.1 创建一个技能从模板库到可分发资产在Skills Manager里创建技能走的是“模板→编辑→校验→发布”一条龙。我内置了几套模板最常用的就是“数据库运维”、“代码审查”、“项目脚手架”、“文档生成”这四类也有一个空白模板给重度用户自己发挥。以创建“API接口文档生成”技能为例选择模板后应用会生成一个结构完整的目录包含SKILL.md、examples/示例目录、scripts/工具脚本目录。我只需要在界面上填名称、描述、触发场景然后正文里把生成文档的步骤写具体比如“先扫描项目的Controller层和路由定义识别所有接口”“提取参数校验、鉴权方式、响应码”“按OpenAPI规范生成Markdown文档”。这个流程里最容易忽视的是触发场景的描述。我发现很多人写技能时只写“这是什么”不写“什么时候用”结果在Claude Code里这个技能从来不出现。所以模板里我把scene字段做成必填并且提示用户至少写三个具体场景例如“当用户要求输出接口文档时”“当接口变更需要同步更新文档时”“当新增路由需要补充API说明时”。这一步做扎实了后面分发到任意工具触发效率都会高很多。4.2 批量分发一个技能的跨工具同步实操分发是Skills Manager的核心价值所在目标就是让你在界面上点一下技能就自动同步到所有已配置的工具目录中。这里以把上面那个API文档技能分发到三个工具为例实际操作流程如下第一步在技能列表中选中该技能点击“分发”按钮第二步在弹出的面板中勾选目标工具可以全选也可以按标签过滤第三步系统按每个适配器的generate方法生成目标格式存入对应的工具目录第四步应用执行一次分发后校验确保目标文件中没有残留占位符资源文件完整。分发前还可以做“按场景过滤”。比如我有六七个技能都跟“数据库”相关但当前这个API文档技能只涉及read权限不需要落地到某些安全限制严格的工具环境中这时就可以通过interaction字段批量排除。分发结束后会生成一份报告显示每个目标目录写入了哪些文件、文件大小、哈希值方便和上一次分发做对比。我自己实践下来日常维护二十多个技能每天可能要调整三到五处有了批量分发每次操作从原来半小时缩减到两分钟以内这个效率提升是整个项目最大的胜利。4.3 内置校验器分发前先体检别把残缺技能推给Agent技能文件不出问题则以一出问题就是莫名其妙的Agent行为异常不执行步骤、找不到资源文件、甚至直接报解析错误。这里面一半以上的问题都出在元信息不完整、资源引用断裂、正文格式错误上。所以Skills Manager从第一个可用版本开始就内置了校验器在每个技能保存时自动跑一遍快速检查在分发之前跑一遍完整检查。校验器检查的项目包括元信息是否完整name是否存在、description是否足够描述意图、scene是否有至少一条正文是否含有引用但不存在的资源文件路径资源配置中的文件名是否和目录内实际文件名一一对应大小写敏感是否有明显的前置依赖缺失比如技能要求目标环境有jq、python3等命令代码块是否标注了语言类型。这个校验器的好处是把错误拦截在分发之前不把坏技能推到Agent里。校验失败时系统不会阻止你手动导出但会弹出一个警告列表你可以选择忽略错误强制分发也可以回到编辑页修正。4.4 CLI子命令把技能同步接进自动化工作流除了图形界面我还给Skills Manager加了一组CLI子命令用于自动化场景。最常用的两个命令是skills-manager list和skills-manager sync# 列出当前中枢中所有技能按标签过滤 skills-manager list --tag database --format table # 将所有已发布技能同步到当前机器的所有目标工具目录 skills-manager sync --target claude,codex,cursor --dry-run # 执行一次完整校验输出错误报告 skills-manager validate --skill api-doc-generator --strictsync子命令里的--dry-run参数是我强烈建议的先在不落盘的情况下计算出会新增、覆盖、删除哪些文件确认无误后再真正执行。我一般在CI脚本里跑validate和dry-run把输出写进构建日志这样就算人不在电脑前也能看到技能库的健康状态。CLI和数据层共用一套核心逻辑所以不存在图形界面和命令行行为不一致的问题。5. 踩坑实录这些问题官方文档里不会写5.1 文件监听的“自触发”灾难Skills Manager有一个功能是监控原生工具目录一旦工具内部新增或修改了技能文件就自动同步到中枢。这个功能的实现依赖文件系统监听库但我在第一次联调时遇到了一个极其隐蔽的问题当应用把技能写回工具目录时监听器检测到变化又把文件重新导回中枢中枢看到内容没有变化但文件事件触发了又触发一次写回结果陷入无限循环。这个问题的解决方式是在监听回调里加入“来源标记”所有由Skills Manager自己写入的文件都会在暂存区写一个状态标记在收到事件通知后先判断该文件是否处于“最近由本应用写入”的状态如果是就直接忽略。还有一个更稳妥的兜底方案比较文件哈希如果内容哈希没有变化就不触发导入流程。后来我在所有涉及文件双向同步的功能里都采用了“哈希比对 写入标记”双保险到目前为止没有再现过死循环。5.2 CRLF和LF换行符带来的解析血案Windows上很多工具保存文件时默认使用CRLF换行符而Claude Code在Linux环境下的技能解析器对\r\n是完全正常的但Codex的某些老版本会直接把换行符作为完整行的一部分解析导致frontmatter碎成一团乱麻。我在内部分发器里加了一个全局的换行符归一化规则导入时统一转换成LF存储导出到Windows工具目录时再视情况转换回CRLF。这个看似不起眼的小设置几乎消灭了我在Windows和WSL之间来回操作时报出的所有“frontmatter解析失败”错误。另一个和编码相关的坑是文件名的大小写。Linux和macOS默认区分大小写但macOS的文件系统默认大小写不敏感Windows也是。有些技能资源文件名写的是Backup.Template.sh实际落盘时变成了backup.template.sh在Linux环境里运行没有任何问题但分发到Windows工作站上直接就找不到文件。我后来在导入和分发时都强制要求文件名与引用保持一致并在校验器中加入了“目标平台大小写敏感性检查”分发前自动重命名不一致的文件。5.3 技能库膨胀之后性能优化实战技能从十几个涨到八十多个后界面开始出现明显的卡顿尤其在打开技能列表和目录树时。定位之后发现瓶颈有两个一是每次打开列表都在做全量目录扫描遍历了所有资源文件并计算哈希二是前端在渲染长列表时没有做虚拟滚动。优化方案是加一层索引缓存应用在启动或手动触发刷新时扫一遍所有技能目录并把元信息写入本地SQLite缓存后续打开列表直接读缓存只有在文件事件触发时才增量更新对应的技能记录。前端方面我把技能列表换成了虚拟滚动只渲染可视区域内的约二三十行配合预加载策略操作手感恢复了即时反馈。还有一个值得分享的小技巧在计算几十个技能目录的哈希时用并行遍历而不是单线程顺序扫描在Rust里用rayon或者tokio就能轻松实现扫描时长从十几秒压缩到了两秒以内。这些优化做完之后整个应用才算真正达到了“桌面中枢”该有的流畅度。5.4 常见问题速查表现象根本原因解决方式分发后目标工具不识别技能目标目录权限或文件命名不符合该工具规范查看适配器日志确认生成文件名和frontmatter格式是否匹配技能列表直接空白技能目录扫描索引损坏删除本地索引缓存目录手动重新触发一次全量扫描重建索引分发时资源文件丢失技能正文引用了尚未导入的资源路径在编辑器里执行“自动补全资源引用”确认所有resources字段填写完整Agent执行时找不到技能技能目录路径名和Agent配置的skill目录不一致使用skills-manager doctor检查每个工具目录的健康状态同步到Windows后frontmatter解析失败CRLF换行符导致部分工具解析器处理异常在分发设置中开启换行符自动转换将目标系统强制设为LF兼容模式高亮实时变更时不生效文件监听事件被系统的Volume Shadow Copy干扰在设置中调整监听策略改为主动轮询哈希比对模式我在实际使用中发现这个项目最容易被低估的收益不是“统一管理”这个概念本身而是它强迫你建立了一套“技能领域的版本化习惯”。以前技能文件散落各处时我改完一段规则根本不会去考虑它影响到了哪些工具也不会去追溯哪一次修改让某个Agent行为产生了变化。现在所有技能都以标准化Schema存进Skills Manager后每一次修改都有记录分发出去的版本可以被追溯异常出现时可以迅速回滚到上一个可用版本。这种感觉就像从“把文件扔进多个文件夹”升级成了“在代码仓库里做发布管理”。最后再分享一个我对想要搭建自己技能库的人的建议不要一上来就追求把54个工具全部接入那只是我这个场景的需求。你先从自己最常用的两三个工具开始把手上的三五个高频技能规范成内部Schema跑通“编辑→校验→分发”的闭环等这套流程顺手了再逐步扩展工具覆盖范围。技能这种东西数量不是重点被Agent真正加载并高质量执行才是重点。我用Skills Manager统一管理这54工具的Agent技能之后最深的体会是工具可以时常更换技能资产才是真正属于你自己的积累。