
如果你手头同时用着 Claude Code、Codex、OpenCode 这类 AI 编码 Agent大概率已经遇到过同一个尴尬在 Claude Code 里精心调好的 Skills换到 Codex 上完全不认Codex 能跑的那套自定义指令OpenCode 读起来又是一脸懵。每个工具都有自己的规则、自己的格式、自己的加载路径明明干的都是同一件事——让 Agent 按你定义的技能干活结果却搞出了一堆互不相通的孤岛。这篇文章想聊的就是怎么打破这个局面让同一套 Skills 在不同 AI Agent 之间真正共用起来。我也不会照搬官方文档就按自己实际折腾过几轮的经验把思路、格式差异、兼容写法、踩坑记录一次说清楚。无论你手头是 Claude Code、Codex、OpenCode 还是其他支持自定义技能的 Agent这篇文章都能给你一套可以直接落地的方案。1. 现状复盘为什么不同 Agent 的 Skills 会各有各的写法1.1 Skills 到底是什么它解决了什么问题先说个基本定义方便刚接触这个概念的朋友对上号。Skills技能是给 AI Agent 预定义的一组行为规范和操作清单本质上是把一个复杂任务拆成 Agent 能理解、能执行的标准化流程。举个例子你写一套“前端代码审查 Skills”里面就包含“检查组件划分是否合理”“确认样式类命名是否规范”“验证状态管理有没有做到单一数据源”等步骤。Agent 在拿到编码任务时检测到匹配场景就会自动调用这套技能来干活。早期没有 Skills 这个概念的时候你想让 Claude Code 按你的团队规范写代码只能把相关要求堆在系统提示词或者项目说明文件里。结果就是提示词越来越长、互相覆盖同一个团队的 Agent 行为还经常不一致。Skills 的提出本质上是把“人给 Agent 写提示词”这件事工程化和模块化了让技能和 Agent 本体解耦可以单独维护、单独测试、单独分享。1.2 主流 Agent 的差异到底差在哪目前市面上的主流编码 Agent例如 Claude Code、OpenAI Codex、OpenCode虽然都引入了类似的技能机制但各自的实现差异相当明显。抛开底层模型不一样这件事光看外部形态就有这么几个维度各不相同技能文件的组织位置不同有的放项目内.claude/skills有的读.codex/skillsOpenCode 则有自己的全局配置目录。技能描述格式不同有 YAML 风格的 frontmatter也有纯 Markdown 的表格描述。加载和匹配的机制不同有的是语义向量匹配有的是关键词匹配还有的是先全部读入再让模型自己挑。技能内步骤的指令语法不同尤其是执行终端命令的方式各家有各家的写法。这些差异叠加在一起就让“同一套 Skills 在不同 Agent 间复用”这件事变得有点棘手但还没到做不了的程度。后面几节我会逐个拆开来说并给出实际可操作的兼容方案。2. 设计一套可复用的 Skills 之前先想清楚这几件事2.1 先定义技能边界不是所有流程都适合做成 Skills我见过不少朋友一上来就写了一套特别宏大的 Skills恨不得把整个研发流程都塞进去最后的结果往往是 Agent 读了一大堆规则反而不知道该干什么。这里有个很实用的判断原则一个 Skills 最好只覆盖一个具体的能力域。比如“代码审查”“生成 API 文档”“写单元测试”“处理 Git 冲突”这种颗粒度就刚刚好。要是把“从需求分析到上线发布”整个流程压成一个技能里面充斥着互相冲突的条件分支Agent 大概率会堆砌出一堆没用的废话执行效果反而更差。另外一个容易被忽略的维度是技能应该倾向于定义“做事的方法和边界”而不是“一次性的具体答案”。我早期写过一个“数据库表设计 Skills”上去就是一整套模板要求 Agent 建表时必须有 created_at、updated_at 这些字段。这种写法看起来标准实际很死板——如果业务里有一张只读字典表这个技能就会开始胡说八道。后来我把它改成“先判断表的业务性质再决定是否需要审计字段”效果一下子好了很多。Skills 真正应该封装的是判断力和流程约束而不是具体答案。2.2 站在 Agent 的角度想它需要靠什么来命中一个技能不同的 Agent 在决定“该不该使用某个技能”时使用的机制不同但有一个共性是逃不开的它得能读懂你的技能描述。说白了你在技能文件的描述里写清楚“这个技能是做什么的、适用于什么场景、解决什么问题”Agent 才能在恰当的时机把它调用出来。这里我踩过一个大坑。早期我给一个测试技能写的描述是“单元测试相关”这个词过于宽泛导致 Agent 在写业务代码时都试着套这个技能动不动就硬塞一堆测试代码进来。后来我把它改成“当需要为 Python 后端新增函数编写单元测试时使用覆盖 pytest 风格与 mock 用法不用于前端代码测试”命中率才正常起来。这条经验放到任何 Agent 上都是通用的——描述写得越模糊Agent 乱调用的概率就越高描述写得越具体执行准确率就越高。2.3 核心机制为什么“同一个技能文件”能跑在多个 Agent 上讲到这你可能已经意识到了既然各家 Agent 读的是不同目录、不同格式那怎么才能共用一套文件我在实践里摸索出的方案并不是做一堆不同格式的镜像副本而是抓住一个核心思路——把技能内容的“描述与步骤”和“Agent 特有语法”分开。技能文件的“描述与步骤”部分用纯 Markdown 写这是各家 Agent 都能读的。涉及具体 Agent 特有能力的部分比如执行命令、读取上下文统一放到最外层通过环境变量或配置做隔离。然后写两个很薄的适配入口一个是 Claude Code 用的CLAUDE.md一个是 Codex 和其他工具兼容的AGENTS.md这两个文件只做“加载哪个技能、按什么顺序加载”这件事。这样整套技能的核心资产其实只有一份Agent 特有部分通过适配层去接。后面第三、四节我会展开讲这个方案的落地细节你照做就能复现。3. 从零到一写一套兼容多 Agent 的 Skills 的具体步骤3.1 目录结构规划兼顾项目级与全局级在实际操作里我会把 Skills 放在项目的.claude/skills目录下同时用AGENTS.md做跨 Agent 的配置入口。具体目录结构如下project_root/ ├── .claude/ │ ├── CLAUDE.md │ └── skills/ │ ├── code-review/ │ │ ├── SKILL.md │ │ └── prompt_templates/ │ │ └── frontend.md │ └── unit-testing/ │ ├── SKILL.md │ └── examples/ │ └── pytest_basic.md ├── AGENTS.md └── .codex/ └── skills/这个结构有几个好处。第一.claude/skills是 Claude Code 的约定路径它会自动递归读取这个目录下的所有技能。第二SKILL.md是通用的技能描述文件几乎所有 Agent 都能解析。第三AGENTS.md是目前 Codex、OpenCode 等工具通用的项目说明文件既可以用来说明项目背景也可以用来加载技能。3.2 SKILL.md 的写法要点frontmatter 和正文的分工SKILL.md 是一款技能的核心描述文件它的结构基本可以分成两段。第一段是 frontmatter也就是开头用三个短横线包起来的元信息部分至少要有name和description两个字段。第二段是正文用来写完整的执行流程和规范。我实际使用的模板长这样--- name: code-review description: 用于代码审查重点检查可维护性、边界情况和性能隐患。仅当用户要求审查代码或合并请求时使用。不用于解释代码逻辑。 --- # 代码审查技能 ## 目标 在代码合入前找出潜在缺陷和可读性问题。 ## 执行流程 1. 确认当前分支相对于主分支的变更范围。 2. 逐个文件审查关注 - 是否存在重复逻辑 - 异常处理是否完善 - 性能上是否有明显浪费 3. 输出问题时先给严重级别阻断/重要/建议再给具体位置和修改示例。 ## 注意事项 - 审查不是重写不要输出大段“更好的实现”。 - 如果发现的问题已经被注释说明视为已知问题不要重复提出。写这段的时候有几个关键点值得提醒。description里一定要包含“什么时候用”和“什么时候不用”这直接决定了 Agent 的命中率。正文部分的原则是“给边界、给流程、给输出格式”不要长篇大论讲理论Agent 不需要听你讲什么是代码整洁之道它只需要知道按什么顺序做什么检查、输出格式长什么样。3.3 给 Claude Code 和 Codex 分别写适配入口接下来就是兼容层的核心操作了。在项目根目录下创建CLAUDE.md和AGENTS.md两个文件的内容基本可以保持相同格式只在命令语法上做一点差异处理。举个例子我在CLAUDE.md里是这么写的## Skills 加载方式 当遇到以下任务时先加载对应技能再执行 - 代码审查任务加载 code-review 技能 - 单元测试任务加载 unit-testing 技能 加载方式读取 .claude/skills/技能名/SKILL.md 文件并按其中的执行流程操作。在AGENTS.md里我会用同样的逻辑但把技能目录扩展为“先读.claude/skills如果没有则读.codex/skills”## Skills 加载规则 - 代码审查任务加载 code-review 技能 - 单元测试任务加载 unit-testing 技能 技能目录顺序优先 .claude/skills/技能名/SKILL.md其次 .codex/skills/技能名/SKILL.md。这里为什么要把 CLAUDE.md 和 AGENTS.md 分开写原因在于 Claude Code 对 CLAUDE.md 有特殊的递归加载机制而 Codex 对 AGENTS.md 有支持。你完全可以期待 Codex 去读 CLAUDE.md 让它理解项目背景但如果你把技能相关的明确指令同时放在两个文件里兼容性会好很多。实际操作起来也没多花多少功夫复制 改一句路径描述就搞定了。3.4 一个完整技能的实战演练从需求到落地为了让你对上文有直观感受我完整演示一个“生成接口文档”技能从零到落地的过程。第一步先想清楚这个技能的边界。它要解决什么问题后端新增或修改 API 时按统一格式输出接口文档方便前端联调和后端自测。它不要管什么事情不负责生成 OpenAPI 规范文件不负责推送文档到在线平台。第二步创建技能目录和 SKILL.md。mkdir -p .claude/skills/api-doc touch .claude/skills/api-doc/SKILL.md然后写入以下内容--- name: api-doc description: 生成或更新 API 接口文档。当用户要求编写接口文档、补充接口说明或更新已有 API 文档时使用。不用于生成 OpenAPI 规范文件。 --- # API 接口文档生成技能 ## 目标 输出清晰可维护的接口文档格式统一。 ## 信息收集流程 1. 从代码中定位路由定义和对应处理函数。 2. 提取 HTTP 方法、路径、请求参数、请求体结构、响应体结构。 3. 如果代码中已有注释或类型定义优先使用缺失部分标注“待补充”。 ## 文档输出格式 - 接口名称 - HTTP 方法 路径 - 请求参数表字段名、类型、是否必须、说明 - 响应示例JSON 代码块 - 错误码说明如有 ## 注意事项 - 不要臆造参数代码里没有的参数不要出现在文档中。 - 参数说明要写用途不要只写类型。 - 如果接口和已有接口功能重复在文档里注明并建议合并。第三步在 CLAUDE.md 和 AGENTS.md 里都加上一段“当用户要求生成接口文档时加载 api-doc 技能”的说明。这套流程走完之后你在 Claude Code 里发一句“给这个登录接口写份文档”它就会按这套规范的格式输出换到 Codex 里问同样的问题它的行为也会基本一致。因为两者都能读到同一份 SKILL.md而且描述写得足够清晰。4. 让技能文件在不同 Agent 间平滑运行的几个关键策略4.1 指令设计少用“工具专属语法”多用“自然语言步骤”这是兼容多 Agent 的最高优先级原则。我见过有人把 Skills 写成这样“使用execute_command执行 pytest把输出重定向到report.txt”。这种写法只对特定 Agent 有效换一个工具命令引擎的名字都变了直接就废了。更好的写法是“运行测试命令生成测试报告文件 report.txt如果测试失败定位到第一个失败的用例分析可能原因并给出修复建议。”这样写Claude Code 能执行Codex 能执行OpenCode 也能执行——它们各有各的跑命令方式但你的指令里不含专属语法它们会用自己的方式完成同一件事。当然总有实在绕不开的专属能力比如某些 Agent 独有文件修改权限。这种时候我一般会在技能正文里加一段“实现提示”平台 A 可以这样实现平台 B 可以那样实现。写作风格上完全中性不自吹自擂就是朴实地列出来。4.2 用“Use Cases”和“校验规则”来弥补不同 Agent 的理解偏差不同模型对同一段自然语言的理解会有偏差写 Skills 时不能默认每个 Agent 都像你想的那样聪明。一个很有效的补救措施是在技能正文里增加两个固定章节专治理解偏差。Use Cases列出这个技能适用的典型场景至少写 3 个真实案例。校验规则列出 Agent 完成技能流程后需要自检的事项相当于给 Agent 一个“做完之后的检查清单”。以“代码审查技能”为例我在 Use Cases 里写了“审查前端组件的 props 边界”“审查 Node.js 回调函数的异常捕获”“审查数据库查询是否命中索引”。这些具体案例让 Agent 知道什么场景该套用这个技能。在校验规则里我写了“每个问题都必须给出对应文件路径和行号”“阻断级别的问题必须给出一个修改思路”。这样一来即使不同 Agent 本身的理解能力有差异它们输出的作品也算有个保底质量。4.3 命名规范小写、连字符、别用空格和特殊字符这个细节最不起眼但最能省事。技能目录名和name字段必须是小写字母加连字符比如code-review、api-doc、unit-testing。不要用空格不要用大写字母不要用下划线。原因很现实不同 Agent 对文件路径的解析方式不同空格和大写在 Windows 和 Linux 下会引发各种诡异问题。这套约定我吃过亏后来统一改规范后跨平台跨 Agent 的报错少了很多。同时还有一个隐藏的坑有些 Agent 对技能名称的索引逻辑会忽略特殊字符如果你的目录名是API_DOC_v2它在某些工具里可能被解析成apidocv2而你在执行指令里写的却是API_DOC_v2两边对不上技能就直接命中不了。所以名字越简单越稳定。4.4 测试你的兼容性从“一个 Agent 能跑”到“多个 Agent 都稳定”我在本地同时装了 Claude Code 和 Codex 两个 CLI 工具每写一套新技能都会在两个工具里用同一批测试用例各跑一遍。具体操作不复杂在 Claude Code 里发一条会触发技能的任务指令比如“审查一下 src/utils 下的代码”观察它是否加载了对应技能。把同样的话复述给 Codex看它的回答是否符合预期。如果两边输出差异大优先检查是不是技能描述有歧义其次检查是不是哪个文件路径写错了。反复迭代直到两边都输出稳定的结果。这套流程看起来原始却是最有效的。不同 Agent 对自然语言的理解方式不一致光靠读文档没法提前判断只能实测。我通常还会把测试命令整理成一个简单脚本每次改完技能文件跑一遍省得手动敲来敲去。5. 常见问题与排查技巧实录5.1 技能不生效先排除这三个原因技能文件写了、目录也放对了但 Agent 就是不按你的流程走这种情况我从新手期到现在见得太多了。八成以上问题出在三个地方描述命中不了技能里的 description 写得太笼统Agent 没有把它和当前任务建立关联。解决办法是增加场景关键词越具体越好比如把“写测试”改成“当要求为数据处理模块编写 pytest 单元测试时”。路径不正确你放技能的位置和 Agent 实际扫描的位置不一致。Claude Code 扫.claude/skillsCodex 部分版本扫.codex/skills如果你两边都没建对应目录它自然找不到。文件命名不规范目录名或文件名有空格、大写字母或特殊字符导致 Agent 解析失败。我把所有技能名统一成小写加连字符后这类问题基本绝迹。5.2 指令内容冲突多个技能互相打架怎么办当你积累了多套技能后会碰到一个新的烦恼——技能 A 说要这样做技能 B 又说要那样做Agent 当场陷入混乱。比如你有一套“通用代码审查技能”强调要关注性能和边界情况又有一套“前端安全审查技能”强调要关注 XSS 和数据脱敏。如果两个技能同时被加载Agent 可能会采用模糊的加权策略导致输出内容四不像。我的处理方式是在每个技能的 description 里明确写清楚“不适用”的场景尽量让技能的适用范围互斥。另外在 CLAUDE.md 和 AGENTS.md 里也可以给一个优先级提示比如“当安全审查技能命中时以它为准其他审查技能作为补充”。这个优先级写得越明确Agent 越不会乱。5.3 不同 Agent 对新技能格式的兼容程度不一样即使你已经做了一套很规范的兼容写法也不要指望每个 Agent 的解析行为百分之百一致。以 Codex 为例它对 AGENTS.md 的读取是比较积极的但对.claude/skills目录下的技能文件不同版本的行为可能不一样。OpenCode 早期版本对 SKILL.md frontmatter 的解析要求也比较严格如果你在 frontmatter 里写了过于复杂的嵌套结构它会直接跳过整个文件。所以我在实际使用中会把最重要的技能文件同时做一份.codex/skills下的副本虽然这在一定程度上违背了“单一来源”的理想但确实能规避不少兼容性问题。这个取舍到底划不划算取决于你对复现稳定性的要求有多高。5.4 写一套兼容 Skills 的避坑清单按我反复折腾下来的经验最后给你一份避坑清单别用绝对路径引用资源不同 Agent 的工作目录基准可能不同。别在技能正文里写“如果……那么……否则……”这种三层嵌套的条件Agent 很容易执行到中间就迷路。别把所有知识点都写进去技能不是知识库它是操作手册。别把模型能力限定死比如写“只能用 GPT-4 才能处理”感觉上很专业实际上不同 Agent 的模型选择权在你自己手里技能不用管。改完技能一定要在至少两个 Agent 里各跑一遍不然别拿出去说兼容。写在最后我的一点实际体会用了快半年的跨 Agent Skills 方案后我最深的感受是真正提升效率的并不是某个特定的 Agent 有多强而是你能不能用一套稳定的行为规范把多个工具拧成一股绳。SKILL.md 的兼容写法一开始会让人感觉有点繁琐但跑顺之后你只需要维护一份技能描述所有 Agent 都能以相同的方式理解你的要求这种一致性带来的省心程度是很高的。如果你正卡在“Claude Code 里能用的技能到 Codex 上就变傻”这个问题上我建议你先别急着改技能内容而是从目录结构和描述文本入手按这篇文章的方式做一层适配。很多时候问题出在路径和格式而不是技能逻辑本身。这套方法我验证过很多次希望也能帮你省下几小时的调试时间。