Claude Code 与 Codex 协同使用指南

通过 codex exec 和 claude -p,让 Claude Code 与 Codex 在同一个终端工作流中双向调用。

Claude Code 和 Codex 都是可以独立运行的编码 Agent,也都提供了适合脚本调用的非交互模式。只要把其中一个 CLI 当作另一个 Agent 可执行的命令,就能实现双向协作:

Claude Code  -- codex exec -->  Codex
Codex        -- claude -p  -->  Claude Code

这不是让两个 Agent 无限制地互相对话,而是由当前主 Agent 发起一次有明确输入、权限和输出格式的子任务,等待另一个 Agent 返回结果后继续工作。

<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 920 360" role="img" aria-label="Claude Code 与 Codex 的三种协同方式">
  <rect width="920" height="360" rx="8" fill="#f7f7f5"/>

  <rect x="55" y="72" width="230" height="100" rx="8" fill="#e9f2ff" stroke="#202124" stroke-width="2"/>
  <text x="170" y="113" text-anchor="middle" font-family="Arial, sans-serif" font-size="23" font-weight="700" fill="#202124">Claude Code</text>
  <text x="170" y="144" text-anchor="middle" font-family="Arial, sans-serif" font-size="16" fill="#4b5563">claude -p</text>

  <rect x="635" y="72" width="230" height="100" rx="8" fill="#eaf7ec" stroke="#202124" stroke-width="2"/>
  <text x="750" y="113" text-anchor="middle" font-family="Arial, sans-serif" font-size="23" font-weight="700" fill="#202124">Codex</text>
  <text x="750" y="144" text-anchor="middle" font-family="Arial, sans-serif" font-size="16" fill="#4b5563">codex exec</text>

  <path d="M295 100 H625" fill="none" stroke="#2563eb" stroke-width="3"/>
  <path d="M612 91 L628 100 L612 109" fill="none" stroke="#2563eb" stroke-width="3"/>
  <text x="460" y="88" text-anchor="middle" font-family="Arial, sans-serif" font-size="15" fill="#1d4ed8">codex exec</text>

  <path d="M625 147 H295" fill="none" stroke="#15803d" stroke-width="3"/>
  <path d="M308 138 L292 147 L308 156" fill="none" stroke="#15803d" stroke-width="3"/>
  <text x="460" y="169" text-anchor="middle" font-family="Arial, sans-serif" font-size="15" fill="#166534">claude -p</text>

  <path d="M460 196 V239" fill="none" stroke="#202124" stroke-width="2.5"/>
  <path d="M451 226 L460 242 L469 226" fill="none" stroke="#202124" stroke-width="2.5"/>

  <rect x="245" y="247" width="430" height="72" rx="8" fill="#fff4d8" stroke="#202124" stroke-width="2"/>
  <text x="460" y="277" text-anchor="middle" font-family="Arial, sans-serif" font-size="19" font-weight="700" fill="#202124">可观察会话与插件化连接</text>
  <text x="460" y="303" text-anchor="middle" font-family="Arial, sans-serif" font-size="15" fill="#4b5563">tmux session · app-server · job</text>
</svg>

本文介绍三种组织方式:

方式运行载体上下文与结果
非交互 CLIcodex exec / claude -p 子进程每次传入完整任务,通过标准输出、JSON 或文件返回结果
CatPaw 可观察会话tmux 中的 claude / codex 交互进程同一进程承接多轮输入,通过 session 状态和终端输出观察进展
codex-plugin-ccCodex app-server、后台 Worker 和本地 jobthread 保存会话,turn 执行任务,job 记录状态、日志与结果

前置条件

先确认两个 CLI 都已安装、登录,并且可以在当前项目目录单独运行:

claude --version
codex --version

如果使用第三方 Provider,可以先参考:

只有两个 CLI 各自可用后,互相调用才容易排查问题。

方式一:非交互 CLI 调用

这种方式直接使用两个 CLI 的非交互入口。每次调用接收一段明确输入,执行完成后通过标准输出、JSON 或文件返回结果。

Claude Code 调用 Codex

Codex 的非交互入口是 codex exec。在 Claude Code 会话中,可以直接要求 Claude 执行下面的命令:

以下命令使用 Bash/zsh 语法,Prompt 统一通过标准输入传递:

printf '%s\n' \
  "审查当前工作区的改动。重点检查行为回归、边界条件和遗漏测试,只报告具体问题,不修改文件。" \
  | codex --sandbox read-only --ask-for-approval never exec --ephemeral -

codex exec 会在当前目录读取项目上下文,任务结束后把最终结果写到标准输出,Claude Code 可以继续读取和处理。

需要把结果保存下来时,可以使用 -o:

mkdir -p .tmp
printf '%s\n' "审查当前 git diff,只报告可复现的问题。" \
  | codex --sandbox read-only --ask-for-approval never exec \
      --ephemeral \
      -o .tmp/codex-review.md \
      -

这里把权限限制为 read-only,适合代码审查和方案复核。确实需要 Codex 修改文件时,再明确授予工作区写权限,并避免两个 Agent 同时编辑相同文件。

Codex 调用 Claude Code

Claude Code 的非交互入口是 claude -p,其中 -p 等价于 --print。在 Codex 会话中,可以要求 Codex 执行:

(
  printf '%s\n\n' "结合当前项目审查下面的 git diff。从架构一致性、可维护性和遗漏场景三个方面复核,不要修改文件。"
  git diff HEAD --no-ext-diff
) | claude -p \
      --no-session-persistence \
      --safe-mode \
      --permission-mode plan \
      --strict-mcp-config \
      --tools "Read,Grep,Glob"

Claude Code 完成任务后会把结果写到标准输出,Codex 可以将它作为第二意见继续分析。

git diff HEAD 会同时包含已暂存和未暂存的 tracked changes。未跟踪文件不会出现在 diff 中,需要先用 git add -N <path> 将其标记为 intent-to-add,或者在提示词中单独列出。

如果调用方需要稳定解析结果,可以指定 JSON 输出:

(
  printf '%s\n\n' "检查下面的 git diff,只做审查,不修改文件。"
  git diff HEAD --no-ext-diff
) | claude -p \
      --output-format json \
      --no-session-persistence \
      --safe-mode \
      --permission-mode plan \
      --strict-mcp-config \
      --tools "Read,Grep,Glob"

为了限制 Claude Code 可使用的内置工具,可以通过 --tools 明确收窄范围。例如只允许读取和搜索代码:

printf '%s\n' "检查当前实现是否遗漏错误处理,只输出结论和文件位置。" \
  | claude -p \
      --no-session-persistence \
      --safe-mode \
      --permission-mode plan \
      --strict-mcp-config \
      --tools "Read,Grep,Glob"

这里由 --tools 限制可用的内置工具,--strict-mcp-config 在没有传入 --mcp-config 时阻止加载已有 MCP,--safe-mode 则关闭 CLAUDE.md、Skills、插件和 Hooks 等自定义项。--allowedTools 只控制哪些工具无需再次请求权限,不用于收窄工具集合。

双向调用的关键

无论从哪一边发起,稳定的调用都包含四部分:

部分作用
工作目录让被调用方看到同一个仓库和工作区状态
明确任务说明要审查、分析还是修改,以及期望的结果
权限边界默认只读,写文件、运行高风险命令时再单独放开
可回收输出使用标准输出、JSON 或输出文件交还结果

调用时不必把整个会话历史塞进提示词。更稳妥的做法是让被调用方直接读取仓库,只补充它无法从文件和 git diff 中知道的信息,例如设计目标、已排除的方案和验收标准。

避免递归调用

双向可调用不等于应该形成调用环。最危险的情况是:Claude Code 调用 Codex 后,Codex 又按照项目指令调用 Claude Code,随后继续循环。

建议在子任务中明确加入边界:

这是由另一个 Agent 委托的一次性子任务。
不要再次调用 claude 或 codex CLI。
完成分析后直接返回最终结果。

同时遵循两个原则:

  • 一次任务只指定一个主 Agent,另一个只作为子任务执行者。
  • 子 Agent 返回结果后结束,由主 Agent 决定是否采纳和继续修改。

一个实用分工

互相调用最有价值的地方不是让两个 Agent 重复完成同一件事,而是把第二个 Agent 当作独立复核者:

主 Agent:理解需求、修改代码、运行验证
子 Agent:只读审查、挑战假设、指出遗漏
主 Agent:核对意见、决定是否修正

例如,主要在 Claude Code 中实现功能时,让 Codex 审查当前 diff;主要在 Codex 中工作时,则用 claude -p 做一次独立复核。这样既保留当前会话的连续性,也能获得不同 Agent 的判断。

方式二:CatPaw 可观察会话

shiqkuangsan/catpaw 使用 tmux 创建可观察的后台终端,并在其中运行 Claude Code 或 Codex 的交互进程。主 Agent 通过 CatPaw 命令投递输入、查看状态和读取终端输出:

主 Agent
  -> CatPaw 命令
  -> tmux 后台会话
  -> claude / codex 交互进程

项目 README 使用 catpaw 作为入口简写。安装后的实际入口是 ~/.catpaw/bin/catpaw.mjs,可以在当前 shell 中建立别名:

alias catpaw='node ~/.catpaw/bin/catpaw.mjs'

在源码仓库中使用时,也可以把命令替换为 node /abs/catpaw/src/runtime/bin/catpaw.mjs。

CatPaw 提供的会话生命周期是:

catpaw agent open
catpaw agent send
catpaw agent status
catpaw agent read
catpaw agent close

例如,在当前项目中打开一个 Codex 审查会话:

catpaw agent open \
  --agent cx \
  --label contract-review \
  --project /abs/project

向同一个会话继续发送任务:

catpaw agent send \
  --agent cx \
  --label contract-review \
  --project /abs/project \
  --prompt "继续检查错误处理和边界条件,不要修改文件。"

随后可以查看状态和最近输出:

catpaw agent status --agent cx --label contract-review --project /abs/project
catpaw agent read --agent cx --label contract-review --project /abs/project --lines 200

每条 CatPaw 命令完成操作后退出;tmux server 和其中的 Claude Code 或 Codex 交互进程持续运行。后续 send 会把新输入投递给同一个进程,因此多轮输入共享该交互会话的上下文。

CatPaw 根据 Agent、项目绝对路径和任务 label 生成稳定的 tmux session 名。底层通过 load-buffer、paste-buffer 和 send-keys 投递 Prompt,通过 capture-pane 读取输出。status 会整理以下会话状态:

  • session 是否仍然存在;
  • Provider 进程是否退出以及退出码;
  • 终端输出相对上次检查是 changed 还是 stable;
  • 输出中是否出现明确的等待输入或等待批准提示。

changed 和 stable 描述两次检查之间终端输出是否发生变化;完成判断由主 Agent 在执行 read、读取实际输出后作出。

会话上下文如何保持

tmux 保持交互进程和终端输出,终端断开后仍可以重新连接该 session。CatPaw 的交互模式保留 Claude Code 和 Codex 各自默认的原生会话持久化机制;需要跨进程继续时,可以从对应 Provider 的 claude --resume 或 codex resume 入口重新打开会话。

tmux 可在 Linux、macOS 和 Windows WSL 环境中运行。CatPaw 使用同一组 open、send、status、read、close 命令管理两种 Agent 会话。

方式三:codex-plugin-cc 的 app-server 与 job

OpenAI 的 openai/codex-plugin-cc 是一个现成实例。它封装的是 Claude Code → Codex 这一侧,可以在 Claude Code 中安装:

插件要求 Node.js 18.18 或更高版本,安装前先确认:

node --version
/plugin marketplace add openai/codex-plugin-cc
/plugin install codex@openai-codex
/reload-plugins
/codex:setup

安装后,Claude Code 可以通过 slash command 把任务交给 Codex:

/codex:review --background
/codex:status
/codex:result

这些 slash command 由插件脚本转换成 app-server 请求,并通过本地 job 状态记录后台任务。

它的实现思路

它的大致调用链是:

Claude Code slash command
  -> commands/*.md
  -> scripts/codex-companion.mjs
  -> Codex app-server
  -> Codex thread / turn / review
  -> job 状态与结果

各层分别负责不同的事情:

层作用
commands/*.md定义 Claude Code 中的命令入口、参数和允许使用的工具
codex-companion.mjs解析任务、启动 Codex、记录 job,并处理状态、结果和取消操作
Codex app-server创建 thread,执行 turn 或 code review,并持续返回事件
本地任务状态让耗时任务可以在后台运行,稍后再读取结果

/codex:review --background 发起任务后,Worker 在后台接收 app-server 事件,并持续更新 job。/codex:status 读取 job 状态和进度日志,/codex:result 读取任务完成后保存的输出。

插件还提供 /codex:transfer,把当前 Claude Code 会话整理后交给一个可通过 codex resume 继续的 Codex thread。可选的 stop hook 则可以在 Claude Code 准备结束任务时触发 Codex 审查,发现问题时阻止过早收工。

Thread 与 job 如何配合

app-server 使用 thread 保存 Codex 会话,使用 turn 表示 thread 中的一轮执行。插件的 job 则记录 Claude Code 发起的后台委托,包括状态、进程、threadId、turnId、日志和最终结果:

Claude Code command
  -> job
  -> app-server thread
  -> turn
  -> 事件与结果回写 job

任务继续执行时,插件可以用已保存的 threadId 调用 thread/resume,再启动新的 turn。/codex:cancel 通过 turn/interrupt 中断执行,并同步更新 job 状态;/codex:transfer 则把 Claude Code 会话导入一个可由 codex resume 打开的 Codex thread。

安全边界

  • 默认让被调用方只读,审查任务不要授予写权限。
  • 不要在提示词或输出文件中传递 API Key、Cookie、SSH Key 等敏感信息。
  • 不要让两个 Agent 在同一工作区同时修改文件。
  • 涉及删除、迁移、发布、推送和部署时,由主 Agent 或人工确认。
  • 把临时结果写入项目已有的临时目录,并避免误加入 Git。

总结

双向互调依赖的是两个 CLI 的非交互接口:

# Claude Code -> Codex
printf '%s\n' "任务" \
  | codex --sandbox read-only --ask-for-approval never exec --ephemeral -

# Codex -> Claude Code
printf '%s\n' "任务" \
  | claude -p \
      --no-session-persistence \
      --safe-mode \
      --permission-mode plan \
      --strict-mcp-config \
      --tools "Read,Grep,Glob"

选定一个主 Agent,把另一个当作边界明确的一次性子任务执行者,再通过标准输出或文件取回结果,就能组成简单、透明、可控制的协作链路。

参考资料