TellWorldAI World Archive
Ask中文

Home›Practice›Practice

Practice

Codex Non-Interactive Mode: Scripting with codex exec

Run Codex from scripts and CI with codex exec. Learn to pass prompts, pipe input and output, choose sandbox permissions, get JSON or schema-bound results, and keep API keys out of shared job environments.

Who this is for and what you will get

If you want Codex to run inside CI, a scheduled job or a shell pipeline instead of an interactive session, this guide is for you. You will learn to run codex exec, capture its output, choose a sandbox, produce machine-readable JSON and handle API keys safely.[1]

What codex exec is

Non-interactive mode runs Codex from scripts without opening the interactive interface. You start it with codex exec.[1] It fits pipelines such as CI, pre-merge checks and scheduled jobs. It also suits feeding output to other tools, chaining command output into Codex, and running with sandbox and approval settings fixed in advance.[1] Every flag is described under the codex exec entry in the developer command reference.[1]

Your first run

Pass the task as the only argument. The following command asks for a short risk assessment of the repository:[1]

codex exec "summarize the repository structure and list the top 5 risky areas"

While it works, progress goes to stderr, and stdout carries only the final message. That makes the result easy to redirect or pipe into the next command.[1]

codex exec "generate release notes for the last 10 commits" | tee release-notes.md

To avoid saving session files to disk, add --ephemeral:[1]

codex exec --ephemeral "triage this repository and suggest next steps"

Feeding data through a pipe

When you give both stdin and a prompt argument, Codex treats the prompt as the instruction and the piped text as extra context. This example fetches some comments and asks Codex to turn them into a table:[1]

curl -s https://jsonplaceholder.typicode.com/comments \
  | codex exec "format the top 20 items into a markdown table" \
  > table.md

There are two more stdin patterns. In prompt-plus-stdin, you write the instruction and the command output serves as context. Here, failing tests are summarized after a test run:[1]

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

In the second pattern, stdin becomes the entire prompt. This suits prompts that a script assembles:[1]

cat prompt.txt | codex exec -

If you omit the prompt argument, Codex reads the prompt from stdin anyway. The - makes that behavior explicit.[1]

Choosing permissions

codex exec starts in a read-only sandbox. Add --sandbox workspace-write to allow edits. --sandbox danger-full-access grants broader access and belongs only on an isolated CI runner or inside a container.[1]

--full-auto is no longer supported. Replace it with --sandbox workspace-write, or use --approve-for-me to send approval requests through automatic review while staying in the workspace-write sandbox.[1]

Use --ignore-user-config to skip $CODEX_HOME/config.toml, and --ignore-rules to skip user and project execpolicy .rules files in a controlled environment.[1]

If an enabled MCP server marked required = true fails to initialize, codex exec exits with an error rather than carrying on without it.[1]

Machine-readable output

Add --json and stdout becomes a JSON Lines stream that logs each event as it happens:[1]

codex exec --json "summarize the repo structure" | jq

Event types include thread.started, turn.started, turn.completed, turn.failed, item.* and error. Items cover agent messages, reasoning, command runs, file edits, MCP tool calls, web searches and plan updates.[1] A short sample stream looks like this:[1]

{"type":"thread.started","thread_id":"0199a213-81c0-7800-8aa1-bbab2a035a53"}
{"type":"turn.started"}
{"type":"item.started","item":{"id":"item_1","type":"command_execution","command":"bash -lc ls","status":"in_progress"}}
{"type":"item.completed","item":{"id":"item_3","type":"agent_message","text":"Repo contains docs, sdk, and examples directories."}}
{"type":"turn.completed","usage":{"input_tokens":24763,"cached_input_tokens":24448,"output_tokens":122,"reasoning_output_tokens":0}}

If you only need the last message, pass -o <path> or --output-last-message <path>. The message is written to that file and still printed to stdout.[1]

Structured results with a schema

--output-schema makes the final response match a JSON Schema. This helps when later steps depend on fixed field names, such as job summaries, risk reports or release metadata.[1] A schema file looks like this:[1]

{
  "type": "object",
  "properties": {
    "project_name": { "type": "string" },
    "programming_languages": {
      "type": "array",
      "items": { "type": "string" }
    }
  },
  "required": ["project_name", "programming_languages"],
  "additionalProperties": false
}

Then run Codex with the schema and write the result to a file:[1]

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

Authentication in CI

By default codex exec reuses the CLI login saved on the machine. Automation usually supplies credentials explicitly.[1] To use a different API key for one run, set CODEX_API_KEY inline:[1]

CODEX_API_KEY=<api-key> codex exec --json "triage open bug reports"

CODEX_API_KEY works with codex exec, codex review, the TypeScript SDK and codex exec-server --remote.[1]

Keep keys out of job-wide variables. In workflows that check out or run repository code, do not set OPENAI_API_KEY or CODEX_API_KEY at job level. Build scripts, tests, dependency lifecycle hooks or a compromised action in the same job can read them.[1]

For GitHub Actions, the documentation recommends the official Codex GitHub Action over installing and logging in to the CLI yourself. The action installs Codex, starts a Responses API proxy and runs Codex under a configurable safety strategy.[1]

Using ChatGPT-managed auth in CI is an advanced option for running jobs under a Codex user account. The ~/.codex/auth.json file holds access tokens, so guard it like a password and never commit it, paste it into a ticket or share it in chat. Do not use this approach for public or open-source repositories.[1]

Resuming a session

In a two-stage pipeline, pick up the earlier session with resume:[1]

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

You can also name a specific session with codex exec resume <SESSION_ID>.[1]

The Git requirement

Codex expects commands to run inside a Git repository, which guards against destructive edits. Only pass --skip-git-repo-check if you are sure the environment is safe.[1]

An auto-fix pattern for failing CI

The documentation outlines one pattern. When the main CI workflow fails, a follow-up workflow starts. It checks out the failing commit with read-only permissions, runs setup steps before Codex without giving those steps the OpenAI API key, runs the Codex GitHub Action, saves Codex's local changes as a patch artifact, and lets a separate job apply the patch and open a pull request.[1]

The Codex job has only contents: read. The job that opens the pull request gets write permissions but never receives OPENAI_API_KEY.[1]

Next steps

The full list of flags is in the official developer command reference.[1]

Sources

  1. 1
    Non-interactive modeOpenAI Codex docs

Cite this page: Codex Non-Interactive Mode: Scripting with codex exec. TellWorld, https://www.tellworld.net/practice/practice-codex-non-interactive. Updated 2026-11-14

Related news

View all