3行でいうと

  • codex exec は、進捗を標準エラー出力に流し、最後のメッセージだけを標準出力に出します。機械で読みたいときは --json(全イベントをJSON Linesで)、-o(最後のメッセージをファイルへ)、--output-schema(返答の形をJSON Schemaで指定)を使い分けます。
  • 既定のサンドボックスは読み取り専用です。編集を許すのは --sandbox workspace-write、広い権限は --sandbox danger-full-access で、公式は後者を隔離したCIランナーやコンテナだけに限っています。--full-auto はもう使えません。
  • GitHub Actionは openai/codex-action@v1 です。既定の safety-strategy は drop-sudo で、既定では書き込み権限のある人しか起動できません。READMEには、新しい権限プロファイル(permission-profile、ベータ)の入力もあります。
  • 公式が繰り返す警告は3つです。APIキーをジョブ全体の環境変数に置かない、PRやIssueの文章は信用しない、~/.codex/auth.json はパスワードとして扱う。

この記事は、実際に使って確かめた記録ではありません。運営者はCodexを入れていますが、使い心地はこの記事には書いていません。この記事は、2026年10月24日に公式の資料を読んでまとめたものです。コマンド、フラグ、YAMLは公式に書かれていた断片を写したもので、動作確認はしていません。ページの取得は、要約を返すツール経由です。長いYAMLは原文どおりには取れず、断片を並べ直した箇所があります(その箇所には、そう書きました)。公式の資料が読めなかった部分は、書かずに「確認できていない」と書きました。

先に結論

前提:用語をそろえる

1. codex exec の基本

公式の「Non-interactive mode」は、次のような場面で codex exec を使うよう書いています。CIやマージ前の検査、予定の作業のようなパイプラインの一部として動かす、リリースノートや要約のように他の道具に渡せる出力を作る、コマンドの出力をCodexに渡してCodexの出力をまた別の道具に渡す、サンドボックスと承認の設定をあらかじめ決めて動かす、です。

進捗は標準エラー出力(stderr)に流れ、最後のメッセージだけが標準出力(stdout)に出ます。だからパイプやリダイレクトでつなげます。

公式の例は次のとおりです(動作確認はしていません)。

codex exec "summarize the repository structure and list the top 5 risky areas"
codex exec "generate release notes for the last 10 commits" | tee release-notes.md
codex exec --ephemeral "triage this repository and suggest next steps"

--ephemeral は、セッションの記録(ロールアウトのファイル)をディスクに残さない指定です。

標準入力を渡す

プロンプトの引数と、標準入力の両方を渡すと、引数が指示、標準入力が追加の文脈として扱われます。公式の例は次のとおりです。

npm test 2>&1 \
  | codex exec "summarize the failing tests and propose the smallest likely fix" \
  | tee test-summary.md

標準入力の全体をプロンプトにしたいときは、- を渡します。

cat prompt.txt | codex exec -
generate_prompt.sh | codex exec - --json > result.jsonl

公式の例にはもう1つ、printf で文章を組み立てて codex exec - に渡す形もあります。

公式の「標準入力を渡す」例には、ほかに次の形があります(読んだ要約に書かれていた形を、僕らが整えて写しました。プロンプトの文言は公式の原文と照合してください)。

tail -n 200 app.log | codex exec "<likely root cause and next debugging steps>" > log-triage.md
gh run view 123456 --log | codex exec "<summarize the failure in five bullets>" | gh pr comment 789 --body-file -

1つ目はログの末尾200行を渡して原因の見立てを log-triage.md に受ける形、2つ目はCIのログを要約させてPRのコメントに投稿する形です。<...> の部分は、僕らが意味を書いた置き場で、公式の文言ではありません。

前の続きをやる

codex exec "review the change for race conditions"
codex exec resume --last "fix the race conditions you found"

特定のセッションを続けるときは codex exec resume <SESSION_ID> と書く、と公式にあります。ソースコード(GitHubの cli.rs)の読めた範囲では、resume には --last、--all(作業フォルダで絞らず全セッションを対象にする)、--image(画像)があり、fork(既存のセッションを新しいセッションとして分ける)というサブコマンドもあります。

標準入力まわりの細かい挙動(ソースコードを読んだ範囲)

公式のドキュメントにない細部を、GitHubの公式リポジトリの lib.rs と cli.rs(mainの内容、要約を読んだもの)から拾います。実際の挙動は手元で確かめてください。

2. オプション一覧:どこに何が書かれているか

公式のコマンド一覧のページでは、codex exec のフラグ表が描画の都合で読めず、本文に出てくる項目だけが拾えました。足りない部分は、GitHubの公式リポジトリの cli.rs(clapという引数処理の定義)の要約で補いました。

オプション 役割 書かれている所
--json(別名 --experimental-json) イベントをJSON Linesで標準出力に出す 非対話モードのページ、cli.rs
-o <ファイル>、--output-last-message <ファイル> 最後のメッセージをファイルに書く(標準出力にも出る) 非対話モードのページ、cli.rs
--output-schema <ファイル> 最終の返答の形を、JSON Schemaで指定する 非対話モードのページ、cli.rs
--ephemeral セッションの記録をディスクに残さない 非対話モードのページ、cli.rs
--skip-git-repo-check Gitリポジトリの外でも動かす 非対話モードのページ、cli.rs
--sandbox <値> サンドボックスの種類(read-only、workspace-write、danger-full-access) 非対話モードのページ
--ignore-user-config $CODEX_HOME/config.toml を読まない(認証には CODEX_HOME を使う) 非対話モードのページ、cli.rs
--ignore-rules ユーザーとプロジェクトのexecpolicyの .rules を読まない 非対話モードのページ、cli.rs
--approve-for-me 承認の依頼を、workspace-write の中で自動レビューに回す 非対話モードのページ(--full-auto の代わりとして)
--dangerously-bypass-approvals-and-sandbox(別名 --yolo) サンドボックスも承認もなしにする Agent approvals & security、前のガイド02(cli.rs には共有オプションとしてフィールド名があるだけ)
[PROMPT] と - 指示。省略または - なら標準入力から読む cli.rs

読めた範囲の補足は次のとおりです。

周辺のフラグ(コマンド一覧のページに書かれていたもの)

フラグ・サブコマンド 書かれていること
--image 画像を添付する。プロンプトが必要。codex exec fork でも使う
--worktree 新規または分岐した実行のために、管理されたGit worktreeを作る。ローカル実行が前提で、resume、review、--ephemeral、--ignore-user-config とは組み合わせられない
fork <SESSION_ID> [PROMPT] 保存済みのセッションを新しいセッションとしてコピーする。プロンプトを省くと、ターンを始めずに分岐だけ作る。- で標準入力から読む
--output-last-message プロンプトが必要。ページは、CIでは --json と組み合わせるよう勧めている
--add-dir 追加のディレクトリへの書き込みを許す、推奨の方法(安全のヒントの中に出る。前のガイド02)

--cd、--color、--strict-config は、cli.rs の要約には出てきますが、コマンド一覧のページには説明がありませんでした。公式ドキュメントでの意味は確認できていません。

3. 出力:3つの取り出し方

3-1. いちばん簡単:最後のメッセージだけ

既定の動きです。標準出力に最後のメッセージが出るので、> out.md や | tee で受けられます。ファイルに直接書きたいときは -o です。

3-2. 全部のイベントを取る:--json

--json を付けると、標準出力がJSON Linesになり、動いている間のイベントが1行ずつ出ます。公式が挙げるイベントの種類は、thread.started、turn.started、turn.completed、turn.failed、item.*、error です。item の種類は、エージェントのメッセージ、推論、コマンドの実行、ファイルの変更、MCPツールの呼び出し、Web検索、計画の更新です。

公式の説明にある例では、最初の行は {"type":"thread.started","thread_id":"..."} の形で、最後に turn.completed の行があり、そこにトークン使用量(入力、キャッシュされた入力、出力、推論の出力)が入ります。item.* の中の各項目のフィールド名は、読んだ範囲では見つからなかったので、ここでは書きません。

ソースコード(lib.rs)の冒頭のコメントは、標準出力に出すのは最後のメッセージだけで、診断は標準エラー出力に出す、と読めました。--json のときの標準出力がJSONLだけかどうかは、読んだ範囲では確認できていません。パイプで jq に渡す前に、手元で1回確かめてください。

この記事の例です(実行していません)。行ごとに type の欄があるので、jq で失敗のイベントだけを見張れます。

codex exec --json "..." | jq -c 'select(.type == "turn.failed" or .type == "error")'

3-3. 返答の形を決める:--output-schema

ジョブの要約やリスクのレポート、リリース情報など、後の処理が決まったフィールドを必要とするときのための機能です。公式の例では、JSON Schemaのファイルを作り、次のように指定します。例のスキーマは、project_name(文字列)と programming_languages(文字列の配列)を持ち、2つとも必須で、それ以外は許さない形でした。

codex exec "Extract project metadata" --output-schema ./schema.json -o ./project-metadata.json

GitHub Actionの側では、output-schema(スキーマの中身)か output-schema-file(ファイルの場所)の入力で渡せます。両方は指定できません。

3-4. 終了コード

公式の非対話モードのページには、終了コードの数字の説明は見つかりませんでした。書かれていた失敗の動きは、required = true のMCPサーバーが起動に失敗したときにエラーで終わること、--json でイベントに turn.failed と error が出ることです。

ソースコード(lib.rs)の要約から読めたのは、設定、スキーマ、標準入力、Gitリポジトリの確認で失敗すると終了コード1、セッションの最後に再試行されないエラーがあったりターンが失敗か中断で終わったりしていても終了コード1、それ以外は0、ということです(確実とは言えず、公式の約束でもありません)。CIの成否の判定に使う前に、失敗する依頼を1つ流して確かめてください。また、jq で turn.failed や error を拾う方法は、イベントが出ない失敗や、終了コードだけが非0になる失敗を見逃しうるので、終了コードの確認と併用するのが安全だと思います(僕らの見立てです)。

4. 権限の指定

画面なしの実行では、「何を許すか」を、実行する側があらかじめ決めます。関係するつまみを、公式に書かれている順に並べます。

つまみ 公式の記述 書かれている所
既定のサンドボックス 読み取り専用 非対話モードのページ
編集を許す --sandbox workspace-write 非対話モードのページ
広いアクセス --sandbox danger-full-access。管理された環境(隔離したCIランナーやコンテナ)だけ 非対話モードのページ
承認の自動レビュー --approve-for-me(workspace-write の中で、承認の依頼を自動レビューに回す) 非対話モードのページ
承認を聞かない --ask-for-approval never(-a never)。どの --sandbox とも組み合わせられ、設定した制約の中でできる範囲を試す Agent approvals & security
CI向けの読み取り専用 --sandbox read-only --ask-for-approval never Agent approvals & security
全部外す --dangerously-bypass-approvals-and-sandbox(--yolo)。公式は推奨しないと書く Agent approvals & security
設定ファイルを読まない --ignore-user-config、--ignore-rules 非対話モードのページ
設定の切り替え codex --profile ci($CODEX_HOME/ci.config.toml のような別ファイルで切り替える) Sample Configuration

承認の既定:ソースコードのコメント

公式のドキュメントでは、codex exec の承認ポリシーの既定は、読んだ範囲では見つかりませんでした(前のガイド04にもそう書きました)。GitHubの公式リポジトリの lib.rs の要約には、画面なしのモードでは、既定で承認を聞かない設定にする、という趣旨のコメントと、AskForApproval::Never の設定がありました。承認の依頼が来ても、対話せずに拒否する作りで、コマンド実行、ファイルの変更、ユーザーへの入力、動的なツールは拒否、MCPの確認(elicitation)だけはキャンセルで返す、と読めました。つまり、承認が必要になった操作は、聞かれずに断られるはずです。ただし、これはソースの要約から読んだもので、実機の動作は確かめていません。

サンドボックスの既定は、lib.rs の要約では、--sandbox の指定があればそれを使い、無ければ設定ファイル側の既定に任せる作りでした。Sample Configurationの sandbox_mode の既定は read-only です。ドキュメントの「既定は読み取り専用」と合っています。

--approve-for-me の読み方

非対話モードのページは、--full-auto の代わりとして挙げ、承認の依頼を workspace-write の中で自動レビューに回す、と説明しています。コマンド例は見つかりませんでした。前のガイド02のとおり、--sandbox や --yolo とは同時に使えず、公式が「完全な安全の保証ではない」と書く仕組みです。lib.rs の要約には、レビュアーが自動レビューのときは、承認を聞かない設定の上書きを外す処理があるように読めました。そのため、前の節の「聞かれずに断られる」という動きは、--approve-for-me のときは当てはまらない可能性があります(確かめていません)。

Gitリポジトリの確認と、必須のMCPサーバー

非対話モードのページは、破壊的な変更を防ぐため、Gitリポジトリの中で動かす必要があると書いています。--skip-git-repo-check で確認を飛ばせますが、環境が安全だと分かっているときだけにします。また、required = true のMCPサーバーが起動に失敗すると、codex exec はエラーで終わります(前のガイド04)。CIでは、黙って進むより止まるほうが安全な場面が多いと思います(僕らの見立てです)。

shell_environment_policy:コマンドに渡す環境変数

Sample Configurationの [shell_environment_policy] の節には、Codexが起動するコマンドに渡す環境変数を絞る項目があります。読めた範囲は次のとおりです。

僕らの見立てです。公式のこの節は、CIの話としては書かれていません。ただ、CIでCodexに渡したくない変数がある場合の選択肢として、読んでおく価値があると思います。この設定が、GitHub Actionの openai-api-key の扱いまで守るかどうかは、読んだ範囲では分かりません。

5. 認証:CIでどう入るか

公式の資料に書かれている入り方は、次の3つです。

方法 公式の位置づけ 書かれている所
APIキー CI/CDのようなプログラムからの利用には、これを使う、と書かれている 認証のページ
Codexのアクセストークン ChatGPT Enterpriseで、管理者が許可したメンバーが作れる。ブラウザのサインインなしの非対話の作業向け。スクリプト、スケジューラ、プライベートなCIランナー向け 認証のページ
ChatGPT管理の認証(auth.json) 上級向け。信頼できるプライベートな基盤で、ChatGPTのレート制限を使いたい場合など 非対話モードのページ、CI/CD認証の上級ページ

APIキーの渡し方は、公式の認証のページに、標準入力から渡す例があります。

printenv OPENAI_API_KEY | codex login --with-api-key

アクセストークンは、同じ形で次のように渡します。

printenv CODEX_ACCESS_TOKEN | codex login --with-access-token

1回の実行だけに、APIキーを CODEX_API_KEY として直接渡す形は、非対話モードのページが書いています(対象は codex exec、codex review、TypeScriptのSDK、codex exec-server --remote)。CODEX_API_KEY=<キー> codex exec --json "..." の形です(前のガイド04と同じです)。認証のページには、CODEX_API_KEY の記述は見つかりませんでした。

APIキーでの利用は、標準のAPI料金で課金され、ChatGPTのプランに含まれる枠は使われません。APIキーでは、ChatGPTのワークスペースやクラウドに頼る機能が制限されるか使えないことがある、とも書かれています。

ブラウザのない機械でログインするとき

認証のページに、公式の方法が3つあります。デバイスコード認証(codex login --device-auth、公式はベータと書き、事前に有効化が必要)、ブラウザのある機械で codex login して ~/.codex/auth.json をコピーする方法、SSHでコールバックの localhost:1455 を転送する方法です。いずれも、auth.json をパスワードと同じに扱う注意つきです。

ChatGPT管理の認証をCIで保つ(公式の上級ガイド)

「Maintain Codex account auth in CI/CD (advanced)」のページは、自動化にはAPIキーが正しい方法で、これは「Codexアカウントとしてワークフローを動かす必要がある場合」に限る、と最初に書いています。使ってよい条件は、すべて満たす必要があります。

流れは、信頼できる機械で codex login して auth.json を作る、ランナーに置く、通常どおりCodexを動かす(古くなればCodexがリフレッシュする)、更新されたファイルを次の実行に引き継ぐ、です。最初の準備は、設定で cli_auth_credentials_store = "file" にしてから codex login、そのあと、auth_mode が "chatgpt" で、リフレッシュ用のトークンがあることを jq で確かめます。

運用のルールとして、公式は次を挙げています。ランナーごと、または順番に動くワークフローごとに auth.json を1つにする(並列のジョブや複数の機械で共有しない)。常駐するランナーでは、更新されたファイルを毎回元のシークレットで上書きしない。auth.json をリポジトリ、ログ、公開のアーティファクトに置かない(ディレクトリは 700、ファイルは 600)。使い捨てのランナーでは、保管先から復元し、Codexを動かし、更新されたファイルを書き戻す。401が返るなど自動のリフレッシュが効かなくなったら、信頼できる機械から入れ直す。

公式の例には、セッションが約8日で古くなるとみなすので、常駐のランナーでは週1回のスケジュールで足りる、という趣旨の記述があります。この日数は「そのときのクライアントの動き」で、変わりえます。ページにはベータや実験的という表記も、対象プランの名前もありませんでした(非対話モードのページ側には、エンタープライズのチームや信頼できるプライベートな自動化向け、という趣旨の説明があります)。

6. GitHub Action(openai/codex-action)

公式のページ(Codex GitHub Action)は、アクションの働きを、Codex CLIを入れ、APIキーを渡したときはResponses APIのプロキシを起動し、指定した権限で codex exec を動かすもの、と説明しています。用途として、PRの自動レビュー、CIでの品質チェック、リリース準備などを挙げています。非対話モードのページは、GitHub Actionsでは openai/codex-action を使うことが推奨される、と書いています。

前提(公式のページ)

公式の例:PRが開かれたらレビューを投稿する

公式のページとREADMEの例から、断片を拾って並べ直しました。順番とインデントはこの記事で整え、実行はしていません。取得ツールが長いYAMLを原文のまま返さないため、1つの完全な写しではありません。READMEの例は、トリガーがPRの作成時(opened)だけ、公式ページの例は opened、synchronize、reopened で、プロンプトの与え方も違います(READMEはインライン、ページは prompt-file)。ここでは、ページの形に合わせました。

on:
  pull_request:
    types: [opened, synchronize, reopened]

jobs:
  codex:
    runs-on: ubuntu-latest
    permissions:
      contents: read
    outputs:
      final_message: ${{ steps.run_codex.outputs.final-message }}
    steps:
      - uses: actions/checkout@v5
        with:
          ref: refs/pull/${{ github.event.pull_request.number }}/merge
          fetch-depth: 0
          persist-credentials: false

      - name: Run Codex
        id: run_codex
        uses: openai/codex-action@v1
        with:
          openai-api-key: ${{ secrets.OPENAI_API_KEY }}
          prompt-file: .github/codex/prompts/review.md
          output-file: codex-output.md

  post_feedback:
    runs-on: ubuntu-latest
    needs: codex
    if: needs.codex.outputs.final_message != ''
    permissions:
      issues: write
      pull-requests: write
    steps:
      - name: Report Codex feedback
        uses: actions/github-script@v7
        env:
          CODEX_FINAL_MESSAGE: ${{ needs.codex.outputs.final_message }}
        with:
          github-token: ${{ github.token }}
          script: |
            await github.rest.issues.createComment({
              owner: context.repo.owner,
              repo: context.repo.repo,
              issue_number: context.payload.pull_request.number,
              body: process.env.CODEX_FINAL_MESSAGE,
            });

この形の要点は、Codexを動かすジョブを contents: read だけにし、書き込み権限はコメントを投稿する別のジョブに分けてあることです。READMEは、チェックアウトで persist-credentials: false を付けること、GitHubの式(${{ ... }})をシェルに直接埋め込まず環境変数を経由して渡すことも注意として書いています。コードをビルドして動かしたいときは、Codexのステップより前に依存関係を入れておく必要があります(推奨の :workspace プロファイルがネットワークを許さないため)。.github/codex/prompts/review.md は自分のファイルに置き換えるか、prompt でインラインにも書けます。

入力(inputs)の一覧

GitHubのREADMEの表(mainの内容)から、主なものを要約から写しました。既定値は、READMEの表示のままです。ほかに、working-directory(codex exec --cd に渡すディレクトリ。空ならリポジトリのルート)、codex-version(入れる @openai/codex の版を固定する)、codex-home(Codex CLIのホーム。空ならCLIの既定)、responses-api-endpoint(Responses APIの宛先を上書きする。Azureなど)の入力があります。公式の「Codex GitHub Action」のページには、この表がなく、入力の名前と簡単な説明だけでした。

入力 内容 既定値
openai-api-key Responses APIのプロキシを起動するためのキー。シークレットに入れる 空
prompt / prompt-file 指示(インラインかファイル)。同時には指定できない 空
output-file 最後のメッセージを書くファイル。空ならファイルを書かない 空
sandbox 従来のサンドボックスの種類。permission-profile とは同時に指定できない 空
permission-profile 権限プロファイル(例::workspace) 空
codex-args codex exec に渡す追加の引数。JSON配列か、シェル形式の文字列 空
output-schema / output-schema-file 返答の形。中身を直接か、ファイルで。同時には指定できない 空
model / effort モデルと推論の強さ。空ならCodexの既定 空
safety-strategy Codexの権限をどう絞るか drop-sudo
codex-user unprivileged-user のときの実行ユーザー名 空
allow-users 書き込み権限がなくても起動できるGitHubユーザー名の一覧 空
allow-bots 信頼されたボット(github-actions[bot])の実行を、書き込み権限の確認から外すか false
allow-bot-users 書き込み権限の確認を外してよいボット名の一覧。* は使えない 空

出力(outputs)は final-message(最後のメッセージ)だけです。上のYAMLのように、ジョブの出力にして、次のジョブで使います。全体のやりとりを集めたいときは、公式のページは output-file とアーティファクトのアップロードを組み合わせるよう案内しています。

safety-strategy:キーを守る仕組み

公式のページとREADMEによると、既定は drop-sudo です。選べる値と、書かれている内容は次のとおりです。

値 公式の説明(要点) 注意
drop-sudo(既定) LinuxとmacOSで、Codexを動かす前に、実行ユーザーの sudo を取り消す。Linuxでは /run 以下のroot所有のソケット(Dockerのデーモンを含む)への到達も制限する。ジョブの中では元に戻せない 使い回すセルフホストのランナーでは、アカウントやソケットの変更が後のジョブにも残るので、使い捨てのランナーで、ジョブの最後のステップに。READMEは、sudo が外された後にプロンプト付きでもう一度動かすと失敗する、と書いている。Linuxで適用済みなら、新しいジョブを使う
unprivileged-user codex-user で指定した非特権ユーザーで動かす そのユーザーが、チェックアウト先を読み書きできる必要がある。READMEには参考例(examples/unprivileged-user.yml)の名前が出る
read-only 読み取り専用のサンドボックスで動かす。ファイルの変更と、ネットワークの直接の利用ができない 実行の権限は高いままで、キーはプロキシを通るので、プロセスのメモリを読めれば参照されうる。これだけでシークレットを守れるとは考えない
unsafe 制限をしない。通常は sudo が使えるユーザーで動く プロンプトを完全に信頼できるときだけ。マルチテナントのランナーでは使わない。Windowsでは、これが唯一の選択肢

OSごとの前提として、Windowsでは unsafe が必要です。Linuxの drop-sudo には、パスワードなしの sudo と setpriv、setfacl などが必要で、セルフホストのLinuxは自分で整える、という趣旨がREADMEの要約にありました。

unprivileged-user と、セルフホストのLinuxの落とし穴(READMEの要約)

権限プロファイル(permission-profile):READMEにあり、ページにない

READMEは、permission-profile を、ファイルとネットワークのアクセスを別々に決める仕組みで、リポジトリを編集する用途には :workspace、読み取り専用なら :read-only と説明しています。また、次の条件も書いています。

一方、公式のページ(learn.chatgpt.com)には、permission-profile の記述が見つかりませんでした。前のガイド(04)の入力の一覧にも、この項目はありません。READMEの追加ヒントには、新しい連携では、従来のサンドボックスのフラグより、権限プロファイル(まず :workspace)を優先する、という趣旨の記述がありました。僕らの見立てです。ページとREADMEで、更新の時期が違うのかもしれません。どちらが新しいかは、ページに日付がなく、判断できていません。

バージョンの動き

GitHubのCHANGELOG(要約)には、v1.7(2026-04-24)でボットによる権限の迂回を制限、v1.8(2026-04-29)でボットに許す範囲を厳しく、v1.10(2026-07-02)で権限プロファイルへの対応を追加、v1.11(2026-07-04)で補助を後方互換に修正、という記録がありました。CHANGELOGの最新の記録は v1.11(2026-07-04)でした。タグの一覧は読めていません。

起動できる人と、ボット

既定では、書き込み権限のある人だけが起動できます。権限のない人を許すには allow-users、ボットを許すには allow-bots か allow-bot-users を使います。公式は、これらを変えるなら信頼できるアカウントだけにするよう書いています。

その他のヒント(READMEの要約)

後続のスクリプトから codex を直接呼ぶと、アクションがかけた no_new_privs などの制限はかかりません。Codexは、prompt か prompt-file を使い、アクションを通して動かすのが推奨です。Azureなどを使うときは、responses-api-endpoint に完全なURL(.../openai/v1/responses の形)を指定します。

7. CIで安全に使う:公式が書いている注意

GitHub Actionの「セキュリティのチェックリスト」

公式のページが挙げている項目を、並べます。

  1. ワークフローを起動できる人を絞る。誰でも自由にCodexを動かせる状態を避け、信頼できるイベントや、明示的な承認を使う。
  2. PR、コミットメッセージ、Issueの本文から来る入力は、プロンプトインジェクションを防ぐために検査する。Codexに渡す前に、HTMLのコメントや見えない文字が入っていないか確かめる。
  3. OPENAI_API_KEY を守るため、safety-strategy は drop-sudo のままにするか、非特権のユーザーでCodexを動かす。複数の利用者が共有するランナーでは、unsafe を使わない。
  4. Codexは、ジョブの最後のステップとして動かす。後のステップが、予期しない状態の変化を引き継がないようにするため。
  5. プロキシのログやアクションの出力にシークレットが漏れた疑いがあれば、すぐにキーを入れ替える。

非対話モードのページの警告

OPENAI_API_KEY や CODEX_API_KEY をジョブ全体の環境変数にしない(同じジョブの中の信用できないコードから読めてしまうため)。~/.codex/auth.json はパスワードと同じに扱う。ChatGPT管理の認証は公開リポジトリやオープンソースでは避ける。danger-full-access と --skip-git-repo-check は、安全と分かっている環境だけ。

公式の「CIの自動修正」の形:ジョブを2つに分ける

非対話モードのページには、「GitHub ActionsでCIの失敗を自動で直す」例があります。取得できたのは要約で、YAMLの全文は原文どおりには写せませんでした。要約から確かめられた流れと、そこに出ていたコマンドは次のとおりです。

つまり、AIが動くジョブには書き込み権限を与えず、書き込めるジョブにはAIもキーも置かない、という分け方です。僕らの見立てです。READMEのレビューボットの例と同じ考え方で、公式は、権限の分離を一貫して勧めていると読めます。

公式が書いていないこと(読んだ範囲)

codex exec の再試行の回数やタイムアウトの設定、費用の上限を指定するフラグは、読んだ範囲では見つかりませんでした。使用量は、ChatGPTのプランの枠か、APIの料金から引かれます(前のガイド03)。

8. 最小の自動化レシピ(公式の例を写す)

コードは、上の節に写したものを使います。どれも公式の例の写しで、動作確認はしていません。

9. 最初の10分でやること

公式に書かれた範囲で、手を動かす順番を組みました。順番は僕らの整理です。

  1. Gitで管理している小さなフォルダで、レシピAを実行する。標準出力に最後のメッセージだけが出て、ファイルが変わっていないことを見る。
  2. 同じ指示に --json を付けて、イベントの流れを見る。thread.started で始まり、turn.completed で終わるか確かめる。
  3. 失敗する依頼(存在しないファイルの要約など)を流して、終了コードを確かめる(echo $?)。CIの成否に使えるかどうかの判断は、これを見てからにする。
  4. --output-schema で小さなスキーマを書き、-o で結果をファイルに受ける(レシピC)。
  5. GitHubに載せる前に、シークレットの置き場所を決める。APIキーは、リポジトリのシークレットに入れ、アクションの openai-api-key にだけ渡す。ジョブ全体の env: には書かない。
  6. 練習用のリポジトリで、前のYAMLを写し、権限(contents: read)、safety-strategy(既定のまま)、起動できる人(既定のまま)を確かめてから、本番に広げる。
  7. permission-profile(ベータ)を使うなら、READMEにあるとおり Codex CLI 0.138.0 以降が必要です。codex-version で古い版を固定していないかを、先に見ます。

僕らの見立て

ここからは僕らの見立てです。公式が勧めているわけではありません。

気をつけること

出典