Skip to content

A 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.

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.

  1. Container start. Codex starts a container from the universal base image, or resumes a cached container, and checks out your repository at the branch you selected.

  2. Setup script. Your setup script runs with internet access. This is the only phase where secrets exist.

  3. Maintenance script. When Codex resumes a cached container, it runs the optional maintenance script instead of the full setup.

  4. Lockdown. Secrets are removed and the agent-phase internet policy takes effect. The default is no internet access.

  5. Agent loop. The agent reads files, edits code and runs commands. It reads AGENTS.md for your build, lint and test commands, so the environment only has to make those commands runnable.

  6. 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 universal image, 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 change
set -euo pipefail
apt-get update && apt-get install -y --no-install-recommends postgresql-client redis-tools
pnpm install --frozen-lockfile
pnpm exec playwright install --with-deps chromium
pnpm run codegen
pnpm run build:shared
# Prove the environment works before the agent starts
pnpm run typecheck

Three rules make this script worth having:

  • set -euo pipefail on the first line. Without it, a failed apt-get install does 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 typecheck fails 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.

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:

Terminal window
# Does not reach the agent phase
export DATABASE_URL="postgresql://localhost:5432/test"
# Reaches the agent phase
echo 'export DATABASE_URL="postgresql://localhost:5432/test"' >> ~/.bashrc

Choose between environment variables and secrets

Section titled “Choose between environment variables and secrets”
SettingAvailable duringUse it forNever use it for
Environment variableSetup and agent phasesNODE_ENV=test, a local test DATABASE_URL, feature flags for testsAnything you would not paste into a pull request
SecretSetup script only (removed before the agent starts)A private registry token for pnpm install, a ghcr.io pull tokenA 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):

Terminal window
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:latest

Inside 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:

Terminal window
# Setup script: expensive, rarely changes
apt-get update && apt-get install -y --no-install-recommends build-essential
pnpm install --frozen-lockfile
# Maintenance script: cheap, runs on every cached resume
pnpm install --frozen-lockfile # picks up lockfile changes since the cache was built
pnpm run codegen # schemas may have changed

Because 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.

PostureSettingsUse when
Off (default)No agent internetEverything the task needs is installed during setup. Start here.
Locked downOn · Common dependencies preset plus named domains · methods GET, HEAD, OPTIONSThe agent must fetch packages or read a public API during the task
Hand-builtOn · None preset (empty list) plus every domain you name · read-only methodsA regulated codebase where every host needs a written reason
UnrestrictedOn · All presetA 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):

Terminal window
# Submit a task; prints the task URL
codex cloud exec --env payments-api "Fix the failing integration tests in src/payments/"
# Run on a specific pushed branch instead of your current one
codex 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 JSON
codex cloud list --env payments-api --json | jq '.tasks[] | {id, status, attempt_total, summary}'
# Read a diff, then apply it to your working tree
codex cloud diff TASK_ID
codex cloud apply TASK_ID

TASK_ID is the ID or the full task URL that codex cloud exec prints. Details worth knowing, all checked against 0.157.1:

  • --env is required and accepts an environment ID or its label (case-insensitive). If a label is ambiguous, run codex cloud to pick the ID.
  • --branch defaults 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 list returns at most 20 tasks per page (--limit 1-20) and a cursor for the next page. JSON status values are pending, ready, applied and error.

--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”).

Terminal window
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 and
report the exact command and its result. Do not modify tests outside tests/users/.
EOF
# Compare attempts, then apply the one you choose
codex cloud diff TASK_ID --attempt 2
codex cloud apply TASK_ID --attempt 2

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 bash
set -euo pipefail
ENV_ID="payments-api"
BRANCH="$(git branch --show-current)"
: > cloud-tasks.txt
pids=()
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+=($!)
done
failed=0
for p in "${pids[@]}"; do
wait "$p" || { echo "submit failed (pid $p)" >&2; failed=1; }
done
cat cloud-tasks.txt # one task URL per successful submission
exit "$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:

  1. The environment runs the same gates as CI. AGENTS.md names 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.

  2. Check the blast radius from metadata. codex cloud list --json reports files_changed, lines_added and lines_removed per 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)"'
  3. 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_BRANCH is 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_BRANCH
    git worktree add ../verify-task origin/TASK_BRANCH && cd ../verify-task
    pnpm install --frozen-lockfile
    codex cloud apply TASK_ID
    pnpm run typecheck && pnpm run lint && pnpm test
  4. Send the pull request through automated review. Ask for @codex review on the PR, and route anything that touches authentication, payments or migrations to a human owner. See Codex code review.

  5. 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.

SymptomLikely causeRecovery
The agent reports “command not found” for a tool the setup installsThe setup script failed silently, or the tool’s path was exported in the setup shell onlyAdd 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 CIThe cached container has stale dependencies or generated codeAdd pnpm install --frozen-lockfile and codegen to the maintenance script; Reset cache once
Every task pays the full setup timeFrequent edits to scripts, variables or secrets keep invalidating the cacheBatch environment changes; move volatile steps into the maintenance script
The agent cannot install a package it wantsAgent 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 taskThe token is a secret, and secrets are removed before the agent phaseInstall 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 labelRun codex cloud and copy the exact ID
The task ran on the wrong codeThe branch was not pushed, or --branch pointed elsewherePush first; pass --branch explicitly in scripts
codex cloud apply fails or applies partiallyYour working tree diverged from the task’s baseApply in a clean worktree on the task’s base branch, or ask the task to rebase and re-run
The language version differs from productionThe base image default does not match your pinPin the version in the environment settings or install it in the setup script