记一次 Codex 和 Claude Code 共用项目规范
项目里我主要还是用 Claude Code CLI。它的目录规范很清楚:CLAUDE.md、.claude/skills、.claude/agents,再加上用户目录下面的 ~/.claude。
但我现在也会在 Codex 里干活,于是就冒出一个很现实的问题:
一个项目同时给 Claude Code 和 Codex 用,skills 和 agents 到底放哪?
一开始我还想过软链接。后来发现不太靠谱,尤其项目要同时在 Win11 和 macOS 上开发,软链接这东西很容易变成另一个坑。
最后定下来的思路
我最后把 Claude Code 的目录当成源。
也就是:
text
CLAUDE.md
.claude/
skills/
agents/
Codex 这边只做本地镜像。
text
.codex/
config.toml
hooks.json
hooks/
sync-claude-to-codex.mjs
agents/
.gitkeep
*.toml # 生成,不提交
.agents/
skills/ # 生成,不提交
CLAUDE_BRIDGE.md # 生成,不提交
claude-sync-manifest.json
简单说就是:
.claude是源头.codex放 Codex 的 hook 配置和脚本.agents/skills放 Codex 能读取的项目级 skills.codex/agents/*.toml放 Codex 能读取的项目级 agents- 生成物都不提交
这样团队成员如果不用 Codex,也不会被这些生成文件污染。
Hook 配置
Codex 的 Hook 不是随便放个脚本就行,还是要写 .codex/hooks.json。
我现在的配置大概是这样:
json
{
"description": "Sync Claude Code project skills and agents into local Codex bridge output.",
"hooks": {
"SessionStart": [
{
"hooks": [
{
"type": "command",
"command": "node .codex/hooks/sync-claude-to-codex.mjs",
"timeout": 30
}
]
}
],
"UserPromptSubmit": [
{
"hooks": [
{
"type": "command",
"command": "node .codex/hooks/sync-claude-to-codex.mjs",
"timeout": 30
}
]
}
]
}
}
SessionStart 是启动时同步一次。
后来我又加了 UserPromptSubmit,因为我发现有时候启动时没看到生成结果,或者生成顺序比 Codex 扫描 skills 晚。加上这个之后,至少提交第一条提示词时还能补一次。
还有一个小坑,feature flag 现在要写:
toml
[features]
hooks = true
之前的 codex_hooks = true 已经过期了,会有 warning。
名字不要乱加前缀
一开始我给生成出来的 skill 和 agent 加了项目名前缀,比如:
text
claude-react-nnnnzs-cn-glb-model-inspector
看起来很稳,不会冲突。
但后来想想,这东西本来就是项目目录级别的,没必要这么长。
现在就保持和 Claude Code 源名字一致:
text
.claude/skills/glb-model-inspector
↓
.agents/skills/glb-model-inspector
.claude/agents/feature-planner.md
↓
.codex/agents/feature-planner.toml
这样看起来舒服很多。
真正踩坑的是 Windows 权限
我删掉生成目录以后,重新启动 Codex,发现 Hook 没有正常重新生成。
一开始我以为是 Hook 没触发。
后来手动跑脚本才发现,真凶是权限。
在当前 Codex 沙箱里,.codex 目录下面有额外的 ACL 限制,普通 hook 执行时不一定能新建 .codex/agents,甚至写 .codex/agents/*.toml 也可能失败。
但是 .agents/skills 能正常写。
所以脚本最后做了两个处理:
.codex/agents/.gitkeep提交进仓库,保证目录一直存在- agent 生成失败时只打 warning,不让整个 hook 失败
也就是说,skills 一定尽量恢复,agents 如果当前环境没权限写,就跳过。
有完整权限的时候,agents 还是会生成到官方路径:
text
.codex/agents/doc-sync-specialist.toml
.codex/agents/feature-planner.toml
AGENTS.md 也别写太多
我一开始把 AGENTS.md 写得很详细,后来发现和 .codex/README.md 重复了。
其实给大模型看的东西不应该太啰嗦。
最后我只保留了几句:
md
# Codex Instructions
Use @CLAUDE.md as the source of truth for this project.
Claude Code assets in `.claude/` are mirrored locally for Codex by the project hook. Do not edit generated bridge files; update the `.claude/` source instead.
这就够了。
详细的目录解释、Hook 说明,放 .codex/README.md 给人看。
最后
这套方案现在看起来比较舒服:
- Claude Code 继续用自己的
.claude - Codex 用 hook 自动同步
- 生成物不进 git
- Win11 和 macOS 都不依赖软链接
- 项目规范只有一份源头
说实话,这事本身不复杂,复杂的是两个工具都在快速变,目录规范、feature flag、hook 事件名这些都可能变。
所以我现在的态度是:源头尽量少,生成物尽量本地化,能不软链就不软链。
少一点玄学,多一点可删了重来的东西。