Instruction manual
openai/codex instruction manual
Apache-2.0 OpenAI coding-agent platform centered on the standalone Codex CLI, with desktop and IDE entry points, Python and TypeScript SDKs, structured and streaming turns, persistent sessions, model-visible tools, and OS-specific sandbox enforcement; it is an alternative or companion to Claude Code rather than a Claude Code extension.
1. Repository purpose, product boundaries, and Claude Code classification
`openai/codex` is the Apache-2.0-licensed source repository for Codex CLI, described by OpenAI as a lightweight coding agent that runs locally in a terminal. The repository metadata identifies Rust as its primary language. The supplied files also document Python and TypeScript SDKs, Rust support crates, development containers, CI strategy, and release-maintenance procedures.
Do not confuse the documented products. **Codex CLI** is the local terminal agent. The IDE integration is for VS Code, Cursor, and Windsurf. `codex app` starts the desktop-app experience. **Codex Web** is the cloud-based agent at ChatGPT. The supplied repository files do not document these as interchangeable deployment modes.
**Claude Code classification: unclassified.** No supplied first-party file mentions Claude Code, a Claude plugin manifest, Claude hooks, `SKILL.md`, MCP wiring for Claude, or installation into a Claude directory. The evidence therefore does not establish a reliable Claude Code extension mechanism. Codex is best understood from these sources as a separate OpenAI coding-agent platform, not as a Claude Code plugin. Although the candidate catalog includes a different official repository named `openai/codex-plugin-cc`, that is not this repository and must not be attributed to `openai/codex`.
This manual is limited to supplied first-party files. Links in those files point to broader Codex documentation, but functionality present only behind those links is not treated here as documented repository behavior.
2. Install, launch, and authenticate Codex CLI
On macOS or Linux, install the CLI with the documented standalone installer:
curl -fsSL https://chatgpt.com/codex/install.sh | shOn Windows, use the documented PowerShell installer:
powershell -ExecutionPolicy ByPass -c "irm https://chatgpt.com/codex/install.ps1 | iex"These installers normally obtain files from `https://releases.openai.com/codex`, falling back to GitHub Releases if metadata or an asset is unavailable. To force GitHub Releases, use the documented environment variable:
curl -fsSL https://chatgpt.com/codex/install.sh | CODEX_INSTALLER_USE_RELEASES_OPENAI_COM=false sh$env:CODEX_INSTALLER_USE_RELEASES_OPENAI_COM='false'; irm https://chatgpt.com/codex/install.ps1 | iexAlternative package-manager installations are:
npm install -g @openai/codexbrew install --cask codexAfter installation, start the terminal agent with:
codexAt startup, select **Sign in with ChatGPT** to reuse an eligible Plus, Pro, Business, Edu, or Enterprise plan. API-key use is also supported, but the supplied README says it requires additional setup and does not provide a copy-paste CLI command. Do not invent one. The latest GitHub Release also offers platform archives for macOS arm64/x86_64 and Linux x86_64/arm64; each contains one platform-named executable that can be renamed to `codex` after extraction. No Windows archive-selection details are supplied in the README.
To enter the separately described desktop experience, the only documented command is:
codex app3. Use the Python SDK for threads, turns, and authentication
Install the Python package:
pip install openai-codex`Codex` is a context-managed client. `thread_start()` creates a thread, and `thread.run(prompt)` performs one turn. It returns a `TurnResult` containing the final response, collected items, and token usage:
from openai_codex import Codex
with Codex() as codex:
thread = codex.thread_start()
result = thread.run("Explain this repository in three bullets.")
print(result.final_response)The SDK automatically reuses existing Codex authentication when available. `login_chatgpt()` explicitly begins browser login; its result exposes `auth_url`, while `wait()` waits for completion and reports `success`:
from openai_codex import Codex
with Codex() as codex:
login = codex.login_chatgpt()
print(login.auth_url)
print(login.wait().success)`login_chatgpt_device_code()` begins device-code login. Display `verification_url` and `user_code`, then call `wait()`:
from openai_codex import Codex
with Codex() as codex:
login = codex.login_chatgpt_device_code()
print(login.verification_url, login.user_code)
login.wait()`login_api_key()` records API-key authentication for the client:
from openai_codex import Codex
with Codex() as codex:
codex.login_api_key("sk-...")Treat the placeholder as illustrative and do not commit a real key. For locally installed API details, use Python’s documented introspection facilities: `help(openai_codex)`, `help(Codex)`, or `python -m pydoc openai_codex`. The supplied file links to separate getting-started, API-reference, FAQ, and examples pages but does not reproduce their additional contents.
4. Embed Codex with the TypeScript SDK
The TypeScript SDK requires Node.js 18+ and wraps the `codex` CLI, spawning it and exchanging JSONL events over standard input/output. Install it with:
npm install @openai/codex-sdk`new Codex()` creates a client, `startThread()` starts a conversation, and `run()` waits for a completed turn. Reuse the same thread for follow-up turns:
import { Codex } from "@openai/codex-sdk";
const codex = new Codex();
const thread = codex.startThread();
const turn = await thread.run("Diagnose the test failure and propose a fix");
console.log(turn.finalResponse);
console.log(turn.items);
const nextTurn = await thread.run("Implement the fix");`runStreamed()` returns structured progress through an async event generator. The documented events include completed items and completed-turn usage:
const { events } = await thread.runStreamed("Diagnose the test failure and propose a fix");
for await (const event of events) {
switch (event.type) {
case "item.completed": console.log("item", event.item); break;
case "turn.completed": console.log("usage", event.usage); break;
}
}Pass `outputSchema` to request schema-conforming JSON. Pass an array of `text` and `local_image` entries to attach local images; text is concatenated into the prompt and image paths are sent through the CLI’s image option. `resumeThread(id)` reconstructs a persisted thread from `~/.codex/sessions`.
Thread options include `workingDirectory` and `skipGitRepoCheck`; Codex otherwise requires the working directory to be a Git repository. A client-level `env` fully controls the inherited environment, although the SDK adds required variables. `baseUrl` becomes an `openai_base_url` CLI override.
The `config` object is flattened into dotted keys and TOML values. `configOverrides` forwards raw TOML arguments unchanged. Raw overrides beat structured `config`; SDK-managed and thread-specific settings are applied later and take precedence.
5. Development containers and their security boundaries
Two container definitions serve different purposes. `.devcontainer/devcontainer.json` is the lightweight arm64 contributor environment for developing Codex itself. `.devcontainer/devcontainer.secure.json` is a customer-oriented runtime profile that installs Codex, common build tools, setuid bubblewrap, and an allowlist-driven outbound firewall. It disables Docker’s outer seccomp and AppArmor profiles so Codex’s inner bubblewrap sandbox can initialize, blocks IPv6 by default, and requires `NET_ADMIN` and `NET_RAW` to install the firewall.
Start the secure profile with the documented command:
devcontainer up --workspace-folder . --config .devcontainer/devcontainer.secure.jsonIn VS Code, use **Dev Containers: Open Folder in Container...** and choose `.devcontainer/devcontainer.secure.json`.
Critical limitation: the firewall does not apply its domain allowlist to DNS. Untrusted code can exfiltrate through DNS, and allowed HTTPS destinations remain another possible channel. The repository explicitly says to use this profile only with trusted repositories. Custom DNS filtering and restricting outbound DNS to that resolver mitigate one path but do not make untrusted repositories safe.
For an x64 contributor image with the repository mounted at `/workspace`, use exactly the supplied sequence:
CODEX_DOCKER_IMAGE_NAME=codex-linux-dev
docker build --platform=linux/amd64 -t "$CODEX_DOCKER_IMAGE_NAME" ./.devcontainer
docker run --platform=linux/amd64 --rm -it -e CARGO_TARGET_DIR=/workspace/codex-rs/target-amd64 -v "$PWD":/workspace -w /workspace/codex-rs "$CODEX_DOCKER_IMAGE_NAME"For arm64, replace both platform values with `linux/arm64`. The separate `CARGO_TARGET_DIR` prevents container-built binaries from mixing with host outputs. The file notes that x64 musl work additionally requires manually installing the `x86_64-unknown-linux-musl` Rust target, but it supplies no command.
6. Core execution, sandbox behavior, and shared tool architecture
`codex-core` implements Codex business logic for Rust user interfaces. Its sandbox behavior is platform-specific. On macOS it expects `/usr/bin/sandbox-exec`; Seatbelt enforces resolved network and filesystem policy, keeps `.git`, its resolved git directory, and `.codex` read-only under workspace-write policy, and permits legacy preference reads needed by macOS.
On Linux, the executable can act as `codex-linux-sandbox` through argument-zero dispatch. Legacy sandbox policies can use Landlock only when a split filesystem policy can round-trip without changing meaning. Policies requiring exact denied/read-only carveouts use bubblewrap. Codex prefers a `bwrap` on `PATH` outside the current directory, supports older versions lacking `--argv0`, and falls back to a bundled binary with a startup warning. It also warns if user namespaces cannot be created. WSL2 follows the Linux path; WSL1 rejects commands that would require bubblewrap.
Windows supports legacy and selected split-filesystem policies through elevated or restricted-token backends. Unsupported policies fail closed rather than run with weaker enforcement. On every platform, argument dispatch also simulates the virtual `apply_patch` CLI when the second argument is `--codex-run-as-apply-patch`.
The documented Windows execution integration test on x86-64 Linux is:
bazel test //codex-rs/core:core-all-wine-exec-testTest skip macros distinguish Windows target behavior, Windows host constraints, local-only, remote-only, missing remote environment, and Wine-specific debt.
`codex-tools` holds reusable host-facing tool definitions and adapters outside core: aggregate specs, discovery/install-request models, schema sanitization, MCP/dynamic conversion, code-mode augmentation, image-detail normalization, and execution contracts (`ToolExecutor`, `ToolCall`, `ToolOutput`). Session, turn, approvals, and runtime orchestration remain in core. Its convention is exports-only `lib.rs`, named implementation modules, and sibling test modules wired with `#[cfg(test)]` and `#[path = "foo_tests.rs"]`.
7. OpenTelemetry providers, events, metrics, and trace context
`codex-otel` supplies OpenTelemetry log, trace, and metric wiring. `OtelProvider::try_new(&settings)` creates a provider when configured; `logger_layer()` and `tracing_layer()` attach it to a `tracing_subscriber` registry. `OtelSettings` identifies environment, service, version, Codex home, exporters, span attributes, and tracestate. Exporters may use OTLP HTTP with binary or JSON protocol; metrics can be disabled independently.
Configured `[otel.span_attributes]` are added to spans. Nested `[otel.tracestate.<member>]` tables become semicolon-separated `key:value` fields. Existing named members are upserted while unrelated fields are retained. This format cannot set opaque member values. Invalid W3C trace metadata is ignored during configuration loading and reported as a startup warning.
`SessionTelemetry::new(...)` creates a session-scoped event manager carrying consistent conversation, model, account, authentication, origin, prompt-logging, terminal, and source metadata. `manager.user_prompt(&prompt_items)` records the documented user-prompt event. Rich business events belong here; subsystem audit events may remain with their subsystem.
`MetricsClient::new(MetricsConfig::otlp(...))` creates an OTLP metrics client. `counter(name, value, attributes)` records counts, while `histogram(name, value, attributes)` records distributions. `OtelExporter::Statsig` is a shorthand for Codex-internal OTLP/HTTP JSON defaults; the supplied example instead shows an explicit Statsig endpoint and a `statsig-api-key` read from `STATSIG_SERVER_SDK_SECRET`.
For tests, `MetricsConfig::in_memory(...)` records into `InMemoryMetricExporter`; call `shutdown()` to flush before assertions. `current_span_w3c_trace_context` reads the current W3C context and `set_parent_from_w3c_trace_context` restores a parent from one. `OtelProvider::shutdown()` stops exporters, while `SessionTelemetry::shutdown_metrics()` flushes and stops metrics. Drop performs best-effort cleanup, but explicit shutdown gives deterministic flushing or a timeout error.
8. Contribution checks, npm staging, V8 maintenance, and repository limits
CI separates quick pull-request feedback from heavy post-merge coverage. PRs test GitHub’s synthetic merge commit. `bazel.yml` runs Bazel tests and Clippy, including generated Rust test binaries. `rust-ci.yml` runs formatting checks, Cargo Shear, cross-platform argument-comment linting, and the lint package’s tests when relevant. On `main`, `rust-ci-full.yml` adds full Cargo Clippy and nextest matrices, Windows ARM64 archive replay, release builds, cross-platform linting, and Linux remote-environment tests. The stated rule is to prefer Bazel for PR-time checks and reserve heavyweight Cargo-native coverage for post-merge.
Release maintainers stage npm packages with the repository helper. The supplied example stages CLI, responses proxy, and SDK version `0.6.0`:
./scripts/stage_npm_packages.py \
--release-version 0.6.0 \
--package codex \
--package codex-responses-api-proxy \
--package codex-sdkIt downloads native archives, hydrates package `vendor/` directories, and writes tarballs to `dist/npm/`. Selecting `codex` also builds the lightweight meta-package and platform-native variants. Direct package building is for debugging; release packaging should use the staging helper.
The V8 integration pins Rust `v8` 150.4.0 and embedded upstream V8 15.0.245.2. Bazel uses upstream Windows MSVC archives but source-built artifacts on Darwin, GNU/musl Linux, and Windows GNU. Maintainers bump the crate/lockfile, update Bazel inputs and checksums, validate a `v8-canary` release candidate, publish, then rebuild and test the candidate. The documented checksum commands are:
python3 .github/scripts/rusty_v8_bazel.py update-module-bazel
python3 .github/scripts/rusty_v8_bazel.py check-module-bazelNever mix archive and binding assets across crate versions. Finally, the `chatgpt` crate concerns first-party ChatGPT APIs and accepts no external code contributions; report its bugs or feature requests through the Codex issue tracker.