OpenAI Codex CLIの仕組み

OpenAIからCodex CLIというOSSがリリースされました。Codex CLIは、Claude Codeのようなコマンドラインで利用するコーディングエージェントのTUIツールです。Node.jsで実装されており、使用しているnpmパッケージからして構造はClaude Codeと類似していますが、設計に違いがあります。

GitHub - openai/codex: Lightweight coding agent that runs in your terminal
Lightweight coding agent that runs in your terminal - openai/codex

OpenAI Codex CLIの概要

あなたは、OpenAIによって構築されたターミナルベースのエージェント型コーディングアシスタントであるCodex CLIとして、その内部で動作しています。これはOpenAIモデルをラップし、ローカルのコードベースとの自然言語による対話を可能にします。あなたは、正確で、安全で、役立つ存在であることが期待されています。

あなたができること:

* ユーザーのプロンプト、プロジェクトのコンテキスト、ファイルを受け取る。
* 応答をストリーミングし、関数呼び出し(シェルコマンド、コード編集など)を発行する。
* ポリシーに基づいてパッチを適用し、コマンドを実行し、ユーザーの承認を管理する。
* ロールバックサポート付きの、サンドボックス化されたgit管理下のワークスペース内で作業する。
* 後でセッションを再生または検査できるように、テレメトリをログに記録する。
* あなたの機能に関する詳細は、`codex --help` で確認できます。

codex-cli/src/utils/agent/agent-loop.ts の冒頭だけ翻訳

Codex CLIは、ユーザーの指示に基づき、ローカル環境からコンテキスト(指示+プロンプト)を生成してOpenAIのResponses APIに送信します。これを使ってFunction Callingを通じ、受け取った情報からシェルコマンドを実行するという基本設計です。Claude CodeやGooseのようなMCPクライアント/サーバー分離アーキテクチャと比べると、より簡易的ですね。ただし、入力に対してシェルコマンドのみを実行する制約は、意図的なデザインだと著者は考えます。

toolは「shell」のみ

apply_patchメカニズムとDiff書式

Codex CLIがソースコードをファイルに保存する仕組みは、apply_patchと呼ばれています。まずシステムプロンプト内でapply_patchという架空のシェルコマンドを定義します。このapply_patchの引数がモデルによって決定されると、OpenAI Codex CLIはシェルでの実行をバイパスし、内部のファイルパッチ処理関数を実行します。

- ファイルの編集には apply_patch を使用してください:{"cmd":["apply_patch","*** Begin Patch\\n*** Update File: path/to/file.py\\n@@ def example():\\n- pass\\n+ return 123\\n*** End Patch"]}

codex-cli/src/utils/agent/agent-loop.ts から抜粋

OpenAI Codex CLIで採用されているパッチは、独自のMarkdown風のDIFF書式です。APIレスポンスを通じてコード編集のリクエストを行う際、以下のようなプレーンテキスト形式を受信し、この形式をパースしてファイルの読み書きを行います。

*** Begin Patch
*** Add File: foo.txt
+hello world
*** Update File: bar.txt
@@
-old line
+new line
*** Delete File: baz.txt
*** End Patch

この見出しがディレクティブに対応していて以下がシーケンシャルに適用されます。

  • Add File … 新ファイル作成
  • Update File … 既存ファイルの差分適用
  • Delete File … ファイル削除

デバッグ用の機能なのですが、このパッチ適用処理をスクリプトとして単体で確認できます。

❯ cat a.patch
*** Begin Patch
*** Add File: foo.txt
+hello world
*** End Patch

❯ cat a.patch | node dist/src/utils/agent/apply-patch.js
Done!

❯ cat foo.txt
hello world

他ツールと比較した設計のシンプルさ

これに対して、ClineやClaude Codeなどのすでに普及しているコーディングエージェントは、パス、置き換え元テキスト、置き換え先テキストをXMLやJSONでマークアップすることでファイル編集の情報源にしています。Codex方式の利点は、パッチのパース時間が速く、トークン数を削減できる点にありますが、その差は誤差程度と考えられます。

それよりは、Codex CLIでは、LLMが推論を必要とするFunction Callingが「shell関数のみで実現されている」のが注目するところです。

システムにおける汎用的なシェルコマンドと同じレイヤーで、先ほどのapply_patchも実行されます(patchコマンドのメタファーになっています)。モデルに推論させるためだけのコンテキスト上にある独自のツール定義ではなく、学習データセットに含まれるであろうコマンドに落とし込まれているのが良いですね。UNIX哲学に通じるものと感じられます。

このシンプルさをこのまま維持できるのかという点も気になります。Clineの長大なプロンプトや、ロングコンテキスト時の不安定な挙動から、ツール(Function Calling)の数とトークン消費、適切なツール選択の精度がエージェントの性能に直結することがわかります。MCPサーバーのtool/listはこのツール定義の数が膨大になりがちです。OpenAI Codex CLIのリポジトリにも「MCPサーバー対応」の機能リクエストIssueがありますが、どのように実現されるのかは不明です。

Add MCP support. · Issue #5 · openai/codex
Would it be possible to have MCP servers support in codex? i’d defo love to see that. me and many others.

おまけ:macOSでのサンドボックス実行

OpenAI Codex CLIは、macOSでコマンドを実行する際にsandbox-execを使用します。これはmacOSのサンドボックス機能で、設定にはS式のDSLによる専用ポリシーを記述します。たとえば、特定のパスへのアクセスを拒否したり、範囲を制御したりできます。

(version 1)

(allow default)

(deny file-read* (subpath "/tmp"))
❯ file /tmp
/tmp: sticky, directory

❯ sandbox-exec -p '(version 1) (deny file-read* (subpath "/tmp"))' file /tmp
sandbox-exec: execvp() of 'file' failed: No such file or directory

この機能自体を初めて知ったのですけど面白いですね。というかAppleドキュメントのどこに書いてあるんだ・・

A quick glance at macOS’ sandbox-exec - Julio Merino (jmmv.dev)
macOS includes a sandboxing mechanism to closely control what processes can do on the system. Sandboxing can restrict file system accesses on a path level, control which host/port pairs can be reached over the network, limit which binaries can be executed, and much more. All applications installed via the App Store are subject to sandboxing. This sandboxing functionality is exposed via the sandbox-exec(1) command-line utility, which unfortunately has been listed as deprecated for at least the last two major versions of macOS. It is still there, however, and the supplemental manual pages like sandbox(7) or sandboxd(8) do not mention the deprecation… which makes me think that the new App Sandboxing feature is built on the same kernel subsystem as sandbox-exec(1).

Subscribe to laiso

Sign up now to get access to the library of members-only issues.
Jamie Larson
Subscribe