CodexHowSupport Us

Setting Up a Read-Only CI Profile

A CI check that only needs to read code and report findings — a lint pass, a review comment, a policy check — has no business running with write access at all, and setting it up as genuinely read-only from the start removes an entire category of "what could this step accidentally change" risk before it exists.

The exact configuration

--sandbox read-only --ask-for-approval never is the published combination built for this specific shape: reads only, and no prompting since there's nobody present in an automated run to answer one. This isn't a workaround or an approximation of a CI-appropriate mode — it's the mode this exact combination is documented for.

Why "never" is the right approval choice here, not a risk

It's worth being explicit about why removing prompts entirely is fine in this specific pairing: under read-only, there's nothing destructive for Codex to do in the first place — the sandbox mode itself is the safety mechanism, and the approval mode's job is just to avoid hanging the pipeline waiting on a prompt nobody can answer. The destructive-tool-call override that still applies under never is a non-issue here too, since a read-only session calling a destructive MCP tool would be blocked by the sandbox before the approval question even arises.

What this profile is actually good for

Code review passes that produce comments or a report without touching the repository, policy or convention checks against AGENTS.md or similar project rules, and any exploratory analysis task where the output is information, not a file change. If a CI step's entire job is "look at this and tell me something," read-only with never-prompt is close to the ideal shape for it — fast to set up, and structurally incapable of the class of mistake a write-capable step could make.

What it can't do, and how to tell early

A read-only profile will fail, predictably, the moment a task tries to write a file — auto-formatting, applying a suggested fix directly, generating a file as output. That's expected behavior, not a bug, and the fix isn't to loosen the sandbox reflexively; it's to confirm the task genuinely needs write access and, if so, move it to a properly scoped workspace-write profile instead, kept separate from the genuinely read-only checks in your pipeline.

Separating read-only checks from write-capable steps in the same pipeline

A pipeline that runs both a read-only review step and a separate write-capable formatting step shouldn't run them under one shared, more permissive configuration just to avoid maintaining two profiles — keeping the read-only step genuinely read-only, even when a write-capable step exists elsewhere in the same pipeline, means a bug or a misconfiguration in the write-capable step can't accidentally make the review step start writing too, because they're configured independently.

Network access under a read-only profile

Read-only sandbox mode doesn't need the network-access discussion that applies to workspace-write — read-only mode's restriction is broader than just network access, so there's no separate network flag to think about for this specific profile. If a read-only check genuinely needs to make an external call — checking an external service, fetching reference data — that's worth checking against the CLI's current documentation for whether it's actually compatible with a strict read-only posture, since a network dependency inside a read-only step is a less common pattern worth confirming explicitly rather than assumed to work.

Testing the profile before trusting it in production CI

Before wiring a read-only, never-prompt profile into a pipeline that gates real work, running it manually once against a representative task and confirming it behaves the way you expect — fails cleanly on anything requiring write access, produces the read-only output you actually wanted — is worth the few minutes it takes. A misconfigured CI step that silently does nothing useful, discovered only when someone notices a review pass has been producing empty output for weeks, is a worse failure mode than one caught in a manual test run before the pipeline ever went live.

A minimal, defensible default worth reaching for

For any new CI integration where you're genuinely unsure whether write access will be needed, starting with this read-only profile and only expanding to workspace-write once a specific need is confirmed is the more defensible default than the reverse — it's much easier to loosen a deliberately narrow starting point than to discover, after the fact, that a broadly permissive CI step had access it never actually used.

Cost characteristics of a read-only CI profile

A read-only review pass tends to be a genuinely predictable, bounded cost — it reads a fixed set of files or a fixed diff, produces a bounded amount of output, and doesn't iterate against test failures or retry attempted edits the way a write-capable session might. That predictability makes it a good candidate for budgeting precisely: run it against a representative pull request, note the actual token counts from the usage object, and multiply by your team's typical PR volume for a realistic monthly estimate, rather than a rough guess.

Auditing what a read-only step actually did

Even though a read-only profile can't modify the repository, it's still worth periodically reviewing what it actually reported — a check that's been silently producing low-value or repetitive output for months is wasted spend regardless of how safely it was configured. Treat the review pass itself as something worth reviewing occasionally, the same scrutiny you'd apply to any other recurring automated cost.

Combining this with a scheduled, non-blocking run

Not every read-only check needs to gate a merge — a read-only profile is equally well suited to a scheduled, non-blocking analysis pass (a weekly codebase health report, say) that runs on a timer rather than per-commit. The configuration is identical; only the trigger changes, and it's worth considering this pattern for anything valuable enough to want regularly but not urgent enough to justify running — and paying for — on every single commit.

Verified 2026-08-09 against CodexHow facts module (src/data/facts/) — see /about/#accuracy.