# How to run OpenAI Codex CLI in a cloud sandbox Install `@openai/codex` with npm in a Linux microVM. Store the API key as a secret, run `codex exec` on a cloned repo, and copy the diff. **On Runtime, Codex gets a whole machine to itself and never holds your key.** Every sandbox is a Firecracker microVM with its own Linux kernel, Ubuntu 24.04 and Node.js 24, so the npm package installs unchanged. The OpenAI key is stored as a Runtime secret. The sandbox sees a placeholder, and the host's proxy adds the real key only to requests to `api.openai.com`. A 2 vCPU, 4 GiB sandbox costs $0.03125 an hour while the agent waits on the model. Codex 0.164.0 was the current npm release on 25 October 2026. | You want | Do this | | --------------------------------------------- | ----------------------------------------------------------- | | Codex to work on a repo away from your laptop | Run Codex inside a sandbox (below) | | Codex on your machine to run code safely | Add Runtime's MCP server, and it creates sandboxes as tools | ## Store the key once `codex exec` reads its key from `CODEX_API_KEY`. Store yours as a secret bound to OpenAI's API host: ```bash no-run printf %s "$OPENAI_API_KEY" | npx withruntime secrets set CODEX_API_KEY --host api.openai.com ``` Every sandbox in your account then has `CODEX_API_KEY` set to a placeholder, such as `rtsec_3f9c…`. Only an HTTPS request to `api.openai.com` carries the real value. The value is sealed when you store it. No API, tool or command returns it ([secrets sandboxes never see](/docs/security#secrets-sandboxes-never-see)). OpenAI's guide says to set `CODEX_API_KEY` inline, not job-wide, when running code that a repository controls. A secret goes further. The code in the sandbox, Codex included, can read only the placeholder. ## Run Codex on a repo ```ts check import { writeFile } from "node:fs/promises"; import { Sandbox } from "withruntime"; const repo = "https://github.com/your-org/your-repo"; const task = "Find and fix the failing test in the parser, then run the tests."; await using sbx = await Sandbox.create({ diskMiB: 8192, timeoutSeconds: 3600 }); const slow = { check: true, timeoutMs: 600_000 } as const; await sbx.exec("npm install -g --prefix /workspace/.local @openai/codex", slow); await sbx.exec(["git", "clone", "--depth", "1", repo, "/workspace/app"], slow); // From here on the agent reaches only the model and the npm registry. await sbx.network.set({ internet: true, allow: ["api.openai.com", "registry.npmjs.org"] }); const run = await sbx.exec( ["codex", "exec", "--sandbox", "danger-full-access", "--ephemeral", task], { cwd: "/workspace/app", timeoutMs: 1_800_000, onStderr: (text) => process.stderr.write(text), }, ); console.log(run.exitCode, run.stdout); // stdout holds Codex's final message await sbx.exec("git add -A && git diff --cached > /workspace/change.patch", { cwd: "/workspace/app", check: true, }); await writeFile("change.patch", await sbx.files.readText("/workspace/change.patch")); ``` ```python check import sys from withruntime import Sandbox repo = "https://github.com/your-org/your-repo" task = "Find and fix the failing test in the parser, then run the tests." with Sandbox.create(disk_mib=8192, timeout_seconds=3600) as sbx: sbx.exec("npm install -g --prefix /workspace/.local @openai/codex", check=True, timeout_ms=600_000) sbx.exec(["git", "clone", "--depth", "1", repo, "/workspace/app"], check=True, timeout_ms=600_000) sbx.network.set(internet=True, allow=["api.openai.com", "registry.npmjs.org"]) run = sbx.exec( ["codex", "exec", "--sandbox", "danger-full-access", "--ephemeral", task], cwd="/workspace/app", timeout_ms=1_800_000, on_stderr=sys.stderr.write, ) print(run.exit_code, run.stdout) # stdout holds Codex's final message sbx.exec("git add -A && git diff --cached > /workspace/change.patch", cwd="/workspace/app", check=True) with open("change.patch", "w") as file: file.write(sbx.files.read_text("/workspace/change.patch")) ``` What each part does: - **`--prefix /workspace/.local`** puts the `codex` command in `/workspace/.local/bin`, first on the sandbox's `PATH`, with no `sudo`. - **`--sandbox danger-full-access`** turns off Codex's own command sandbox. OpenAI's guide says to use it "only in a controlled environment (for example, an isolated CI runner or container)". A microVM that holds no key and reaches two hosts is that environment. For Codex's own read-only default, leave the flag out. `--sandbox workspace-write` lets Codex edit files in the checkout. - **`--ephemeral`** keeps session files off the disk. - **The clone** matters. `codex exec` refuses to run outside a Git repository unless you pass `--skip-git-repo-check`. - **Output:** Codex streams progress to stderr and prints its final message to stdout. The diff comes back as a file. A large change is therefore never cut at the 64 KiB result limit. - **The task is an array element,** so no shell reads its quotes or symbols. The sandbox trusts the certificate that its proxy uses for a secret's host. It does this through `SSL_CERT_FILE`, which Codex reads for its HTTPS and WebSocket clients. ## Headless flags that matter Checked in OpenAI's documentation on 25 October 2026: | Flag | What it does | | ------------------------------------ | ----------------------------------------------- | | `codex exec ""` | Runs one task non-interactively | | `--sandbox workspace-write` | Lets Codex edit files; the default is read-only | | `--sandbox danger-full-access` | No Codex sandbox, for an isolated runner | | `--json` | A JSON Lines event stream | | `-o`, `--output-last-message ` | Writes the final message to a file | | `--output-schema ` | Holds the final answer to a JSON Schema | | `--skip-git-repo-check` | Runs outside a Git repository | | `--ephemeral` | Keeps no session files | | `codex exec resume --last ""` | Carries on the previous run | `--full-auto` is no longer supported. OpenAI's guide names `--sandbox workspace-write` in its place. To keep a checkout between tasks, [pause the sandbox](/how-to/pause-and-resume-a-sandbox) instead of stopping it. Its files, memory and processes are kept, and compute billing stops. ## Give Codex Runtime as a tool Codex on your own machine can create sandboxes, run commands in them and read files back through Runtime's MCP server: ```bash no-run codex mcp add runtime -- npx -y withruntime mcp ``` Or, in `~/.codex/config.toml`: ```toml [mcp_servers.runtime] command = "npx" args = ["-y", "withruntime", "mcp"] ``` The first call shows a link and a code. Approve **Connect agent** in your browser, and every Runtime tool appears, with no key to copy ([MCP](/docs/mcp#add-it-to-your-agent)). A machine already connected by `npx withruntime login` skips that step. In CI, `RUNTIME_API_KEY` from a secret manager takes its place. | Tool | What it does | | --------------------------------------------------------------- | --------------------------------------------------- | | `runtime_sandboxes_create` | A new sandbox, ready when the call returns | | `runtime_sandboxes_exec` | Runs a command and returns its exit code and output | | `runtime_sandboxes_files_read`, `runtime_sandboxes_files_write` | Reads and writes files in the sandbox | | `runtime_sandboxes_network` | Narrows or turns off the sandbox's internet | | `runtime_sandboxes_fork` | Running copies of a sandbox, memory included | | `runtime_sandboxes_manage` | Pause, wake, extend or stop | Every tool is listed in [MCP tools](/docs/mcp#tools). [Coding agents](/docs/frameworks#coding-agents) has the same setup for Claude Code, Cursor, Gemini CLI and VS Code. ## What it costs Runtime bills the CPU the agent uses at $0.025 per vCPU-hour, with a floor of a twentieth of a vCPU. Memory is billed at $0.0075 per GiB-hour. A 2 vCPU, 4 GiB sandbox costs $0.03125 an hour while Codex waits on the model. With both CPUs busy, it costs $0.08 an hour ([pricing](/docs/pricing)). OpenAI bills model tokens on your key. A new account gets 100 free hours of a 1 GB machine in its first 30 days. No card is needed: ```bash no-run npx withruntime sandboxes run -- node --version ``` The first run prints a link to approve in your browser. The same setup for Anthropic's agent is in [Claude Code in a sandbox](/integrations/claude-code). [A sandbox for coding agents](/use-cases/coding-agent-sandbox) covers running many at the same time. ## Sources Checked 25 October 2026. - [Codex on GitHub](https://github.com/openai/codex): `npm install -g @openai/codex` - [Non-interactive mode](https://learn.chatgpt.com/docs/non-interactive-mode): `codex exec`, `--sandbox`, `--json`, `-o`, `--skip-git-repo-check`, `--ephemeral`, `CODEX_API_KEY`, and the guidance on `danger-full-access` - [Environment variables](https://learn.chatgpt.com/docs/config-file/environment-variables): `CODEX_API_KEY`, `CODEX_CA_CERTIFICATE` and `SSL_CERT_FILE` - [Authentication](https://learn.chatgpt.com/docs/auth): API keys for CI - [@openai/codex on npm](https://www.npmjs.com/package/@openai/codex): version 0.164.0 Facts on this page were checked on 25 October 2026.