Codex cloud environments: setup, caching, network and best-of-N
PLA Codex cloud environment is the container definition that every Codex cloud task runs in: the repository checkout, a setup script that runs with internet access, an optional maintenance script for cached containers, variables and setup-only secrets, and an agent-phase internet policy that is off by default. A well-built environment makes cloud tasks fast, repeatable and safe to run unattended.
Your first cloud task took twelve minutes, eight of them spent on pnpm install. The second one failed because the agent could not reach a registry, and the third returned a diff whose tests never ran, because the Playwright browsers were never installed. Each of those failures is an environment problem, not a model problem. This page is for the developer who owns the repository’s Codex setup and the tech lead who wants the whole team’s cloud tasks to land as reviewable, test-backed pull requests.
What a production-ready Codex cloud environment gives you
Section titled “What a production-ready Codex cloud environment gives you”- A setup script that fails loudly, a maintenance script that keeps cached containers current, and a way to test both on your laptop before you save them.
- A clear rule for what goes in environment variables and what goes in secrets.
- An internet-access posture you can defend in a security review, plus a prompt that drafts the allowlist.
- A CLI workflow for submitting, gating and applying cloud tasks, including best-of-N attempts and a fan-out script.
- A verification gate that decides whether a cloud diff is worth a human look, without reading every line.
How does a Codex cloud task run?
Section titled “How does a Codex cloud task run?”Every cloud task, whether you start it from the web, the CLI, a GitHub comment or a @ChatGPT mention in Slack (Cloud delegation), goes through the same phases. The phase boundaries explain almost every failure later on this page.
-
Container start. Codex starts a container from the
universalbase image, or resumes a cached container, and checks out your repository at the branch you selected. -
Setup script. Your setup script runs with internet access. This is the only phase where secrets exist.
-
Maintenance script. When Codex resumes a cached container, it runs the optional maintenance script instead of the full setup.
-
Lockdown. Secrets are removed and the agent-phase internet policy takes effect. The default is no internet access.
-
Agent loop. The agent reads files, edits code and runs commands. It reads
AGENTS.mdfor your build, lint and test commands, so the environment only has to make those commands runnable. -
Result. The task ends with a summary and a diff (one per attempt). You open a pull request, ask a follow-up, or apply the diff locally.
Phase, caching, secrets and preset behaviour follows OpenAI’s cloud environment and agent internet access docs (checked 2026-08-28); the CLI commands are checked against codex 0.157.1 and its source. OpenAI has rewritten its Codex Cloud docs around published, reusable cloud environments; the setup-script model described on this page is documented there as “Codex Cloud (Legacy)”, which “continues to support environments for Code Review and the Linear and GitHub integrations” (checked 2026-10-12).
What are published cloud environments, and how do they differ from the setup scripts below?
Section titled “What are published cloud environments, and how do they differ from the setup scripts below?”On 2026-09-29 (DevDay 2026) OpenAI rebuilt Codex Cloud around published, reusable cloud environments. OpenAI describes the idea this way: “Describe your development setup, let Codex prepare and test it, then publish the environment. New tasks start in isolated workspaces using the prepared filesystem.” The flow on OpenAI’s cloud page is to create or select an environment, choose “Let Codex prepare your project”, choose “Review and publish”, and start a task. Tasks “keep working while your computer is asleep”, and you “Review changes and continue from the web, mobile, or desktop app” (OpenAI’s cloud and DevDay 2026 pages, read 2026-10-12).
Two consequences matter for this page:
- The setup-script model below is the legacy one. OpenAI now documents it as “Codex Cloud (Legacy)”, with the same container, setup script and
universalimage, and says it “continues to support environments for Code Review and the Linear and GitHub integrations”. Keep using this page for those integrations. - Slack needs a published environment. ChatGPT’s Cloud delegation in Slack “requires a published environment shared with the workspace”; see Codex in Slack and Linear.
OpenAI’s pricing page lists Codex cloud and cloud environments for Plus, Pro, Business and Enterprise plans, and not for an API-key sign-in (read 2026-10-12). This page does not walk through the published-environment screens; follow OpenAI’s cloud environments page for those.
Configure the environment’s setup script
Section titled “Configure the environment’s setup script”You create and edit environments in the Codex web settings, under Environments. Each environment points at one repository and holds the scripts, variables, secrets and internet policy described below.
Start with automatic setup, then write a script
Section titled “Start with automatic setup, then write a script”For projects that use npm, yarn, pnpm, pip, pipenv or poetry, Codex can install dependencies automatically. Start there. Write a manual setup script when the agent needs something automatic setup does not provide: system packages, a code generator, browser binaries for end-to-end tests, or a build step that other packages depend on.
#!/usr/bin/env bash# Setup script: expensive steps that rarely changeset -euo pipefail
apt-get update && apt-get install -y --no-install-recommends postgresql-client redis-tools
pnpm install --frozen-lockfilepnpm exec playwright install --with-deps chromium
pnpm run codegenpnpm run build:shared
# Prove the environment works before the agent startspnpm run typecheckThree rules make this script worth having:
set -euo pipefailon the first line. Without it, a failedapt-get installdoes not stop the script, and the agent later spends its budget on “command not found”.- Lockfile installs (
--frozen-lockfile,npm ci,poetry install --no-update), so every container resolves the same dependency tree. - A verification step at the end. If
typecheckfails here, the setup fails with a clear log. If it fails during the task, the agent may “fix” your code to work around a broken environment.
Persist variables the agent needs
Section titled “Persist variables the agent needs”The setup script runs in a separate shell session from the agent, so export does not carry over. Write the value to ~/.bashrc, or better, define it as an environment variable in the settings UI:
# Does not reach the agent phaseexport DATABASE_URL="postgresql://localhost:5432/test"
# Reaches the agent phaseecho 'export DATABASE_URL="postgresql://localhost:5432/test"' >> ~/.bashrcChoose between environment variables and secrets
Section titled “Choose between environment variables and secrets”| Setting | Available during | Use it for | Never use it for |
|---|---|---|---|
| Environment variable | Setup and agent phases | NODE_ENV=test, a local test DATABASE_URL, feature flags for tests | Anything you would not paste into a pull request |
| Secret | Setup script only (removed before the agent starts) | A private registry token for pnpm install, a ghcr.io pull token | A value the agent needs at run time |
The split is a deliberate security boundary: a secret the agent never sees cannot leak into a diff, a log or a prompt-injected request. If a test genuinely needs a credential at run time, give it a test-only credential with no production reach, or stub the service.
Test the setup script on your laptop first
Section titled “Test the setup script on your laptop first”Saving a broken script and waiting for a cloud run is a slow feedback loop. OpenAI publishes codex-universal, a reference image close to the cloud base image, so you can rehearse the setup phase locally (run in your repository root):
docker run --rm -it --platform linux/amd64 \ -e CODEX_ENV_NODE_VERSION=22 \ -e CODEX_ENV_PYTHON_VERSION=3.12 \ -v "$(pwd)":/workspace/"$(basename "$(pwd)")" -w /workspace/"$(basename "$(pwd)")" \ ghcr.io/openai/codex-universal:latestInside the container, paste your setup script and watch it run. The CODEX_ENV_* variables select the language versions, and the codex-universal README lists the supported values (checked 2026-09-26). The image is “not an identical environment”, in OpenAI’s words, so treat a local pass as necessary rather than sufficient.
Keep the container warm with caching and maintenance scripts
Section titled “Keep the container warm with caching and maintenance scripts”Codex caches the container state after setup for up to 12 hours. Later tasks in the same environment resume from that state, skip the setup script, and run the maintenance script instead.
The cache is invalidated automatically when you change the setup script, the maintenance script, an environment variable or a secret. When a repository change breaks compatibility (a major dependency upgrade, a new system package), use Reset cache in the environment settings. The cache belongs to the environment, not to you: if teammates share the environment, a reset makes everyone’s next task pay the full setup cost, so treat it as a team action.
Split the work by how often it changes:
# Setup script: expensive, rarely changesapt-get update && apt-get install -y --no-install-recommends build-essentialpnpm install --frozen-lockfile
# Maintenance script: cheap, runs on every cached resumepnpm install --frozen-lockfile # picks up lockfile changes since the cache was builtpnpm run codegen # schemas may have changedBecause the cache can be hours older than your branch, the maintenance script is what stops the agent from testing today’s code against yesterday’s dependencies. Keep it fast, because it runs before every cached task.
Decide how much internet access the agent gets
Section titled “Decide how much internet access the agent gets”The setup script always has internet access. The agent phase has none by default, and that default protects you from three things: prompt injection from fetched content, exfiltration of your code, and the agent installing packages you never reviewed.
When the agent does need the network, turn it on per environment and shape it with two controls: a domain allowlist and the allowed HTTP methods.
| Posture | Settings | Use when |
|---|---|---|
| Off (default) | No agent internet | Everything the task needs is installed during setup. Start here. |
| Locked down | On · Common dependencies preset plus named domains · methods GET, HEAD, OPTIONS | The agent must fetch packages or read a public API during the task |
| Hand-built | On · None preset (empty list) plus every domain you name · read-only methods | A regulated codebase where every host needs a written reason |
| Unrestricted | On · All preset | A disposable sandbox with no secrets and nothing worth exfiltrating. Avoid on real repositories. |
The Common dependencies preset covers the usual package registries and source-control hosts, so you add only what your tests need, for example api.stripe.com for a Stripe test-mode suite. Restricting methods to GET, HEAD and OPTIONS blocks POST, PUT, PATCH and DELETE, so an injected instruction cannot POST your code anywhere; data can still leave in a GET URL to an allowlisted host, which is why the allowlist stays as narrow as possible.
Submit and manage cloud tasks from the CLI
Section titled “Submit and manage cloud tasks from the CLI”The codex cloud subcommand is marked experimental in codex 0.157.1. Run it with no arguments to open an interactive picker that browses tasks and applies diffs; press o in the task list (or Ctrl+O while composing a new task) to choose an environment. For scripts, use the subcommands (run in your terminal, inside the repository):
# Submit a task; prints the task URLcodex cloud exec --env payments-api "Fix the failing integration tests in src/payments/"
# Run on a specific pushed branch instead of your current onecodex cloud exec --env payments-api --branch fix/refund-rounding "Add a regression test for refund rounding"
# Check one task; exits 1 unless the status is READY (pending, applied and error all exit 1)codex cloud status TASK_ID
# List recent tasks as JSONcodex cloud list --env payments-api --json | jq '.tasks[] | {id, status, attempt_total, summary}'
# Read a diff, then apply it to your working treecodex cloud diff TASK_IDcodex cloud apply TASK_IDTASK_ID is the ID or the full task URL that codex cloud exec prints. Details worth knowing, all checked against 0.157.1:
--envis required and accepts an environment ID or its label (case-insensitive). If a label is ambiguous, runcodex cloudto pick the ID.--branchdefaults to your current branch, and the cloud container clones from your remote, so push the branch first.- The prompt can come from standard input:
codex cloud exec --env payments-api - < task.md. codex cloud listreturns at most 20 tasks per page (--limit 1-20) and acursorfor the next page. JSONstatusvalues arepending,ready,appliedanderror.
When is best-of-N worth paying for?
Section titled “When is best-of-N worth paying for?”--attempts runs up to four independent agents on the same prompt, each producing its own diff (1–4; codex cloud exec rejects any other value). Each attempt is a full agent run, so budget for N tasks, not one. Use it when a wrong first answer costs more than the extra runs:
- A bug whose root cause is ambiguous, such as a race or a caching issue.
- A refactor or migration with several valid designs you want to compare.
- A performance change where strategies trade off differently.
Skip it for mechanical changes; three identical diffs tell you nothing. If attempts do come back identical on a task that should have options, name the alternatives in the prompt (“compare a cache-aside and a write-through approach”).
codex cloud exec --env payments-api --attempts 3 - <<'EOF'The /api/users endpoint returns stale data after a profile update.First write a failing test that updates a profile and immediately reads it back.Then find the caching bug and fix it. Run the full user-service test suite andreport the exact command and its result. Do not modify tests outside tests/users/.EOF
# Compare attempts, then apply the one you choosecodex cloud diff TASK_ID --attempt 2codex cloud apply TASK_ID --attempt 2Fan one change out across a monorepo
Section titled “Fan one change out across a monorepo”For one well-scoped change repeated across packages, submit one task per package and review the diffs side by side. Keep the prompt identical so the diffs are comparable; improve the prompt once and every package benefits.
#!/usr/bin/env bashset -euo pipefailENV_ID="payments-api"BRANCH="$(git branch --show-current)": > cloud-tasks.txtpids=()
for pkg in api web worker; do codex cloud exec --env "$ENV_ID" --branch "$BRANCH" \ "In packages/$pkg, replace lodash calls with native ES2023 equivalents. Keep behavior identical, do not touch other packages, and run that package's test suite." \ >> cloud-tasks.txt & pids+=($!)donefailed=0for p in "${pids[@]}"; do wait "$p" || { echo "submit failed (pid $p)" >&2; failed=1; }donecat cloud-tasks.txt # one task URL per successful submissionexit "$failed"For fan-out inside one local session instead, use multi-agent workflows.
How do you verify a cloud task without reading every line?
Section titled “How do you verify a cloud task without reading every line?”A cloud diff is a proposal. Decide what it has to prove before you open it, and let machines do the first pass:
-
The environment runs the same gates as CI.
AGENTS.mdnames the lint, type-check and test commands, and the setup script makes them runnable. The task summary must quote the commands it ran and their results. No test output means the task is not done, however good the diff looks. -
Check the blast radius from metadata.
codex cloud list --jsonreportsfiles_changed,lines_addedandlines_removedper task. A “fix one endpoint” task that touches 40 files goes back with a narrower prompt before anyone reads it.Terminal window codex cloud list --env payments-api --json \| jq -r '.tasks[] | select(.status == "ready" and .summary.files_changed > 10) | "\(.id) \(.title)"' -
Re-run the gates outside the agent. Apply the diff in a clean worktree and run your checks yourself, or open the pull request and let CI run them.
TASK_BRANCHis the branch you passed to--branch, or the branch you were on when you submitted the task. CI is the authority, not the agent’s summary.Terminal window git fetch origin TASK_BRANCHgit worktree add ../verify-task origin/TASK_BRANCH && cd ../verify-taskpnpm install --frozen-lockfilecodex cloud apply TASK_IDpnpm run typecheck && pnpm run lint && pnpm test -
Send the pull request through automated review. Ask for
@codex reviewon the PR, and route anything that touches authentication, payments or migrations to a human owner. See Codex code review. -
A named person merges. The developer who submitted the task owns the merge. Best-of-N and fan-out change how many diffs exist, not who signs off.
Watch for diffs that make tests pass by editing the tests: changed assertions, deleted cases, updated snapshots or loosened type checks. Make “flag any change to tests” part of every review prompt, as the best-of-N prompt above does.
When Codex cloud environments break
Section titled “When Codex cloud environments break”| Symptom | Likely cause | Recovery |
|---|---|---|
| The agent reports “command not found” for a tool the setup installs | The setup script failed silently, or the tool’s path was exported in the setup shell only | Add set -euo pipefail; append PATH and variables to ~/.bashrc or set them in the UI; rehearse with codex-universal |
| Tests pass in the task but fail in CI | The cached container has stale dependencies or generated code | Add pnpm install --frozen-lockfile and codegen to the maintenance script; Reset cache once |
| Every task pays the full setup time | Frequent edits to scripts, variables or secrets keep invalidating the cache | Batch environment changes; move volatile steps into the maintenance script |
| The agent cannot install a package it wants | Agent internet is off (the default) | Install the package in the setup script; if it must be fetched at run time, allow its registry with read-only methods |
| A private registry install fails during the task | The token is a secret, and secrets are removed before the agent phase | Install private packages during setup; never copy the token into an environment variable |
codex cloud exec fails with “environment … not found” or “ambiguous” | Wrong ID, or two environments share a label | Run codex cloud and copy the exact ID |
| The task ran on the wrong code | The branch was not pushed, or --branch pointed elsewhere | Push first; pass --branch explicitly in scripts |
codex cloud apply fails or applies partially | Your working tree diverged from the task’s base | Apply in a clean worktree on the task’s base branch, or ask the task to rebase and re-run |
| The language version differs from production | The base image default does not match your pin | Pin the version in the environment settings or install it in the setup script |
Where to go next with Codex cloud tasks
Section titled “Where to go next with Codex cloud tasks”- Prerequisite: make sure cloud tasks get your commands from
AGENTS.md, then tighten it with AGENTS.md optimization. - Start cloud tasks from chat and tickets: Slack and Linear integration.
- Run Codex unattended in your own CI instead of the cloud: non-interactive mode and Codex in CI/CD.
- Keep best-of-N and fan-out affordable: Codex cost management.
- Compare cloud environments across Claude Code, Codex and Cursor: ephemeral environments.
- Share environments and review rules across a team: Codex team workflows.