OpenCode / ClaudeCode / Codex Skills 等文件夹兼容性对比
多个维度(Instructions / Skills / Commands / Agents / Hooks / Rules / MCP / 配置文件)逐项拆解
- 直接读:skills 文件内容基本上能得到三家互认。
- 搬目录:commands / agents 从
.claude/复制到.opencode/,内容通常能复用。 - 要重写:hooks(配置 vs JS/TS 模块)/ config(JSON vs TOML)范式不同。
- 软链共享:用
.shared/+ 软链把 skills / AGENTS.md 做成单一源;其他目录格式 / 范式不同,必须独立维护。 - Skills 互认:遵循 Agent Skills 开放标准,最低 SKILL.md 可直接迁移。
一图看懂:三个工具的兼容性矩阵
| 对比维度 | ClaudeCode | Codex | OpenCode |
|---|---|---|---|
| Instructions | CLAUDE.md | AGENTS.mdCLAUDE.md(需配置)1 | AGENTS.mdCLAUDE.md(fallback) |
| Skills | .claude/skills/ | .agents/skills/ | .opencode/skills/.agents/skills/.claude/skills/ |
| Commands | .claude/commands/ | 不支持(仅内置) | .opencode/commands/ |
| Agents | .claude/agents/(markdown) | .codex/agents/(TOML) | .opencode/agents/(markdown) |
| Hooks | .claude/settings.json.claude/hooks/ 是脚本存放约定,不自动加载2事件: PreToolUse / PostToolUse 等 | .codex/hooks.json 或 .codex/config.toml没有 .codex/hooks/ 目录事件: PreToolUse / PostToolUse / SessionStart 等 | .opencode/plugins/*.{js,ts}没有 .opencode/hooks/ 目录事件: tool.execute.before / tool.execute.after 等 |
| Rules | .claude/rules/*.md(paths frontmatter)3 | .codex/rules/(prefix_rule)4 | 不支持 |
| MCP | .mcp.json5字段: mcpServers类型: stdio / http | .codex/config.toml字段: [mcp_servers.<name>]类型: stdio / http | opencode.json6字段: mcp类型: local / remote |
| 配置文件 | .claude/settings.json | .codex/config.toml | opencode.json6 |
-
"需配置"是什么意思:Codex 默认只读
AGENTS.md——CLAUDE.md要在config.toml里显式加上才会读:project_doc_fallback_filenames = ["CLAUDE.md"]不写这一行,
CLAUDE.md就被忽略。和 OpenCode 的CLAUDE.md自动 fallback 形成对比。 -
"不自动加载"是什么意思:放在
.claude/hooks/xxx.sh的脚本不会自己跑——必须在~/.claude/settings.json或.claude/settings.json里用hooks.<event>.hooks[].command字段显式引用脚本路径才会触发。常见配置:{"hooks": {"PostToolUse": [{"matcher": "Edit|Write","hooks": [{ "type": "command", "command": "${CLAUDE_PROJECT_DIR}/.claude/hooks/format.sh" }]}]}}不放 settings.json 引用的话,
.claude/hooks/里的脚本就是孤儿文件,Claude Code 永远不会执行。所以叫"约定俗成的脚本存放位置"——目录是给人看的,不是工具读的。 -
"paths frontmatter"是什么:Claude Code 规则文件顶部用 YAML 写
paths字段,只在 Claude 操作匹配这些 glob 模式的文件时才加载规则:---paths:- "src/api/**/*.ts"- "lib/**/*.ts"---# API 开发规则- 所有 API 端点必须做入参校验不写
paths字段的规则文件无条件加载(每次会话都进上下文)。paths支持 glob 模式:模式 匹配 **/*.ts所有 TypeScript 文件 src/**/*src/目录下所有文件*.md项目根的 markdown src/components/*.tsx特定目录的 React 组件 -
"prefix_rule"是什么:Codex 规则系统用函数式语法
prefix_rule()定义命令前缀 + 决策(allow / deny / ask),比 Claude Code 的路径作用域更底层——直接拦截 shell 命令前缀而不是加载提示词:prefix_rule(pattern = ["git"], decision = "allow")prefix_rule(pattern = ["rm", "-rf"], decision = "deny")prefix_rule(pattern = ["sudo"], decision = "ask")pattern:匹配的命令前缀数组(按 token 匹配,不是正则)decision:匹配后 Codex 的处理方式(allow直接执行、deny直接拒绝、ask询问用户)
规则文件用
codex execpolicy check <cmd>测试是否被拦截。和 Claude Code 的差异:Claude 用 prompt 引导("操作这些文件时..."),Codex 用命令拦截("这些命令前缀...做...")——一个在输入端劝导,一个在执行端强制。 -
.mcp.json不在.claude/下:Claude Code 大部分配置(settings.json/rules//hooks//agents//skills/)都藏在.claude/里,但.mcp.json是例外——它在项目根,和package.json同级。原因是设计上要git add进去让团队共享(参考 Claude Code MCP 文档 - project-scope 小节):{"mcpServers": {"context7": {"type": "stdio","command": "npx","args": ["-y", "@upstash/context7-mcp"]}}}如果想团队共享某个 MCP 配置:放在项目根
.mcp.json(commit 进去);如果只想本地用:放~/.claude.json(不 commit)。 -
opencode.json也不在.opencode/下:OpenCode 把所有东西都藏进.opencode/(agents / commands / skills / plugins)——但主配置文件是例外,放在项目根,和package.json同级。和 Claude Code 的.mcp.json(见注脚 5)是同一种设计哲学:让工具的核心配置git add进版本控制,方便团队共享。{"$schema": "https://opencode.ai/config.json","model": "anthropic/claude-sonnet-4-6"}如果想团队共享:放在项目根
opencode.json(commit 进去);如果只想本地用:放~/.config/opencode/opencode.json(不 commit)。
关键限定:OpenCode 的原生目录是 .opencode/——表格里 Skills 行那三个并列的路径(.opencode/、.claude/、.agents/)只对 skills 成立。所有 commands / agents 必须放 .opencode/ 下,.agents/commands/、.agents/agents/ 这类路径不会被读取。换句话说,.agents/ 只在 skills 这一层作为兼容路径存在,不要把它当成 OpenCode 的"通用命名空间"。
Codex 的目录命名约定:.agents/ vs .codex/
矩阵表里 Codex 那列混用了 .agents/ 和 .codex/ 两种前缀——别搞混,两个前缀用途完全不同:
| 前缀 | Codex 放什么 | 跨工具吗 |
|---|---|---|
.agents/ | Skills(.agents/skills/、~/.agents/skills/) | ✅ OpenCode / Claude Code 也读 |
.codex/ | config / rules / agents / hooks(.codex/config.toml、.codex/rules/、.codex/agents/ 等) | ❌ Codex 专属 |
简单记法:
.agents/= "agent 生态通用"的命名空间——OpenAI 刻意选了中立前缀,方便和 OpenCode / Claude Code 互操作(只对 skills 有效).codex/= "Codex 自己"的命名空间——所有 Codex 特有的配置、规则、agents、hooks 都放这里
这是 Codex 和 Claude Code 的关键设计差异:Anthropic 把所有东西塞在 .claude/(自家品牌),OpenAI 把"通用"和"自家"分开放。结果就是:Codex 的 skills 天然能跨工具用(.agents/skills/ 是中立前缀),但 agents / rules 必须重新实现(.codex/ 没工具认)。
三个工具的 Skills 语法兼容性
三家 skill 格式层完全统一——都遵循 Agent Skills 开放标准。SKILL.md 的最低要求在三个工具里一致:
---
name: my-skill # 必填,kebab-case,要和目录名一致
description: ... # 必填,告诉模型什么时候触发
---
# Skill 正文(markdown 指令)
最低要求下,一个 SKILL.md 可以塞到任意一个工具的 skills 目录直接用——三家互认。
工具专属扩展(frontmatter 字段)
最低要求之外,三家各自加了私有字段。这些字段不互通——一家写的,另一家会忽略但不会报错:
| 字段 | ClaudeCode | Codex | OpenCode |
|---|---|---|---|
name | ✅ 必填 | ✅ 必填 | ✅ 必填 |
description | ✅ 必填 | ✅ 必填 | ✅ 必填 |
license | ✅ 通用 | ✅ 通用 | ✅ 通用 |
compatibility | ✅ 通用 | ✅ 通用 | ✅ 通用 |
metadata | ✅ 通用 | ✅ 通用 | ✅ 通用 |
disable-model-invocation | ✅ Claude 专属 | ❌ 不识别 | ❌ 不识别 |
paths(路径作用域触发) | ✅ Claude 专属 | ❌ 不识别 | ❌ 不识别 |
| Codex 专属字段 | ❌ 不识别 | ✅ Codex 专属 | ❌ 不识别 |
| OpenCode 专属字段 | ❌ 不识别 | ❌ 不识别 | ✅ OpenCode 专属 |
通用字段三家都认,但实际"工具专属"字段(如下面的
disable-model-invocation)只有那个工具会用——其他工具默默忽略,不会报错。
实战建议
写跨工具 skill 时只写最低要求字段:
---
name: deploy-staging
description: Deploy current project to staging environment. Use when the user asks to deploy or push to staging.
---
# Deploy to Staging
1. Run `pnpm build`
2. Run `pnpm test`
3. Deploy to staging server via `pnpm deploy:staging`
这种 skill 放到 .opencode/skills/、.claude/skills/、.agents/skills/ 都能跑——三个工具都会按 description 触发。
如果要用工具独有特性(比如 Claude 的 disable-model-invocation 让用户手动 /skill-name 才触发,不让模型自动调用),就要为那个工具单独写一份,不能共享。
资源目录也通用
SKILL.md 同级可以放 scripts/、references/、assets/ 等子目录,三家都认——子目录里可以放脚本、模板、参考资料,模型会按 SKILL.md 里的指引去读。
用软链接共享同一份文件
既然矩阵表里有不少重复扫描的目录(OpenCode 同时读 .opencode/、.claude/、.agents/;Codex 也读 .agents/skills/ 和 .claude/skills/ 等),用软链接把同一份文件映射到多个目标就能避免复制——一份源文件,多个工具共享。
1. 共享 skill 文件夹
把 skills 放在一个源目录,每个工具的 skills 目录建软链接指过去:
# 假设 skills 放在 .shared/skills/
mkdir -p .shared/skills
# 三个工具的 skills 目录都指向同一个源
ln -s ../.shared/skills/deploy-staging .opencode/skills/deploy-staging
ln -s ../.shared/skills/deploy-staging .claude/skills/deploy-staging
ln -s ../.shared/skills/deploy-staging .agents/skills/deploy-staging
改一份全部生效——不用在三个工具分别维护。
2. CLAUDE.md ↔ AGENTS.md 别名
矩阵 Instructions 行显示两家都读 AGENTS.md(OpenCode 主选)+ CLAUDE.md(Claude 主选 / OpenCode fallback)。用软链接让两个文件名指向同一份内容:
# 实际写一份 AGENTS.md,CLAUDE.md 用软链接指向它
echo "# Project rules..." > AGENTS.md
ln -s AGENTS.md CLAUDE.md
这样:
- Claude Code 读
CLAUDE.md(它的主选) - OpenCode 读
AGENTS.md(主选)+CLAUDE.md(fallback)——两个文件名同一个内容,零冲突 - Codex 读
AGENTS.md(它的原生)
3. 跨命名空间映射
如果你已经在 .claude/skills/ 下维护了一套 skills,想让 Codex 和 OpenCode 也能用,最省事的是软链接映射:
# 让 Codex 和 OpenCode 直接读 Claude 维护的 skills
ln -s ../.claude/skills .agents/skills # Codex 看得到
ln -s ../.claude/skills .opencode/skills # OpenCode 看得到
或者反过来——
# 维护一份共享 skills,让 Claude Code 也能用
mkdir -p .shared/skills
ln -s ../.shared/skills .claude/skills
4. 跨项目共享
软链接还能跨项目边界——比如把全局共享的规则放在 ~/.config/shared/,再软链接到每个项目:
mkdir -p ~/.config/shared/rules
ln -s ~/.config/shared/rules ~/projects/project-a/.claude/rules
ln -s ~/.config/shared/rules ~/projects/project-b/.claude/rules
Claude Code 文档显式支持这种用法("symlinks are resolved and loaded normally, and circular symlinks are detected and handled gracefully")。