TL;DR
Codex CLI v0.148.0 を実際にインストールして --approve-for-me の挙動を測った結果です。
-
--approve-for-meは承認の粒度を細かく指定するフラグではなく、approval: on-requestとworkspace-writeサンドボックスの組み合わせに固定する 1 スイッチでした -
-s/--sandbox、-a/--ask-for-approval、--dangerously-bypass-approvals-and-sandboxのいずれとも併用できず、引数パースの時点でエラーになります -
codex sandboxサブコマンドで境界を測ると、workspace-writeはカレントディレクトリと/tmpには書けて$HOMEには書けず、ネットワークは既定で遮断されていました - そのネットワーク遮断が実行環境側の都合ではなくサンドボックス由来であることは、
danger-full-accessとnetwork_access=trueの 2 つの対照実験で切り分けました -
codex execの既定サンドボックスはworkspace-write、codex sandboxの既定は read-only で、同じ CLI の中で既定値が違いました
はじめに
Codex CLI を CI やスケジュール実行のようなヘッドレス環境で回していると、承認プロンプトをどこまで自動で通してよいかが最後まで決まりません。rust-v0.147.0 で追加された --approve-for-me は、この決めきれない部分を埋めるフラグとして紹介されています。対象読者は、Codex CLI を人が張り付かない環境で動かしていて、承認と隔離の設定を詰めたい開発者です。
ただ、リリース情報を読むと「粒度の細かい自動承認」と表現されている一方で、codex --help に並ぶ他の承認系フラグとの関係は書かれていません。-s read-only と組み合わせたら安全側に寄せられるのか、-a never と併用したらどちらが勝つのか。ここは手を動かさないと分かりませんでした。
検証環境
- Linux コンテナ(x86_64 / kernel 6.18.5)
-
npm install @openai/codexでローカル導入した codex-cli 0.148.0(実測は./node_modules/.bin/codexを叩いています。以下のコマンド例はグローバル導入を想定してcodexと表記します) - 検証日: 2026-08-19(JST)
- モデル API の認証情報は意図的に外して実行しました(承認ポリシーとサンドボックスの解決結果は、モデル呼び出しの前にセッションヘッダーへ出力されるため、推論を走らせずに測れます)
openai/codex は 2026-08-19 時点で 106.7k stars の OSS で、npm install -g @openai/codex でインストールできます(出典: openai/codex)。
1. --approve-for-me が実際に切り替えるもの
codex exec はセッション開始時に、解決済みの承認ポリシーとサンドボックスをヘッダーへ出力します。ここを読めば、フラグが最終的に何へ落ちたのかが分かります。
echo "" | codex exec --skip-git-repo-check "say hi" 2>&1 | grep -E "^(approval|sandbox|model):"
フラグを変えて 4 パターン測った結果です。
| 指定したフラグ | approval | sandbox |
|---|---|---|
なし(codex exec 既定) |
never |
workspace-write [workdir, /tmp, $TMPDIR] |
-s read-only |
never |
read-only |
-s danger-full-access |
never |
danger-full-access |
--approve-for-me |
on-request |
workspace-write [workdir, /tmp, $TMPDIR] |
実際の出力はこうなりました。
OpenAI Codex v0.148.0
--------
workdir: /tmp/.../sbtest
model: gpt-5.6-sol
provider: openai
approval: on-request
sandbox: workspace-write [workdir, /tmp, $TMPDIR]
reasoning effort: none
codex exec の既定は approval: never です。つまりヘッドレス実行では、そもそも承認は求められず、サンドボックスの中で失敗したらその結果がモデルへ返るだけでした。--approve-for-me はそこを on-request へ 引き上げます。承認を減らすフラグではなく、いったん承認要求を発生させたうえで、その可否の判断を人ではなく自動レビューへ回す、という向きの変更です。
サンドボックス側は workspace-write に固定されます。ヘッダーの [workdir, /tmp, $TMPDIR] が書き込み可能なルートの一覧で、これが後段の実測とそのまま一致しました。
2. 併用できないフラグが 3 つある
「粒度」という言葉から、--approve-for-me に -s を足して隔離を強める使い方を想定していました。これは通りません。
$ codex exec --approve-for-me -s read-only "say hi"
error: the argument '--approve-for-me' cannot be used with '--sandbox <SANDBOX_MODE>'
$ codex exec --approve-for-me --dangerously-bypass-approvals-and-sandbox "say hi"
error: the argument '--approve-for-me' cannot be used with '--dangerously-bypass-approvals-and-sandbox'
$ codex --approve-for-me -a never "hi"
error: the argument '--approve-for-me' cannot be used with '--ask-for-approval <APPROVAL_POLICY>'
3 つとも引数パースの時点で落ちるため、実行前に気づけます。設定の組み合わせ爆発を CLI 側が禁じている形で、read-only なのに自動承認、のような矛盾した組を作れません。裏を返すと、workspace-write 以外のサンドボックスで自動レビューを使う手段は現時点でありませんでした。
なお codex exec には -a/--ask-for-approval 自体が存在せず、-a を渡すと unexpected argument '-a' found になります。承認ポリシーを明示指定できるのは対話モードの codex 側だけで、exec では --approve-for-me が唯一の切り替え手段でした。
3. workspace-write の境界を codex sandbox で測る
--approve-for-me が固定してくる workspace-write が実際にどこまで許すのかは、codex sandbox サブコマンドで直接測れます。このサブコマンドはモデルを呼ばず、任意のコマンドを Codex のサンドボックスに入れて実行します。
codex sandbox -c sandbox_mode='"workspace-write"' -- bash -c 'echo hi > ./t5.txt'
codex sandbox には -s/--sandbox がなく、モードは -c sandbox_mode=... で渡します。既定と workspace-write を並べた結果です。
| 試したこと | 既定(モード未指定) | sandbox_mode="workspace-write" |
|---|---|---|
| カレントディレクトリへ書き込み | Read-only file system |
成功 |
/tmp へ書き込み |
Read-only file system |
成功 |
$HOME(/root)へ書き込み |
Read-only file system |
Read-only file system |
| カレントディレクトリの読み取り | 成功 | 成功 |
https://example.com へ HTTP |
000(失敗) |
000(失敗) |
失敗時のメッセージは、権限拒否ではなく bash: line 1: /root/t7.txt: Read-only file system という読み取り専用マウントのエラーでした。ファイルシステムを丸ごと read-only で見せて、許可したルートだけ書けるように重ねる作りだと分かります。
ここで引っかかったのが既定値です。codex exec の既定サンドボックスは workspace-write なのに、codex sandbox サブコマンドの既定は read-only でした。同じ CLI でも入口によって既定が違うため、codex sandbox -- ... で試して「書けないから安全だ」と判断すると、エージェント本体の挙動を見誤ります。
--sandbox-state-disable-network というネットワークを落とすオプションもありますが、単独では使えませんでした。
Usage: codex sandbox --sandbox-state-json <JSON> --sandbox-state-disable-network --config <key=value> <COMMAND>...
--sandbox-state-json とセットで渡す前提のオプションで、codex/sandbox-state-meta から受け取った状態を加工するためのものでした。
4. ネットワークの 000 はサンドボックス由来か
HTTP が 000 で返ったとき、サンドボックスが遮断したのか、実行環境のプロキシ設定が効いていないだけなのかは区別が付きません。ここを混同すると記事ごと間違うため、対照実験で切り分けました。
| 条件 | HTTP ステータス |
|---|---|
| サンドボックス外(素の shell) | 200 |
サンドボックス内で env | grep -i proxy
|
プロキシ変数は継承されていた |
sandbox_mode="danger-full-access" |
200 |
sandbox_mode="workspace-write" |
000 |
workspace-write + sandbox_workspace_write.network_access=true
|
200 |
プロキシ環境変数はサンドボックスの中にも渡っており、danger-full-access に切り替えるだけで同じ curl が 200 を返しました。したがって 000 は環境要因ではなくサンドボックスの遮断です。network_access=true を足せば workspace-write のまま通信できることも確認できました。
この 1 行を足すかどうかが、--approve-for-me を使うときの実質的な判断ポイントになります。承認を自動レビューへ委ねる以上、通信の可否は人の目を通らないためです。
5. bubblewrap が無くても動いた
Linux でのサンドボックスは bubblewrap(bwrap)に依存しますが、この環境には入っていませんでした。それでも実行は続きます。
warning: Codex could not find bubblewrap on PATH. Install bubblewrap with your OS package manager.
See the sandbox prerequisites: https://developers.openai.com/codex/concepts/sandboxing#prerequisites.
Codex will use the bundled bubblewrap in the meantime.
同梱の bubblewrap にフォールバックする旨が警告として出て、実際に上の表のとおり隔離は機能していました。CLI によってはここで停止するため、Codex CLI は導入時の前提条件が 1 つ少ない作りになっています。
著者視点の発見ポイント
フラグ名から受ける印象と、実装が置かれている位置がずれていた点が一番の収穫でした。--approve-for-me は「自分の代わりに承認しておいて」という名前どおりの機能ですが、codex exec の文脈では 承認が発生しない状態から、承認が発生する状態へ移す フラグです。すでに approval: never で回している CI に足すと、自動レビューという新しい判断者が増える方向に働きます。
もう 1 つは、併用禁止が 3 つもある点です。設定の自由度を削る仕様は使いにくく見えますが、承認ポリシーとサンドボックスは片方だけ緩めると意味が崩れる組み合わせなので、パースエラーで弾かれるほうが安全でした。実際に筆者が最初に書こうとしたコマンドは --approve-for-me -s read-only で、これは「自動レビューに任せつつ書き込みは許さない」という一見もっともらしい、しかし成立しない指定でした。
最後に、検証の順番として codex sandbox を先に触ったのは正解でした。モデルを呼ばずに境界だけ測れるので、API のコストも認証も要りません。エージェントの隔離設定を検討するときは、まずこのサブコマンドで机上の設定が実際にどう効くかを確かめるのが早い、というのが今回の実感です。
公式ソースの記述との突き合わせ
実測の裏取りとして公式側の記述も確認しました。ここは二次情報です。
--approve-for-me を追加した Pull Request(openai/codex#36373・2026-07-31 マージ)には、approval_policy="on-request" と workspace-write サンドボックスで構成すること、対話モードと exec の双方に適用され、root / exec / resume / fork の引数処理に伝播することが書かれています。今回ヘッダーで観測した値と一致しました。
サンドボックスと承認ポリシーの定義は公式ドキュメントにあり、workspace-write は「エージェントはファイルを読み、ワークスペース内を編集し、その境界の中で日常的なローカルコマンドを実行できる」、on-request は「エージェントは既定でサンドボックス内で作業し、その境界を越える必要があるときに尋ねる」と説明されています。--approve-for-me は、この「尋ねる」先を人から自動レビューへ差し替えるスイッチだと読めます。
実務での使いどころ
今回の実測を踏まえた使い分けです。
- 人が見ていない CI で、書き込みをワークスペースに閉じたまま自動で進めたい場合は
--approve-for-meが素直です。既定のneverと違い、境界を越える操作が黙って失敗せず、自動レビューの判断を経ます - 通信を伴うタスク(依存解決・API 疎通)を含むなら
sandbox_workspace_write.network_access=trueを明示します。既定では遮断されるため、原因不明のタイムアウトとして現れます - 隔離を
read-onlyまで絞りたい場合は--approve-for-meを諦めて-s read-onlyを選びます。両立できません - 事前検証は
codex sandboxで行い、既定モードの違い(execはworkspace-write、sandboxは read-only)を踏まえてモードを明示的に渡します