cool-solution — dev.blog
Technologies

Codex CLI codex exec: automating Codex in CI and scripts

I use Codex CLI every day in interactive mode, but the real leap comes when I need to run it without sitting in front of a screen: inside a CI pipeline, in a nightly cron job, in a script that chains multiple commands. That's what the codex exec command is for — the non-interactive mode of Codex: I hand it a task, it runs once and returns only the final message on stdout, while progress streams on stderr. In this article I look at what codex exec does under the hood, how to make its output machine-readable, and the path I follow to use it in automation without granting too many permissions.

$ claude "refactor user.service to async/await" reading src/services/user.service.ts... proposing 12 edits across 3 files ✓ tests still pass (47 / 47) applying patch...AI PAIRsupervised

🔍 What codex exec does and why it exits the terminal

The everyday codex command opens a TUI, the interactive interface where I talk to the agent. codex exec does the opposite: it runs a single task in a non-interactive way and exits, without asking me anything mid-way. It's the right primitive for CI/CD, cron, and scripts, where nobody is in front of the screen to confirm.

The most important practical difference is how Codex separates its output streams: while it works it sends progress to stderr, and at the end it prints only the agent's message to stdout. This lets me redirect or pipe the result without the process noise contaminating it.

One example I use often is codex exec "generate release notes for the last 10 commits" with the output sent straight to a file. It also works the other way: if I pipe data in alongside a prompt, Codex treats the prompt as the instruction and whatever arrives from stdin as additional context.

📄 Output a script can read: JSON, files, and schema

In automation, a prose message isn't enough: I need something a program can parse. That's why codex exec has the --json flag, which turns stdout into a JSON Lines stream — one event per line: thread start, turn start and end, command executions, file changes, MCP tool calls. Every state change becomes a JSON line I can filter with tools like jq.

When I only care about the final answer I use -o (that is, --output-last-message) to write it to a file, while still seeing it on screen. And if downstream I need stable fields — a summary, a risk report, some metadata — I pass a schema with --output-schema: Codex guarantees the final response matches that JSON Schema.

This is the part that changes everything compared to copy-pasting: with a schema the agent's result becomes structured and predictable, so it can be chained into the next pipeline step without brittle parsing.

The codex exec flow in a pipeline
  1. 01
    Pass the taskI launch codex exec with the prompt as an argument, or pipe it in from a previous command.
  2. 02
    Read-only sandboxBy default Codex works in read mode: it inspects the repo without modifying it, until I raise the permissions.
  3. 03
    Progress on stderrWhile it reasons and executes commands it sends progress to stderr, separate from the final result.
  4. 04
    Result on stdoutAt the end it prints only the final message (or JSON with --json), ready to be piped into the next step.

Source: official OpenAI Codex documentation — Non-interactive mode.

🔐 Minimal permissions: the sandbox and security in automation

The rule I follow in automation is simple: grant the minimum permissions necessary. By default codex exec runs in a read-only sandbox, which is fine for analysis tasks. When it needs to modify files I raise to --sandbox workspace-write; only in an isolated and controlled environment — a disposable CI runner — do I reach for --sandbox danger-full-access.

The old --full-auto flag is now deprecated and prints a warning: in new scripts I always prefer the explicit flag --sandbox workspace-write, which states clearly what the agent is allowed to do. For locked-down environments there are also --ignore-user-config, which avoids loading the personal config.toml, and --ignore-rules, which skips local policies.

Two useful guardrails to know. Codex requires a Git repository to avoid irreversible changes, and if I'm certain it's safe I can override this with --skip-git-repo-check. On authentication: in CI I never expose the key at the job level — on GitHub Actions I use the Codex GitHub Action, elsewhere I pass CODEX_API_KEY inline only for that single invocation.

⚖️ Interactive or codex exec? How I choose

The question I ask myself is simple: is there a person watching the result and reacting, or not?. If I'm exploring, doing guided refactoring, or discussing an architecture, I stay in interactive codex. If the task is repeatable and starts automatically — a pre-merge check, a nightly summary, an automatic fix — then it's work for codex exec.

They're not competing alternatives: I use both in the same projects, at different moments. Interactive is my workshop; codex exec is the arm I send into the pipeline when the work is already clear and I want it to repeat exactly, a thousand times, without me.

codex interactive and codex exec: two modes, two moments

codex — interactive

  • Opens the TUI and talks to me
  • Asks for confirmation on risky actions
  • Ideal for exploring, refactoring, deciding
  • A person is there guiding and reacting

codex exec — non-interactive

  • Runs a task once and exits
  • Progress on stderr, result on stdout
  • Ideal for CI, cron, repeatable scripts
  • Nobody present: permissions and schema decided upfront

🗺️ The flow I follow to put codex exec in a pipeline

When I move a task from interactive to automated I always start small and with minimal permissions, then expand only if needed. The goal isn't "Codex does everything on its own", but a reliable step that fits into the rest of the pipeline.

The mini-playbook I apply, in order:

  • Start in read-only mode: run the analysis task without write permissions until the output is what I expect.
  • Make the output machine-readable with --json for events, or --output-schema when downstream steps need stable fields.
  • Chain via stdin: pipe logs or test output into codex exec and use the result in the next step, for example to summarize a failure.
  • Resume when needed with codex exec resume --last, useful in two-stage pipelines: first analyze, then fix.
  • Protect credentials: on GitHub Actions I use the Codex GitHub Action, never the key at the job level.

Frequently asked questions about codex exec command

Are codex exec and interactive codex the same thing?

No. Interactive codex opens the TUI and talks to me, asking for confirmation on risky actions; codex exec runs a single task non-interactively and exits. I use interactive for exploring and deciding, codex exec when the work is repeatable and needs to start without me, in CI or in a script.

How do I get output from codex exec that a script can read?

With the --json flag I turn stdout into a JSON Lines stream, one event per line. If I only need the final answer I write it to a file with -o; if downstream steps need stable fields I impose a JSON Schema with --output-schema, so the result is structured and predictable instead of free-form prose.

Can codex exec modify files in my repository?

Only if I allow it. By default it runs in a read-only sandbox. To let it write I raise to --sandbox workspace-write, and I reserve danger-full-access for isolated environments like a disposable CI runner. Codex also requires a Git repository, so changes remain trackable and reversible.

How do I manage authentication in CI without exposing the API key?

I never put the key as a job-level variable. On GitHub Actions I use the Codex GitHub Action, which starts a proxy and reduces key exposure. In other environments I pass CODEX_API_KEY inline only for the single codex exec invocation, preventing other code in the same process from reading it.

Let's talk

If this topic is relevant to you, write to me: comparing notes on code and AI is always time well spent.

All articles

More articles from the blog

tips-claude-resume-luglio-2026.mdJuly 10, 2026claude-code-hooks-quality-gate-2026.mdJuly 9, 2026orchestrazione-agenti-ai-multi-agent-dotnet-2026.mdJuly 8, 2026