ai-agent-ops /

Claude Code vs Codex:役割分担の実践論

設計をClaude Code、実装をCodexに分ける運用に落ち着くまでに、Windowsで書き込めない問題、WSL越しにgitが壊れる問題、未コミットの変更を消した事故を踏みました。実測ログとともに、なぜこの分担なのかを書きます。

Claude CodeとCodexを併用し、設計・レビューをClaude Code、実装をCodexに分けて運用しています。

この記事は「どちらが優秀か」の比較ではありません。この分担にたどり着くまでに何を踏んだかの記録です。結論から言うと、私の分担は賢さの比較ではなく、環境の制約から逆算して決まりました。

そして記事の最後で、その制約がすでに消えていたことを書きます。


最初に決めた分担

出発点はシンプルでした。

役割 担当 やること
設計・レビュー Claude Code 要件を実装指示書に落とす、実装後のレビュー、git操作
実装 Codex 指示書だけを読んでコードを書く

分ける理由は、同じモデルが自分の書いたコードを自分でレビューすると見落とすからです。実装フェーズと検証フェーズを別のモデルに分ければ、片方の判断をもう片方が検証する形になります。

方針としては素直です。問題は、これがそのままでは動かなかったことです。

つまずき1:Codexが Windows でファイルを書けなかった

2026年7月14日、codex exec に何を渡しても apply_patch が通りませんでした。

実測したエラーは次の3種類です(codex-cli 0.144.4)。

# -c default_permissions=":workspace" を指定
patch rejected: writing outside of the project; rejected by user approval settings

# -s workspace-write を指定
patch rejected: writing is blocked by read-only sandbox

現物をディスクで確認して、1バイトも作られていませんでした。

潰した仮説(全部外れました)

設定ミスだと思い込んで、半日を溶かしました。試して外れたものを並べます。

試したこと 結果
-c default_permissions=":workspace" 効果なし
-s workspace-write 効果なし
--add-dir <リポジトリ> 効果なし
--ignore-rules 効果なし
[permissions.<name>.filesystem] に絶対パスを名指しで write 効果なし
書き込み先を隠しディレクトリから通常ファイルへ変更 効果なし

疑って外れた原因も書いておきます。trust未登録(登録済みでした)、gitignore対象だから、隠しディレクトリだから、パスがジャンクションだから(LinkType が空=リンクではありませんでした)。codex doctor は作業ディレクトリもリポジトリのルートも正しく認識していました。

設定では直りませんでした。Codex側の未修正バグでした。当時参照した Issue は次の4件です。

  • openai/codex#6667 — Sandbox mode always set to readonly even if set to workspace_write in config.toml
  • openai/codex#15850 — Windows workspace-write sandbox still broken after state reset; bypass mode works
  • openai/codex#13574 — apply_patch fails under sandboxed default permission on Windows
  • openai/codex#6374 — Codex running Read-Only even when Sandbox set to danger-full-access

唯一知られていた回避策は --dangerously-bypass-approvals-and-sandbox でしたが、サンドボックスを丸ごと無効にするため使いませんでした。

一度、役割を逆にしました

「Codex=実装」が原理的に成立しないなら、書き込みを要するフェーズをClaudeに、読み取りだけで完結するフェーズをCodexに渡せばよい。そう考えて、2026年7月14日に役割を入れ替えました。

入れ替え前 入れ替え後
設計・レビュー Claude Code Codex
実装・修正 Codex Claude Code

二モデルで相互チェックするという狙いは、入れ替えても保たれます。

このとき、Codexの読み取りは正常に動くことも確認できました。git status --short git diff --cached git diff rg --files はすべて exit 0 を返し、Codexは差分とファイル一覧を正確に要約しました。レビュー役としては成立していました。

なお blocked by policy というエラーは「PowerShellが禁止されている」という意味ではありませんでした。複数の処理を1本にまとめた複合コマンドが弾かれるだけで、素の git diff や rg は通ります。しかもCodexは弾かれると自力で単純なコマンドに分割して再試行し、成功します。実用上は問題になりませんでした。

WSLなら書けると分かって、元に戻しました

翌7月15日、WSL上の同一バージョンなら書けることを実測しました。

環境 codex-cli 結果
Windows・リポジトリ直下 0.144.4 / 0.144.1 ❌ patch rejected: writing outside of the project
WSL2 / Ubuntu 24.04・ext4 0.144.4 ✅ patch: completed / exit 0
WSL2 / Ubuntu 24.04・/mnt/c 越しの実リポジトリ 0.144.4 ✅ patch: completed / exit 0

起動時のバナー表示(approval: never / sandbox: workspace-write)も同一でした。差分はOSだけです。Windows固有のバグだと確定しました。

これで役割を戻せます。実装側の変更は小さく済みました。

// 変更前: codex を直接起動
spawn("codex", ["exec", "--json", ...])

// 変更後: wsl 経由にするだけ
spawn("wsl", ["--", "codex", "exec", "--json",
              "-c", 'default_permissions=":workspace"'], { shell: false })

JSONLのパーサも、プロセスの停止処理も、イベントの正規化も、すべて無変更で流用できました。wsl.exe は実体のあるexeなので shell: true が不要になり、以前入れていた ENOENT 対策はむしろ削除できました。

追加したのは、パスを変換する小さな関数1つだけです。

// spawn の cwd は wsl.exe が /mnt/c/... へ自動変換して引き継ぐ。
// ただしプロンプトに埋め込む絶対パスは変換されない(実測)。
export function toWslPath(winPath: string): string { /* ... */ }

代償もあります。このワークフローはWSL必須になり、配布と両立しません。 利用者にWSL2・Ubuntu・Node・codexのインストールとログインを要求することになります。自分専用のツールと割り切って採用しました。

なお、Docker案は否定しました。Docker Desktop for Windows はWSL2の上で動くため、WSL必須という条件は何も解決しません。Windows上でLinuxバイナリを動かす手段は、実質すべてWSL2に行き着きます。

つまずき2:WSL越しに .git へ書けない

役割を戻して実行したところ、別の問題が出ました。

実装(4ファイルの変更)自体は成功したのに、Codexが指示どおりブランチ作成とコミットを試みた瞬間、.git が Read-only file system として扱われ、一切書き込めませんでした。

Windows側から見ると、同じリポジトリで普通にgit操作ができます。/mnt/c 越しにWSL側からアクセスしたときだけ発生する問題でした。

似た問題をもう1つ踏んでいます。WSL側のgitが /mnt/c のリポジトリを全ファイル「変更済み」と誤認するというものです。

# WSL から /mnt/c/.../hiboard を見ると全52ファイルが M になる
$ git ls-files --eol
i/lf    w/crlf  ...

原因は改行コードでした。index側がLF、作業ツリー側がCRLFです。Windows側は Git for Windows のシステム設定 core.autocrlf=true が変換しますが、**WSL側のgitは未設定(既定 false)**のため変換されず、全行が不一致になります。

# WSL 側で設定すれば直る(52ファイル → 1ファイルでWindows側と一致)
git config --global core.autocrlf true

core.filemode=false なのでパーミッションは無関係でした。.gitattributes もありません。ここを疑って時間を使わないでください。

リポジトリの .git/config はWindows側と共有しているので触らないこと。 WSL側の ~/.gitconfig に閉じる設定で直します。

事故:未コミットの変更を消しました

Read-only file system の対応中に、事故が起きました。

複数の変更が1つのブランチに混在していました。私(代表)が未コミットのまま作業していた package.json のバージョン変更と、Codexが実装した4ファイルです。これを整理しようとして、次を実行しました。

git checkout -- package.json

結果、未コミットのバージョン変更(0.3.2 → 0.4.0)が完全に失われました。

git checkout -- <file> は「作業ツリーを直前のコミット状態へ戻す」コマンドです。git add すら経ていない変更は跡形もなく消えます。

git reflog にも git fsck の dangling blob にも一切残りません。 add前の変更は、gitのオブジェクトデータベースに一度も乗らないからです。

今回は運良く復旧できました。直前のCodex実行ログに変更前後の完全なdiffが残っていて、そこから1行の変更内容を特定して手で書き戻せました。ログが無ければ復旧は不可能でした。

教訓は2つです。

  • 複数の変更が混在したブランチを整理するときは、git checkout -- のような破棄系ではなく git stash を使う(退避すれば消えません)
  • 「戻す」系のgit操作を実行する前に、対象ブランチに未コミットの変更が残っていないか必ず確認する

いま確定している分担

この事故を受けて、分担を次のように確定しました。

役割 担当
要件整理・実装指示書の作成 Claude Code
実装(コード変更のみ) Codex
ブランチ作成・コミット・stash等のgit操作 Claude Code(一切Codexにさせない)
実装後のレビュー Claude Code

Codexにgit操作をさせないのが要点です。 これは「Codexが信用できないから」ではありません。WSL越しに .git へ書けないという環境の制約を、役割の境界に変換したものです。

この方針で再実行したところ、実装は事故なくコミットできました。

運用で効いている細かい話

分担そのものとは別に、併用で踏んだ罠を3つ挙げます。

codex exec は stdin を閉じないとハングする

プロンプトを引数で渡し、かつ stdin を開いたままにすると、Reading additional input from stdin... と表示したきり永久に待ちます。

エラーも出ず、セッションログ(~/.codex/sessions/)すら1件も作られません。 そのため「APIが遅い」ようにしか見えません。実際に29分気づきませんでした。プロセスは生きたままフォアグラウンドで待機しています。

# 切り分け: セッションログが皆無ならAPI呼び出しに到達していない=ハング
ps -eo pid,etime,stat,cmd | grep codex

対処は < /dev/null で閉じることです。より確実なのは、プロンプトを引数ではなく stdin へ書いて閉じる方式です(codex は引数なしなら stdin をプロンプトとして読みます)。シェルの引用符問題も同時に避けられます。

Codexの終了コードは成否と無関係に揺れる

同じ「作業をブロックして停止」という結果でも、ある実行は exit 1、別の実行は exit 0 でした。

終了コードで成否を判断してはいけません。 成果物のファイルを実際に読んで判断します。異常終了でも成果物を書き切っていれば、次の評価へ進めてよい場合があります。

レビューは差分を読むので、差分が壊れていると機能しない

前述の autocrlf の問題は、単なる見た目の問題ではありません。Codexのレビューは git diff を読みます。 全52ファイルが「変更済み」になっていると、差分が全行で埋まり、レビューが機能不全になります。

「表示が汚いだけ」と放置すると、レビュー役が黙って役に立たなくなります。

後日談:制約は消えていました

ここまでが2026年7月の話です。

この記事を書くにあたって、現在のバージョンで再現するか確かめました。手元の codex-cli は 0.144.5、テスト環境はWindows上のgitリポジトリです。

$ echo 'hello.txt というファイルを作り、中身に OK とだけ書いてください。' \
  | codex exec -c 'default_permissions=":workspace"'

結果です。

diff --git a/hello.txt b/hello.txt
new file mode 100644
--- /dev/null
+++ b/hello.txt
@@ -0,0 +1 @@
+OK

=== EXIT: 0 ===
hello.txt の中身: OK

書けました。 0.144.4 で半日かけて全滅した書き込みが、0.144.5 では通ります。参照していたIssueも、確認したところ4件とも既にクローズされていました。

つまり、WSL経由にした回避策は、もう必要ないかもしれません。

そして、ここが一番書きたかったことです。当時この設計を採用したとき、記録にこう書き残していました。

将来 Codex が Windows のバグを直したら、wsl -- を外すだけで Windows ネイティブに戻せる(役割配置は変えていないので他の変更は不要)

その通りになりました。 回避策を1箇所に閉じ込め、役割分担そのものには手を入れなかったので、制約が消えたときに戻すコストがほぼゼロで済みます。

ここから引き出した3つの原則

1. 役割分担は、賢さではなく制約で決まる

「どちらが優秀か」で分けていたら、Windowsで書けないという事実に当たった時点で破綻していました。実際に決め手になったのは、どちらのモデルが賢いかではなく、どの操作がその環境で通るかでした。

2. 回避策は1箇所に閉じ込める

wsl -- を付ける変更をアダプタ1箇所に閉じ込めたので、役割配置・パーサ・停止処理は無変更で済みました。AIツールの制約への回避策には賞味期限があります。 消えたときに剥がせる形にしておくかどうかで、後のコストが変わります。

3. 事故の再発防止は、規約ではなく役割の境界にする

「git操作は慎重にやる」では再発します。「Codexにはgit操作をさせない」という境界にすると、そもそも起きません。人間側の注意力に依存しない形に落とすのが確実です。

この分担が効かない場面

万能ではありません。次のケースでは、無理に分けず Claude Code 単体で通したほうが早いです。

  • 探索的なデバッグ — 原因が分からない状態からの調査は、情報の受け渡しコストのほうが高くつきます
  • 設計が未確定なタスク — 実装しながら方針を固めていく種類の作業は、指示書に落とせません
  • 変更が数行で終わる修正 — 指示書を書く時間のほうが長くなります

分業は「実装量が読める状況で初めて効くレバレッジ」だと捉えています。

まとめ

Claude CodeとCodexの比較は「どちらが優秀か」ではなく「どう組み合わせるか」で考えたほうが実りがあります。ただしその組み合わせは、机上で決まるものではありませんでした。

私の場合は、書けない → 役割を逆にする → WSLなら書ける → 戻す → git操作だけ切り離すという順で、実測とひとつの事故を経て今の形になりました。そして制約自体は、3週間後には消えていました。

Claude Codeそのものの導入と基本設定については、個人開発者のためのClaude Code完全ガイドにまとめています。


この記事の実測環境

項目 内容
OS Windows 11
codex-cli 0.144.4(2026-07の記録) / 0.144.5(2026-08-03の再検証)
WSL WSL2 / Ubuntu 24.04
検証日 2026-07-14 〜 07-16、および 2026-08-03

バージョン依存の記述が多く含まれます。 とくに「Windowsで書けない」は 0.144.5 で解消していることを確認済みです。ご自身の環境で確かめてから判断してください。