SpyBara
Go Premium

Documentation 2026-11-01 23:00 UTC to 2026-11-02 23:02 UTC

40 files changed +1,929 −482. View all changes and history on the product overview
2026
Tue 10 03:02 Mon 9 23:02 Fri 6 23:02 Thu 5 23:03 Wed 4 23:02 Tue 3 23:57 Mon 2 23:02
Details

159 href: "/codex/enterprise/windows-deployment",159 href: "/codex/enterprise/windows-deployment",

160 icon: "settings",160 icon: "settings",

161 },161 },

162 {

163 title: "Run Codex with an NFS home directory",

164 description:

165 "Migrate a shared Linux home, verify cross-host resume, or keep independent jobs on local scratch.",

166 href: "/codex/environments/network-file-systems",

167 icon: "settings",

168 },

162 {169 {

163 title: "Manage app updates",170 title: "Manage app updates",

164 description:171 description:

Details

151. Create a `.rules` file under a `rules/` folder next to an active config layer (for example, `~/.codex/rules/default.rules`).151. Create a `.rules` file under a `rules/` folder next to an active config layer (for example, `~/.codex/rules/default.rules`).

162. Add a rule. This example prompts before allowing `gh pr view` to run outside the sandbox.162. Add a rule. This example prompts before allowing `gh pr view` to run outside the sandbox.

17 17 

18```python18```python snippet=configuration reason="Starlark policy configuration interpreted by Codex"

19 # Prompt before running commands with the prefix `gh pr view` outside the sandbox.19 # Prompt before running commands with the prefix `gh pr view` outside the sandbox.

20 prefix_rule(20 prefix_rule(

21 # The prefix to match.21 # The prefix to match.

Details

234```234```

235 235 

236```javascript236```javascript

237const summary = document.getElementById("delivery-summary");237const summary = /** @type {HTMLElement} */ (

238const button = document.getElementById("discuss-delivery");238 document.getElementById("delivery-summary")

239);

240const button = /** @type {HTMLButtonElement} */ (

241 document.getElementById("discuss-delivery")

242);

239 243 

240button.hidden = typeof document.oai?.annotation?.request !== "function";244button.hidden = typeof document.oai?.annotation?.request !== "function";

241 245 


328Run this script after both elements exist:333Run this script after both elements exist:

329 334 

330```javascript335```javascript

331const passage = document.getElementById("draft-passage");336const passage = /** @type {HTMLElement} */ (

332const button = document.getElementById("discuss-passage");337 document.getElementById("draft-passage")

338);

339const button = /** @type {HTMLButtonElement} */ (

340 document.getElementById("discuss-passage")

341);

333 342 

334button.hidden = typeof document.oai?.annotation?.request !== "function";343button.hidden = typeof document.oai?.annotation?.request !== "function";

335 344 


449Run this script after creating the preview:459Run this script after creating the preview:

450 460 

451```javascript461```javascript

452const preview = document.getElementById("component-preview");462const preview = /** @type {HTMLElement} */ (

463 document.getElementById("component-preview")

464);

453const annotation = document.oai?.annotation;465const annotation = document.oai?.annotation;

454 466 

467/** @param {CustomEvent<{ callback: string; value: number | string }>} event */

455function previewSpacing(event) {468function previewSpacing(event) {

456 const { callback, value } = event.detail;469 const { callback, value } = event.detail;

457 if (callback === "setCardPadding") {470 if (callback === "setCardPadding") {


459 }472 }

460}473}

461 474 

475/** @type {{ dispose(): void } | undefined} */

462let registration;476let registration;

463if (typeof annotation?.registerControls === "function") {477if (typeof annotation?.registerControls === "function") {

464 preview.addEventListener("oaiannotationcontrolchange", previewSpacing);478 preview.addEventListener("oaiannotationcontrolchange", previewSpacing);


538```553```

539 554 

540```javascript555```javascript

541const draft = document.getElementById("email-draft");556const draft = /** @type {HTMLElement} */ (

557 document.getElementById("email-draft")

558);

542const registration = document.oai?.annotation?.registerControls?.({559const registration = document.oai?.annotation?.registerControls?.({

543 targets: draft,560 targets: draft,

544 controlsHeading: "Email options",561 controlsHeading: "Email options",


744```762```

745 763 

746```javascript764```javascript

747const canvas = document.getElementById("revenue-canvas");765const canvas = /** @type {HTMLCanvasElement} */ (

748const context = canvas.getContext("2d");766 document.getElementById("revenue-canvas")

767);

768const context = /** @type {CanvasRenderingContext2D} */ (

769 canvas.getContext("2d")

770);

749const bar = { x: 40, y: 60, width: 320, height: 100 };771const bar = { x: 40, y: 60, width: 320, height: 100 };

750 772 

751context.fillStyle = "#2563eb";773context.fillStyle = "#2563eb";


872`renderSelection: renderRevenueSelection` to the `registerSurface()` options:895`renderSelection: renderRevenueSelection` to the `registerSurface()` options:

873 896 

874```javascript897```javascript

898/** @param {{ hoveredId: string | null; selectedId: string | null }} selection */

875function renderRevenueSelection({ hoveredId, selectedId }) {899function renderRevenueSelection({ hoveredId, selectedId }) {

876 context.clearRect(0, 0, canvas.width, canvas.height);900 context.clearRect(0, 0, canvas.width, canvas.height);

877 context.fillStyle = "#2563eb";901 context.fillStyle = "#2563eb";


922```947```

923 948 

924```javascript949```javascript

925const button = document.getElementById("toggle-annotations");950const button = /** @type {HTMLButtonElement} */ (

951 document.getElementById("toggle-annotations")

952);

926const annotation = document.oai?.annotation;953const annotation = document.oai?.annotation;

927 954 

955/** @param {boolean} active */

928function renderMode(active) {956function renderMode(active) {

929 button.textContent = active957 button.textContent = active

930 ? "Exit annotation mode"958 ? "Exit annotation mode"

931 : "Enter annotation mode";959 : "Enter annotation mode";

932}960}

933 961 

962/** @param {CustomEvent<{ active: boolean }>} event */

934const onModeChange = (event) => renderMode(event.detail.active);963const onModeChange = (event) => renderMode(event.detail.active);

935const onClick = () => annotation.toggle(!annotation.isActive());964const onClick = () => annotation?.toggle(!annotation.isActive());

936 965 

937if (966if (

938 typeof annotation?.toggle === "function" &&967 typeof annotation?.toggle === "function" &&

app-server.md +123 −73

Details

38 38 

39## Connect a remote Code Mode host39## Connect a remote Code Mode host

40 40 

41By default, app-server starts a local Code Mode host. To use a remote host41By default, app-server starts a local Code Mode host. To share a remote host

42instead, pass its secure WebSocket URL:42across threads in the same app-server process, pass the remote host's HTTP/2

43gRPC endpoint to `--code-mode-host`.

43 44 

44```bash45```bash

45codex app-server --code-mode-host wss://code-mode.example.com/host46codex app-server --code-mode-host https://code-mode.example.com

46```47```

47 48 

48`--code-mode-host` controls the outbound connection from app-server to its Code49Use HTTPS for a remote host to protect tool arguments and results. Use HTTP

49Mode host. It doesn't change `--listen`, which controls how clients connect to50only on loopback or through a secure tunnel. The URL accepts a hostname and

50app-server. Every thread in the same app-server process shares the selected51optional port. Omit credentials, paths, query strings, and fragments. Use

51Code Mode host connection.52`--listen` to configure the separate connection from clients to app-server.

52 

53Use `wss://` for a remote host. Use `ws://` only for a localhost or

54SSH-forwarded connection. The app-server command and WebSocket transport are

55experimental and aren't supported for production workloads.

56 53 

57## Protocol54## Protocol

58 55 


151 148 

152```typescript149```typescript

153import { spawn } from "node:child_process";150import { spawn } from "node:child_process";

154 151import readline from "node:readline";

155const proc = spawn("codex", ["app-server"], {152const proc = spawn("codex", ["app-server"], {

156 stdio: ["pipe", "pipe", "inherit"],153 stdio: ["pipe", "pipe", "inherit"],

157});154});


163rl.on("line", (line) => {160rl.on("line", (line) => {

164 const msg = JSON.parse(line) as any;161 const msg = JSON.parse(line) as any;

165 console.log("server:", msg);162 console.log("server:", msg);

163 if (msg.id === 0 && msg.result) {

164 send({ method: "initialized", params: {} });

165 send({

166 method: "thread/start",

167 id: 1,

168 params: { model: "gpt-6.1-sol" },

169 });

170 }

171 if (msg.method === "turn/completed") {

172 proc.stdin.end();

173 rl.close();

174 }

175 if (msg.error) {

176 console.error(msg.error);

177 process.exitCode = 1;

178 proc.stdin.end();

179 rl.close();

180 }

166 if (msg.id === 1 && msg.result?.thread?.id && !threadId) {181 if (msg.id === 1 && msg.result?.thread?.id && !threadId) {

167 threadId = msg.result.thread.id;182 threadId = msg.result.thread.id;

168 send({183 send({


186 },201 },

187 },202 },

188});203});

189send({ method: "initialized", params: {} });204proc.on("error", (error) => {

190send({ method: "thread/start", id: 1, params: { model: "gpt-6.1-sol" } });205 console.error(error);

206 process.exitCode = 1;

207 rl.close();

208});

191```209```

192 210 

193 211 


203 221 

204- **Initialize once per connection**: Immediately after opening a transport connection, send an `initialize` request with your client metadata, then emit `initialized`. The server rejects any request on that connection before this handshake.222- **Initialize once per connection**: Immediately after opening a transport connection, send an `initialize` request with your client metadata, then emit `initialized`. The server rejects any request on that connection before this handshake.

205- **Start (or resume) a thread**: Call `thread/start` for a new conversation, `thread/resume` to continue an existing one, or `thread/fork` to branch history into a new thread id.223- **Start (or resume) a thread**: Call `thread/start` for a new conversation, `thread/resume` to continue an existing one, or `thread/fork` to branch history into a new thread id.

206- **Begin a turn**: Call `turn/start` with the target `threadId` and user input. Optional fields override model, personality, `cwd`, sandbox policy, and more.224- **Begin a turn**: Call `turn/start` with the target `threadId` and user input. Optional fields override the model, working directory, and sandbox policy.

207- **Steer an active turn**: Call `turn/steer` to append user input to the currently in-flight turn without creating a new turn.225- **Steer an active turn**: Call `turn/steer` to append user input to the currently in-flight turn without creating a new turn.

208- **Stream events**: After `turn/start`, keep reading notifications on stdout: `thread/archived`, `thread/unarchived`, `item/started`, `item/completed`, `item/agentMessage/delta`, tool progress, and other updates.226- **Stream events**: After `turn/start`, keep reading notifications on stdout: `thread/archived`, `thread/unarchived`, `item/started`, `item/completed`, `item/agentMessage/delta`, tool progress, and other updates.

209- **Finish the turn**: The server emits `turn/completed` with final status when the model finishes or after a `turn/interrupt` cancellation.227- **Finish the turn**: The server emits `turn/completed` with final status when the model finishes or after a `turn/interrupt` cancellation.


297- `thread/resume` - reopen an existing thread by id so later `turn/start` calls append to it.315- `thread/resume` - reopen an existing thread by id so later `turn/start` calls append to it.

298- `thread/fork` - fork a thread into a new thread id by copying stored history. Pass `lastTurnId` to copy history through that turn and omit later turns, or `ephemeral: true` to create an in-memory fork. Emits `thread/started` for the new thread; returned threads include `forkedFromId` when available.316- `thread/fork` - fork a thread into a new thread id by copying stored history. Pass `lastTurnId` to copy history through that turn and omit later turns, or `ephemeral: true` to create an in-memory fork. Emits `thread/started` for the new thread; returned threads include `forkedFromId` when available.

299- `thread/read` - read stored thread metadata by id without resuming it. Use `thread/turns/list` and `thread/items/list` to load history. Returned `thread` objects include runtime `status`.317- `thread/read` - read stored thread metadata by id without resuming it. Use `thread/turns/list` and `thread/items/list` to load history. Returned `thread` objects include runtime `status`.

300- `thread/list` - page through stored thread logs; supports cursor-based pagination plus `modelProviders`, `sourceKinds`, `archived`, `isPinned`, `cwd`, `useStateDbOnly`, `searchTerm`, and experimental `parentThreadId` or `ancestorThreadId` filters. Returned `thread` objects include runtime `status`.318- `thread/list` - page through stored threads and their runtime status. See [pagination and filters](#list-threads-with-pagination--filters).

301- `thread/turns/list` - page through a stored thread's turn history without resuming it. `itemsView` controls whether turn items are omitted, summarized, or fully loaded.319- `thread/turns/list` - page through a stored thread's turn history without resuming it. `itemsView` controls whether turn items are omitted, summarized, or fully loaded.

302- `thread/items/list` - page through persisted thread items, optionally restricted to one `turnId`. The active thread store must support item pagination.320- `thread/items/list` - page through persisted thread items, optionally restricted to one `turnId`. The active thread store must support item pagination.

303- `thread/loaded/list` - list the thread ids currently loaded in memory.321- `thread/loaded/list` - list the thread ids currently loaded in memory.


305- `thread/goal/set` - set the goal for a thread; emits `thread/goal/updated`.323- `thread/goal/set` - set the goal for a thread; emits `thread/goal/updated`.

306- `thread/goal/get` - read the current goal for a thread.324- `thread/goal/get` - read the current goal for a thread.

307- `thread/goal/clear` - clear the goal for a thread; emits `thread/goal/cleared`.325- `thread/goal/clear` - clear the goal for a thread; emits `thread/goal/cleared`.

308- `thread/metadata/update` - patch SQLite-backed stored thread metadata, including persisted `gitInfo` and `isPinned`.326- `thread/metadata/update` - update the Git metadata stored for a thread.

309- `thread/archive` - move a thread's log file into the archived directory and attempt to archive spawned descendant thread logs that aren't already archived; returns `{}` on success and emits `thread/archived` for each archived thread.327- `thread/archive` - move a thread's log file into the archived directory and attempt to archive spawned descendant thread logs that aren't already archived; returns `{}` on success and emits `thread/archived` for each archived thread.

310- `thread/delete` - permanently delete a persisted active or archived thread and any spawned descendant threads; returns `{}` on success and emits `thread/deleted` for each deleted thread.328- `thread/delete` - permanently delete a persisted active or archived thread and any spawned descendant threads; returns `{}` on success and emits `thread/deleted` for each deleted thread.

311- `thread/unsubscribe` - unsubscribe this connection from thread turn/item events. If this was the last subscriber, the server unloads the thread after a no-subscriber inactivity grace period and emits `thread/closed`.329- `thread/unsubscribe` - unsubscribe this connection from thread turn/item events. If this was the last subscriber, the server unloads the thread after a no-subscriber inactivity grace period and emits `thread/closed`.


355- `app/list` - list available apps (connectors) with pagination plus accessibility/enabled metadata.373- `app/list` - list available apps (connectors) with pagination plus accessibility/enabled metadata.

356- `app/read` - fetch metadata and optional display-only tool summaries for specific app ids.374- `app/read` - fetch metadata and optional display-only tool summaries for specific app ids.

357- `skills/config/write` - enable or disable skills by path.375- `skills/config/write` - enable or disable skills by path.

358- `mcpServer/oauth/login` - start an OAuth login for a configured MCP server; returns an authorization URL and emits `mcpServer/oauthLogin/completed` on completion.376- `mcpServer/oauth/login` - start an OAuth login for a configured MCP server. Open the returned HTTP or HTTPS `authorizationUrl` and match `loginId` to the `mcpServer/oauthLogin/completed` notification.

359- `tool/requestUserInput` - prompt the user with 1-3 short questions for a tool call (experimental); questions can set `isOther` for a free-form option.377- `tool/requestUserInput` - prompt the user with 1-3 short questions for a tool call (experimental); questions can set `isOther` for a free-form option.

360- `mcpServer/elicitation/request` (server request) - ask the client for structured form input or confirmation of a URL flow requested by an MCP server.378- `mcpServer/elicitation/request` (server request) - ask the client for structured form input or confirmation of a URL flow requested by an MCP server.

361- `item/permissions/requestApproval` (server request) - ask the client to grant a subset of network or filesystem permissions requested by the built-in `request_permissions` tool.379- `item/permissions/requestApproval` (server request) - ask the client to grant a subset of network or filesystem permissions requested by the built-in `request_permissions` tool.

362- `config/mcpServer/reload` - reload MCP server configuration from disk and queue a refresh for loaded threads.380- `config/mcpServer/reload` - reload MCP server configuration from disk and queue a refresh for loaded threads.

363- `mcpServerStatus/list` - list MCP servers, tools, resources, and auth status (cursor + limit pagination). Use `detail: "full"` for full data or `detail: "toolsAndAuthOnly"` to omit resources. Pass `serverName` to discover one server; with `threadId`, the request reuses that thread's MCP connection.381- `mcpServerStatus/list` - list MCP servers, tools, resources, and auth status (cursor + limit pagination). Use `detail: "full"` for full data or `detail: "toolsAndAuthOnly"` to omit resources. Both detail modes include the server's advertised `serverCapabilities`, or `null` before successful initialization. Pass `serverName` to discover one server. With `threadId`, the request reuses that thread's MCP connection.

364- `mcpServer/resource/read` - read a single MCP resource through an initialized MCP server.382- `mcpServer/resource/read` - read a single MCP resource through an initialized MCP server.

365- `mcpServer/tool/call` - call a tool on a thread's configured MCP server.383- `mcpServer/tool/call` - call a tool on a thread's configured MCP server.

366- `mcpServer/startupStatus/updated` (notify) - emitted when a configured MCP server's startup status changes for a loaded thread.384- `mcpServer/startupStatus/updated` (notify) - emitted when a configured MCP server's startup status changes for a loaded thread.

367- `windowsSandbox/setupStart` - start Windows sandbox setup for `elevated` or `unelevated` mode; returns quickly and later emits `windowsSandbox/setupCompleted`.385- `windowsSandbox/readiness` - check whether the Windows sandbox is ready. If it returns `updateRequired`, call `windowsSandbox/setupStart` and wait for `windowsSandbox/setupCompleted`.

368- `feedback/upload` - submit a feedback report (classification + optional reason/logs + conversation id, plus optional `extraLogFiles` attachments).386- `feedback/upload` - submit a feedback report (classification + optional reason/logs + conversation id, plus optional `extraLogFiles` attachments).

369- `config/read` - fetch the effective configuration on disk after resolving configuration layering.387- `config/read` - fetch the effective configuration on disk after resolving configuration layering.

370- `externalAgentConfig/detect` - detect external-agent artifacts that can be migrated with `includeHome` and optional `cwds`; each detected item includes `cwd` (`null` for home).388- `externalAgentConfig/detect` - detect external-agent artifacts that can be migrated with `includeHome` and optional `cwds`; each detected item includes `cwd` (`null` for home).

371- `externalAgentConfig/import` - apply selected external-agent migration items by passing explicit `migrationItems` with `cwd` (`null` for home). Supported item types include config, skills, `AGENTS.md`, plugins, MCP server config, subagents, hooks, commands, and sessions; non-empty imports emit `externalAgentConfig/import/progress` and `externalAgentConfig/import/completed` as work finishes. Plugin and session imports can complete asynchronously.389- `externalAgentConfig/import` - apply selected external-agent migration items by passing explicit `migrationItems` with `cwd` (`null` for home). Supported item types include config, skills, `AGENTS.md`, plugins, MCP server config, subagents, hooks, commands, and sessions; non-empty imports emit `externalAgentConfig/import/progress` and `externalAgentConfig/import/completed` as work finishes. Plugin and session imports can complete asynchronously.

372- `config/value/write` - write a single configuration key/value to the user's `config.toml` on disk.390- `config/value/write` - write a single configuration key/value to the user's `config.toml` on disk.

373- `config/batchWrite` - apply configuration edits atomically to the user's `config.toml` on disk.391- `config/batchWrite` - apply configuration edits atomically to the user's `config.toml` on disk.

374- `configRequirements/read` - fetch requirements from `requirements.toml` and/or MDM, including exact managed configuration, allowlists, pinned `featureRequirements`, and network requirements (or `null` if you haven't set any up).392- `configRequirements/read` - fetch requirements from `requirements.toml` and/or MDM, including allowlists and pinned `featureRequirements`. Clients that enable `experimentalApi` can also read managed network requirements.

375- `fs/readFile`, `fs/writeFile`, `fs/createDirectory`, `fs/getMetadata`, `fs/readDirectory`, `fs/remove`, `fs/copy`, `fs/watch`, `fs/unwatch`, and `fs/changed` (notify) - operate on absolute filesystem paths through the app-server v2 filesystem API.393- `fs/readFile`, `fs/writeFile`, `fs/createDirectory`, `fs/getMetadata`, `fs/readDirectory`, `fs/remove`, `fs/copy`, `fs/watch`, `fs/unwatch`, and `fs/changed` (notify) - operate on absolute filesystem paths through the app-server v2 filesystem API.

376 394 

377Plugin summaries include a `source` union. Local plugins return395Plugin summaries include a `source` union. Local plugins return


388 406 

389### List models (`model/list`)407### List models (`model/list`)

390 408 

391Call `model/list` to discover available models and their capabilities before rendering model or personality selectors.409Call `model/list` to populate a model picker with the available models and reasoning efforts.

392 410 

393The response below illustrates the structure. Available models, reasoning411The response below illustrates the structure. Available models, reasoning

394efforts, and defaults depend on the client and account; use the returned412efforts, and defaults depend on the client and account; use the returned


426- `supportsPersonality` - deprecated compatibility field; always `false`. Models no longer support personality selection.444- `supportsPersonality` - deprecated compatibility field; always `false`. Models no longer support personality selection.

427- `isDefault` - whether the model is the recommended default.445- `isDefault` - whether the model is the recommended default.

428 446 

447If the startup provider no longer satisfies managed requirements, `model/list`

448returns `-32600` and asks the client to restart Codex.

449 

429By default, `model/list` returns picker-visible models only. Set `includeHidden: true` if you need the full list and want to filter on the client side using `hidden`.450By default, `model/list` returns picker-visible models only. Set `includeHidden: true` if you need the full list and want to filter on the client side using `hidden`.

430 451 

431When `inputModalities` is missing (older model catalogs), treat it as `["text", "image"]` for backward compatibility.452When `inputModalities` is missing (older model catalogs), treat it as `["text", "image"]` for backward compatibility.


476 resuming it. Use `itemsView` to choose whether turn items are omitted,497 resuming it. Use `itemsView` to choose whether turn items are omitted,

477 summarized, or fully loaded.498 summarized, or fully loaded.

478- `thread/items/list` pages through persisted thread items, optionally restricted to one turn.499- `thread/items/list` pages through persisted thread items, optionally restricted to one turn.

479- `thread/list` supports cursor pagination plus `modelProviders`, `sourceKinds`, `archived`, `isPinned`, `cwd`, `useStateDbOnly`, `searchTerm`, and experimental `parentThreadId` or `ancestorThreadId` filtering.500- `thread/list` pages through stored threads. Use `sectionId` to list the threads in a section or `excludedThreadIds` to omit threads already on screen.

480- `thread/loaded/list` returns the thread IDs currently in memory.501- `thread/loaded/list` returns the thread IDs currently in memory.

481- `thread/archive` moves the thread's persisted JSONL log into the archived directory and attempts to archive spawned descendant thread logs that aren't already archived.502- `thread/archive` moves the thread's persisted JSONL log into the archived directory and attempts to archive spawned descendant thread logs that aren't already archived.

482- `thread/delete` permanently deletes a persisted active or archived thread and its spawned descendant threads.503- `thread/delete` permanently deletes a persisted active or archived thread and its spawned descendant threads.

483- `thread/metadata/update` patches stored thread metadata, including persisted `gitInfo` and `isPinned`.504- `thread/metadata/update` updates the stored `gitInfo` for a thread.

484- `thread/unsubscribe` unsubscribes the current connection from a loaded thread and can trigger `thread/closed` after an inactivity grace period.505- `thread/unsubscribe` unsubscribes the current connection from a loaded thread and can trigger `thread/closed` after an inactivity grace period.

485- `thread/unarchive` restores an archived thread rollout back into the active sessions directory.506- `thread/unarchive` restores an archived thread rollout back into the active sessions directory.

486- `thread/compact/start` triggers compaction and returns `{}` immediately.507- `thread/compact/start` triggers compaction and returns `{}` immediately.


496 "model": "gpt-6.1-sol",517 "model": "gpt-6.1-sol",

497 "cwd": "/Users/me/project",518 "cwd": "/Users/me/project",

498 "approvalPolicy": "never",519 "approvalPolicy": "never",

499 "sandbox": "workspaceWrite",520 "sandbox": "workspace-write",

500 "serviceName": "my_app_server_client"521 "serviceName": "my_app_server_client"

501} }522} }

502{ "id": 10, "result": {523{ "id": 10, "result": {


559 580 

560`dynamicTools` on `thread/start` is an experimental field (requires `capabilities.experimentalApi = true`). Codex persists these dynamic tools in the thread rollout metadata and restores them on `thread/resume` when you don't supply new dynamic tools.581`dynamicTools` on `thread/start` is an experimental field (requires `capabilities.experimentalApi = true`). Codex persists these dynamic tools in the thread rollout metadata and restores them on `thread/resume` when you don't supply new dynamic tools.

561 582 

583If the configured model provider differs from the thread's saved provider,

584`thread/resume` and new input return `-32600` with `data.type` set to

585`modelProviderMismatch`. To display the thread's history, [page through its turns](#list-thread-turns)

586with `thread/turns/list`. Switch back to the saved provider to continue the

587thread, or call `thread/fork` to start a new thread from its history with the

588current provider.

589 

562If you resume with a different model than the one recorded in the rollout, Codex emits a warning and applies a one-time model-switch instruction on the next turn.590If you resume with a different model than the one recorded in the rollout, Codex emits a warning and applies a one-time model-switch instruction on the next turn.

563 591 

564### Manage a thread goal592### Manage a thread goal


720 748 

721- `cursor` - opaque string from a prior response; omit for the first page.749- `cursor` - opaque string from a prior response; omit for the first page.

722- `limit` - server defaults to a reasonable page size if unset.750- `limit` - server defaults to a reasonable page size if unset.

723- `sortKey` - `created_at` (default), `updated_at`, or `recency_at`.751- `sortKey` - `created_at` (default), `updated_at`, `recency_at`, or `section_position`. To use `section_position`, supply a non-null `sectionId`.

724- `sortDirection` - `desc` (default) or `asc`.752- `sortDirection` - `asc` or `desc`. If you omit `sortDirection`, `section_position` sorts in ascending order and time-based keys sort in descending order.

725- `modelProviders` - restrict results to specific providers; unset, null, or an empty array includes all providers.753- `sectionId` - pass a section ID to list its threads or `null` for unassigned threads. Omit the field to include threads from all sections and unassigned threads.

754- `excludedThreadIds` - omit up to 100 thread IDs. Duplicate IDs count toward the 100-ID cap. The server excludes matching threads before applying the page limit. Send the same exclusions with each cursor.

755- `modelProviders` - restrict results to specific providers. Pass `[]` to include all providers. If you omit this field or pass `null`, the server uses the configured provider unless you filter by a thread relationship, in which case it includes all providers.

726- `sourceKinds` - restrict results to specific thread sources. When omitted or `[]`, the server defaults to interactive sources only: `cli` and `vscode`.756- `sourceKinds` - restrict results to specific thread sources. When omitted or `[]`, the server defaults to interactive sources only: `cli` and `vscode`.

727- `archived` - when `true`, list archived threads only. When `false` or omitted, list non-archived threads (default).757- `archived` - when `true`, list archived threads only. When `false` or omitted, list non-archived threads (default).

728- `isPinned` - when provided, return only threads with the matching persisted pin state. Omit it to return pinned and unpinned threads.

729- `cwd` - restrict results to threads whose session current working directory exactly matches this path, or one of the paths in an array. Relative paths resolve from the app-server process working directory.758- `cwd` - restrict results to threads whose session current working directory exactly matches this path, or one of the paths in an array. Relative paths resolve from the app-server process working directory.

730- `useStateDbOnly` - when `true`, return state database results without scanning JSONL thread logs to repair metadata. Omit it or pass `false` for the default scan-and-repair behavior.759- `useStateDbOnly` - when `true`, return state database results without scanning JSONL thread logs to repair metadata. Omit it or pass `false` for the default scan-and-repair behavior.

731- `searchTerm` - restrict results to threads whose extracted title contains this case-sensitive text fragment.760- `searchTerm` - restrict results to threads whose extracted title contains this case-sensitive text fragment.


755} }784} }

756{ "id": 20, "result": {785{ "id": 20, "result": {

757 "data": [786 "data": [

758 { "id": "thr_a", "preview": "Create a TUI", "ephemeral": false, "isPinned": true, "modelProvider": "openai", "createdAt": 1730831111, "updatedAt": 1730831111, "name": "TUI prototype", "status": { "type": "notLoaded" } },787 { "id": "thr_a", "preview": "Create a TUI", "ephemeral": false, "section": { "id": "01984de2-8f74-7c91-a3b2-5c5e937cf318", "name": "Pinned", "appearance": null }, "modelProvider": "openai", "createdAt": 1730831111, "updatedAt": 1730831111, "name": "TUI prototype", "status": { "type": "notLoaded" } },

759 { "id": "thr_b", "preview": "Fix tests", "ephemeral": false, "isPinned": false, "modelProvider": "openai", "createdAt": 1730750000, "updatedAt": 1730750000, "status": { "type": "notLoaded" } }788 { "id": "thr_b", "preview": "Fix tests", "ephemeral": false, "section": null, "modelProvider": "openai", "createdAt": 1730750000, "updatedAt": 1730750000, "status": { "type": "notLoaded" } }

760 ],789 ],

761 "nextCursor": "opaque-token-or-null"790 "nextCursor": "opaque-token-or-null"

762} }791} }


764 793 

765When `nextCursor` is `null`, you have reached the final page.794When `nextCursor` is `null`, you have reached the final page.

766 795 

796### Organize threads into sections

797 

798Create a named section with `threadSection/create` and use the returned

799`section.id` in `thread/section/move`. Pass `beforeThreadId` to insert the

800thread before another thread in the section, or omit it to append. Pass

801`sectionId: null` to remove a thread from its section. Use `threadSection/list`,

802`threadSection/update`, and `threadSection/delete` to page through, rename,

803and remove custom sections. To pin a thread, move it to the built-in Pinned

804section returned by `threadSection/list`.

805 

806### Manage thread attachments

807 

808Use attachments to associate resources such as pull requests with a stored

809thread. You can manage these references without resuming the thread.

810 

811- `thread/attachment/add` takes `threadId`, `attachmentType`, `identityKey`, and a JSON `payload`. Adding the same type and key to the same thread again returns the existing attachment.

812- `thread/attachment/list` pages through a thread's attachments. To find threads that reference a resource, call `thread/attachmentOwner/list` with its `attachmentType` and `identityKey`.

813- `thread/attachment/remove` takes `threadId`, `attachmentType`, and `identityKey`. The underlying resource stays available.

814- `thread/attachment/updated` reports a `created` or `deleted` operation when the association changes.

815 

767### Update stored thread metadata816### Update stored thread metadata

768 817 

769Use `thread/metadata/update` to patch stored thread metadata without resuming the818Use `thread/metadata/update` to patch stored thread metadata without resuming the

770thread. Set `isPinned` to pin or unpin the thread, or update `gitInfo` to change819thread. Pass the Git fields you want to update in `gitInfo`. Omit a field

771persisted Git metadata. Omitted fields stay unchanged; explicit `null` clears a820to keep its value or pass `null` to clear it.

772stored Git metadata value.

773 821 

774```json822```json

775{ "method": "thread/metadata/update", "id": 21, "params": {823{ "method": "thread/metadata/update", "id": 21, "params": {

776 "threadId": "thr_123",824 "threadId": "thr_123",

777 "isPinned": true,

778 "gitInfo": { "branch": "feature/sidebar-pr" }825 "gitInfo": { "branch": "feature/sidebar-pr" }

779} }826} }

780{ "id": 21, "result": {827{ "id": 21, "result": {

781 "thread": {828 "thread": {

782 "id": "thr_123",829 "id": "thr_123",

783 "isPinned": true,

784 "gitInfo": { "sha": null, "branch": "feature/sidebar-pr", "originUrl": null }830 "gitInfo": { "sha": null, "branch": "feature/sidebar-pr", "originUrl": null }

785 }831 }

786} }832} }


817- `notSubscribed` when the connection wasn't subscribed to that thread.863- `notSubscribed` when the connection wasn't subscribed to that thread.

818- `notLoaded` when the thread isn't loaded.864- `notLoaded` when the thread isn't loaded.

819 865 

820If this was the last subscriber, the server keeps the thread loaded until it has no subscribers and no thread activity for 30 minutes. When the grace period expires, app-server unloads the thread and emits a `thread/status/changed` transition to `notLoaded` plus `thread/closed`.866After the last subscriber leaves, app-server unloads the thread once it has

867been idle for 60 seconds by default. Set

868[`thread_unload_delay_secs`](https://learn.chatgpt.com/docs/config-file/config-reference) to change the

869interval. When it unloads the thread, app-server emits `thread/status/changed`

870with status `notLoaded` and a `thread/closed` notification.

821 871 

822```json872```json

823{ "method": "thread/unsubscribe", "id": 22, "params": { "threadId": "thr_123" } }873{ "method": "thread/unsubscribe", "id": 22, "params": { "threadId": "thr_123" } }


1018 "threadId": "thr_123",1068 "threadId": "thr_123",

1019 "input": [ { "type": "text", "text": "Run tests" } ],1069 "input": [ { "type": "text", "text": "Run tests" } ],

1020 "cwd": "/Users/me/project",1070 "cwd": "/Users/me/project",

1021 "approvalPolicy": "unlessTrusted",1071 "approvalPolicy": "on-request",

1022 "sandboxPolicy": {1072 "sandboxPolicy": {

1023 "type": "workspaceWrite",1073 "type": "workspaceWrite",

1024 "writableRoots": ["/Users/me/project"],1074 "writableRoots": ["/Users/me/project"],


1027 "model": "gpt-6.1-sol",1077 "model": "gpt-6.1-sol",

1028 "effort": "medium",1078 "effort": "medium",

1029 "summary": "concise",1079 "summary": "concise",

1030 "personality": "friendly",

1031 "outputSchema": {1080 "outputSchema": {

1032 "type": "object",1081 "type": "object",

1033 "properties": { "answer": { "type": "string" } },1082 "properties": { "answer": { "type": "string" } },


1039```1088```

1040 1089 

1041 1090 

1091Set `serviceTierForTurn` to override the service tier for one new turn. Use

1092`"default"` for standard speed, or omit the field to inherit the thread's tier.

1093To change the tier for this turn and later turns, set `serviceTier`.

1094 

1042To start a turn with output from a tool your client ran, pass `toolOutput`1095To start a turn with output from a tool your client ran, pass `toolOutput`

1043with a nonempty `name`, an optional `namespace`, and an `output` string or1096with a nonempty `name`, an optional `namespace`, and an `output` string or

1044array of content items. Set `input` to an empty array; you can't combine1097array of content items. Set `input` to an empty array; you can't combine


1133- `commit` (review a specific commit)1186- `commit` (review a specific commit)

1134- `custom` (free-form instructions)1187- `custom` (free-form instructions)

1135 1188 

1136Use `delivery: "inline"` (default) to run the review on the existing thread.1189`review/start` runs the review on the supplied thread. Omit `delivery` or pass

1137For a separate review thread, call `thread/start` and then run an inline1190`"inline"`. To run a separate review, use `thread/fork` to include the existing

1138review on the new thread.1191history or `thread/start` for a fresh thread. Then call `review/start` with the

1192new thread ID.

1139 1193 

1140Example request/response:1194Example request/response:

1141 1195 


1158} }1212} }

1159```1213```

1160 1214 

1161`delivery: "detached"` is deprecated, emits `deprecationNotice`, and isn't

1162supported for paginated parent threads. If a separate review needs the

1163existing conversation history, use `thread/fork` followed by `turn/start`

1164with your review instructions.

1165 

1166Codex streams the usual `turn/started` notification followed by an `item/started` with an `enteredReviewMode` item:1215Codex streams the usual `turn/started` notification followed by an `item/started` with an `enteredReviewMode` item:

1167 1216 

1168```json1217```json


1262{ "method": "configRequirements/read", "id": 52, "params": {} }1311{ "method": "configRequirements/read", "id": 52, "params": {} }

1263{ "id": 52, "result": {1312{ "id": 52, "result": {

1264 "requirements": {1313 "requirements": {

1265 "allowedApprovalPolicies": ["onRequest", "unlessTrusted"],1314 "allowedApprovalPolicies": ["on-request", "never"],

1266 "allowedSandboxModes": ["readOnly", "workspaceWrite"],1315 "allowedSandboxModes": ["read-only", "workspace-write"],

1267 "featureRequirements": {1316 "featureRequirements": {

1268 "personality": true,

1269 "unified_exec": false1317 "unified_exec": false

1270 },

1271 "network": {

1272 "enabled": true,

1273 "allowedDomains": ["api.openai.com"],

1274 "allowUnixSockets": ["/tmp/example.sock"],

1275 "dangerouslyAllowAllUnixSockets": false

1276 }1318 }

1277 }1319 }

1278} }1320} }

1279```1321```

1280 1322 

1281`result.requirements` is `null` when no requirements are configured. See the docs on [`requirements.toml`](https://learn.chatgpt.com/docs/config-file/config-reference#requirementstoml) for details on supported keys and values.1323`result.requirements` is `null` when no requirements are configured.

1324When `result.supportsIndependentSpeedModes` is `true`, the `fast_mode` and

1325`ultrafast_mode` requirements apply independently. Older servers omit this

1326field and use `fast_mode` for both. For supported keys and values, see the

1327[`requirements.toml` reference](https://learn.chatgpt.com/docs/config-file/config-reference#requirementstoml).

1282 1328 

1283### Windows sandbox setup (`windowsSandbox/setupStart`)1329### Windows sandbox setup (`windowsSandbox/setupStart`)

1284 1330 

1285Custom Windows clients can trigger sandbox setup asynchronously instead of blocking on startup checks.1331Call `windowsSandbox/readiness` before prompting for setup. Both MXC and a

1332configured legacy sandbox can return `ready`. If the legacy sandbox returns

1333`updateRequired`, call `windowsSandbox/setupStart` to start setup

1334asynchronously. The readiness check returns `notConfigured` if the Windows

1335sandbox is disabled or the host runs another operating system.

1286 1336 

1287```json1337```json

1288{ "method": "windowsSandbox/setupStart", "id": 53, "params": { "mode": "elevated" } }1338{ "method": "windowsSandbox/setupStart", "id": 53, "params": { "mode": "elevated" } }


1380- `reasoning` - `{id, summary, content}` where `summary` holds streamed reasoning summaries and `content` holds raw reasoning blocks.1430- `reasoning` - `{id, summary, content}` where `summary` holds streamed reasoning summaries and `content` holds raw reasoning blocks.

1381- `commandExecution` - `{id, command, cwd, status, commandActions, aggregatedOutput?, exitCode?, durationMs?}`.1431- `commandExecution` - `{id, command, cwd, status, commandActions, aggregatedOutput?, exitCode?, durationMs?}`.

1382- `fileChange` - `{id, changes, status}` describing proposed edits; `changes` list `{path, kind, diff}`.1432- `fileChange` - `{id, changes, status}` describing proposed edits; `changes` list `{path, kind, diff}`.

1383- `mcpToolCall` - `{id, server, tool, status, arguments, appContext?, pluginId?, result?, error?}`. For trusted MCP apps, `appContext` can include `connectorId`, `linkId`, `resourceUri`, `appName`, `templateId`, and the stable connector `actionName`. Older persisted items can omit newer metadata. Use `appContext.resourceUri` instead of the deprecated top-level `mcpAppResourceUri`.1433- `mcpToolCall` - Records the call's `id`, `server`, `tool`, `status`, and `arguments`.

1434 The call also includes `appContext`, `mcpAppUi`, `pluginId`, `readOnlyHint`, `result`, `error`, and `durationMs`. Each of these fields can be `null`. The legacy `mcpAppResourceUri` field is optional.

1435 For trusted MCP apps, `appContext` contains `connectorId`. Its other fields (`linkId`, `resourceUri`, `appName`, and `actionName`) can be `null`.

1436 When the tool descriptor specifies a resource URI and a display mode (`inline` or `fullscreen`), `mcpAppUi` contains `resourceUri` and `preferredModelDisplayMode`. For calls saved without this presentation metadata, app-server returns `null` for `mcpAppUi`.

1384- `dynamicToolCall` - `{id, tool, arguments, status, contentItems?, success?, durationMs?}` for client-executed dynamic tool invocations.1437- `dynamicToolCall` - `{id, tool, arguments, status, contentItems?, success?, durationMs?}` for client-executed dynamic tool invocations.

1385- `collabToolCall` - `{id, tool, status, senderThreadId, receiverThreadId?, newThreadId?, prompt?, agentStatus?}`.1438- `collabToolCall` - `{id, tool, status, senderThreadId, receiverThreadId?, newThreadId?, prompt?, agentStatus?}`.

1386- `webSearch` - `{id, query, action?}` for web search requests issued by the agent.1439- `webSearch` - `{id, query, action?}` for web search requests issued by the agent.


1410 1463 

1411## Errors1464## Errors

1412 1465 

1413If a turn fails, the server emits an `error` event with `{ error: { message, codexErrorInfo?, additionalDetails? } }` and then finishes the turn with `status: "failed"`. When an upstream HTTP status is available, it appears in `codexErrorInfo.httpStatusCode`.1466When app-server rejects new work during graceful shutdown, it returns a JSON-RPC

1414 1467error with code `-32600` and `data.reason` set to `serverShuttingDown`.

1415Common `codexErrorInfo` values include:

1416 1468 

1417- `ContextWindowExceeded`1469The `error` notification includes a nested `error` object with a `message`

1418- `UsageLimitExceeded`1470and optional `additionalDetails`. Its `codexErrorInfo` field can be `null`.

1419- `HttpConnectionFailed` (4xx/5xx upstream errors)1471If `willRetry` is `true`, the server retries and the turn stays active. A turn

1420- `ResponseStreamConnectionFailed`1472that fails finishes with `status: "failed"`. Common `codexErrorInfo` values include

1421- `ResponseStreamDisconnected`1473`contextWindowExceeded`, `usageLimitExceeded`, `badRequest`, `unauthorized`,

1422- `ResponseTooManyFailedAttempts`1474and `sandboxError`. For upstream request failures, the value can be an

1423- `BadRequest`, `Unauthorized`, `SandboxError`, `InternalServerError`, `Other`1475object such as `{ "httpConnectionFailed": { "httpStatusCode": 503 } }`.

1424 

1425When an upstream HTTP status is available, the server forwards it in `httpStatusCode` on the relevant `codexErrorInfo` variant.

1426 1476 

1427## Approvals1477## Approvals

1428 1478 


1538 1588 

1539Example:1589Example:

1540 1590 

1541```1591```text

1542$skill-creator Add a new skill for triaging flaky CI and include step-by-step usage.1592$skill-creator Add a new skill for triaging flaky CI and include step-by-step usage.

1543```1593```

1544 1594 


1989- `account/rateLimitResetCredit/consume` - consume one earned rate-limit reset using a caller-provided `idempotencyKey` value.2039- `account/rateLimitResetCredit/consume` - consume one earned rate-limit reset using a caller-provided `idempotencyKey` value.

1990- `account/usage/read` - fetch ChatGPT account token-activity summaries and daily buckets.2040- `account/usage/read` - fetch ChatGPT account token-activity summaries and daily buckets.

1991- `account/workspaceMessages/read` - fetch active workspace messages, including notification headlines when available.2041- `account/workspaceMessages/read` - fetch active workspace messages, including notification headlines when available.

1992- `mcpServer/oauthLogin/completed` (notify) - emitted after a `mcpServer/oauth/login` flow finishes; payload includes `{ name, threadId, success, error? }`. `threadId` can be `null` for app-scoped or plugin OAuth flows.2042- `mcpServer/oauthLogin/completed` (notify) - emitted after a `mcpServer/oauth/login` flow finishes; payload includes `{ name, threadId, loginId?, success, error? }`. Older servers omit `loginId`. `threadId` can be `null` for app-scoped or plugin OAuth flows.

1993- `mcpServer/startupStatus/updated` (notify) - emitted when a configured MCP server's startup status changes; payload includes `{ threadId, name, status, error, failureReason }`. `threadId` is `null` for app-scoped startup. On failed startup, `failureReason: "reauthenticationRequired"` means stored OAuth credentials expired and couldn't be refreshed, so the client should offer to reconnect the server.2043- `mcpServer/startupStatus/updated` (notify) - emitted when a configured MCP server's startup status changes; payload includes `{ threadId, name, status, error, failureReason }`. `threadId` is `null` for app-scoped startup. On failed startup, `failureReason: "reauthenticationRequired"` means stored OAuth credentials expired and couldn't be refreshed, so the client should offer to reconnect the server.

1994 2044 

1995### 1) Check auth state2045### 1) Check auth state

Details

164 164 

165Suppose Codex finishes some work on a worktree and you choose to create a `feature/a` branch on it using **Create branch here**. Now, you want to try it on your local checkout. If you tried to check out the branch, you would get the following error:165Suppose Codex finishes some work on a worktree and you choose to create a `feature/a` branch on it using **Create branch here**. Now, you want to try it on your local checkout. If you tried to check out the branch, you would get the following error:

166 166 

167```167```text

168fatal: 'feature/a' is already used by worktree at '<WORKTREE_PATH>'168fatal: 'feature/a' is already used by worktree at '<WORKTREE_PATH>'

169```169```

170 170 

build-skills.md +14 −2

Details

144| `REPO` | `$REPO_ROOT/.agents/skills` <br /> The topmost root folder when you launch Codex inside a Git repository. | If you're in a repository with nested folders, organizations can check in skills relevant to everyone using the repository. These serve as root skills available to any subfolder in the repository. |144| `REPO` | `$REPO_ROOT/.agents/skills` <br /> The topmost root folder when you launch Codex inside a Git repository. | If you're in a repository with nested folders, organizations can check in skills relevant to everyone using the repository. These serve as root skills available to any subfolder in the repository. |

145| `USER` | `$HOME/.agents/skills` <br /> Any skills checked into the user's personal folder. | Use to curate skills relevant to a user that apply to any repository the user may work in. |145| `USER` | `$HOME/.agents/skills` <br /> Any skills checked into the user's personal folder. | Use to curate skills relevant to a user that apply to any repository the user may work in. |

146| `ADMIN` | `/etc/codex/skills` <br /> Any skills checked into the machine or container in a shared, system location. | Use for SDK scripts, automation, and for checking in default admin skills available to each user on the machine. |146| `ADMIN` | `/etc/codex/skills` <br /> Any skills checked into the machine or container in a shared, system location. | Use for SDK scripts, automation, and for checking in default admin skills available to each user on the machine. |

147| `SYSTEM` | Bundled with Codex by OpenAI. | Useful skills relevant to a broad audience such as the skill-creator and plan skills. Available to everyone when they start Codex. |147| `SYSTEM` | Bundled with Codex by OpenAI. | Includes `skill-creator` and `skill-installer`. Enabled by default. |

148 148 

149Codex supports symlinked skill folders and follows the symlink target when scanning these locations.149Codex supports symlinked skill folders and follows the symlink target when scanning these locations.

150 150 


188enabled = false188enabled = false

189```189```

190 190 

191Restart Codex after changing `~/.codex/config.toml`.191Use exactly one selector per entry. An absolute `path` matches one

192`SKILL.md` file. A `name` matches every skill with that name. When more than

193one entry matches a skill, the last matching entry wins.

194 

195To turn off all bundled system skills for the current project, add this setting

196to its trusted `.codex/config.toml`:

197 

198```toml

199[skills.bundled]

200enabled = false

201```

202 

203Restart Codex after changing the configuration.

192 204 

193## Optional metadata205## Optional metadata

194 206 

codex-sdk.md +40 −5

Details

37 38 

38Start a thread with Codex and run it with your prompt.39Start a thread with Codex and run it with your prompt.

39 40 

40```ts41```typescript

41 42import { Codex } from "@openai/codex-sdk";

42 43 

43const codex = new Codex();44const codex = new Codex();

44const thread = codex.startThread();45const thread = codex.startThread();


49console.log(result.finalResponse);50console.log(result.finalResponse);

50```51```

51 52 

53 

52Call `run()` again to continue on the same thread, or resume a past thread by providing a thread ID.54Call `run()` again to continue on the same thread, or resume a past thread by providing a thread ID.

53 55 

54```ts56```typescript

55// running the same thread57// running the same thread

56const result = await thread.run("Implement the plan");58const result = await thread.run("Implement the plan");

57 59 


59 61 

60// resuming past thread62// resuming past thread

61 63 

62const threadId = "<thread-id>";64const threadId = thread.id!;

63const thread2 = codex.resumeThread(threadId);65const thread2 = codex.resumeThread(threadId);

64const result2 = await thread2.run("Pick up where you left off");66const result2 = await thread2.run("Pick up where you left off");

65 67 

66console.log(result2.finalResponse);68console.log(result2.finalResponse);

67```69```

68 70 

71 

72To identify threads created by your integration, set `threadSource` when you create a thread.

73For example, `codex.startThread({ threadSource: "ci" })` labels the thread

74as `ci`. Resuming a thread preserves its original source.

75 

69### Configuration overrides76### Configuration overrides

70 77 

71Pass `config` to set structured Codex configuration. For keys that can't be78Pass `config` to set structured Codex configuration. For keys that can't be

72expressed as dotted paths, use `configOverrides` to pass raw TOML strings as79expressed as dotted paths, use `configOverrides` to pass raw TOML strings as

73separate `--config` arguments:80separate `--config` arguments:

74 81 

75```ts82```typescript

76const codex = new Codex({83const codex = new Codex({

77 config: { default_permissions: "audit" },84 config: { default_permissions: "audit" },

78 configOverrides: [85 configOverrides: [


138```151```

139 152 

140 153 

154### Pass content from another system

155 

156When a tool, application, or another agent supplies content, pass an

157`ExternalMessage` as the entire input to `thread.run()` or `thread.turn()`.

158For example, `ExternalMessage(tool_name="issue_tracker", content=issue_body)`

159identifies the tool that supplied an issue description. Codex treats the

160description as tool output, at a lower priority than user and developer instructions. The message

161can start a turn or join an active regular turn.

162 

163### Resume a thread without loading its history

164 

165Pass `include_turns=False` to `codex.thread_resume()` or `codex.thread_fork()`

166to skip loading old turns into the response. The model still has the thread's

167context. To retrieve the history later, call `thread.read(include_turns=True)`.

168 

169With Codex CLI 0.166.0 or later, use the thread's saved model provider to resume it. If you switch providers, call `codex.thread_fork(thread_id)` to

170continue from the same history on the new provider.

171 

172### Set the service tier for one turn

173 

174To choose the service tier for a single new turn, pass `turn_service_tier` to

175`run()` or `turn()`. For example, `turn_service_tier="default"` uses standard

176speed for that turn. To change the tier for this and later turns, pass

177`service_tier`. Joining an active turn leaves its tier unchanged.

178 

179If you supply your own Codex executable, `ExternalMessage`, explicit

180`include_turns` on resume or fork, and `turn_service_tier` require Codex CLI

1810.151.0 or later.

182 

141### Sandbox presets183### Sandbox presets

142 184 

143Use the same `Sandbox` presets when creating a thread or changing its filesystem185Use the same `Sandbox` presets when creating a thread or changing its filesystem

config-advanced.md +62 −15

Details

184for client setup and verification. For organization-wide deployment, see184for client setup and verification. For organization-wide deployment, see

185[Roll out a gateway](https://learn.chatgpt.com/docs/enterprise/roll-out-a-gateway).185[Roll out a gateway](https://learn.chatgpt.com/docs/enterprise/roll-out-a-gateway).

186 186 

187A model provider defines how Codex connects to a model (base URL, wire API, authentication, and optional HTTP headers). Custom providers can't reuse the reserved built-in provider IDs: `openai`, `ollama`, and `lmstudio`.187A model provider defines how Codex connects to a model (base URL, wire API, authentication, and optional HTTP headers). Choose a unique ID for custom providers. Codex reserves `openai`, `ollama`, `lmstudio`, `amazon-bedrock`, `amazon-bedrock-runtime`, and `gcp` for its built-in providers.

188 188 

189Define more providers and point `model_provider` at them:189Define more providers and point `model_provider` at them:

190 190 


258 258 

259### Amazon Bedrock provider259### Amazon Bedrock provider

260 260 

261Codex includes a built-in `amazon-bedrock` model provider. Set it directly as261Set `model_provider` to `amazon-bedrock` for the Bedrock Mantle endpoint or

262`model_provider`; unlike custom providers, this built-in provider supports only262`amazon-bedrock-runtime` for the Runtime endpoint. To select the AWS credentials

263the nested AWS profile and region overrides.263and region for Mantle, configure its `aws` table.

264 264 

265```toml265```toml

266model_provider = "amazon-bedrock"266model_provider = "amazon-bedrock"


278availability, see [Use ChatGPT Work and Codex with Amazon278availability, see [Use ChatGPT Work and Codex with Amazon

279Bedrock](https://learn.chatgpt.com/docs/amazon-bedrock).279Bedrock](https://learn.chatgpt.com/docs/amazon-bedrock).

280 280 

281### Google Cloud Vertex AI provider

282 

283To use a model your project can access on Vertex AI, set the built-in provider in `config.toml`.

284 

285```toml

286model_provider = "gcp"

287 

288[model_providers.gcp]

289project_id = "my-project"

290location = "global"

291```

292 

293If you omit `project_id` or `location`, Codex reads `GOOGLE_CLOUD_PROJECT` or

294`GOOGLE_CLOUD_LOCATION`, respectively. The location defaults to `global`.

295 

296To use default authentication, install the Google Cloud CLI on the machine

297running Codex. To sign in locally, run `gcloud auth application-default login`.

298Codex runs `gcloud auth application-default print-access-token` to obtain

299access tokens.

300 

301To use a specific ADC file, set `credential_file` to its absolute path under

302`[model_providers.gcp]`. Codex sets `GOOGLE_APPLICATION_CREDENTIALS` to that

303path for the authentication command.

304 

305If your deployment uses a different endpoint, token command, or static

306headers, configure `base_url`, `auth`, or `http_headers` under

307`[model_providers.gcp]`.

308 

281## OSS mode (local providers)309## OSS mode (local providers)

282 310 

283Codex can run against a local "open source" provider such as Ollama or LM311Codex can run against a local "open source" provider such as Ollama or LM


322```toml350```toml

323model_reasoning_summary = "none" # Disable summaries351model_reasoning_summary = "none" # Disable summaries

324model_verbosity = "low" # Shorten responses352model_verbosity = "low" # Shorten responses

325model_supports_reasoning_summaries = true # Force reasoning

326model_context_window = 128000 # Context window size353model_context_window = 128000 # Context window size

327```354```

328 355 


451log_user_prompt = false # redact user prompts unless explicitly enabled478log_user_prompt = false # redact user prompts unless explicitly enabled

452```479```

453 480 

481Administrators can enforce the exporters and individual logging settings in

482[`requirements.toml`](https://learn.chatgpt.com/docs/enterprise/managed-configuration#enforce-opentelemetry-settings).

483 

454Choose an exporter:484Choose an exporter:

455 485 

456```toml486```toml


481- `codex.sse_event` (stream event kind, success/failure, duration, plus token counts on `response.completed`)511- `codex.sse_event` (stream event kind, success/failure, duration, plus token counts on `response.completed`)

482- `codex.websocket_request` and `codex.websocket_event` (request duration plus per-message kind/success/error)512- `codex.websocket_request` and `codex.websocket_event` (request duration plus per-message kind/success/error)

483- `codex.user_prompt` (length; content redacted unless explicitly enabled)513- `codex.user_prompt` (length; content redacted unless explicitly enabled)

514- `codex.agent_response` (final answers from the main agent and spawned subagents when `otel.log_agent_responses = true`)

515- `codex.guardian_assessment` (completed automatic approval reviews when `otel.log_guardian_assessments = true`)

484- `codex.tool_decision` (approved/denied and whether the decision came from config vs user)516- `codex.tool_decision` (approved/denied and whether the decision came from config vs user)

485- `codex.tool_result` (duration, success, output snippet)517- `codex.tool_result` (duration, success, output snippet)

486 518 


509 541 

510By default, Codex periodically sends a small amount of anonymous usage and health data back to OpenAI. This helps detect when Codex isn't working correctly and shows what features and configuration options are being used, so the Codex team can focus on what matters most. These metrics don't contain any personally identifiable information (PII). Metrics collection is independent of OTel log/trace export.542By default, Codex periodically sends a small amount of anonymous usage and health data back to OpenAI. This helps detect when Codex isn't working correctly and shows what features and configuration options are being used, so the Codex team can focus on what matters most. These metrics don't contain any personally identifiable information (PII). Metrics collection is independent of OTel log/trace export.

511 543 

512To disable analytics and metrics collection in Codex CLI, set the analytics flag in your config:544To disable analytics and the built-in `statsig` metrics exporter, set the analytics flag in your config:

513 545 

514```toml546```toml

515[analytics]547[analytics]

516enabled = false548enabled = false

517```549```

518 550 

519This also disables custom OTLP metrics exporters in Codex CLI.551To disable a custom OTLP metrics exporter as well, set `otel.metrics_exporter = "none"`.

520 552 

521Each metric includes its own fields plus the default context fields below.553Each metric includes its own fields plus the default context fields below.

522 554 


702 734 

703```python735```python

704#!/usr/bin/env python3736#!/usr/bin/env python3

705import json, subprocess, sys737import argparse

738import json

739import subprocess

740import sys

741 

706 742 

707def main() -> int:743def main() -> int:

708 notification = json.loads(sys.argv[1])744 parser = argparse.ArgumentParser(

745 description="Show a Codex turn-completion notification on macOS."

746 )

747 parser.add_argument("notification", type=json.loads, help="Codex notification JSON")

748 notification = parser.parse_args().notification

709 if notification.get("type") != "agent-turn-complete":749 if notification.get("type") != "agent-turn-complete":

710 return 0750 return 0

711 title = f"Codex: {notification.get('last-assistant-message', 'Turn Complete!')}"751 title = f"Codex: {notification.get('last-assistant-message', 'Turn Complete!')}"

712 message = " ".join(notification.get("input-messages", []))752 message = " ".join(notification.get("input-messages", []))

713 subprocess.check_output([753 subprocess.check_output(

754 [

714 "terminal-notifier",755 "terminal-notifier",

715 "-title", title,756 "-title",

716 "-message", message,757 title,

717 "-group", "codex-" + notification.get("thread-id", ""),758 "-message",

718 "-activate", "com.googlecode.iterm2",759 message,

719 ])760 "-group",

761 "codex-" + notification.get("thread-id", ""),

762 "-activate",

763 "com.googlecode.iterm2",

764 ]

765 )

720 return 0766 return 0

721 767 

768 

722if __name__ == "__main__":769if __name__ == "__main__":

723 sys.exit(main())770 sys.exit(main())

724```771```

config-basic.md +2 −2

Details

201### Common feature flags201### Common feature flags

202 202 

203| Key | Default | Maturity | Description |203| Key | Default | Maturity | Description |

204| -------------------- | :-----: | ------------ | ---------------------------------------------------------------------------------------- |204| -------------------- | :-----: | ---------- | ---------------------------------------------------------------------------------------- |

205| `apps` | true | Stable | Enable app (connector) integrations |205| `apps` | true | Stable | Enable app (connector) integrations |

206| `goals` | true | Stable | Enable persisted goals and automatic continuation |206| `goals` | true | Stable | Enable persisted goals and automatic continuation |

207| `hooks` | true | Stable | Enable lifecycle hooks from `hooks.json` or inline `[hooks]`. See [Hooks](https://learn.chatgpt.com/docs/hooks). |207| `hooks` | true | Stable | Enable lifecycle hooks from `hooks.json` or inline `[hooks]`. See [Hooks](https://learn.chatgpt.com/docs/hooks). |

208| `fast_mode` | true | Stable | Enable Fast mode selection and the `service_tier = "fast"` path |208| `fast_mode` | true | Stable | Enable Fast mode selection and the `service_tier = "fast"` path |

209| `memories` | false | Experimental | Enable [Memories](https://learn.chatgpt.com/docs/customization/memories) |209| `memories` | false | Stable | Enable [Memories](https://learn.chatgpt.com/docs/customization/memories) |

210| `multi_agent` | true | Stable | Enable subagent collaboration tools |210| `multi_agent` | true | Stable | Enable subagent collaboration tools |

211| `remote_plugin` | true | Stable | Enable the remote plugin catalog |211| `remote_plugin` | true | Stable | Enable the remote plugin catalog |

212| `shell_snapshot` | true | Stable | Snapshot your shell environment to speed up repeated commands |212| `shell_snapshot` | true | Stable | Snapshot your shell environment to speed up repeated commands |

Details

184for client setup and verification. For organization-wide deployment, see184for client setup and verification. For organization-wide deployment, see

185[Roll out a gateway](https://learn.chatgpt.com/docs/enterprise/roll-out-a-gateway).185[Roll out a gateway](https://learn.chatgpt.com/docs/enterprise/roll-out-a-gateway).

186 186 

187A model provider defines how Codex connects to a model (base URL, wire API, authentication, and optional HTTP headers). Custom providers can't reuse the reserved built-in provider IDs: `openai`, `ollama`, and `lmstudio`.187A model provider defines how Codex connects to a model (base URL, wire API, authentication, and optional HTTP headers). Choose a unique ID for custom providers. Codex reserves `openai`, `ollama`, `lmstudio`, `amazon-bedrock`, `amazon-bedrock-runtime`, and `gcp` for its built-in providers.

188 188 

189Define more providers and point `model_provider` at them:189Define more providers and point `model_provider` at them:

190 190 


258 258 

259### Amazon Bedrock provider259### Amazon Bedrock provider

260 260 

261Codex includes a built-in `amazon-bedrock` model provider. Set it directly as261Set `model_provider` to `amazon-bedrock` for the Bedrock Mantle endpoint or

262`model_provider`; unlike custom providers, this built-in provider supports only262`amazon-bedrock-runtime` for the Runtime endpoint. To select the AWS credentials

263the nested AWS profile and region overrides.263and region for Mantle, configure its `aws` table.

264 264 

265```toml265```toml

266model_provider = "amazon-bedrock"266model_provider = "amazon-bedrock"


278availability, see [Use ChatGPT Work and Codex with Amazon278availability, see [Use ChatGPT Work and Codex with Amazon

279Bedrock](https://learn.chatgpt.com/docs/amazon-bedrock).279Bedrock](https://learn.chatgpt.com/docs/amazon-bedrock).

280 280 

281### Google Cloud Vertex AI provider

282 

283To use a model your project can access on Vertex AI, set the built-in provider in `config.toml`.

284 

285```toml

286model_provider = "gcp"

287 

288[model_providers.gcp]

289project_id = "my-project"

290location = "global"

291```

292 

293If you omit `project_id` or `location`, Codex reads `GOOGLE_CLOUD_PROJECT` or

294`GOOGLE_CLOUD_LOCATION`, respectively. The location defaults to `global`.

295 

296To use default authentication, install the Google Cloud CLI on the machine

297running Codex. To sign in locally, run `gcloud auth application-default login`.

298Codex runs `gcloud auth application-default print-access-token` to obtain

299access tokens.

300 

301To use a specific ADC file, set `credential_file` to its absolute path under

302`[model_providers.gcp]`. Codex sets `GOOGLE_APPLICATION_CREDENTIALS` to that

303path for the authentication command.

304 

305If your deployment uses a different endpoint, token command, or static

306headers, configure `base_url`, `auth`, or `http_headers` under

307`[model_providers.gcp]`.

308 

281## OSS mode (local providers)309## OSS mode (local providers)

282 310 

283Codex can run against a local "open source" provider such as Ollama or LM311Codex can run against a local "open source" provider such as Ollama or LM


322```toml350```toml

323model_reasoning_summary = "none" # Disable summaries351model_reasoning_summary = "none" # Disable summaries

324model_verbosity = "low" # Shorten responses352model_verbosity = "low" # Shorten responses

325model_supports_reasoning_summaries = true # Force reasoning

326model_context_window = 128000 # Context window size353model_context_window = 128000 # Context window size

327```354```

328 355 


451log_user_prompt = false # redact user prompts unless explicitly enabled478log_user_prompt = false # redact user prompts unless explicitly enabled

452```479```

453 480 

481Administrators can enforce the exporters and individual logging settings in

482[`requirements.toml`](https://learn.chatgpt.com/docs/enterprise/managed-configuration#enforce-opentelemetry-settings).

483 

454Choose an exporter:484Choose an exporter:

455 485 

456```toml486```toml


481- `codex.sse_event` (stream event kind, success/failure, duration, plus token counts on `response.completed`)511- `codex.sse_event` (stream event kind, success/failure, duration, plus token counts on `response.completed`)

482- `codex.websocket_request` and `codex.websocket_event` (request duration plus per-message kind/success/error)512- `codex.websocket_request` and `codex.websocket_event` (request duration plus per-message kind/success/error)

483- `codex.user_prompt` (length; content redacted unless explicitly enabled)513- `codex.user_prompt` (length; content redacted unless explicitly enabled)

514- `codex.agent_response` (final answers from the main agent and spawned subagents when `otel.log_agent_responses = true`)

515- `codex.guardian_assessment` (completed automatic approval reviews when `otel.log_guardian_assessments = true`)

484- `codex.tool_decision` (approved/denied and whether the decision came from config vs user)516- `codex.tool_decision` (approved/denied and whether the decision came from config vs user)

485- `codex.tool_result` (duration, success, output snippet)517- `codex.tool_result` (duration, success, output snippet)

486 518 


509 541 

510By default, Codex periodically sends a small amount of anonymous usage and health data back to OpenAI. This helps detect when Codex isn't working correctly and shows what features and configuration options are being used, so the Codex team can focus on what matters most. These metrics don't contain any personally identifiable information (PII). Metrics collection is independent of OTel log/trace export.542By default, Codex periodically sends a small amount of anonymous usage and health data back to OpenAI. This helps detect when Codex isn't working correctly and shows what features and configuration options are being used, so the Codex team can focus on what matters most. These metrics don't contain any personally identifiable information (PII). Metrics collection is independent of OTel log/trace export.

511 543 

512To disable analytics and metrics collection in Codex CLI, set the analytics flag in your config:544To disable analytics and the built-in `statsig` metrics exporter, set the analytics flag in your config:

513 545 

514```toml546```toml

515[analytics]547[analytics]

516enabled = false548enabled = false

517```549```

518 550 

519This also disables custom OTLP metrics exporters in Codex CLI.551To disable a custom OTLP metrics exporter as well, set `otel.metrics_exporter = "none"`.

520 552 

521Each metric includes its own fields plus the default context fields below.553Each metric includes its own fields plus the default context fields below.

522 554 


702 734 

703```python735```python

704#!/usr/bin/env python3736#!/usr/bin/env python3

705import json, subprocess, sys737import argparse

738import json

739import subprocess

740import sys

741 

706 742 

707def main() -> int:743def main() -> int:

708 notification = json.loads(sys.argv[1])744 parser = argparse.ArgumentParser(

745 description="Show a Codex turn-completion notification on macOS."

746 )

747 parser.add_argument("notification", type=json.loads, help="Codex notification JSON")

748 notification = parser.parse_args().notification

709 if notification.get("type") != "agent-turn-complete":749 if notification.get("type") != "agent-turn-complete":

710 return 0750 return 0

711 title = f"Codex: {notification.get('last-assistant-message', 'Turn Complete!')}"751 title = f"Codex: {notification.get('last-assistant-message', 'Turn Complete!')}"

712 message = " ".join(notification.get("input-messages", []))752 message = " ".join(notification.get("input-messages", []))

713 subprocess.check_output([753 subprocess.check_output(

754 [

714 "terminal-notifier",755 "terminal-notifier",

715 "-title", title,756 "-title",

716 "-message", message,757 title,

717 "-group", "codex-" + notification.get("thread-id", ""),758 "-message",

718 "-activate", "com.googlecode.iterm2",759 message,

719 ])760 "-group",

761 "codex-" + notification.get("thread-id", ""),

762 "-activate",

763 "com.googlecode.iterm2",

764 ]

765 )

720 return 0766 return 0

721 767 

768 

722if __name__ == "__main__":769if __name__ == "__main__":

723 sys.exit(main())770 sys.exit(main())

724```771```

Details

201### Common feature flags201### Common feature flags

202 202 

203| Key | Default | Maturity | Description |203| Key | Default | Maturity | Description |

204| -------------------- | :-----: | ------------ | ---------------------------------------------------------------------------------------- |204| -------------------- | :-----: | ---------- | ---------------------------------------------------------------------------------------- |

205| `apps` | true | Stable | Enable app (connector) integrations |205| `apps` | true | Stable | Enable app (connector) integrations |

206| `goals` | true | Stable | Enable persisted goals and automatic continuation |206| `goals` | true | Stable | Enable persisted goals and automatic continuation |

207| `hooks` | true | Stable | Enable lifecycle hooks from `hooks.json` or inline `[hooks]`. See [Hooks](https://learn.chatgpt.com/docs/hooks). |207| `hooks` | true | Stable | Enable lifecycle hooks from `hooks.json` or inline `[hooks]`. See [Hooks](https://learn.chatgpt.com/docs/hooks). |

208| `fast_mode` | true | Stable | Enable Fast mode selection and the `service_tier = "fast"` path |208| `fast_mode` | true | Stable | Enable Fast mode selection and the `service_tier = "fast"` path |

209| `memories` | false | Experimental | Enable [Memories](https://learn.chatgpt.com/docs/customization/memories) |209| `memories` | false | Stable | Enable [Memories](https://learn.chatgpt.com/docs/customization/memories) |

210| `multi_agent` | true | Stable | Enable subagent collaboration tools |210| `multi_agent` | true | Stable | Enable subagent collaboration tools |

211| `remote_plugin` | true | Stable | Enable the remote plugin catalog |211| `remote_plugin` | true | Stable | Enable the remote plugin catalog |

212| `shell_snapshot` | true | Stable | Snapshot your shell environment to speed up repeated commands |212| `shell_snapshot` | true | Stable | Snapshot your shell environment to speed up repeated commands |

Details

139 description:139 description:

140 "Controls whether the auto-compaction threshold counts the full active context (`total`, the default) or only growth after the carried compaction-window prefix (`body_after_prefix`).",140 "Controls whether the auto-compaction threshold counts the full active context (`total`, the default) or only growth after the carried compaction-window prefix (`body_after_prefix`).",

141 },141 },

142 {

143 key: "model_post_turn_compact_threshold_percent",

144 type: "integer (0–100)",

145 description:

146 "Compact history after a final response when active context reaches this percentage of the usable context window. Omit or set to `0` to disable turn-end compaction. The usual auto-compaction limits still apply.",

147 },

142 {148 {

143 key: "model_catalog_json",149 key: "model_catalog_json",

144 type: "string (path)",150 type: "string (path)",


211 description:217 description:

212 "Allow shell-based tools to use login-shell semantics. Defaults to `true`; when `false`, `login = true` requests are rejected and omitted `login` defaults to non-login shells.",218 "Allow shell-based tools to use login-shell semantics. Defaults to `true`; when `false`, `login = true` requests are rejected and omitted `login` defaults to non-login shells.",

213 },219 },

220 {

221 key: "allow_symlinked_codex_home",

222 type: "boolean",

223 description:

224 "On macOS, allow writable sandbox roots at or under `$CODEX_HOME` to follow symlinks. Codex reads this only from the execution host's `$CODEX_HOME/config.toml` at startup. Enabling it trusts targets outside that directory and targets that change between commands. It grants no additional writable roots. Defaults to `false`.",

225 },

214 {226 {

215 key: "sandbox_mode",227 key: "sandbox_mode",

216 type: "read-only | workspace-write | danger-full-access",228 type: "read-only | workspace-write | danger-full-access",


316 key: "analytics.enabled",328 key: "analytics.enabled",

317 type: "boolean",329 type: "boolean",

318 description:330 description:

319 "Enable or disable analytics for this machine/profile. In Codex CLI, `false` also disables custom OTLP metrics exporters. When unset, the client default applies.",331 "Enable or disable analytics for this machine or profile. Setting this to `false` disables the built-in Statsig metrics exporter. Explicit OTLP metrics exporters remain active. When unset, the client default applies.",

320 },332 },

321 {333 {

322 key: "instructions",334 key: "instructions",


371 description:383 description:

372 "Load the compaction prompt override from a file (experimental).",384 "Load the compaction prompt override from a file (experimental).",

373 },385 },

386 {

387 key: "skills.bundled.enabled",

388 type: "boolean",

389 description:

390 "Load the system skills bundled with Codex. Defaults to `true`. Set to `false` in a trusted project configuration to disable bundled skills for that project.",

391 },

392 {

393 key: "skills.include_instructions",

394 type: "boolean",

395 description:

396 "Include the automatic skills instructions in the model context. Defaults to `true`.",

397 },

374 {398 {

375 key: "skills.max_context_tokens",399 key: "skills.max_context_tokens",

376 type: "integer (positive)",400 type: "integer (positive)",


380 {404 {

381 key: "skills.config",405 key: "skills.config",

382 type: "array<object>",406 type: "array<object>",

383 description: "Per-skill enablement overrides stored in config.toml.",407 description:

408 "Enable or disable skills by name or path. If several rules match a skill, the last one wins.",

384 },409 },

385 {410 {

386 key: "skills.config.<index>.path",411 key: "skills.config.<index>.path",

387 type: "string (path)",412 type: "string (path)",

388 description: "Path to a skill folder containing `SKILL.md`.",413 description: "Absolute path to one `SKILL.md` file.",

414 },

415 {

416 key: "skills.config.<index>.name",

417 type: "string",

418 description:

419 "Match every skill with this exact name. Specify either `name` or `path` for each entry.",

389 },420 },

390 {421 {

391 key: "skills.config.<index>.enabled",422 key: "skills.config.<index>.enabled",


458 description:489 description:

459 "Default approval behavior for tools in this app unless a per-tool override exists.",490 "Default approval behavior for tools in this app unless a per-tool override exists.",

460 },491 },

492 {

493 key: "apps.<id>.omit_tools_from",

494 type: "array<string>",

495 description:

496 "Omit this app's tools from the `direct`, `deferred`, or `code_mode` surfaces. App and MCP server omissions apply together.",

497 },

461 {498 {

462 key: "apps.<id>.tools.<tool>.enabled",499 key: "apps.<id>.tools.<tool>.enabled",

463 type: "boolean",500 type: "boolean",


521 key: "features.rollout_budget.enabled",558 key: "features.rollout_budget.enabled",

522 type: "boolean",559 type: "boolean",

523 description:560 description:

524 "Enable rollout budget tracking. This feature is under development and off by default. When enabled, `features.rollout_budget.limit_tokens` is required.",561 "Enable rollout budget tracking. This feature is under development and off by default. When enabled, set both `limit_tokens` and `reminder_at_remaining_tokens`.",

525 },562 },

526 {563 {

527 key: "features.rollout_budget.limit_tokens",564 key: "features.rollout_budget.limit_tokens",


530 "Positive token limit for rollout budget tracking. Required when rollout budget is enabled.",567 "Positive token limit for rollout budget tracking. Required when rollout budget is enabled.",

531 },568 },

532 {569 {

533 key: "features.rollout_budget.reminder_interval_tokens",570 key: "features.rollout_budget.reminder_at_remaining_tokens",

534 type: "integer",571 type: "array<integer>",

535 description:572 description:

536 "Positive token interval between rollout budget reminders. Defaults to 10% of `limit_tokens`, with a minimum of 1 token.",573 "Send a reminder as the remaining weighted token budget crosses each threshold. Supply the list when rollout budget tracking is enabled. Each value must be positive and below `limit_tokens`.",

537 },574 },

538 {575 {

539 key: "features.rollout_budget.sampling_token_weight",576 key: "features.rollout_budget.sampling_token_weight",


557 key: "hooks.<Event>",594 key: "hooks.<Event>",

558 type: "array<table>",595 type: "array<table>",

559 description:596 description:

560 "Matcher groups for hook events such as `PreToolUse`, `PermissionRequest`, `PostToolUse`, `PreCompact`, `PostCompact`, `SessionStart`, `SessionEnd`, `SubagentStart`, `SubagentStop`, `UserPromptSubmit`, `Stop`, or `Interrupt`.",597 "Matcher groups for hook events such as `PreModelRequest`, `PostModelRequest`, `PreToolUse`, `PermissionRequest`, `PostToolUse`, `PreCompact`, `PostCompact`, `SessionStart`, `SessionEnd`, `SubagentStart`, `SubagentStop`, `UserPromptSubmit`, `Stop`, or `Interrupt`.",

561 },598 },

562 {599 {

563 key: "hooks.<Event>[].hooks",600 key: "hooks.<Event>[].hooks",


688 key: "mcp_servers.<id>.required",725 key: "mcp_servers.<id>.required",

689 type: "boolean",726 type: "boolean",

690 description:727 description:

691 "When true, fail startup/resume if this enabled MCP server cannot initialize.",728 'Require this enabled server to be ready at startup. With `startup_readiness = "catalog"`, a valid cached catalog can satisfy that requirement.',

729 },

730 {

731 key: "mcp_servers.<id>.startup_readiness",

732 type: "connection | catalog",

733 description:

734 "Use a live connection to establish startup readiness (`connection`, the default), or let a valid cached tool catalog satisfy startup while the connection opens (`catalog`). Calling a tool still requires a live connection.",

692 },735 },

693 {736 {

694 key: "mcp_servers.<id>.startup_timeout_sec",737 key: "mcp_servers.<id>.startup_timeout_sec",


718 description:761 description:

719 "Deny list applied after `enabled_tools` for the MCP server.",762 "Deny list applied after `enabled_tools` for the MCP server.",

720 },763 },

764 {

765 key: "mcp_servers.<id>.supports_parallel_tool_calls",

766 type: "boolean",

767 description:

768 "Mark every tool on this server as safe to run in parallel. Enable only when the server can handle concurrent calls to all its tools. Defaults to `false`.",

769 },

770 {

771 key: "mcp_servers.<id>.tool_input_schema_max_bytes",

772 type: "integer (positive)",

773 description:

774 "Compact each ordinary MCP tool's input schema when it exceeds this many UTF-8 bytes. The default is 5,000 bytes. Code Mode also uses an explicit value when rendering tool input types.",

775 },

776 {

777 key: "mcp_servers.<id>.omit_tools_from",

778 type: "array<string>",

779 description:

780 "Omit this server’s tools from selected model-facing surfaces. Choose `direct` (initial tools), `deferred` (tool search), or `code_mode` (Code Mode scripts). Use `disabled_tools` to block a tool. An empty list clears inherited omissions.",

781 },

721 {782 {

722 key: "mcp_servers.<id>.default_tools_approval_mode",783 key: "mcp_servers.<id>.default_tools_approval_mode",

723 type: "auto | prompt | writes | approve",784 type: "auto | prompt | writes | approve",


740 key: "mcp_servers.<id>.scopes",801 key: "mcp_servers.<id>.scopes",

741 type: "array<string>",802 type: "array<string>",

742 description:803 description:

743 "OAuth scopes to request when authenticating to that MCP server.",804 "OAuth scopes to request at login. If omitted, Codex uses the initial authentication challenge's scopes, falling back to the protected resource's metadata.",

744 },805 },

745 {806 {

746 key: "mcp_servers.<id>.oauth_resource",807 key: "mcp_servers.<id>.oauth_resource",


749 "Optional RFC 8707 OAuth resource parameter to include during MCP login.",810 "Optional RFC 8707 OAuth resource parameter to include during MCP login.",

750 },811 },

751 {812 {

752 key: "mcp_servers.<id>.experimental_environment",813 key: "mcp_servers.<id>.environment_id",

753 type: "local | remote",814 type: "string",

754 description:815 description:

755 "Experimental placement for an MCP server. `remote` starts stdio servers through a remote executor environment; streamable HTTP remote placement is not implemented.",816 "Execution environment for the MCP server. Defaults to `local`. Use the ID of a configured executor to run a stdio server or connect to a streamable HTTP server there.",

756 },817 },

757 {818 {

758 key: "agents",819 key: "agents",


807 description:868 description:

808 "Path to a TOML config layer for that role; relative paths resolve from the config file that declares the role.",869 "Path to a TOML config layer for that role; relative paths resolve from the config file that declares the role.",

809 },870 },

871 {

872 key: "memories.version",

873 type: "v1 | v2",

874 description:

875 "Select the local memory store. With memories enabled, Codex defaults to `v2` for a fresh home and `v1` if `$CODEX_HOME/memories/` exists. Explicitly setting `dual_write = false` keeps the default at `v1`.",

876 },

877 {

878 key: "memories.dual_write",

879 type: "boolean",

880 description:

881 "With `v1` selected, set to `true` to generate both stores while continuing to read `v1`. With `v2` selected, Codex writes only `v2`.",

882 },

810 {883 {

811 key: "memories.generate_memories",884 key: "memories.generate_memories",

812 type: "boolean",885 type: "boolean",


871 type: "string",944 type: "string",

872 description: "Optional model override for global memory consolidation.",945 description: "Optional model override for global memory consolidation.",

873 },946 },

947 {

948 key: "memories.consolidation_service_tier",

949 type: "string",

950 description:

951 "Service tier for global memory consolidation. Defaults to `default` (Standard).",

952 },

874 {953 {

875 key: "features.prefer_mxc",954 key: "features.prefer_mxc",

876 type: "boolean",955 type: "boolean",


883 description:962 description:

884 "Use resumable command execution (stable; enabled on all platforms). User opt-outs are ignored. Managed requirements can disable resumable processes and `write_stdin`, leaving one-shot `exec_command` available.",963 "Use resumable command execution (stable; enabled on all platforms). User opt-outs are ignored. Managed requirements can disable resumable processes and `write_stdin`, leaving one-shot `exec_command` available.",

885 },964 },

965 {

966 key: "features.view_image",

967 type: "boolean",

968 description:

969 "Enable the built-in `view_image` tool for opening local images. Defaults to `true`.",

970 },

886 {971 {

887 key: "features.shell_snapshot",972 key: "features.shell_snapshot",

888 type: "boolean",973 type: "boolean",


901 description:986 description:

902 "Enable persisted goals and automatic continuation (stable; on by default).",987 "Enable persisted goals and automatic continuation (stable; on by default).",

903 },988 },

989 {

990 key: "goals.max_goal_token_budget",

991 type: "integer (positive)",

992 description:

993 "Set the default token budget for new goals and the largest budget a goal can request. Omit to leave goals without a configured limit.",

994 },

904 {995 {

905 key: "features.remote_plugin",996 key: "features.remote_plugin",

906 type: "boolean",997 type: "boolean",


916 key: "features.network_proxy",1007 key: "features.network_proxy",

917 type: "boolean | table",1008 type: "boolean | table",

918 description:1009 description:

919 "Start the network proxy for sandboxed commands (experimental; off by default). Required to enforce permission-profile domain rules unless enabled administrator-managed `experimental_network` requirements start the proxy. Use a table when setting feature-level policy options such as `domains`. Does not filter web search, apps, MCP, or other hosted tools.",1010 "Start the network proxy for sandboxed commands (experimental; off by default). Required to enforce permission-profile domain rules unless enabled administrator-managed `network_proxy` requirements start the proxy. Use a table when setting feature-level policy options such as `domains`. Does not filter web search, apps, MCP, or other hosted tools.",

920 },1011 },

921 {1012 {

922 key: "features.network_proxy.enabled",1013 key: "features.network_proxy.enabled",


1182 type: "string (path)",1273 type: "string (path)",

1183 description: "Working directory for the token command.",1274 description: "Working directory for the token command.",

1184 },1275 },

1276 {

1277 key: "model_providers.gcp.base_url",

1278 type: "string",

1279 description:

1280 "Override the built-in Google Cloud Vertex AI endpoint. Otherwise, Codex builds it from the project ID and location.",

1281 },

1282 {

1283 key: "model_providers.gcp.project_id",

1284 type: "string",

1285 description:

1286 "Google Cloud project ID for the Vertex AI endpoint. Takes precedence over `GOOGLE_CLOUD_PROJECT`.",

1287 },

1288 {

1289 key: "model_providers.gcp.location",

1290 type: "string",

1291 description:

1292 "Google Cloud location for the Vertex AI endpoint. Takes precedence over `GOOGLE_CLOUD_LOCATION`. Defaults to `global`.",

1293 },

1294 {

1295 key: "model_providers.gcp.credential_file",

1296 type: "string (absolute path)",

1297 description:

1298 "Path to a Google Application Default Credentials (ADC) file. Overrides `GOOGLE_APPLICATION_CREDENTIALS` only for the provider\u2019s authentication command.",

1299 },

1185 {1300 {

1186 key: "model_providers.amazon-bedrock.aws.profile",1301 key: "model_providers.amazon-bedrock.aws.profile",

1187 type: "string",1302 type: "string",


1217 description:1332 description:

1218 "Optional GPT-5 Responses API verbosity override; when unset, the selected model/preset default is used.",1333 "Optional GPT-5 Responses API verbosity override; when unset, the selected model/preset default is used.",

1219 },1334 },

1220 {

1221 key: "model_supports_reasoning_summaries",

1222 type: "boolean",

1223 description: "Force Codex to send or not send reasoning metadata.",

1224 },

1225 {1335 {

1226 key: "shell_environment_policy.inherit",1336 key: "shell_environment_policy.inherit",

1227 type: "all | core | none",1337 type: "all | core | none",


1292 description:1402 description:

1293 "Token budget for storing individual tool/function outputs in history.",1403 "Token budget for storing individual tool/function outputs in history.",

1294 },1404 },

1405 {

1406 key: "thread_unload_delay_secs",

1407 type: "integer (nonnegative)",

1408 description:

1409 "Seconds the app server waits before unloading an inactive thread with no subscribers. Set to `0` to unload it as soon as it meets both conditions. Defaults to `60` seconds.",

1410 },

1295 {1411 {

1296 key: "background_terminal_max_timeout",1412 key: "background_terminal_max_timeout",

1297 type: "number",1413 type: "number",


1332 key: "otel.metrics_exporter",1448 key: "otel.metrics_exporter",

1333 type: "none | statsig | otlp-http | otlp-grpc",1449 type: "none | statsig | otlp-http | otlp-grpc",

1334 description:1450 description:

1335 "Select the OpenTelemetry metrics exporter (defaults to `statsig`). In Codex CLI, `analytics.enabled = false` disables this exporter, including custom OTLP exporters. Set to `none` to disable metrics export independently.",1451 "Select the OpenTelemetry metrics exporter. The default, `statsig`, follows `analytics.enabled`. Explicit OTLP exporters work independently of that setting. Set to `none` to disable metrics export.",

1336 },1452 },

1337 {1453 {

1338 key: "otel.log_user_prompt",1454 key: "otel.log_user_prompt",


1340 description:1456 description:

1341 "Opt in to exporting raw user prompts with OpenTelemetry logs.",1457 "Opt in to exporting raw user prompts with OpenTelemetry logs.",

1342 },1458 },

1459 {

1460 key: "otel.log_agent_responses",

1461 type: "boolean",

1462 description:

1463 "Export final response text from the main agent and spawned subagents to the configured OTLP log exporter. Defaults to `false`. Response text can contain sensitive data and is capped at 64 KiB per response.",

1464 },

1465 {

1466 key: "otel.log_guardian_assessments",

1467 type: "boolean",

1468 description:

1469 "Export completed automatic approval reviews to the configured OTLP log exporter. Defaults to `false`. Review rationales can contain sensitive data and are capped at 64 KiB each.",

1470 },

1471 {

1472 key: "otel.span_attributes",

1473 type: "map<string,string>",

1474 description: "Add string attributes to every exported trace span.",

1475 },

1476 {

1477 key: "otel.tracestate",

1478 type: "map<string,map<string,string>>",

1479 description:

1480 "Set fields on W3C tracestate members when propagating trace context. Each member maps field names to string values.",

1481 },

1482 {

1483 key: "otel.tool_result.max_bytes",

1484 type: "integer (nonnegative)",

1485 description:

1486 "Maximum number of UTF-8 bytes from each tool result to include in logs, before the truncation notice. Defaults to `2048`. This setting affects only logged output.",

1487 },

1343 {1488 {

1344 key: "otel.exporter.<id>.endpoint",1489 key: "otel.exporter.<id>.endpoint",

1345 type: "string",1490 type: "string",


1572 description:1717 description:

1573 "Optional sparse checkout paths for a Git marketplace. Include the marketplace catalog and any local plugin directories it references.",1718 "Optional sparse checkout paths for a Git marketplace. Include the marketplace catalog and any local plugin directories it references.",

1574 },1719 },

1720 {

1721 key: "plugins._default.enabled",

1722 type: "boolean",

1723 description:

1724 "Set the default activation state for installed plugins. An explicit `plugins.<plugin>.enabled` overrides this default for plugins their source enables. Omit the table to keep the source or account activation settings.",

1725 },

1575 {1726 {

1576 key: "plugins.<plugin>.enabled",1727 key: "plugins.<plugin>.enabled",

1577 type: "boolean",1728 type: "boolean",


1608 description:1759 description:

1609 "Per-tool approval behavior override for a plugin-provided MCP tool.",1760 "Per-tool approval behavior override for a plugin-provided MCP tool.",

1610 },1761 },

1762 {

1763 key: "tui.presets.<digit>.input",

1764 type: "string",

1765 description:

1766 "Save a prompt or slash command in one of the ten slots (`0`–`9`) shown by `/presets`. Use up to 8,000 UTF-8 bytes of nonempty text. Shell commands beginning with `!` are unsupported.",

1767 },

1768 {

1769 key: "tui.presets.<digit>.label",

1770 type: "string",

1771 description:

1772 "Optional name for the preset in the picker and shortcut hints.",

1773 },

1611 {1774 {

1612 key: "tui.model_availability_nux.<model>",1775 key: "tui.model_availability_nux.<model>",

1613 type: "integer",1776 type: "integer",


1631 description:1794 description:

1632 "Legacy fallback for `tui.disable_paste_burst`. Prefer the setting under `[tui]`.",1795 "Legacy fallback for `tui.disable_paste_burst`. Prefer the setting under `[tui]`.",

1633 },1796 },

1634 {

1635 key: "windows_wsl_setup_acknowledged",

1636 type: "boolean",

1637 description: "Track Windows onboarding acknowledgement (Windows only).",

1638 },

1639 {1797 {

1640 key: "chatgpt_base_url",1798 key: "chatgpt_base_url",

1641 type: "string",1799 type: "string",


1675 description:1833 description:

1676 "Optional web search tool configuration. The object form can set search context size, allowed search domains, and approximate user location. These search-domain filters are separate from sandboxed-command network domain rules and do not restrict connectors or MCP servers.",1834 "Optional web search tool configuration. The object form can set search context size, allowed search domains, and approximate user location. These search-domain filters are separate from sandboxed-command network domain rules and do not restrict connectors or MCP servers.",

1677 },1835 },

1678 {

1679 key: "tools.view_image",

1680 type: "boolean",

1681 description: "Enable the local-image attachment tool `view_image`.",

1682 },

1683 {1836 {

1684 key: "web_search",1837 key: "web_search",

1685 type: "disabled | cached | indexed | live",1838 type: "disabled | cached | indexed | live",


1990 description:2143 description:

1991 "Enforce the directory where Codex stores SQLite-backed runtime state.",2144 "Enforce the directory where Codex stores SQLite-backed runtime state.",

1992 },2145 },

2146 {

2147 key: "unsafe_enforce_sqlite_journal_mode",

2148 type: "boolean",

2149 description:

2150 "On Linux, set to `true` to migrate existing SQLite databases on NFS from WAL to DELETE journaling before opening them for writes. Defaults to `false`. The mount must support POSIX locks across hosts. Keep every other SQLite client that uses the databases stopped on every host until migration succeeds. Replacements preserve file mode bits but belong to the user running the migration and do not copy the original owner, group, or extended ACLs.",

2151 },

1993 {2152 {

1994 key: "log_dir",2153 key: "log_dir",

1995 type: "string (path)",2154 type: "string (path)",


2010 type: "boolean",2169 type: "boolean",

2011 description: "Enforce whether shell tools can start a login shell.",2170 description: "Enforce whether shell tools can start a login shell.",

2012 },2171 },

2172 {

2173 key: "config_server",

2174 type: "table",

2175 description:

2176 "Enroll Codex with a configuration server through local managed requirements. Codex retrieves its policy bundle from this server. A cloud policy cannot configure its own server.",

2177 },

2178 {

2179 key: "config_server.base_url",

2180 type: "string",

2181 description:

2182 "Required HTTPS base URL. Codex appends `/codex/config/bundle`. Omit credentials, query parameters, and fragments from the base URL.",

2183 },

2184 {

2185 key: "config_server.oauth",

2186 type: "table",

2187 description:

2188 "OAuth settings for configuration server sign-in. Requires `authorization_url`, `token_url`, and a nonempty `client_id`. Optional fields are `device_authorization_url`, `resource`, `scopes` (defaults to an empty list), and `redirect_port` (nonzero). All endpoint URLs must use HTTPS.",

2189 },

2013 {2190 {

2014 key: "allowed_login_methods",2191 key: "allowed_login_methods",

2015 type: "array<string>",2192 type: "array<string>",


2197 description:2374 description:

2198 "Set to `false` to prohibit both explicit MXC selection and automatic selection through `features.prefer_mxc`. Omitting this requirement or setting it to `true` permits MXC but doesn't enable it or require it. Legacy implementation restrictions still apply to fallback.",2375 "Set to `false` to prohibit both explicit MXC selection and automatic selection through `features.prefer_mxc`. Omitting this requirement or setting it to `true` permits MXC but doesn't enable it or require it. Legacy implementation restrictions still apply to fallback.",

2199 },2376 },

2377 {

2378 key: "windows.require_mxc",

2379 type: "boolean",

2380 description:

2381 "On Windows, set to `true` to reject any effective sandbox implementation other than MXC. Select MXC separately. If Codex cannot use it, configuration fails instead of falling back to a legacy sandbox.",

2382 },

2200 {2383 {

2201 key: "remote_sandbox_config",2384 key: "remote_sandbox_config",

2202 type: "array<table>",2385 type: "array<table>",


2269 description:2452 description:

2270 "Pin Apps integration availability on or off for managed users.",2453 "Pin Apps integration availability on or off for managed users.",

2271 },2454 },

2455 {

2456 key: "features.api_key_cyber_access_programs",

2457 type: "boolean",

2458 description:

2459 "Allow Codex to send an explicitly selected cyber access program with requests to the built-in OpenAI provider when using API key authentication. The account and model must already have access to the program.",

2460 },

2272 {2461 {

2273 key: "features.in_app_updates",2462 key: "features.in_app_updates",

2274 type: "boolean",2463 type: "boolean",


2281 description:2470 description:

2282 "Set to `false` in `requirements.toml` to disable the built-in browser pane that users open and control directly.",2471 "Set to `false` in `requirements.toml` to disable the built-in browser pane that users open and control directly.",

2283 },2472 },

2473 {

2474 key: "features.browser_annotation_api",

2475 type: "boolean",

2476 description:

2477 "Set to `false` to block website-provided annotation customizations in the built-in browser. Users can still annotate pages themselves. Set to `true` to allow customizations when the app and account support them.",

2478 },

2284 {2479 {

2285 key: "features.in_app_chat",2480 key: "features.in_app_chat",

2286 type: "boolean",2481 type: "boolean",


2293 description:2488 description:

2294 "Set to `false` to disable in-app dictation in the desktop app. Setting it to `true` does not bypass other availability checks.",2489 "Set to `false` to disable in-app dictation in the desktop app. Setting it to `true` does not bypass other availability checks.",

2295 },2490 },

2491 {

2492 key: "features.in_app_voice",

2493 type: "boolean",

2494 description:

2495 "Set to `false` to disable real-time Codex voice in the desktop app. Use `features.in_app_dictation` to manage dictation separately.",

2496 },

2296 {2497 {

2297 key: "features.in_app_local_automation",2498 key: "features.in_app_local_automation",

2298 type: "boolean",2499 type: "boolean",


2321 key: "features.fast_mode",2522 key: "features.fast_mode",

2322 type: "boolean",2523 type: "boolean",

2323 description:2524 description:

2324 "Pin the canonical `fast_mode` feature on or off for managed users.",2525 "Allow or block Fast mode for managed users. Older app servers also use this setting to control Ultrafast mode.",

2526 },

2527 {

2528 key: "features.ultrafast_mode",

2529 type: "boolean",

2530 description:

2531 "Allow or block Ultrafast mode for managed users. On app servers that support independent speed settings, this applies even when Fast mode is disabled. Availability depends on the model and account.",

2532 },

2533 {

2534 key: "features.standalone_web_search",

2535 type: "boolean",

2536 description:

2537 "Experimental. Set to `true` to keep the desktop app's native web search configuration when hosted search through MCP would otherwise be available.",

2325 },2538 },

2326 {2539 {

2327 key: "features.guardian_approval",2540 key: "features.guardian_approval",


2385 type: "table",2598 type: "table",

2386 description: "Managed requirements for agent-driven Browser Use.",2599 description: "Managed requirements for agent-driven Browser Use.",

2387 },2600 },

2601 {

2602 key: "browser_use.extension",

2603 type: "table",

2604 description:

2605 "Managed settings for Browser Use in supported Chromium browser extensions.",

2606 },

2607 {

2608 key: "browser_use.extension.request_headers",

2609 type: "array<table>",

2610 description:

2611 "Add up to 16 HTTP headers to requests from agent-controlled tabs in supported Chromium extensions. Use an empty list to send no managed headers.",

2612 },

2613 {

2614 key: "browser_use.extension.request_headers[].name",

2615 type: "string",

2616 description:

2617 "Header name. Reserved names, including `Authorization` and `Cookie`, are prohibited. Names and values support `{{session_id}}` as their only substitution.",

2618 },

2619 {

2620 key: "browser_use.extension.request_headers[].value",

2621 type: "string",

2622 description: "Header value to send with matching browser requests.",

2623 },

2388 {2624 {

2389 key: "browser_use.allow_webmcp",2625 key: "browser_use.allow_webmcp",

2390 type: "boolean",2626 type: "boolean",

2391 description:2627 description:

2392 "Set to `true` to opt the desktop app's built-in browser into site tools (WebMCP). Setting it to `false` or omitting it leaves normal feature availability checks in place; `false` does not enforce a block. User preferences and site permissions still apply.",2628 "Allow site tools (WebMCP) through workspace policy on eligible managed plans. Both `true` and an unset value allow access through this policy. Setting `false` turns off this path. Users can still have access through their account rollout. Browser settings and site permissions apply.",

2393 },2629 },

2394 {2630 {

2395 key: "browser_use.allow_history_access",2631 key: "browser_use.allow_history_access",


2605 type: "table",2841 type: "table",

2606 description: "Managed desktop application requirements.",2842 description: "Managed desktop application requirements.",

2607 },2843 },

2844 {

2845 key: "application.storage",

2846 type: "table",

2847 description:

2848 "Pin storage locations for newly created work on desktop builds that support managed storage. Each path independently overrides the local preference. Storage settings do not restrict filesystem access.",

2849 },

2850 {

2851 key: "application.storage.default_project_parent",

2852 type: "string (absolute path)",

2853 description:

2854 "Parent directory for new local projects created with Start from scratch.",

2855 },

2856 {

2857 key: "application.storage.projectless_workspace_root",

2858 type: "string (absolute path)",

2859 description: "Root directory for new chats created without a project.",

2860 },

2608 {2861 {

2609 key: "application.network",2862 key: "application.network",

2610 type: "table",2863 type: "table",


2630 "Allow or deny an exact domain. Use domain names without URL schemes, ports, or wildcards.",2883 "Allow or deny an exact domain. Use domain names without URL schemes, ports, or wildcards.",

2631 },2884 },

2632 {2885 {

2633 key: "experimental_network",2886 key: "otel",

2887 type: "table",

2888 description:

2889 "Enforce the specified OpenTelemetry settings. Each exporter replaces the entire corresponding exporter definition. Span attributes and tracestate fields override only matching entries.",

2890 },

2891 {

2892 key: "otel.environment",

2893 type: "string",

2894 description: "Enforce the environment label on telemetry.",

2895 },

2896 {

2897 key: "otel.exporter",

2898 type: "none | otlp-http | otlp-grpc",

2899 description:

2900 "Enforce the log exporter, including its endpoint, headers, and TLS settings.",

2901 },

2902 {

2903 key: "otel.trace_exporter",

2904 type: "none | otlp-http | otlp-grpc",

2905 description:

2906 "Enforce the trace exporter, including its endpoint, headers, and TLS settings.",

2907 },

2908 {

2909 key: "otel.metrics_exporter",

2910 type: "none | statsig | otlp-http | otlp-grpc",

2911 description:

2912 "Enforce the metrics exporter. The Statsig exporter follows `analytics.enabled`. Explicit OTLP metrics exporters run independently of that setting.",

2913 },

2914 {

2915 key: "otel.log_user_prompt",

2916 type: "boolean",

2917 description: "Control whether exported logs include user prompt text.",

2918 },

2919 {

2920 key: "otel.log_agent_responses",

2921 type: "boolean",

2922 description:

2923 "Control whether OTLP logs include final response text from the main agent and spawned subagents.",

2924 },

2925 {

2926 key: "otel.log_guardian_assessments",

2927 type: "boolean",

2928 description:

2929 "Control whether OTLP logs include completed automatic approval assessments and their rationales.",

2930 },

2931 {

2932 key: "otel.tool_result",

2933 type: "table",

2934 description:

2935 "Enforce the tool-result log settings as a unit. An empty table enforces the default byte limit.",

2936 },

2937 {

2938 key: "otel.tool_result.max_bytes",

2939 type: "integer (nonnegative)",

2940 description:

2941 "Maximum UTF-8 bytes of tool-result text before the truncation notice in logs. Defaults to `2048` when the managed table is present.",

2942 },

2943 {

2944 key: "otel.span_attributes",

2945 type: "map<string,string>",

2946 description:

2947 "Enforce individual string attributes on exported spans. Higher-priority requirements win for the same attribute.",

2948 },

2949 {

2950 key: "otel.tracestate",

2951 type: "map<string,map<string,string>>",

2952 description:

2953 "Enforce individual fields within W3C tracestate members. Higher-priority requirements win for the same member and field.",

2954 },

2955 {

2956 key: "network_proxy",

2634 type: "table",2957 type: "table",

2635 description:2958 description:

2636 "Administrator-managed network requirements for sandboxed local commands, enforced from `requirements.toml`. When enabled, these requirements can start the command network proxy without `features.network_proxy`. Browser tools separately check managed network denies and exclusive allowlists. These requirements do not route browser traffic through the proxy or control web search, apps, MCP servers, native-app traffic, or other capability-specific traffic. On supported managed Codex Cloud paths, these requirements constrain command networking alongside separate Cloud environment internet settings. Approved full sandbox escalation can bypass the command proxy where policy permits it. Work Cloud does not inherit these requirements.",2959 "Administrator-managed network requirements for sandboxed local commands. Codex 0.166.0 accepts `[network_proxy]` and its alias `[experimental_network]`. Use one name per requirements layer. Keep the alias in published policies until every client and policy validator supports the new name. When enabled, these requirements can start the command network proxy without `features.network_proxy`. Browser tools separately check managed network denies and exclusive allowlists. These requirements do not route browser traffic through the proxy or control web search, apps, MCP servers, native-app traffic, or other capability-specific traffic. On supported managed Codex Cloud paths, these requirements constrain command networking alongside separate Cloud environment internet settings. Approved full sandbox escalation can bypass the command proxy where policy permits it. Work Cloud does not inherit these requirements.",

2637 },2960 },

2638 {2961 {

2639 key: "experimental_network.enabled",2962 key: "network_proxy.enabled",

2640 type: "boolean",2963 type: "boolean",

2641 description:2964 description:

2642 "Enable sandboxed networking requirements. This does not grant network access when the active sandbox keeps command networking off.",2965 "Enable sandboxed networking requirements. This does not grant network access when the active sandbox keeps command networking off.",

2643 },2966 },

2644 {2967 {

2645 key: "experimental_network.http_port",2968 key: "network_proxy.http_port",

2646 type: "integer",2969 type: "integer",

2647 description:2970 description:

2648 "Loopback HTTP listener port to use for `[experimental_network]` requirements.",2971 "Loopback HTTP listener port to use for `[network_proxy]` requirements.",

2649 },2972 },

2650 {2973 {

2651 key: "experimental_network.socks_port",2974 key: "network_proxy.socks_port",

2652 type: "integer",2975 type: "integer",

2653 description:2976 description:

2654 "Loopback SOCKS5 listener port to use for `[experimental_network]` requirements.",2977 "Loopback SOCKS5 listener port to use for `[network_proxy]` requirements.",

2655 },2978 },

2656 {2979 {

2657 key: "experimental_network.allow_upstream_proxy",2980 key: "network_proxy.allow_upstream_proxy",

2658 type: "boolean",2981 type: "boolean",

2659 description:2982 description:

2660 "Allow sandboxed networking to chain through an upstream proxy from the environment.",2983 "Allow sandboxed networking to chain through an upstream proxy from the environment.",

2661 },2984 },

2662 {2985 {

2663 key: "experimental_network.dangerously_allow_non_loopback_proxy",2986 key: "network_proxy.dangerously_allow_non_loopback_proxy",

2664 type: "boolean",2987 type: "boolean",

2665 description:2988 description:

2666 "Permit non-loopback listener addresses for `[experimental_network]` requirements. Enabling it can expose listeners beyond localhost.",2989 "Permit non-loopback listener addresses for `[network_proxy]` requirements. Enabling it can expose listeners beyond localhost.",

2667 },2990 },

2668 {2991 {

2669 key: "experimental_network.dangerously_allow_all_unix_sockets",2992 key: "network_proxy.dangerously_allow_all_unix_sockets",

2670 type: "boolean",2993 type: "boolean",

2671 description:2994 description:

2672 "Permit arbitrary Unix socket destinations instead of allowlist-only access. Use only in tightly controlled environments.",2995 "Permit arbitrary Unix socket destinations instead of allowlist-only access. Use only in tightly controlled environments.",

2673 },2996 },

2674 {2997 {

2675 key: "experimental_network.domains",2998 key: "network_proxy.domains",

2676 type: "map<string, allow | deny>",2999 type: "map<string, allow | deny>",

2677 description:3000 description:

2678 "Map-shaped administrator domain policy for sandboxed networking. Supports exact hosts, `*.example.com` for subdomains only, `**.example.com` for apex plus subdomains, and global `*` allow rules. Prefer scoped rules because `*` broadly opens public outbound access. Environment rules can replace the same Global domain key within a policy. Higher-priority values replace the same key, while other inherited keys remain. After composition, a different matching `deny`, including an inherited wildcard, still blocks a request. Empty environment maps do not clear Global rules. Verify executor support. Do not combine this with `experimental_network.allowed_domains` or `experimental_network.denied_domains`.",3001 "Map-shaped administrator domain policy for sandboxed networking. Supports exact hosts, `*.example.com` for subdomains only, `**.example.com` for apex plus subdomains, and global `*` allow rules. Prefer scoped rules because `*` broadly opens public outbound access. Environment rules can replace the same Global domain key within a policy. Higher-priority values replace the same key, while other inherited keys remain. After composition, a different matching `deny`, including an inherited wildcard, still blocks a request. Empty environment maps do not clear Global rules. Verify executor support. Do not combine this with `network_proxy.allowed_domains` or `network_proxy.denied_domains`.",

2679 },3002 },

2680 {3003 {

2681 key: "experimental_network.domains.<pattern>",3004 key: "network_proxy.domains.<pattern>",

2682 type: "allow | deny",3005 type: "allow | deny",

2683 description:3006 description:

2684 "Allow or deny sandboxed network access for the matching domain pattern. A deny rule wins when several patterns match.",3007 "Allow or deny sandboxed network access for the matching domain pattern. A deny rule wins when several patterns match.",

2685 },3008 },

2686 {3009 {

2687 key: "experimental_network.allowed_domains",3010 key: "network_proxy.review_domains",

3011 type: "array<string>",

3012 description:

3013 "Route matching hosts through network approval even if an allow rule matches. An explicit deny takes precedence. Approved requests still undergo DNS and private-address checks. Defaults to an empty list.",

3014 },

3015 {

3016 key: "network_proxy.allowed_domains",

2688 type: "array<string>",3017 type: "array<string>",

2689 description:3018 description:

2690 "Administrator allow rules for sandboxed-command networking while the managed network proxy is enabled. These rules do not apply to web search, apps, or MCP servers. Do not combine this with `experimental_network.domains`.",3019 "Administrator allow rules for sandboxed-command networking while the managed network proxy is enabled. These rules do not apply to web search, apps, or MCP servers. Do not combine this with `network_proxy.domains`.",

2691 },3020 },

2692 {3021 {

2693 key: "experimental_network.denied_domains",3022 key: "network_proxy.denied_domains",

2694 type: "array<string>",3023 type: "array<string>",

2695 description:3024 description:

2696 "List-shaped administrator deny rules for sandboxed networking. Do not combine this with `experimental_network.domains`.",3025 "List-shaped administrator deny rules for sandboxed networking. Do not combine this with `network_proxy.domains`.",

2697 },3026 },

2698 {3027 {

2699 key: "experimental_network.managed_allowed_domains_only",3028 key: "network_proxy.managed_allowed_domains_only",

2700 type: "boolean",3029 type: "boolean",

2701 description:3030 description:

2702 "When networking requirements are enabled and this is true, ordinary user configuration and per-domain approvals cannot expand the managed proxy allowlist. With no effective configured or inherited Allow entries, ordinary managed commands have no allowed destinations. A deny-only policy does not allow the rest of the internet. This does not cover every tool or approved full sandbox escalation.",3031 "When networking requirements are enabled and this is true, ordinary user configuration and per-domain approvals cannot expand the managed proxy allowlist. With no effective configured or inherited Allow entries, ordinary managed commands have no allowed destinations. A deny-only policy does not allow the rest of the internet. This does not cover every tool or approved full sandbox escalation.",

2703 },3032 },

2704 {3033 {

2705 key: "experimental_network.unix_sockets",3034 key: "network_proxy.unix_sockets",

2706 type: "map<string, allow | deny>",3035 type: "map<string, allow | deny>",

2707 description:3036 description:

2708 "Administrator-managed Unix socket allowlist for sandboxed networking on macOS. Paths must be absolute.",3037 "Administrator-managed Unix socket allowlist for sandboxed networking on macOS. Paths must be absolute.",

2709 },3038 },

2710 {3039 {

2711 key: "experimental_network.unix_sockets.<path>",3040 key: "network_proxy.unix_sockets.<path>",

2712 type: "allow | deny",3041 type: "allow | deny",

2713 description:3042 description:

2714 "On macOS, `allow` adds an absolute Unix socket path to the allowlist; `deny` leaves it out. A `deny` entry cannot block a socket when allow-all Unix sockets is enabled.",3043 "On macOS, `allow` adds an absolute Unix socket path to the allowlist; `deny` leaves it out. A `deny` entry cannot block a socket when allow-all Unix sockets is enabled.",

2715 },3044 },

2716 {3045 {

2717 key: "experimental_network.allow_local_binding",3046 key: "network_proxy.allow_local_binding",

2718 type: "boolean",3047 type: "boolean",

2719 description:3048 description:

2720 "Permit broader local/private-network access for sandboxed networking. On the supported Codex Cloud proxy path, an explicit false can prevent upstream-proxy access even if a domain is allowed. It defaults to true only if no applicable requirement, selected network profile, or proxy feature setting provides a value. Inherited false remains explicit. A supported higher-priority Cloud override can change it without broadening Global for Local or adding domain Allow entries. Verify executor support. Do not apply this Cloud default to Local.",3049 "Permit broader local/private-network access for sandboxed networking. On the supported Codex Cloud proxy path, an explicit false can prevent upstream-proxy access even if a domain is allowed. It defaults to true only if no applicable requirement, selected network profile, or proxy feature setting provides a value. Inherited false remains explicit. A supported higher-priority Cloud override can change it without broadening Global for Local or adding domain Allow entries. Verify executor support. Do not apply this Cloud default to Local.",


2741 key: "hooks.<Event>",3070 key: "hooks.<Event>",

2742 type: "array<table>",3071 type: "array<table>",

2743 description:3072 description:

2744 "Matcher groups for a hook event such as `PreToolUse`, `PermissionRequest`, `PostToolUse`, `PreCompact`, `PostCompact`, `SessionStart`, `SessionEnd`, `SubagentStart`, `SubagentStop`, `UserPromptSubmit`, or `Stop`.",3073 "Matcher groups for a hook event such as `PreModelRequest`, `PostModelRequest`, `PreToolUse`, `PermissionRequest`, `PostToolUse`, `PreCompact`, `PostCompact`, `SessionStart`, `SessionEnd`, `SubagentStart`, `SubagentStop`, `UserPromptSubmit`, or `Stop`.",

2745 },3074 },

2746 {3075 {

2747 key: "hooks.<Event>[].hooks",3076 key: "hooks.<Event>[].hooks",

Details

67 67 

68# service_tier = "fast"68# service_tier = "fast"

69 69 

70# For Google Cloud Vertex AI, set model_provider = "gcp" above and configure

71 

72# the project under [model_providers.gcp] below or set GOOGLE_CLOUD_PROJECT.

73 

70# Optional manual model metadata. When unset, Codex uses model or preset defaults.74# Optional manual model metadata. When unset, Codex uses model or preset defaults.

71 75 

72# model_context_window = 128000 # tokens; default: auto for model76# model_context_window = 128000 # tokens; default: auto for model


75 79 

76# model_auto_compact_token_limit_scope = "total" # total | body_after_prefix; default: total80# model_auto_compact_token_limit_scope = "total" # total | body_after_prefix; default: total

77 81 

82# Compact after a final response at 80% of the usable context window.

83 

84# Leave unset or set to 0 to disable turn-end compaction.

85 

86# model_post_turn_compact_threshold_percent = 80

87 

78# tool_output_token_limit = 12000 # tokens stored per tool output88# tool_output_token_limit = 12000 # tokens stored per tool output

79 89 

80# model_catalog_json = "/absolute/path/to/models.json" # optional startup-only model catalog override90# model_catalog_json = "/absolute/path/to/models.json" # optional startup-only model catalog override

81 91 

82# background_terminal_max_timeout = 300000 # ms; max empty write_stdin poll window (default 5m)92# background_terminal_max_timeout = 300000 # ms; max empty write_stdin poll window (default 5m)

83 93 

94# Unload a thread after five minutes with no activity or subscribers (default: 60 seconds).

95 

96# thread_unload_delay_secs = 300

97 

84# log_dir = "/absolute/path/to/codex-logs" # log directory; setting explicitly enables codex-tui.log; default: "$CODEX_HOME/log"98# log_dir = "/absolute/path/to/codex-logs" # log directory; setting explicitly enables codex-tui.log; default: "$CODEX_HOME/log"

85 99 

86# sqlite_home = "/absolute/path/to/codex-state" # optional SQLite-backed runtime state directory100# sqlite_home = "/absolute/path/to/codex-state" # optional SQLite-backed runtime state directory


107 121 

108# model_verbosity = "medium"122# model_verbosity = "medium"

109 123 

110# Force enable or disable reasoning summaries for current model.

111 

112# model_supports_reasoning_summaries = true

113 

114################################################################################124################################################################################

115 125 

116# Instruction Overrides126# Instruction Overrides


185 195 

186allow_login_shell = true196allow_login_shell = true

187 197 

198# macOS only. Set in the execution host's $CODEX_HOME/config.toml, then restart Codex.

199 

200# If true, already writable roots under CODEX_HOME can follow symlinks, including

201 

202# targets outside CODEX_HOME or targets that change between commands.

203 

204# allow_symlinked_codex_home = false

205 

188# Filesystem/network sandbox policy for tool calls:206# Filesystem/network sandbox policy for tool calls:

189 207 

190# - read-only (default)208# - read-only (default)


315 333 

316show_raw_agent_reasoning = false334show_raw_agent_reasoning = false

317 335 

318# Track Windows onboarding acknowledgement (Windows only). Default: false

319 

320windows_wsl_setup_acknowledged = false

321 

322# Check for updates on startup. Default: true336# Check for updates on startup. Default: true

323 337 

324check_for_update_on_startup = true338check_for_update_on_startup = true


377 391 

378# interrupt_message = true392# interrupt_message = true

379 393 

394# Default budget for new goals and maximum allowed goal budget.

395 

396# [goals]

397 

398# max_goal_token_budget = 100000

399 

380# [agents.reviewer]400# [agents.reviewer]

381 401 

382# description = "Find correctness, security, and test risks in code."402# description = "Find correctness, security, and test risks in code."


397 417 

398# max_context_tokens = 2000418# max_context_tokens = 2000

399 419 

400# Disable or re-enable a specific skill without deleting it.420# include_instructions = true

421 

422# [skills.bundled]

423 

424# enabled = false

425 

426# Disable every skill with this name. To match one file, use path instead.

401 427 

402[[skills.config]]428# [[skills.config]]

403 429 

404# path = "/path/to/skill/SKILL.md"430# name = "review-changes"

431 

432# Alternative selector: path = "/path/to/skill/SKILL.md"

405 433 

406# enabled = false434# enabled = false

407 435 


673 701 

674# theme = "catppuccin-mocha"702# theme = "catppuccin-mocha"

675 703 

704# Save a reusable prompt or slash command in slot 1 of /presets.

705 

706# [tui.presets.1]

707 

708# label = "Review changes"

709 

710# input = "/review"

711 

676# Custom key bindings. Selected composer actions fall back to matching [tui.keymap.global] bindings.712# Custom key bindings. Selected composer actions fall back to matching [tui.keymap.global] bindings.

677 713 

678# Use [] to unbind an action.714# Use [] to unbind an action.


701 737 

702# Enable or disable analytics. When unset, the client default applies.738# Enable or disable analytics. When unset, the client default applies.

703 739 

704# In Codex CLI, false also disables custom OTLP metrics exporters.740# Setting this to false disables built-in Statsig metrics. Custom OTLP exporters remain active.

705 741 

706[analytics]742[analytics]

707enabled = true743enabled = true


737 773 

738# Leave this table empty to accept defaults. Set explicit booleans to opt in/out.774# Leave this table empty to accept defaults. Set explicit booleans to opt in/out.

739 775 

776# view_image = false # disable the built-in local image viewer (enabled by default)

777 

740# Prefer MXC on Windows when the device and policy support it; otherwise use the legacy sandbox below.778# Prefer MXC on Windows when the device and policy support it; otherwise use the legacy sandbox below.

741 779 

742# Disabled by default in the standalone CLI.780# Disabled by default in the standalone CLI.


781 819 

782# Rollout budget tracking. This feature is under development and off by default.820# Rollout budget tracking. This feature is under development and off by default.

783 821 

784# limit_tokens is required when enabled.822# Set limit_tokens and reminder_at_remaining_tokens when enabled.

785 

786# Optional reminder_interval_tokens defaults to 10% of limit_tokens.

787 823 

788# Token weights default to 1.0.824# Token weights default to 1.0.

789 825 


793 829 

794# limit_tokens = 100000830# limit_tokens = 100000

795 831 

796# reminder_interval_tokens = 10000832# reminder_at_remaining_tokens = [50000, 25000, 10000]

797 833 

798# sampling_token_weight = 1.0834# sampling_token_weight = 1.0

799 835 


809 845 

810# [memories]846# [memories]

811 847 

848# version = "v1" # keep reading the original store during migration

849 

850# dual_write = true # generate both stores while reading v1

851 

852# consolidation_service_tier = "default" # Standard tier for memory consolidation

853 

812# generate_memories = true854# generate_memories = true

813 855 

814# use_memories = true856# use_memories = true


853 895 

854# enabled = true # optional; default true896# enabled = true # optional; default true

855 897 

856# required = true # optional; fail startup/resume if this server cannot initialize898# required = true # require this server to be ready at startup

857 899 

858# command = "docs-server" # required900# command = "docs-server" # required

859 901 


867 909 

868# cwd = "/path/to/server" # optional working directory override910# cwd = "/path/to/server" # optional working directory override

869 911 

870# experimental_environment = "remote" # experimental: run stdio via a remote executor912# environment_id = "devbox" # ID of a configured executor. Defaults to "local".

871 913 

872# startup_timeout_sec = 10.0 # optional; default 10.0 seconds914# startup_timeout_sec = 10.0 # optional; default 10.0 seconds

873 915 


875 917 

876# tool_timeout_sec = 60.0 # optional; default 60.0 seconds918# tool_timeout_sec = 60.0 # optional; default 60.0 seconds

877 919 

920# supports_parallel_tool_calls = true # only if all tools are safe to call concurrently

921 

878# enabled_tools = ["search", "summarize"] # optional allow-list922# enabled_tools = ["search", "summarize"] # optional allow-list

879 923 

880# disabled_tools = ["slow-tool"] # optional deny-list (applied after allow-list)924# disabled_tools = ["slow-tool"] # optional deny-list (applied after allow-list)

881 925 

882# scopes = ["read:docs"] # optional OAuth scopes926# startup_readiness = "catalog" # use a valid cached tool catalog while connecting

883 927 

884# oauth_resource = "https://docs.example.com/" # optional OAuth resource928# tool_input_schema_max_bytes = 8000 # default 5000 UTF-8 bytes

929 

930# omit_tools_from = ["direct"] # omit from the initial tool list

885 931 

886# [mcp_servers.docs.tools.search]932# [mcp_servers.docs.tools.search]

887 933 


893 939 

894# enabled = true # optional; default true940# enabled = true # optional; default true

895 941 

896# required = true # optional; fail startup/resume if this server cannot initialize942# required = true # require this server to be ready at startup

897 943 

898# url = "https://github-mcp.example.com/mcp" # required944# url = "https://github-mcp.example.com/mcp" # required

899 945 


913 959 

914# disabled_tools = ["delete_issue"] # optional deny-list960# disabled_tools = ["delete_issue"] # optional deny-list

915 961 

916# scopes = ["repo"] # optional OAuth scopes962# scopes = ["repo"] # override scopes discovered from the server

963 

964# oauth_resource = "https://github-mcp.example.com/"

917 965 

918# [mcp_servers.github.oauth]966# [mcp_servers.github.oauth]

919 967 


941 989 

942# - lmstudio990# - lmstudio

943 991 

944# - amazon-bedrock992# - amazon-bedrock and amazon-bedrock-runtime

993 

994# - gcp (Google Cloud Vertex AI)

945 995 

946# These IDs are reserved. Use a different ID for custom providers.996# These IDs are reserved. Use a different ID for custom providers.

947 997 

948[model_providers]998[model_providers]

949 999 

1000# Built-in Vertex AI provider options. The file path applies only to its auth command.

1001 

1002# [model_providers.gcp]

1003 

1004# project_id = "my-project"

1005 

1006# location = "global"

1007 

1008# credential_file = "/absolute/path/to/adc.json"

1009 

950# --- Example: built-in Amazon Bedrock provider options ---1010# --- Example: built-in Amazon Bedrock provider options ---

951 1011 

952# model_provider = "amazon-bedrock"1012# model_provider = "amazon-bedrock"


1055 1115 

1056################################################################################1116################################################################################

1057 1117 

1118# Keep installed plugins inactive by default, with an exception for one

1119 

1120# plugin that its marketplace or account already enables.

1121 

1122# [plugins._default]

1123 

1124# enabled = false

1125 

1126# [plugins."review@team"]

1127 

1128# enabled = true

1129 

1058# Optional per-app controls.1130# Optional per-app controls.

1059 1131 

1060[apps]1132[apps]


1155 1227 

1156# experimental_compact_prompt_file = "./compact_prompt.txt"1228# experimental_compact_prompt_file = "./compact_prompt.txt"

1157 1229 

1158# tools_view_image = true

1159 

1160# features = { shell_snapshot = false }1230# features = { shell_snapshot = false }

1161 1231 

1162################################################################################1232################################################################################


1175 1245 

1176################################################################################1246################################################################################

1177 1247 

1178# Tools1248# OpenTelemetry (OTEL)

1179 1249 

1180################################################################################1250################################################################################

1181 1251 

1182[tools]1252[otel]

1183 1253 

1184# view_image = true1254# Each option sends potentially sensitive text to the configured OTLP log exporter.

1185 1255 

1186################################################################################1256# log_agent_responses = false

1187 1257 

1188# OpenTelemetry (OTEL)1258# log_guardian_assessments = false

1189 1259 

1190################################################################################1260# Byte limit for logged tool results. Model-visible output has a separate limit.

1191 1261 

1192[otel]1262# tool_result.max_bytes = 2048

1263 

1264# span_attributes = { team = "platform" }

1265 

1266# tracestate = { acme = { region = "eu" } }

1193 1267 

1194# Include user prompt text in logs. Default: false1268# Include user prompt text in logs. Default: false

1195 1269 


1209 1283 

1210# Metrics exporter: none | statsig | otlp-http | otlp-grpc1284# Metrics exporter: none | statsig | otlp-http | otlp-grpc

1211 1285 

1212# Default: statsig. In Codex CLI, analytics.enabled = false disables all metrics exporters.1286# The default Statsig exporter follows analytics.enabled. Custom OTLP exporters run independently.

1213 1287 

1214# Set to none to disable metrics export.1288# Set to none to disable metrics export.

1215 1289 

Details

19 19 

20For more about the files stored under `CODEX_HOME`, see20For more about the files stored under `CODEX_HOME`, see

21[Config and state locations](https://learn.chatgpt.com/docs/config-file/config-advanced#config-and-state-locations).21[Config and state locations](https://learn.chatgpt.com/docs/config-file/config-advanced#config-and-state-locations).

22If multiple Linux hosts open the same databases, see [Run Codex with an NFS home directory](https://learn.chatgpt.com/docs/environments/network-file-systems).

22 23 

23## Installer variables24## Installer variables

24 25 

config-reference.md +384 −55

Details

139 description:139 description:

140 "Controls whether the auto-compaction threshold counts the full active context (`total`, the default) or only growth after the carried compaction-window prefix (`body_after_prefix`).",140 "Controls whether the auto-compaction threshold counts the full active context (`total`, the default) or only growth after the carried compaction-window prefix (`body_after_prefix`).",

141 },141 },

142 {

143 key: "model_post_turn_compact_threshold_percent",

144 type: "integer (0–100)",

145 description:

146 "Compact history after a final response when active context reaches this percentage of the usable context window. Omit or set to `0` to disable turn-end compaction. The usual auto-compaction limits still apply.",

147 },

142 {148 {

143 key: "model_catalog_json",149 key: "model_catalog_json",

144 type: "string (path)",150 type: "string (path)",


211 description:217 description:

212 "Allow shell-based tools to use login-shell semantics. Defaults to `true`; when `false`, `login = true` requests are rejected and omitted `login` defaults to non-login shells.",218 "Allow shell-based tools to use login-shell semantics. Defaults to `true`; when `false`, `login = true` requests are rejected and omitted `login` defaults to non-login shells.",

213 },219 },

220 {

221 key: "allow_symlinked_codex_home",

222 type: "boolean",

223 description:

224 "On macOS, allow writable sandbox roots at or under `$CODEX_HOME` to follow symlinks. Codex reads this only from the execution host's `$CODEX_HOME/config.toml` at startup. Enabling it trusts targets outside that directory and targets that change between commands. It grants no additional writable roots. Defaults to `false`.",

225 },

214 {226 {

215 key: "sandbox_mode",227 key: "sandbox_mode",

216 type: "read-only | workspace-write | danger-full-access",228 type: "read-only | workspace-write | danger-full-access",


316 key: "analytics.enabled",328 key: "analytics.enabled",

317 type: "boolean",329 type: "boolean",

318 description:330 description:

319 "Enable or disable analytics for this machine/profile. In Codex CLI, `false` also disables custom OTLP metrics exporters. When unset, the client default applies.",331 "Enable or disable analytics for this machine or profile. Setting this to `false` disables the built-in Statsig metrics exporter. Explicit OTLP metrics exporters remain active. When unset, the client default applies.",

320 },332 },

321 {333 {

322 key: "instructions",334 key: "instructions",


371 description:383 description:

372 "Load the compaction prompt override from a file (experimental).",384 "Load the compaction prompt override from a file (experimental).",

373 },385 },

386 {

387 key: "skills.bundled.enabled",

388 type: "boolean",

389 description:

390 "Load the system skills bundled with Codex. Defaults to `true`. Set to `false` in a trusted project configuration to disable bundled skills for that project.",

391 },

392 {

393 key: "skills.include_instructions",

394 type: "boolean",

395 description:

396 "Include the automatic skills instructions in the model context. Defaults to `true`.",

397 },

374 {398 {

375 key: "skills.max_context_tokens",399 key: "skills.max_context_tokens",

376 type: "integer (positive)",400 type: "integer (positive)",


380 {404 {

381 key: "skills.config",405 key: "skills.config",

382 type: "array<object>",406 type: "array<object>",

383 description: "Per-skill enablement overrides stored in config.toml.",407 description:

408 "Enable or disable skills by name or path. If several rules match a skill, the last one wins.",

384 },409 },

385 {410 {

386 key: "skills.config.<index>.path",411 key: "skills.config.<index>.path",

387 type: "string (path)",412 type: "string (path)",

388 description: "Path to a skill folder containing `SKILL.md`.",413 description: "Absolute path to one `SKILL.md` file.",

414 },

415 {

416 key: "skills.config.<index>.name",

417 type: "string",

418 description:

419 "Match every skill with this exact name. Specify either `name` or `path` for each entry.",

389 },420 },

390 {421 {

391 key: "skills.config.<index>.enabled",422 key: "skills.config.<index>.enabled",


458 description:489 description:

459 "Default approval behavior for tools in this app unless a per-tool override exists.",490 "Default approval behavior for tools in this app unless a per-tool override exists.",

460 },491 },

492 {

493 key: "apps.<id>.omit_tools_from",

494 type: "array<string>",

495 description:

496 "Omit this app's tools from the `direct`, `deferred`, or `code_mode` surfaces. App and MCP server omissions apply together.",

497 },

461 {498 {

462 key: "apps.<id>.tools.<tool>.enabled",499 key: "apps.<id>.tools.<tool>.enabled",

463 type: "boolean",500 type: "boolean",


521 key: "features.rollout_budget.enabled",558 key: "features.rollout_budget.enabled",

522 type: "boolean",559 type: "boolean",

523 description:560 description:

524 "Enable rollout budget tracking. This feature is under development and off by default. When enabled, `features.rollout_budget.limit_tokens` is required.",561 "Enable rollout budget tracking. This feature is under development and off by default. When enabled, set both `limit_tokens` and `reminder_at_remaining_tokens`.",

525 },562 },

526 {563 {

527 key: "features.rollout_budget.limit_tokens",564 key: "features.rollout_budget.limit_tokens",


530 "Positive token limit for rollout budget tracking. Required when rollout budget is enabled.",567 "Positive token limit for rollout budget tracking. Required when rollout budget is enabled.",

531 },568 },

532 {569 {

533 key: "features.rollout_budget.reminder_interval_tokens",570 key: "features.rollout_budget.reminder_at_remaining_tokens",

534 type: "integer",571 type: "array<integer>",

535 description:572 description:

536 "Positive token interval between rollout budget reminders. Defaults to 10% of `limit_tokens`, with a minimum of 1 token.",573 "Send a reminder as the remaining weighted token budget crosses each threshold. Supply the list when rollout budget tracking is enabled. Each value must be positive and below `limit_tokens`.",

537 },574 },

538 {575 {

539 key: "features.rollout_budget.sampling_token_weight",576 key: "features.rollout_budget.sampling_token_weight",


557 key: "hooks.<Event>",594 key: "hooks.<Event>",

558 type: "array<table>",595 type: "array<table>",

559 description:596 description:

560 "Matcher groups for hook events such as `PreToolUse`, `PermissionRequest`, `PostToolUse`, `PreCompact`, `PostCompact`, `SessionStart`, `SessionEnd`, `SubagentStart`, `SubagentStop`, `UserPromptSubmit`, `Stop`, or `Interrupt`.",597 "Matcher groups for hook events such as `PreModelRequest`, `PostModelRequest`, `PreToolUse`, `PermissionRequest`, `PostToolUse`, `PreCompact`, `PostCompact`, `SessionStart`, `SessionEnd`, `SubagentStart`, `SubagentStop`, `UserPromptSubmit`, `Stop`, or `Interrupt`.",

561 },598 },

562 {599 {

563 key: "hooks.<Event>[].hooks",600 key: "hooks.<Event>[].hooks",


688 key: "mcp_servers.<id>.required",725 key: "mcp_servers.<id>.required",

689 type: "boolean",726 type: "boolean",

690 description:727 description:

691 "When true, fail startup/resume if this enabled MCP server cannot initialize.",728 'Require this enabled server to be ready at startup. With `startup_readiness = "catalog"`, a valid cached catalog can satisfy that requirement.',

729 },

730 {

731 key: "mcp_servers.<id>.startup_readiness",

732 type: "connection | catalog",

733 description:

734 "Use a live connection to establish startup readiness (`connection`, the default), or let a valid cached tool catalog satisfy startup while the connection opens (`catalog`). Calling a tool still requires a live connection.",

692 },735 },

693 {736 {

694 key: "mcp_servers.<id>.startup_timeout_sec",737 key: "mcp_servers.<id>.startup_timeout_sec",


718 description:761 description:

719 "Deny list applied after `enabled_tools` for the MCP server.",762 "Deny list applied after `enabled_tools` for the MCP server.",

720 },763 },

764 {

765 key: "mcp_servers.<id>.supports_parallel_tool_calls",

766 type: "boolean",

767 description:

768 "Mark every tool on this server as safe to run in parallel. Enable only when the server can handle concurrent calls to all its tools. Defaults to `false`.",

769 },

770 {

771 key: "mcp_servers.<id>.tool_input_schema_max_bytes",

772 type: "integer (positive)",

773 description:

774 "Compact each ordinary MCP tool's input schema when it exceeds this many UTF-8 bytes. The default is 5,000 bytes. Code Mode also uses an explicit value when rendering tool input types.",

775 },

776 {

777 key: "mcp_servers.<id>.omit_tools_from",

778 type: "array<string>",

779 description:

780 "Omit this server’s tools from selected model-facing surfaces. Choose `direct` (initial tools), `deferred` (tool search), or `code_mode` (Code Mode scripts). Use `disabled_tools` to block a tool. An empty list clears inherited omissions.",

781 },

721 {782 {

722 key: "mcp_servers.<id>.default_tools_approval_mode",783 key: "mcp_servers.<id>.default_tools_approval_mode",

723 type: "auto | prompt | writes | approve",784 type: "auto | prompt | writes | approve",


740 key: "mcp_servers.<id>.scopes",801 key: "mcp_servers.<id>.scopes",

741 type: "array<string>",802 type: "array<string>",

742 description:803 description:

743 "OAuth scopes to request when authenticating to that MCP server.",804 "OAuth scopes to request at login. If omitted, Codex uses the initial authentication challenge's scopes, falling back to the protected resource's metadata.",

744 },805 },

745 {806 {

746 key: "mcp_servers.<id>.oauth_resource",807 key: "mcp_servers.<id>.oauth_resource",


749 "Optional RFC 8707 OAuth resource parameter to include during MCP login.",810 "Optional RFC 8707 OAuth resource parameter to include during MCP login.",

750 },811 },

751 {812 {

752 key: "mcp_servers.<id>.experimental_environment",813 key: "mcp_servers.<id>.environment_id",

753 type: "local | remote",814 type: "string",

754 description:815 description:

755 "Experimental placement for an MCP server. `remote` starts stdio servers through a remote executor environment; streamable HTTP remote placement is not implemented.",816 "Execution environment for the MCP server. Defaults to `local`. Use the ID of a configured executor to run a stdio server or connect to a streamable HTTP server there.",

756 },817 },

757 {818 {

758 key: "agents",819 key: "agents",


807 description:868 description:

808 "Path to a TOML config layer for that role; relative paths resolve from the config file that declares the role.",869 "Path to a TOML config layer for that role; relative paths resolve from the config file that declares the role.",

809 },870 },

871 {

872 key: "memories.version",

873 type: "v1 | v2",

874 description:

875 "Select the local memory store. With memories enabled, Codex defaults to `v2` for a fresh home and `v1` if `$CODEX_HOME/memories/` exists. Explicitly setting `dual_write = false` keeps the default at `v1`.",

876 },

877 {

878 key: "memories.dual_write",

879 type: "boolean",

880 description:

881 "With `v1` selected, set to `true` to generate both stores while continuing to read `v1`. With `v2` selected, Codex writes only `v2`.",

882 },

810 {883 {

811 key: "memories.generate_memories",884 key: "memories.generate_memories",

812 type: "boolean",885 type: "boolean",


871 type: "string",944 type: "string",

872 description: "Optional model override for global memory consolidation.",945 description: "Optional model override for global memory consolidation.",

873 },946 },

947 {

948 key: "memories.consolidation_service_tier",

949 type: "string",

950 description:

951 "Service tier for global memory consolidation. Defaults to `default` (Standard).",

952 },

874 {953 {

875 key: "features.prefer_mxc",954 key: "features.prefer_mxc",

876 type: "boolean",955 type: "boolean",


883 description:962 description:

884 "Use resumable command execution (stable; enabled on all platforms). User opt-outs are ignored. Managed requirements can disable resumable processes and `write_stdin`, leaving one-shot `exec_command` available.",963 "Use resumable command execution (stable; enabled on all platforms). User opt-outs are ignored. Managed requirements can disable resumable processes and `write_stdin`, leaving one-shot `exec_command` available.",

885 },964 },

965 {

966 key: "features.view_image",

967 type: "boolean",

968 description:

969 "Enable the built-in `view_image` tool for opening local images. Defaults to `true`.",

970 },

886 {971 {

887 key: "features.shell_snapshot",972 key: "features.shell_snapshot",

888 type: "boolean",973 type: "boolean",


901 description:986 description:

902 "Enable persisted goals and automatic continuation (stable; on by default).",987 "Enable persisted goals and automatic continuation (stable; on by default).",

903 },988 },

989 {

990 key: "goals.max_goal_token_budget",

991 type: "integer (positive)",

992 description:

993 "Set the default token budget for new goals and the largest budget a goal can request. Omit to leave goals without a configured limit.",

994 },

904 {995 {

905 key: "features.remote_plugin",996 key: "features.remote_plugin",

906 type: "boolean",997 type: "boolean",


916 key: "features.network_proxy",1007 key: "features.network_proxy",

917 type: "boolean | table",1008 type: "boolean | table",

918 description:1009 description:

919 "Start the network proxy for sandboxed commands (experimental; off by default). Required to enforce permission-profile domain rules unless enabled administrator-managed `experimental_network` requirements start the proxy. Use a table when setting feature-level policy options such as `domains`. Does not filter web search, apps, MCP, or other hosted tools.",1010 "Start the network proxy for sandboxed commands (experimental; off by default). Required to enforce permission-profile domain rules unless enabled administrator-managed `network_proxy` requirements start the proxy. Use a table when setting feature-level policy options such as `domains`. Does not filter web search, apps, MCP, or other hosted tools.",

920 },1011 },

921 {1012 {

922 key: "features.network_proxy.enabled",1013 key: "features.network_proxy.enabled",


1182 type: "string (path)",1273 type: "string (path)",

1183 description: "Working directory for the token command.",1274 description: "Working directory for the token command.",

1184 },1275 },

1276 {

1277 key: "model_providers.gcp.base_url",

1278 type: "string",

1279 description:

1280 "Override the built-in Google Cloud Vertex AI endpoint. Otherwise, Codex builds it from the project ID and location.",

1281 },

1282 {

1283 key: "model_providers.gcp.project_id",

1284 type: "string",

1285 description:

1286 "Google Cloud project ID for the Vertex AI endpoint. Takes precedence over `GOOGLE_CLOUD_PROJECT`.",

1287 },

1288 {

1289 key: "model_providers.gcp.location",

1290 type: "string",

1291 description:

1292 "Google Cloud location for the Vertex AI endpoint. Takes precedence over `GOOGLE_CLOUD_LOCATION`. Defaults to `global`.",

1293 },

1294 {

1295 key: "model_providers.gcp.credential_file",

1296 type: "string (absolute path)",

1297 description:

1298 "Path to a Google Application Default Credentials (ADC) file. Overrides `GOOGLE_APPLICATION_CREDENTIALS` only for the provider\u2019s authentication command.",

1299 },

1185 {1300 {

1186 key: "model_providers.amazon-bedrock.aws.profile",1301 key: "model_providers.amazon-bedrock.aws.profile",

1187 type: "string",1302 type: "string",


1217 description:1332 description:

1218 "Optional GPT-5 Responses API verbosity override; when unset, the selected model/preset default is used.",1333 "Optional GPT-5 Responses API verbosity override; when unset, the selected model/preset default is used.",

1219 },1334 },

1220 {

1221 key: "model_supports_reasoning_summaries",

1222 type: "boolean",

1223 description: "Force Codex to send or not send reasoning metadata.",

1224 },

1225 {1335 {

1226 key: "shell_environment_policy.inherit",1336 key: "shell_environment_policy.inherit",

1227 type: "all | core | none",1337 type: "all | core | none",


1292 description:1402 description:

1293 "Token budget for storing individual tool/function outputs in history.",1403 "Token budget for storing individual tool/function outputs in history.",

1294 },1404 },

1405 {

1406 key: "thread_unload_delay_secs",

1407 type: "integer (nonnegative)",

1408 description:

1409 "Seconds the app server waits before unloading an inactive thread with no subscribers. Set to `0` to unload it as soon as it meets both conditions. Defaults to `60` seconds.",

1410 },

1295 {1411 {

1296 key: "background_terminal_max_timeout",1412 key: "background_terminal_max_timeout",

1297 type: "number",1413 type: "number",


1332 key: "otel.metrics_exporter",1448 key: "otel.metrics_exporter",

1333 type: "none | statsig | otlp-http | otlp-grpc",1449 type: "none | statsig | otlp-http | otlp-grpc",

1334 description:1450 description:

1335 "Select the OpenTelemetry metrics exporter (defaults to `statsig`). In Codex CLI, `analytics.enabled = false` disables this exporter, including custom OTLP exporters. Set to `none` to disable metrics export independently.",1451 "Select the OpenTelemetry metrics exporter. The default, `statsig`, follows `analytics.enabled`. Explicit OTLP exporters work independently of that setting. Set to `none` to disable metrics export.",

1336 },1452 },

1337 {1453 {

1338 key: "otel.log_user_prompt",1454 key: "otel.log_user_prompt",


1340 description:1456 description:

1341 "Opt in to exporting raw user prompts with OpenTelemetry logs.",1457 "Opt in to exporting raw user prompts with OpenTelemetry logs.",

1342 },1458 },

1459 {

1460 key: "otel.log_agent_responses",

1461 type: "boolean",

1462 description:

1463 "Export final response text from the main agent and spawned subagents to the configured OTLP log exporter. Defaults to `false`. Response text can contain sensitive data and is capped at 64 KiB per response.",

1464 },

1465 {

1466 key: "otel.log_guardian_assessments",

1467 type: "boolean",

1468 description:

1469 "Export completed automatic approval reviews to the configured OTLP log exporter. Defaults to `false`. Review rationales can contain sensitive data and are capped at 64 KiB each.",

1470 },

1471 {

1472 key: "otel.span_attributes",

1473 type: "map<string,string>",

1474 description: "Add string attributes to every exported trace span.",

1475 },

1476 {

1477 key: "otel.tracestate",

1478 type: "map<string,map<string,string>>",

1479 description:

1480 "Set fields on W3C tracestate members when propagating trace context. Each member maps field names to string values.",

1481 },

1482 {

1483 key: "otel.tool_result.max_bytes",

1484 type: "integer (nonnegative)",

1485 description:

1486 "Maximum number of UTF-8 bytes from each tool result to include in logs, before the truncation notice. Defaults to `2048`. This setting affects only logged output.",

1487 },

1343 {1488 {

1344 key: "otel.exporter.<id>.endpoint",1489 key: "otel.exporter.<id>.endpoint",

1345 type: "string",1490 type: "string",


1572 description:1717 description:

1573 "Optional sparse checkout paths for a Git marketplace. Include the marketplace catalog and any local plugin directories it references.",1718 "Optional sparse checkout paths for a Git marketplace. Include the marketplace catalog and any local plugin directories it references.",

1574 },1719 },

1720 {

1721 key: "plugins._default.enabled",

1722 type: "boolean",

1723 description:

1724 "Set the default activation state for installed plugins. An explicit `plugins.<plugin>.enabled` overrides this default for plugins their source enables. Omit the table to keep the source or account activation settings.",

1725 },

1575 {1726 {

1576 key: "plugins.<plugin>.enabled",1727 key: "plugins.<plugin>.enabled",

1577 type: "boolean",1728 type: "boolean",


1608 description:1759 description:

1609 "Per-tool approval behavior override for a plugin-provided MCP tool.",1760 "Per-tool approval behavior override for a plugin-provided MCP tool.",

1610 },1761 },

1762 {

1763 key: "tui.presets.<digit>.input",

1764 type: "string",

1765 description:

1766 "Save a prompt or slash command in one of the ten slots (`0`–`9`) shown by `/presets`. Use up to 8,000 UTF-8 bytes of nonempty text. Shell commands beginning with `!` are unsupported.",

1767 },

1768 {

1769 key: "tui.presets.<digit>.label",

1770 type: "string",

1771 description:

1772 "Optional name for the preset in the picker and shortcut hints.",

1773 },

1611 {1774 {

1612 key: "tui.model_availability_nux.<model>",1775 key: "tui.model_availability_nux.<model>",

1613 type: "integer",1776 type: "integer",


1631 description:1794 description:

1632 "Legacy fallback for `tui.disable_paste_burst`. Prefer the setting under `[tui]`.",1795 "Legacy fallback for `tui.disable_paste_burst`. Prefer the setting under `[tui]`.",

1633 },1796 },

1634 {

1635 key: "windows_wsl_setup_acknowledged",

1636 type: "boolean",

1637 description: "Track Windows onboarding acknowledgement (Windows only).",

1638 },

1639 {1797 {

1640 key: "chatgpt_base_url",1798 key: "chatgpt_base_url",

1641 type: "string",1799 type: "string",


1675 description:1833 description:

1676 "Optional web search tool configuration. The object form can set search context size, allowed search domains, and approximate user location. These search-domain filters are separate from sandboxed-command network domain rules and do not restrict connectors or MCP servers.",1834 "Optional web search tool configuration. The object form can set search context size, allowed search domains, and approximate user location. These search-domain filters are separate from sandboxed-command network domain rules and do not restrict connectors or MCP servers.",

1677 },1835 },

1678 {

1679 key: "tools.view_image",

1680 type: "boolean",

1681 description: "Enable the local-image attachment tool `view_image`.",

1682 },

1683 {1836 {

1684 key: "web_search",1837 key: "web_search",

1685 type: "disabled | cached | indexed | live",1838 type: "disabled | cached | indexed | live",


1990 description:2143 description:

1991 "Enforce the directory where Codex stores SQLite-backed runtime state.",2144 "Enforce the directory where Codex stores SQLite-backed runtime state.",

1992 },2145 },

2146 {

2147 key: "unsafe_enforce_sqlite_journal_mode",

2148 type: "boolean",

2149 description:

2150 "On Linux, set to `true` to migrate existing SQLite databases on NFS from WAL to DELETE journaling before opening them for writes. Defaults to `false`. The mount must support POSIX locks across hosts. Keep every other SQLite client that uses the databases stopped on every host until migration succeeds. Replacements preserve file mode bits but belong to the user running the migration and do not copy the original owner, group, or extended ACLs.",

2151 },

1993 {2152 {

1994 key: "log_dir",2153 key: "log_dir",

1995 type: "string (path)",2154 type: "string (path)",


2010 type: "boolean",2169 type: "boolean",

2011 description: "Enforce whether shell tools can start a login shell.",2170 description: "Enforce whether shell tools can start a login shell.",

2012 },2171 },

2172 {

2173 key: "config_server",

2174 type: "table",

2175 description:

2176 "Enroll Codex with a configuration server through local managed requirements. Codex retrieves its policy bundle from this server. A cloud policy cannot configure its own server.",

2177 },

2178 {

2179 key: "config_server.base_url",

2180 type: "string",

2181 description:

2182 "Required HTTPS base URL. Codex appends `/codex/config/bundle`. Omit credentials, query parameters, and fragments from the base URL.",

2183 },

2184 {

2185 key: "config_server.oauth",

2186 type: "table",

2187 description:

2188 "OAuth settings for configuration server sign-in. Requires `authorization_url`, `token_url`, and a nonempty `client_id`. Optional fields are `device_authorization_url`, `resource`, `scopes` (defaults to an empty list), and `redirect_port` (nonzero). All endpoint URLs must use HTTPS.",

2189 },

2013 {2190 {

2014 key: "allowed_login_methods",2191 key: "allowed_login_methods",

2015 type: "array<string>",2192 type: "array<string>",


2197 description:2374 description:

2198 "Set to `false` to prohibit both explicit MXC selection and automatic selection through `features.prefer_mxc`. Omitting this requirement or setting it to `true` permits MXC but doesn't enable it or require it. Legacy implementation restrictions still apply to fallback.",2375 "Set to `false` to prohibit both explicit MXC selection and automatic selection through `features.prefer_mxc`. Omitting this requirement or setting it to `true` permits MXC but doesn't enable it or require it. Legacy implementation restrictions still apply to fallback.",

2199 },2376 },

2377 {

2378 key: "windows.require_mxc",

2379 type: "boolean",

2380 description:

2381 "On Windows, set to `true` to reject any effective sandbox implementation other than MXC. Select MXC separately. If Codex cannot use it, configuration fails instead of falling back to a legacy sandbox.",

2382 },

2200 {2383 {

2201 key: "remote_sandbox_config",2384 key: "remote_sandbox_config",

2202 type: "array<table>",2385 type: "array<table>",


2269 description:2452 description:

2270 "Pin Apps integration availability on or off for managed users.",2453 "Pin Apps integration availability on or off for managed users.",

2271 },2454 },

2455 {

2456 key: "features.api_key_cyber_access_programs",

2457 type: "boolean",

2458 description:

2459 "Allow Codex to send an explicitly selected cyber access program with requests to the built-in OpenAI provider when using API key authentication. The account and model must already have access to the program.",

2460 },

2272 {2461 {

2273 key: "features.in_app_updates",2462 key: "features.in_app_updates",

2274 type: "boolean",2463 type: "boolean",


2281 description:2470 description:

2282 "Set to `false` in `requirements.toml` to disable the built-in browser pane that users open and control directly.",2471 "Set to `false` in `requirements.toml` to disable the built-in browser pane that users open and control directly.",

2283 },2472 },

2473 {

2474 key: "features.browser_annotation_api",

2475 type: "boolean",

2476 description:

2477 "Set to `false` to block website-provided annotation customizations in the built-in browser. Users can still annotate pages themselves. Set to `true` to allow customizations when the app and account support them.",

2478 },

2284 {2479 {

2285 key: "features.in_app_chat",2480 key: "features.in_app_chat",

2286 type: "boolean",2481 type: "boolean",


2293 description:2488 description:

2294 "Set to `false` to disable in-app dictation in the desktop app. Setting it to `true` does not bypass other availability checks.",2489 "Set to `false` to disable in-app dictation in the desktop app. Setting it to `true` does not bypass other availability checks.",

2295 },2490 },

2491 {

2492 key: "features.in_app_voice",

2493 type: "boolean",

2494 description:

2495 "Set to `false` to disable real-time Codex voice in the desktop app. Use `features.in_app_dictation` to manage dictation separately.",

2496 },

2296 {2497 {

2297 key: "features.in_app_local_automation",2498 key: "features.in_app_local_automation",

2298 type: "boolean",2499 type: "boolean",


2321 key: "features.fast_mode",2522 key: "features.fast_mode",

2322 type: "boolean",2523 type: "boolean",

2323 description:2524 description:

2324 "Pin the canonical `fast_mode` feature on or off for managed users.",2525 "Allow or block Fast mode for managed users. Older app servers also use this setting to control Ultrafast mode.",

2526 },

2527 {

2528 key: "features.ultrafast_mode",

2529 type: "boolean",

2530 description:

2531 "Allow or block Ultrafast mode for managed users. On app servers that support independent speed settings, this applies even when Fast mode is disabled. Availability depends on the model and account.",

2532 },

2533 {

2534 key: "features.standalone_web_search",

2535 type: "boolean",

2536 description:

2537 "Experimental. Set to `true` to keep the desktop app's native web search configuration when hosted search through MCP would otherwise be available.",

2325 },2538 },

2326 {2539 {

2327 key: "features.guardian_approval",2540 key: "features.guardian_approval",


2385 type: "table",2598 type: "table",

2386 description: "Managed requirements for agent-driven Browser Use.",2599 description: "Managed requirements for agent-driven Browser Use.",

2387 },2600 },

2601 {

2602 key: "browser_use.extension",

2603 type: "table",

2604 description:

2605 "Managed settings for Browser Use in supported Chromium browser extensions.",

2606 },

2607 {

2608 key: "browser_use.extension.request_headers",

2609 type: "array<table>",

2610 description:

2611 "Add up to 16 HTTP headers to requests from agent-controlled tabs in supported Chromium extensions. Use an empty list to send no managed headers.",

2612 },

2613 {

2614 key: "browser_use.extension.request_headers[].name",

2615 type: "string",

2616 description:

2617 "Header name. Reserved names, including `Authorization` and `Cookie`, are prohibited. Names and values support `{{session_id}}` as their only substitution.",

2618 },

2619 {

2620 key: "browser_use.extension.request_headers[].value",

2621 type: "string",

2622 description: "Header value to send with matching browser requests.",

2623 },

2388 {2624 {

2389 key: "browser_use.allow_webmcp",2625 key: "browser_use.allow_webmcp",

2390 type: "boolean",2626 type: "boolean",

2391 description:2627 description:

2392 "Set to `true` to opt the desktop app's built-in browser into site tools (WebMCP). Setting it to `false` or omitting it leaves normal feature availability checks in place; `false` does not enforce a block. User preferences and site permissions still apply.",2628 "Allow site tools (WebMCP) through workspace policy on eligible managed plans. Both `true` and an unset value allow access through this policy. Setting `false` turns off this path. Users can still have access through their account rollout. Browser settings and site permissions apply.",

2393 },2629 },

2394 {2630 {

2395 key: "browser_use.allow_history_access",2631 key: "browser_use.allow_history_access",


2605 type: "table",2841 type: "table",

2606 description: "Managed desktop application requirements.",2842 description: "Managed desktop application requirements.",

2607 },2843 },

2844 {

2845 key: "application.storage",

2846 type: "table",

2847 description:

2848 "Pin storage locations for newly created work on desktop builds that support managed storage. Each path independently overrides the local preference. Storage settings do not restrict filesystem access.",

2849 },

2850 {

2851 key: "application.storage.default_project_parent",

2852 type: "string (absolute path)",

2853 description:

2854 "Parent directory for new local projects created with Start from scratch.",

2855 },

2856 {

2857 key: "application.storage.projectless_workspace_root",

2858 type: "string (absolute path)",

2859 description: "Root directory for new chats created without a project.",

2860 },

2608 {2861 {

2609 key: "application.network",2862 key: "application.network",

2610 type: "table",2863 type: "table",


2630 "Allow or deny an exact domain. Use domain names without URL schemes, ports, or wildcards.",2883 "Allow or deny an exact domain. Use domain names without URL schemes, ports, or wildcards.",

2631 },2884 },

2632 {2885 {

2633 key: "experimental_network",2886 key: "otel",

2887 type: "table",

2888 description:

2889 "Enforce the specified OpenTelemetry settings. Each exporter replaces the entire corresponding exporter definition. Span attributes and tracestate fields override only matching entries.",

2890 },

2891 {

2892 key: "otel.environment",

2893 type: "string",

2894 description: "Enforce the environment label on telemetry.",

2895 },

2896 {

2897 key: "otel.exporter",

2898 type: "none | otlp-http | otlp-grpc",

2899 description:

2900 "Enforce the log exporter, including its endpoint, headers, and TLS settings.",

2901 },

2902 {

2903 key: "otel.trace_exporter",

2904 type: "none | otlp-http | otlp-grpc",

2905 description:

2906 "Enforce the trace exporter, including its endpoint, headers, and TLS settings.",

2907 },

2908 {

2909 key: "otel.metrics_exporter",

2910 type: "none | statsig | otlp-http | otlp-grpc",

2911 description:

2912 "Enforce the metrics exporter. The Statsig exporter follows `analytics.enabled`. Explicit OTLP metrics exporters run independently of that setting.",

2913 },

2914 {

2915 key: "otel.log_user_prompt",

2916 type: "boolean",

2917 description: "Control whether exported logs include user prompt text.",

2918 },

2919 {

2920 key: "otel.log_agent_responses",

2921 type: "boolean",

2922 description:

2923 "Control whether OTLP logs include final response text from the main agent and spawned subagents.",

2924 },

2925 {

2926 key: "otel.log_guardian_assessments",

2927 type: "boolean",

2928 description:

2929 "Control whether OTLP logs include completed automatic approval assessments and their rationales.",

2930 },

2931 {

2932 key: "otel.tool_result",

2933 type: "table",

2934 description:

2935 "Enforce the tool-result log settings as a unit. An empty table enforces the default byte limit.",

2936 },

2937 {

2938 key: "otel.tool_result.max_bytes",

2939 type: "integer (nonnegative)",

2940 description:

2941 "Maximum UTF-8 bytes of tool-result text before the truncation notice in logs. Defaults to `2048` when the managed table is present.",

2942 },

2943 {

2944 key: "otel.span_attributes",

2945 type: "map<string,string>",

2946 description:

2947 "Enforce individual string attributes on exported spans. Higher-priority requirements win for the same attribute.",

2948 },

2949 {

2950 key: "otel.tracestate",

2951 type: "map<string,map<string,string>>",

2952 description:

2953 "Enforce individual fields within W3C tracestate members. Higher-priority requirements win for the same member and field.",

2954 },

2955 {

2956 key: "network_proxy",

2634 type: "table",2957 type: "table",

2635 description:2958 description:

2636 "Administrator-managed network requirements for sandboxed local commands, enforced from `requirements.toml`. When enabled, these requirements can start the command network proxy without `features.network_proxy`. Browser tools separately check managed network denies and exclusive allowlists. These requirements do not route browser traffic through the proxy or control web search, apps, MCP servers, native-app traffic, or other capability-specific traffic. On supported managed Codex Cloud paths, these requirements constrain command networking alongside separate Cloud environment internet settings. Approved full sandbox escalation can bypass the command proxy where policy permits it. Work Cloud does not inherit these requirements.",2959 "Administrator-managed network requirements for sandboxed local commands. Codex 0.166.0 accepts `[network_proxy]` and its alias `[experimental_network]`. Use one name per requirements layer. Keep the alias in published policies until every client and policy validator supports the new name. When enabled, these requirements can start the command network proxy without `features.network_proxy`. Browser tools separately check managed network denies and exclusive allowlists. These requirements do not route browser traffic through the proxy or control web search, apps, MCP servers, native-app traffic, or other capability-specific traffic. On supported managed Codex Cloud paths, these requirements constrain command networking alongside separate Cloud environment internet settings. Approved full sandbox escalation can bypass the command proxy where policy permits it. Work Cloud does not inherit these requirements.",

2637 },2960 },

2638 {2961 {

2639 key: "experimental_network.enabled",2962 key: "network_proxy.enabled",

2640 type: "boolean",2963 type: "boolean",

2641 description:2964 description:

2642 "Enable sandboxed networking requirements. This does not grant network access when the active sandbox keeps command networking off.",2965 "Enable sandboxed networking requirements. This does not grant network access when the active sandbox keeps command networking off.",

2643 },2966 },

2644 {2967 {

2645 key: "experimental_network.http_port",2968 key: "network_proxy.http_port",

2646 type: "integer",2969 type: "integer",

2647 description:2970 description:

2648 "Loopback HTTP listener port to use for `[experimental_network]` requirements.",2971 "Loopback HTTP listener port to use for `[network_proxy]` requirements.",

2649 },2972 },

2650 {2973 {

2651 key: "experimental_network.socks_port",2974 key: "network_proxy.socks_port",

2652 type: "integer",2975 type: "integer",

2653 description:2976 description:

2654 "Loopback SOCKS5 listener port to use for `[experimental_network]` requirements.",2977 "Loopback SOCKS5 listener port to use for `[network_proxy]` requirements.",

2655 },2978 },

2656 {2979 {

2657 key: "experimental_network.allow_upstream_proxy",2980 key: "network_proxy.allow_upstream_proxy",

2658 type: "boolean",2981 type: "boolean",

2659 description:2982 description:

2660 "Allow sandboxed networking to chain through an upstream proxy from the environment.",2983 "Allow sandboxed networking to chain through an upstream proxy from the environment.",

2661 },2984 },

2662 {2985 {

2663 key: "experimental_network.dangerously_allow_non_loopback_proxy",2986 key: "network_proxy.dangerously_allow_non_loopback_proxy",

2664 type: "boolean",2987 type: "boolean",

2665 description:2988 description:

2666 "Permit non-loopback listener addresses for `[experimental_network]` requirements. Enabling it can expose listeners beyond localhost.",2989 "Permit non-loopback listener addresses for `[network_proxy]` requirements. Enabling it can expose listeners beyond localhost.",

2667 },2990 },

2668 {2991 {

2669 key: "experimental_network.dangerously_allow_all_unix_sockets",2992 key: "network_proxy.dangerously_allow_all_unix_sockets",

2670 type: "boolean",2993 type: "boolean",

2671 description:2994 description:

2672 "Permit arbitrary Unix socket destinations instead of allowlist-only access. Use only in tightly controlled environments.",2995 "Permit arbitrary Unix socket destinations instead of allowlist-only access. Use only in tightly controlled environments.",

2673 },2996 },

2674 {2997 {

2675 key: "experimental_network.domains",2998 key: "network_proxy.domains",

2676 type: "map<string, allow | deny>",2999 type: "map<string, allow | deny>",

2677 description:3000 description:

2678 "Map-shaped administrator domain policy for sandboxed networking. Supports exact hosts, `*.example.com` for subdomains only, `**.example.com` for apex plus subdomains, and global `*` allow rules. Prefer scoped rules because `*` broadly opens public outbound access. Environment rules can replace the same Global domain key within a policy. Higher-priority values replace the same key, while other inherited keys remain. After composition, a different matching `deny`, including an inherited wildcard, still blocks a request. Empty environment maps do not clear Global rules. Verify executor support. Do not combine this with `experimental_network.allowed_domains` or `experimental_network.denied_domains`.",3001 "Map-shaped administrator domain policy for sandboxed networking. Supports exact hosts, `*.example.com` for subdomains only, `**.example.com` for apex plus subdomains, and global `*` allow rules. Prefer scoped rules because `*` broadly opens public outbound access. Environment rules can replace the same Global domain key within a policy. Higher-priority values replace the same key, while other inherited keys remain. After composition, a different matching `deny`, including an inherited wildcard, still blocks a request. Empty environment maps do not clear Global rules. Verify executor support. Do not combine this with `network_proxy.allowed_domains` or `network_proxy.denied_domains`.",

2679 },3002 },

2680 {3003 {

2681 key: "experimental_network.domains.<pattern>",3004 key: "network_proxy.domains.<pattern>",

2682 type: "allow | deny",3005 type: "allow | deny",

2683 description:3006 description:

2684 "Allow or deny sandboxed network access for the matching domain pattern. A deny rule wins when several patterns match.",3007 "Allow or deny sandboxed network access for the matching domain pattern. A deny rule wins when several patterns match.",

2685 },3008 },

2686 {3009 {

2687 key: "experimental_network.allowed_domains",3010 key: "network_proxy.review_domains",

3011 type: "array<string>",

3012 description:

3013 "Route matching hosts through network approval even if an allow rule matches. An explicit deny takes precedence. Approved requests still undergo DNS and private-address checks. Defaults to an empty list.",

3014 },

3015 {

3016 key: "network_proxy.allowed_domains",

2688 type: "array<string>",3017 type: "array<string>",

2689 description:3018 description:

2690 "Administrator allow rules for sandboxed-command networking while the managed network proxy is enabled. These rules do not apply to web search, apps, or MCP servers. Do not combine this with `experimental_network.domains`.",3019 "Administrator allow rules for sandboxed-command networking while the managed network proxy is enabled. These rules do not apply to web search, apps, or MCP servers. Do not combine this with `network_proxy.domains`.",

2691 },3020 },

2692 {3021 {

2693 key: "experimental_network.denied_domains",3022 key: "network_proxy.denied_domains",

2694 type: "array<string>",3023 type: "array<string>",

2695 description:3024 description:

2696 "List-shaped administrator deny rules for sandboxed networking. Do not combine this with `experimental_network.domains`.",3025 "List-shaped administrator deny rules for sandboxed networking. Do not combine this with `network_proxy.domains`.",

2697 },3026 },

2698 {3027 {

2699 key: "experimental_network.managed_allowed_domains_only",3028 key: "network_proxy.managed_allowed_domains_only",

2700 type: "boolean",3029 type: "boolean",

2701 description:3030 description:

2702 "When networking requirements are enabled and this is true, ordinary user configuration and per-domain approvals cannot expand the managed proxy allowlist. With no effective configured or inherited Allow entries, ordinary managed commands have no allowed destinations. A deny-only policy does not allow the rest of the internet. This does not cover every tool or approved full sandbox escalation.",3031 "When networking requirements are enabled and this is true, ordinary user configuration and per-domain approvals cannot expand the managed proxy allowlist. With no effective configured or inherited Allow entries, ordinary managed commands have no allowed destinations. A deny-only policy does not allow the rest of the internet. This does not cover every tool or approved full sandbox escalation.",

2703 },3032 },

2704 {3033 {

2705 key: "experimental_network.unix_sockets",3034 key: "network_proxy.unix_sockets",

2706 type: "map<string, allow | deny>",3035 type: "map<string, allow | deny>",

2707 description:3036 description:

2708 "Administrator-managed Unix socket allowlist for sandboxed networking on macOS. Paths must be absolute.",3037 "Administrator-managed Unix socket allowlist for sandboxed networking on macOS. Paths must be absolute.",

2709 },3038 },

2710 {3039 {

2711 key: "experimental_network.unix_sockets.<path>",3040 key: "network_proxy.unix_sockets.<path>",

2712 type: "allow | deny",3041 type: "allow | deny",

2713 description:3042 description:

2714 "On macOS, `allow` adds an absolute Unix socket path to the allowlist; `deny` leaves it out. A `deny` entry cannot block a socket when allow-all Unix sockets is enabled.",3043 "On macOS, `allow` adds an absolute Unix socket path to the allowlist; `deny` leaves it out. A `deny` entry cannot block a socket when allow-all Unix sockets is enabled.",

2715 },3044 },

2716 {3045 {

2717 key: "experimental_network.allow_local_binding",3046 key: "network_proxy.allow_local_binding",

2718 type: "boolean",3047 type: "boolean",

2719 description:3048 description:

2720 "Permit broader local/private-network access for sandboxed networking. On the supported Codex Cloud proxy path, an explicit false can prevent upstream-proxy access even if a domain is allowed. It defaults to true only if no applicable requirement, selected network profile, or proxy feature setting provides a value. Inherited false remains explicit. A supported higher-priority Cloud override can change it without broadening Global for Local or adding domain Allow entries. Verify executor support. Do not apply this Cloud default to Local.",3049 "Permit broader local/private-network access for sandboxed networking. On the supported Codex Cloud proxy path, an explicit false can prevent upstream-proxy access even if a domain is allowed. It defaults to true only if no applicable requirement, selected network profile, or proxy feature setting provides a value. Inherited false remains explicit. A supported higher-priority Cloud override can change it without broadening Global for Local or adding domain Allow entries. Verify executor support. Do not apply this Cloud default to Local.",


2741 key: "hooks.<Event>",3070 key: "hooks.<Event>",

2742 type: "array<table>",3071 type: "array<table>",

2743 description:3072 description:

2744 "Matcher groups for a hook event such as `PreToolUse`, `PermissionRequest`, `PostToolUse`, `PreCompact`, `PostCompact`, `SessionStart`, `SessionEnd`, `SubagentStart`, `SubagentStop`, `UserPromptSubmit`, or `Stop`.",3073 "Matcher groups for a hook event such as `PreModelRequest`, `PostModelRequest`, `PreToolUse`, `PermissionRequest`, `PostToolUse`, `PreCompact`, `PostCompact`, `SessionStart`, `SessionEnd`, `SubagentStart`, `SubagentStop`, `UserPromptSubmit`, or `Stop`.",

2745 },3074 },

2746 {3075 {

2747 key: "hooks.<Event>[].hooks",3076 key: "hooks.<Event>[].hooks",

config-sample.md +107 −33

Details

67 67 

68# service_tier = "fast"68# service_tier = "fast"

69 69 

70# For Google Cloud Vertex AI, set model_provider = "gcp" above and configure

71 

72# the project under [model_providers.gcp] below or set GOOGLE_CLOUD_PROJECT.

73 

70# Optional manual model metadata. When unset, Codex uses model or preset defaults.74# Optional manual model metadata. When unset, Codex uses model or preset defaults.

71 75 

72# model_context_window = 128000 # tokens; default: auto for model76# model_context_window = 128000 # tokens; default: auto for model


75 79 

76# model_auto_compact_token_limit_scope = "total" # total | body_after_prefix; default: total80# model_auto_compact_token_limit_scope = "total" # total | body_after_prefix; default: total

77 81 

82# Compact after a final response at 80% of the usable context window.

83 

84# Leave unset or set to 0 to disable turn-end compaction.

85 

86# model_post_turn_compact_threshold_percent = 80

87 

78# tool_output_token_limit = 12000 # tokens stored per tool output88# tool_output_token_limit = 12000 # tokens stored per tool output

79 89 

80# model_catalog_json = "/absolute/path/to/models.json" # optional startup-only model catalog override90# model_catalog_json = "/absolute/path/to/models.json" # optional startup-only model catalog override

81 91 

82# background_terminal_max_timeout = 300000 # ms; max empty write_stdin poll window (default 5m)92# background_terminal_max_timeout = 300000 # ms; max empty write_stdin poll window (default 5m)

83 93 

94# Unload a thread after five minutes with no activity or subscribers (default: 60 seconds).

95 

96# thread_unload_delay_secs = 300

97 

84# log_dir = "/absolute/path/to/codex-logs" # log directory; setting explicitly enables codex-tui.log; default: "$CODEX_HOME/log"98# log_dir = "/absolute/path/to/codex-logs" # log directory; setting explicitly enables codex-tui.log; default: "$CODEX_HOME/log"

85 99 

86# sqlite_home = "/absolute/path/to/codex-state" # optional SQLite-backed runtime state directory100# sqlite_home = "/absolute/path/to/codex-state" # optional SQLite-backed runtime state directory


107 121 

108# model_verbosity = "medium"122# model_verbosity = "medium"

109 123 

110# Force enable or disable reasoning summaries for current model.

111 

112# model_supports_reasoning_summaries = true

113 

114################################################################################124################################################################################

115 125 

116# Instruction Overrides126# Instruction Overrides


185 195 

186allow_login_shell = true196allow_login_shell = true

187 197 

198# macOS only. Set in the execution host's $CODEX_HOME/config.toml, then restart Codex.

199 

200# If true, already writable roots under CODEX_HOME can follow symlinks, including

201 

202# targets outside CODEX_HOME or targets that change between commands.

203 

204# allow_symlinked_codex_home = false

205 

188# Filesystem/network sandbox policy for tool calls:206# Filesystem/network sandbox policy for tool calls:

189 207 

190# - read-only (default)208# - read-only (default)


315 333 

316show_raw_agent_reasoning = false334show_raw_agent_reasoning = false

317 335 

318# Track Windows onboarding acknowledgement (Windows only). Default: false

319 

320windows_wsl_setup_acknowledged = false

321 

322# Check for updates on startup. Default: true336# Check for updates on startup. Default: true

323 337 

324check_for_update_on_startup = true338check_for_update_on_startup = true


377 391 

378# interrupt_message = true392# interrupt_message = true

379 393 

394# Default budget for new goals and maximum allowed goal budget.

395 

396# [goals]

397 

398# max_goal_token_budget = 100000

399 

380# [agents.reviewer]400# [agents.reviewer]

381 401 

382# description = "Find correctness, security, and test risks in code."402# description = "Find correctness, security, and test risks in code."


397 417 

398# max_context_tokens = 2000418# max_context_tokens = 2000

399 419 

400# Disable or re-enable a specific skill without deleting it.420# include_instructions = true

421 

422# [skills.bundled]

423 

424# enabled = false

425 

426# Disable every skill with this name. To match one file, use path instead.

401 427 

402[[skills.config]]428# [[skills.config]]

403 429 

404# path = "/path/to/skill/SKILL.md"430# name = "review-changes"

431 

432# Alternative selector: path = "/path/to/skill/SKILL.md"

405 433 

406# enabled = false434# enabled = false

407 435 


673 701 

674# theme = "catppuccin-mocha"702# theme = "catppuccin-mocha"

675 703 

704# Save a reusable prompt or slash command in slot 1 of /presets.

705 

706# [tui.presets.1]

707 

708# label = "Review changes"

709 

710# input = "/review"

711 

676# Custom key bindings. Selected composer actions fall back to matching [tui.keymap.global] bindings.712# Custom key bindings. Selected composer actions fall back to matching [tui.keymap.global] bindings.

677 713 

678# Use [] to unbind an action.714# Use [] to unbind an action.


701 737 

702# Enable or disable analytics. When unset, the client default applies.738# Enable or disable analytics. When unset, the client default applies.

703 739 

704# In Codex CLI, false also disables custom OTLP metrics exporters.740# Setting this to false disables built-in Statsig metrics. Custom OTLP exporters remain active.

705 741 

706[analytics]742[analytics]

707enabled = true743enabled = true


737 773 

738# Leave this table empty to accept defaults. Set explicit booleans to opt in/out.774# Leave this table empty to accept defaults. Set explicit booleans to opt in/out.

739 775 

776# view_image = false # disable the built-in local image viewer (enabled by default)

777 

740# Prefer MXC on Windows when the device and policy support it; otherwise use the legacy sandbox below.778# Prefer MXC on Windows when the device and policy support it; otherwise use the legacy sandbox below.

741 779 

742# Disabled by default in the standalone CLI.780# Disabled by default in the standalone CLI.


781 819 

782# Rollout budget tracking. This feature is under development and off by default.820# Rollout budget tracking. This feature is under development and off by default.

783 821 

784# limit_tokens is required when enabled.822# Set limit_tokens and reminder_at_remaining_tokens when enabled.

785 

786# Optional reminder_interval_tokens defaults to 10% of limit_tokens.

787 823 

788# Token weights default to 1.0.824# Token weights default to 1.0.

789 825 


793 829 

794# limit_tokens = 100000830# limit_tokens = 100000

795 831 

796# reminder_interval_tokens = 10000832# reminder_at_remaining_tokens = [50000, 25000, 10000]

797 833 

798# sampling_token_weight = 1.0834# sampling_token_weight = 1.0

799 835 


809 845 

810# [memories]846# [memories]

811 847 

848# version = "v1" # keep reading the original store during migration

849 

850# dual_write = true # generate both stores while reading v1

851 

852# consolidation_service_tier = "default" # Standard tier for memory consolidation

853 

812# generate_memories = true854# generate_memories = true

813 855 

814# use_memories = true856# use_memories = true


853 895 

854# enabled = true # optional; default true896# enabled = true # optional; default true

855 897 

856# required = true # optional; fail startup/resume if this server cannot initialize898# required = true # require this server to be ready at startup

857 899 

858# command = "docs-server" # required900# command = "docs-server" # required

859 901 


867 909 

868# cwd = "/path/to/server" # optional working directory override910# cwd = "/path/to/server" # optional working directory override

869 911 

870# experimental_environment = "remote" # experimental: run stdio via a remote executor912# environment_id = "devbox" # ID of a configured executor. Defaults to "local".

871 913 

872# startup_timeout_sec = 10.0 # optional; default 10.0 seconds914# startup_timeout_sec = 10.0 # optional; default 10.0 seconds

873 915 


875 917 

876# tool_timeout_sec = 60.0 # optional; default 60.0 seconds918# tool_timeout_sec = 60.0 # optional; default 60.0 seconds

877 919 

920# supports_parallel_tool_calls = true # only if all tools are safe to call concurrently

921 

878# enabled_tools = ["search", "summarize"] # optional allow-list922# enabled_tools = ["search", "summarize"] # optional allow-list

879 923 

880# disabled_tools = ["slow-tool"] # optional deny-list (applied after allow-list)924# disabled_tools = ["slow-tool"] # optional deny-list (applied after allow-list)

881 925 

882# scopes = ["read:docs"] # optional OAuth scopes926# startup_readiness = "catalog" # use a valid cached tool catalog while connecting

883 927 

884# oauth_resource = "https://docs.example.com/" # optional OAuth resource928# tool_input_schema_max_bytes = 8000 # default 5000 UTF-8 bytes

929 

930# omit_tools_from = ["direct"] # omit from the initial tool list

885 931 

886# [mcp_servers.docs.tools.search]932# [mcp_servers.docs.tools.search]

887 933 


893 939 

894# enabled = true # optional; default true940# enabled = true # optional; default true

895 941 

896# required = true # optional; fail startup/resume if this server cannot initialize942# required = true # require this server to be ready at startup

897 943 

898# url = "https://github-mcp.example.com/mcp" # required944# url = "https://github-mcp.example.com/mcp" # required

899 945 


913 959 

914# disabled_tools = ["delete_issue"] # optional deny-list960# disabled_tools = ["delete_issue"] # optional deny-list

915 961 

916# scopes = ["repo"] # optional OAuth scopes962# scopes = ["repo"] # override scopes discovered from the server

963 

964# oauth_resource = "https://github-mcp.example.com/"

917 965 

918# [mcp_servers.github.oauth]966# [mcp_servers.github.oauth]

919 967 


941 989 

942# - lmstudio990# - lmstudio

943 991 

944# - amazon-bedrock992# - amazon-bedrock and amazon-bedrock-runtime

993 

994# - gcp (Google Cloud Vertex AI)

945 995 

946# These IDs are reserved. Use a different ID for custom providers.996# These IDs are reserved. Use a different ID for custom providers.

947 997 

948[model_providers]998[model_providers]

949 999 

1000# Built-in Vertex AI provider options. The file path applies only to its auth command.

1001 

1002# [model_providers.gcp]

1003 

1004# project_id = "my-project"

1005 

1006# location = "global"

1007 

1008# credential_file = "/absolute/path/to/adc.json"

1009 

950# --- Example: built-in Amazon Bedrock provider options ---1010# --- Example: built-in Amazon Bedrock provider options ---

951 1011 

952# model_provider = "amazon-bedrock"1012# model_provider = "amazon-bedrock"


1055 1115 

1056################################################################################1116################################################################################

1057 1117 

1118# Keep installed plugins inactive by default, with an exception for one

1119 

1120# plugin that its marketplace or account already enables.

1121 

1122# [plugins._default]

1123 

1124# enabled = false

1125 

1126# [plugins."review@team"]

1127 

1128# enabled = true

1129 

1058# Optional per-app controls.1130# Optional per-app controls.

1059 1131 

1060[apps]1132[apps]


1155 1227 

1156# experimental_compact_prompt_file = "./compact_prompt.txt"1228# experimental_compact_prompt_file = "./compact_prompt.txt"

1157 1229 

1158# tools_view_image = true

1159 

1160# features = { shell_snapshot = false }1230# features = { shell_snapshot = false }

1161 1231 

1162################################################################################1232################################################################################


1175 1245 

1176################################################################################1246################################################################################

1177 1247 

1178# Tools1248# OpenTelemetry (OTEL)

1179 1249 

1180################################################################################1250################################################################################

1181 1251 

1182[tools]1252[otel]

1183 1253 

1184# view_image = true1254# Each option sends potentially sensitive text to the configured OTLP log exporter.

1185 1255 

1186################################################################################1256# log_agent_responses = false

1187 1257 

1188# OpenTelemetry (OTEL)1258# log_guardian_assessments = false

1189 1259 

1190################################################################################1260# Byte limit for logged tool results. Model-visible output has a separate limit.

1191 1261 

1192[otel]1262# tool_result.max_bytes = 2048

1263 

1264# span_attributes = { team = "platform" }

1265 

1266# tracestate = { acme = { region = "eu" } }

1193 1267 

1194# Include user prompt text in logs. Default: false1268# Include user prompt text in logs. Default: false

1195 1269 


1209 1283 

1210# Metrics exporter: none | statsig | otlp-http | otlp-grpc1284# Metrics exporter: none | statsig | otlp-http | otlp-grpc

1211 1285 

1212# Default: statsig. In Codex CLI, analytics.enabled = false disables all metrics exporters.1286# The default Statsig exporter follows analytics.enabled. Custom OTLP exporters run independently.

1213 1287 

1214# Set to none to disable metrics export.1288# Set to none to disable metrics export.

1215 1289 

Details

93`~/.codex`. See [Config and state locations](https://learn.chatgpt.com/docs/config-file/config-advanced#config-and-state-locations)93`~/.codex`. See [Config and state locations](https://learn.chatgpt.com/docs/config-file/config-advanced#config-and-state-locations)

94for how Codex uses `CODEX_HOME`.94for how Codex uses `CODEX_HOME`.

95 95 

96The main memory files live under `~/.codex/memories/` and include summaries,96When you enable memories in a fresh Codex home, the CLI uses

97durable entries, recent inputs, and supporting evidence from prior chats.97`$CODEX_HOME/memories_v2/` by default. If `$CODEX_HOME/memories/` already

98exists, the CLI continues to use that store by default. Set

99`memories.version` to choose a version explicitly. With no explicit version,

100`memories.dual_write = false` keeps even a fresh profile on v1.

101 

102In the desktop app, check both `$CODEX_HOME/memories/` and

103`$CODEX_HOME/memories_v2/` for generated summaries and supporting evidence

104from prior chats. During the migration, a new local chat with memories enabled

105can read from `memories/` and write to both directories, even on a fresh profile.

98 106 

99Treat these files as generated state. You can inspect them when troubleshooting107Treat these files as generated state. You can inspect them when troubleshooting

100or before sharing your Codex home directory, but don't rely on editing them by108or before sharing your Codex home directory, but don't rely on editing them by

Details

261`browser_use.disable_auto_review = true`, or set `auto_review = "deny"` on an261`browser_use.disable_auto_review = true`, or set `auto_review = "deny"` on an

262origin policy to restrict it for that origin.262origin policy to restrict it for that origin.

263 263 

264To enable [Site tools](https://learn.chatgpt.com/docs/webmcp) for an eligible Enterprise workspace,264On eligible managed plans, leave `browser_use.allow_webmcp` unset or set it to

265set `browser_use.allow_webmcp = true`. This managed opt-in applies to the265`true` to allow [Site tools](https://learn.chatgpt.com/docs/webmcp) through workspace policy in the

266desktop app's built-in browser. Setting it to `false` or omitting it leaves266desktop app's built-in browser. Set it to `false` to turn off access through

267normal feature availability checks in place; `false` does not enforce a block.267this policy. Users who already have access through their account rollout can

268User preferences and site permissions still apply.268still use site tools. Model support, browser settings, and site permissions

269also apply.

269 270 

270This native-app example allows Calculator on macOS, denies other apps by default,271This native-app example allows Calculator on macOS, denies other apps by default,

271and prevents app approvals from persisting across sessions:272and prevents app approvals from persisting across sessions:


848### Configure network access requirements849### Configure network access requirements

849 850 

850<WarningTip>851<WarningTip>

851 `[experimental_network]` is experimental and may change. Do not enable these852 Keep `[experimental_network]` in published policies until every client and

852 requirements broadly across an enterprise deployment without validating them853 policy validator supports `[network_proxy]`. Older versions can ignore or

853 on the local client versions and operating systems your users run. Windows854 strip the new name. Test enforcement on the client versions and operating

854 support is still limited; avoid applying this policy to Windows users unless855 systems you deploy, especially Windows, where support is limited.

855 you have tested it in your environment.

856</WarningTip>856</WarningTip>

857 857 

858Use **Requirements** > **Network use controls** to manage supported command858Use **Requirements** > **Network use controls** to manage supported command


884Global rules. Use **Edit as TOML** for advanced network fields or existing legacy884Global rules. Use **Edit as TOML** for advanced network fields or existing legacy

885domain lists that the visual editor can't represent.885domain lists that the visual editor can't represent.

886 886 

887Use `[experimental_network]` in `requirements.toml` when administrators should887In Codex 0.166.0, `[network_proxy]` is the canonical table for managed

888define network access requirements centrally. These requirements are separate888command networking in `requirements.toml`. Codex also accepts the older

889from the user `features.network_proxy` toggle: they can configure sandbox889`[experimental_network]` name. Choose one table name per layer. If layers use

890networking without that feature flag, but they don't grant command network890different names, Codex applies the usual requirements precedence.

891access when the active sandbox keeps networking off. Set891 

892`experimental_network.enabled = true` to activate the managed proxy; domain892Set `enabled = true` in the managed table to start the proxy independently

893rules alone do not make the proxy active.893of the user setting `features.network_proxy`. The active sandbox must also

894allow command network access. The example uses the name that older clients

895and policy validation layers recognize.

894 896 

895```toml897```toml

896[experimental_network]898[experimental_network]


979 981 

980#### Other network runtime limits982#### Other network runtime limits

981 983 

982All field names below are under `experimental_network` in `requirements.toml`. The arrows show a Global value followed by an environment value within the same policy. These local-execution cases do not establish Orchestrator support for the same settings.984All field names below belong to the managed `network_proxy` table (also accepted as `experimental_network`) in `requirements.toml`. The arrows show a Global value followed by an environment value within the same policy. These local-execution cases do not establish Orchestrator support for the same settings.

983 985 

984| **Setting and attempted override** | **Runtime behavior** | **Admin action** |986| **Setting and attempted override** | **Runtime behavior** | **Admin action** |

985| -------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------ |987| -------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------ |


1341See the [requirements reference](https://learn.chatgpt.com/docs/config-file/config-reference#requirementstoml)1343See the [requirements reference](https://learn.chatgpt.com/docs/config-file/config-reference#requirementstoml)

1342for credential storage modes and service URL configuration.1344for credential storage modes and service URL configuration.

1343 1345 

1346### Enforce OpenTelemetry settings

1347 

1348In Codex CLI 0.166.0, use `[otel]` in `requirements.toml` to set the log, trace, and metrics

1349exporters independently, label the environment, and control which content Codex

1350exports. This example sends logs to an OTLP/HTTP collector and limits the

1351text logged for each tool result to 256 UTF-8 bytes. It omits prompt text, final response

1352text, and automatic approval assessments.

1353 

1354The macOS desktop app 26.1027.30824 bundles CLI `0.166.0-alpha.5.1`.

1355That build doesn't support `[otel]` in `requirements.toml`, so it can't

1356enforce `log_user_prompt = false` through this policy.

1357 

1358```toml

1359[otel]

1360environment = "prod"

1361exporter = { otlp-http = { endpoint = "https://otel.example.com/v1/logs", protocol = "binary" } }

1362log_user_prompt = false

1363log_agent_responses = false

1364log_guardian_assessments = false

1365tool_result = { max_bytes = 256 }

1366span_attributes = { team = "platform" }

1367tracestate = { acme = { region = "eu" } }

1368```

1369 

1370Managed values override local configuration. For `exporter`, `trace_exporter`,

1371and `metrics_exporter`, the highest-priority requirement that sets the

1372exporter supplies its entire definition, including headers and TLS settings.

1373Scalar settings and the `tool_result` table also take the highest-priority

1374value supplied for each. Omitted settings remain configurable unless another

1375requirements layer supplies them.

1376 

1377Span attributes merge by attribute name. `tracestate` fields merge by member

1378and field name. Higher-priority values win for matching entries. Other

1379entries remain available, and an empty metadata table doesn't clear them.

1380See [Observability and telemetry](https://learn.chatgpt.com/docs/config-file/config-advanced#observability-and-telemetry)

1381for exporter options and log contents.

1382 

1383### Migrate SQLite databases on NFS

1384 

1385On Linux, Codex creates new SQLite databases on NFS in `DELETE` journal mode.

1386To migrate existing databases from write-ahead logging (WAL), set

1387`unsafe_enforce_sqlite_journal_mode = true` at the top level of

1388`requirements.toml`. This setting is off by default. With it enabled, Codex

1389migrates the databases before opening them for writes.

1390 

1391The NFS mount must support POSIX locks across hosts. Mount options such as

1392`nolock` and `local_lock=all` prevent those locks from working. On every host,

1393stop all SQLite clients that use the databases, including Codex. Start

1394one Codex instance and keep all other clients stopped until migration succeeds.

1395The user running that instance needs write access to the database directory

1396and migration lock. The replacement files retain their Unix permission bits

1397and belong to that user.

1398The migration doesn't copy the original owner, group, or extended access control

1399lists. Codex keeps the originals in a private backup directory.

1400 

1344### Managed defaults (`managed_config.toml`)1401### Managed defaults (`managed_config.toml`)

1345 1402 

1346Use [Agent security Defaults](#set-configuration-defaults) for supported1403Use [Agent security Defaults](#set-configuration-defaults) for supported


1401 1458 

1402[otel]1459[otel]

1403environment = "prod"1460environment = "prod"

1404exporter = "otlp-http" # point at your collector1461exporter = { otlp-http = { endpoint = "https://otel.example.com/v1/logs", protocol = "binary" } }

1405log_user_prompt = false # keep prompts redacted1462log_user_prompt = false # keep prompts redacted

1406# exporter details live under exporter tables; see Monitoring and telemetry above

1407```1463```

1408 1464 

1409#### Recommended guardrails1465#### Recommended guardrails

1410 1466 

1411- Prefer `workspace-write` with approvals for most users; reserve full access for controlled containers.1467- Prefer `workspace-write` with approvals for most users; reserve full access for controlled containers.

1412- Keep `network_access = false` unless your security review allows a collector or domains required by your workflows.1468- Keep `network_access = false` unless your security review allows a collector or domains required by your workflows.

1413- Use managed configuration to pin OTel settings (exporter, environment), but keep `log_user_prompt = false` unless your policy explicitly allows storing prompt contents.1469- To enforce telemetry settings, use [OpenTelemetry requirements](#enforce-opentelemetry-settings). Keep `log_user_prompt = false` unless your policy allows storing prompt contents.

1414- Periodically audit diffs between local `config.toml` and managed policy to catch drift; managed layers should win over local flags and files.1470- Periodically audit diffs between local `config.toml` and managed policy to catch drift; managed layers should win over local flags and files.

1415 1471 

1416### macOS managed preferences (MDM)1472### macOS managed preferences (MDM)

Details

19 19 

20For more about the files stored under `CODEX_HOME`, see20For more about the files stored under `CODEX_HOME`, see

21[Config and state locations](https://learn.chatgpt.com/docs/config-file/config-advanced#config-and-state-locations).21[Config and state locations](https://learn.chatgpt.com/docs/config-file/config-advanced#config-and-state-locations).

22If multiple Linux hosts open the same databases, see [Run Codex with an NFS home directory](https://learn.chatgpt.com/docs/environments/network-file-systems).

22 23 

23## Installer variables24## Installer variables

24 25 

Details

164 164 

165Suppose Codex finishes some work on a worktree and you choose to create a `feature/a` branch on it using **Create branch here**. Now, you want to try it on your local checkout. If you tried to check out the branch, you would get the following error:165Suppose Codex finishes some work on a worktree and you choose to create a `feature/a` branch on it using **Create branch here**. Now, you want to try it on your local checkout. If you tried to check out the branch, you would get the following error:

166 166 

167```167```text

168fatal: 'feature/a' is already used by worktree at '<WORKTREE_PATH>'168fatal: 'feature/a' is already used by worktree at '<WORKTREE_PATH>'

169```169```

170 170 

Details

1# Run Codex with an NFS home directory

2 

3> For the complete documentation index, see [llms.txt](https://learn.chatgpt.com/llms.txt). Markdown versions of documentation pages are available by appending `.md` to the page URL.

4 

5When Linux hosts share a [Codex home](https://learn.chatgpt.com/docs/config-file/config-advanced#config-and-state-locations) (`~/.codex` by default) over Network File System (NFS), they can corrupt a SQLite database if they open it in write-ahead log (WAL) mode at the same time. For interactive work in the CLI or the [Codex app over SSH](https://learn.chatgpt.com/docs/remote-connections#connect-to-an-ssh-host), [migrate the shared home](#migrate-an-existing-nfs-home). For [independent batch jobs](#run-independent-batch-jobs), keep each host’s Codex home or SQLite directory on local disk.

6 

7## Why NFS can break SQLite

8 

9The Codex app and terminal UI use a SQLite index to list conversations. The databases also store goals and memory-processing state. On local disk, Codex normally uses WAL mode. Processes on different hosts can’t share the memory that WAL needs.

10 

11When Codex detects Linux NFS, it creates databases in rollback-journal mode (`DELETE`), which uses file locks instead. Migrate existing WAL databases before opening them from another host.

12 

13Codex also saves conversation events in `rollout-*.jsonl` files. These can already live on NFS because one process writes each rollout at a time. Migrating SQLite leaves those files in place.

14 

15## Migrate an existing NFS home

16 

17### 1. Check the shared home

18 

19Run `codex --version` on each host, including any SSH backend. Use a build that includes `codex migrate-nfs-db`, such as [Codex CLI 0.166.0](https://github.com/openai/codex/releases/tag/rust-v0.166.0). Confirm that all hosts using this shared home use the same [SQLite directory](https://learn.chatgpt.com/docs/config-file/environment-variables#core-locations). Ask your storage administrator to verify that a file lock held on one host blocks a conflicting lock on the other. Keep SQLite local if the mount can’t do this.

20 

21During migration, do not set or change the SQLite home or log directory.

22 

23### 2. Stop Codex on every host

24 

25<WarningTip title="Stop all clients before migrating">

26 End active turns, close the app and CLI, and stop remote app servers,

27 background daemons, and scheduled jobs that use this home. Keep them stopped

28 on every host until migration completes. A concurrent writer can corrupt the

29 database and lose changes to goals or memories.

30 

31Session rollouts are separate files and can’t restore all database state.

32 

33</WarningTip>

34 

35In [daemon mode](https://learn.chatgpt.com/docs/developer-commands?surface=cli#cli-manage-the-background-server-with-daemon), the CLI connects to a background server that stays running between sessions. Its Unix socket works only on the host that started it. We recommend running the CLI without the daemon when hosts share a Codex home over NFS. Stop the daemon on each host that runs it with `codex app-server daemon stop`.

36 

37To keep the CLI from starting it again, set `daemon_auto_start` to `false` under `[features]` in your shared `config.toml`.

38 

39```toml

40[features]

41daemon_auto_start = false

42```

43 

44For a single CLI session, pass [`--no-daemon`](https://learn.chatgpt.com/docs/developer-commands?surface=cli#cli-global-flags). This flag also bypasses a daemon that’s already running.

45 

46### 3. Run the migration

47 

48Run the migration on just one Linux host per shared Codex home. Use the home owner’s account and usual configuration. Keep Codex stopped on the other hosts until the migration finishes.

49 

50```sh

51codex migrate-nfs-db

52```

53 

54### 4. Resume a conversation

55 

56If the command reports `Skipped logs database`, check its location. A logs database on local disk needs no further action. If it’s on NFS, confirm it uses `DELETE` journal mode or move it to local disk before reopening Codex on another host.

57 

58After migration succeeds, open the same project on another host as the same user. Resume a familiar conversation in the app or run [`codex --no-daemon resume`](https://learn.chatgpt.com/docs/developer-commands?surface=cli#cli-codex-resume). Check that your last turn is there and that you can continue the conversation.

59 

60## Move diagnostic logs to local disk

61 

62**Optional, recommended after migration.** Diagnostic logs help you investigate errors and slow launches. Writing them locally reduces traffic on NFS.

63 

64Create a private, writable log directory on each host. Set `log_dir` in the user’s `config.toml` to the absolute path for that user. For example, Alice might use this setting.

65 

66```toml

67log_dir = "/var/local/codex/alice/logs"

68```

69 

70New logs go to that directory. Older logs stay in place.

71 

72A managed `sqlite_home` keeps the SQLite logs database in the required

73 directory even when you set `log_dir`. See [managed

74 configuration](https://learn.chatgpt.com/docs/enterprise/managed-configuration).

75 

76## Enforce the journal mode across a fleet

77 

78First stop all clients on every host that uses an affected home. The setting carries the name `unsafe` because converting a database while another host writes to it can corrupt it.

79 

80With clients stopped, add this setting to the hosts’ [managed configuration](https://learn.chatgpt.com/docs/enterprise/managed-configuration) in `/etc/codex/requirements.toml`.

81 

82```toml

83unsafe_enforce_sqlite_journal_mode = true

84```

85 

86The setting applies to every user on the configured hosts. The next time a user opens Codex, it automatically migrates existing WAL databases as it opens them for writing on NFS. For each shared home, let the migration finish on one host before reconnecting other hosts. If migration fails, leave other clients stopped and follow the [recovery steps](#frequently-asked-questions).

87 

88## Run independent batch jobs

89 

90If an unattended job doesn’t need your interactive session history, run [`codex exec`](https://learn.chatgpt.com/docs/non-interactive-mode) with a Codex home on the worker’s local disk. If session files need to stay on NFS, set `CODEX_SQLITE_HOME` to a private local directory for each job so workers don’t contend for the same database.

91 

92- **Keep a conversation record.** Give each job a private, durable `CODEX_HOME` for its rollout and a private, host-local `CODEX_SQLITE_HOME` for its database. The worker’s index is separate from your interactive index. Keep the rollout under `$CODEX_HOME/sessions/` if you need to inspect the job after the worker exits.

93- **Keep only the result.** Put the job home on local disk and run [`codex exec --ephemeral`](https://learn.chatgpt.com/docs/non-interactive-mode). It skips saving a resumable session. Use `-o` to write the final response to a durable file or `--json` to stream events to your job runner.

94 

95For a job that needs a rollout, have the scheduler create both directories and provision authentication and configuration for the job home. Replace the example paths with this job’s durable Codex home and worker-local SQLite directory. A managed or configured `sqlite_home` takes precedence over `CODEX_SQLITE_HOME`.

96 

97```sh

98CODEX_HOME="/mnt/nfs/codex/jobs/job-1234" \

99CODEX_SQLITE_HOME="/var/local/codex/jobs/job-1234" \

100 codex exec "Summarize this repository's build steps."

101```

102 

103## Frequently asked questions

104 

105<ToggleSection title="How can I tell whether an error is related to NFS?">

106 

107A migration error such as `cannot open source database exclusively` means Codex couldn’t lock the database. Another client can cause this on local disk too. On Linux, run `findmnt -T "$DB_PATH"` with the path to the affected database. If it reports `nfs` or `nfs4`, check for writers on every host and ask the storage administrator to verify cross-host locking on that mount. Stop the remaining clients before retrying.

108 

109</ToggleSection>

110 

111<ToggleSection title="What should I look for in the migration output?">

112 

113For each database, Codex prints `Migrated database:` and `WAL backup:`, or `Already in DELETE mode:`. If you rely on group permissions or extended access rules, verify those after migration and before reopening clients.

114 

115If `log_dir` was already set, the command skips the logs database. Before sharing that database across hosts, make sure it uses `DELETE` or keep it on local disk.

116 

117If you see `No databases found.`, check the [effective SQLite directory](https://learn.chatgpt.com/docs/config-file/environment-variables#core-locations) for the user who owns the home. If local staging space is insufficient, choose a host-local directory with enough space and pass its absolute path with `--staging-dir`.

118 

119</ToggleSection>

120 

121<ToggleSection title="How do I recover after a failed migration?">

122 

123Keep other clients stopped. Save the exact error, the database path, and the printed backup path. Some databases may already have migrated. Keep the original database and its sidecar files together in their backup directory. After resolving a lock or space error, rerun `codex migrate-nfs-db` on the same host. For an integrity error or a missing replacement, work from copies before restoring anything. Session rollouts can help rebuild conversation history. Recovering SQLite-only state, including goals, requires an intact database.

124 

125Before starting a separate CLI session, confirm that managed storage settings won’t redirect writes to the affected home. Then start Codex using a temporary directory on local disk. The new home may require sign-in.

126 

127```sh

128recovery_home=$(mktemp -d /tmp/codex-nfs-recovery.XXXXXXXX) &&

129 CODEX_HOME="$recovery_home" CODEX_SQLITE_HOME="$recovery_home" \

130 codex --no-daemon --sandbox read-only \

131 "Help me recover a failed Codex NFS migration, run `$ codex doctor` to get the information about corrupted databases. Backup paths for databases should be in the original database with `_wal_migration_backup` in the end of the file. Ask user for the original error. Plan a recovery using copies and leave the originals untouched."

132```

133 

134</ToggleSection>

extend/mcp.md +19 −8

Details

271 271 

272Run `codex mcp list` to see configured servers. To see all available MCP272Run `codex mcp list` to see configured servers. To see all available MCP

273commands, run `codex mcp --help`. For a server that supports OAuth, run273commands, run `codex mcp --help`. For a server that supports OAuth, run

274`codex mcp login <server-name>`.274`codex mcp login <server-name>`. If you're using a terminal without a local

275browser, run `codex mcp login <server-name> --no-browser`. Open the printed

276authorization URL in a browser and sign in. Paste the full redirect URL back

277into the terminal, even if the browser can't load the callback page.

275 278 

276#### Terminal UI (TUI)279#### Terminal UI (TUI)

277 280 


317- `env` (optional): Environment variables to set for the server.320- `env` (optional): Environment variables to set for the server.

318- `env_vars` (optional): Environment variables to allow and forward.321- `env_vars` (optional): Environment variables to allow and forward.

319- `cwd` (optional): Working directory to start the server from.322- `cwd` (optional): Working directory to start the server from.

320- `experimental_environment` (optional): Set to `remote` to start the stdio

321 server through a remote executor environment when one is available.

322 323 

323`env_vars` can contain plain variable names or objects with a source:324`env_vars` can contain plain variable names or objects with a source:

324 325 


364 365 

365#### Other configuration options366#### Other configuration options

366 367 

368- `environment_id` selects the environment for a stdio or Streamable HTTP

369 server. It defaults to `local`. To connect through a remote executor, use

370 its registered environment ID.

367- `startup_timeout_sec` (optional): Timeout (seconds) for the server to start. Default: `10`.371- `startup_timeout_sec` (optional): Timeout (seconds) for the server to start. Default: `10`.

368- `tool_timeout_sec` (optional): Timeout (seconds) for the server to run a tool. Default: `60`.372- `tool_timeout_sec` (optional): Timeout (seconds) for the server to run a tool. Default: `60`.

369- `enabled` (optional): Set `false` to disable a server without deleting it.373- `enabled` (optional): Set `false` to disable a server without deleting it.

370- `required` (optional): Set `true` to make startup fail if this enabled server can't initialize.374- Set `required = true` to make startup fail if this enabled server isn't

375 ready. By default, `startup_readiness = "connection"` requires a live connection.

376 Set `startup_readiness = "catalog"` to let a valid cached tool catalog

377 satisfy startup while the server connects. Tool calls still need a live

378 connection.

371- `enabled_tools` (optional): Tool allow list.379- `enabled_tools` (optional): Tool allow list.

372- `disabled_tools` (optional): Tool deny list (applied after `enabled_tools`).380- `disabled_tools` (optional): Tool deny list (applied after `enabled_tools`).

373- `default_tools_approval_mode` (optional): Default approval behavior for381- `default_tools_approval_mode` (optional): Default approval behavior for


404`mcp_servers.example.oauth.client_secret` in `config.toml`. Keep that file412`mcp_servers.example.oauth.client_secret` in `config.toml`. Keep that file

405private and out of version control.413private and out of version control.

406 414 

407Codex displays the complete callback URL to register with your provider:415Register the exact callback URL that `codex mcp add` prints. When the

416authorization server advertises issuer support, the CLI can print this URL.

408 417 

409```text418```text

410OAuth callback URL: http://127.0.0.1/callback419OAuth callback URL: http://127.0.0.1/callback

411```420```

412 421 

413Codex saves the callback alongside the client ID in `config.toml` for later422For the public client in this example, Codex saves the callback and client ID

414logins:423in `config.toml` for later logins:

415 424 

416```toml425```toml

417[mcp_servers.example]426[mcp_servers.example]


477Set `mcp_servers.<server-name>.scopes` in `config.toml` to choose OAuth scopes486Set `mcp_servers.<server-name>.scopes` in `config.toml` to choose OAuth scopes

478for a server. To override them for one login, run487for a server. To override them for one login, run

479`codex mcp login <name> --scopes read,write`.488`codex mcp login <name> --scopes read,write`.

480If neither is set, Codex uses advertised OAuth scopes when available.489If neither is set, Codex requests the scopes in the server's initial

490`WWW-Authenticate` challenge. If the challenge omits scopes, Codex uses the

491scopes advertised in the protected resource metadata when available.

481 492 

482An empty list (`scopes = []`) still lets the OAuth library choose scopes.493An empty list (`scopes = []`) still lets the OAuth library choose scopes.

483The library can also add `offline_access` when the authorization server supports it.494The library can also add `offline_access` when the authorization server supports it.

hooks.md +24 −4

Details

23| When | Hooks |23| When | Hooks |

24| --------------------------------- | ------------------------------------------------------------------------------------------------------------------------- |24| --------------------------------- | ------------------------------------------------------------------------------------------------------------------------- |

25| During a turn | `PreToolUse`, `PermissionRequest`, `PostToolUse`, `PreCompact`, `PostCompact`, `UserPromptSubmit`, `SubagentStop`, `Stop` |25| During a turn | `PreToolUse`, `PermissionRequest`, `PostToolUse`, `PreCompact`, `PostCompact`, `UserPromptSubmit`, `SubagentStop`, `Stop` |

26| For each model request attempt | `PreModelRequest`, `PostModelRequest` |

26| When you interrupt an active turn | `Interrupt` (doesn't run for subagents) |27| When you interrupt an active turn | `Interrupt` (doesn't run for subagents) |

27| When a session or subagent starts | `SessionStart`, `SubagentStart` |28| When a session or subagent starts | `SessionStart`, `SubagentStart` |

28| When the main thread ends | `SessionEnd` (doesn't run for subagents) |29| When the main thread ends | `SessionEnd` (doesn't run for subagents) |


403- Codex also sets `CLAUDE_PLUGIN_ROOT` and `CLAUDE_PLUGIN_DATA` for404- Codex also sets `CLAUDE_PLUGIN_ROOT` and `CLAUDE_PLUGIN_DATA` for

404 compatibility with existing plugin hooks.405 compatibility with existing plugin hooks.

405 406 

406Plugin hooks use the same event schema as other hooks. Installing or enabling a407Plugin hooks use the same event schema as other hooks. Review and trust them

407plugin doesn't automatically trust its hooks; Codex skips plugin-bundled hooks408before they run. In the CLI, open `/hooks`. In the desktop app, select

408until you review and trust the current hook definition.409**Review hooks** in the composer or open **Settings > Hooks**.

410If a plugin update changes a bundled script,

411Codex requires a new review even if the hook definition stays the same.

409 412 

410## Matcher patterns413## Matcher patterns

411 414 


416Only some current Codex events honor `matcher`:419Only some current Codex events honor `matcher`:

417 420 

418| Event | What `matcher` filters | Notes |421| Event | What `matcher` filters | Notes |

419| ------------------- | ---------------------- | -------------------------------------------------------------- |422| ------------------------------------- | ---------------------- | -------------------------------------------------------------- |

420| `PermissionRequest` | tool name | Support includes `Bash`, `apply_patch`\*, and MCP tool names |423| `PermissionRequest` | tool name | Support includes `Bash`, `apply_patch`\*, and MCP tool names |

421| `PostToolUse` | tool name | See [Tool coverage](#tool-coverage) |424| `PostToolUse` | tool name | See [Tool coverage](#tool-coverage) |

422| `PostCompact` | compaction trigger | Values are `manual` or `auto` |425| `PostCompact` | compaction trigger | Values are `manual` or `auto` |

426| `PreModelRequest`, `PostModelRequest` | not supported | Both events run for each model request attempt |

423| `PreCompact` | compaction trigger | Values are `manual` or `auto` |427| `PreCompact` | compaction trigger | Values are `manual` or `auto` |

424| `PreToolUse` | tool name | See [Tool coverage](#tool-coverage) |428| `PreToolUse` | tool name | See [Tool coverage](#tool-coverage) |

425| `SessionEnd` | end reason | Currently only `other` |429| `SessionEnd` | end reason | Currently only `other` |


957| `PostToolUse` returns `decision: "block"` or exits with code `2` | The tool runs, then the promise rejects with the hook reason. |961| `PostToolUse` returns `decision: "block"` or exits with code `2` | The tool runs, then the promise rejects with the hook reason. |

958| `PostToolUse` returns `continue: false` | Codex uses the hook feedback for the model-visible result, but doesn't reject the nested tool promise. |962| `PostToolUse` returns `continue: false` | Codex uses the hook feedback for the model-visible result, but doesn't reject the nested tool promise. |

959 963 

964### PreModelRequest and PostModelRequest

965 

966Use these hooks to log model requests, including retries within the same turn.

967`PreModelRequest` runs before each attempt. `PostModelRequest` reports the

968outcome. Both receive the model and `turn_id`, plus `agent_id` and `agent_type`

969when available. Hook output is diagnostic only. It can't change the model's

970context or block a request.

971 

972`PostModelRequest` includes three additional fields:

973 

974| Field | Meaning |

975| ------------- | -------------------------------------------------------------- |

976| `status` | `completed`, `failed`, or `cancelled`. |

977| `error` | Error message when available, otherwise `null`. |

978| `token_usage` | Token counts for the attempt when available, otherwise `null`. |

979 

960### PreCompact980### PreCompact

961 981 

962`PreCompact` runs before Codex compacts the chat. `matcher` is applied982`PreCompact` runs before Codex compacts the chat. `matcher` is applied

import.md +4 −4

Details

43 43 

44### Import in Codex CLI44### Import in Codex CLI

45 45 

461. Start a local Codex CLI session and type `/import`.461. Type `/import` in an idle Codex CLI session.

472. Choose **Claude Code** or **Cursor**.472. Choose **Claude Code** or **Cursor**.

483. Select the supported setup, project files, and recent chats you want to483. Select the supported setup, project files, and recent chats you want to

49 import.49 import.

504. Review the imported configuration and continue working in Codex.504. Review the imported configuration and continue working in Codex.

51 51 

52Codex CLI imports up to 50 chats from the last 30 days. The `/import` command52Codex CLI imports up to 50 chats from the last 30 days. When connected to a

53isn't available during a running task, in a remote session, or while connected53local daemon or remote server, Codex looks for user settings and recent chats

54to a local app-server daemon. See [CLI slash54on that server. It also checks the current project directory, if available. See [CLI slash

55commands](https://learn.chatgpt.com/docs/developer-commands?surface=cli#cli-import-claude-code-or-cursor-setup-with-import).55commands](https://learn.chatgpt.com/docs/developer-commands?surface=cli#cli-import-claude-code-or-cursor-setup-with-import).

56 56 

57 57 

mcp.md +19 −8

Details

271 271 

272Run `codex mcp list` to see configured servers. To see all available MCP272Run `codex mcp list` to see configured servers. To see all available MCP

273commands, run `codex mcp --help`. For a server that supports OAuth, run273commands, run `codex mcp --help`. For a server that supports OAuth, run

274`codex mcp login <server-name>`.274`codex mcp login <server-name>`. If you're using a terminal without a local

275browser, run `codex mcp login <server-name> --no-browser`. Open the printed

276authorization URL in a browser and sign in. Paste the full redirect URL back

277into the terminal, even if the browser can't load the callback page.

275 278 

276#### Terminal UI (TUI)279#### Terminal UI (TUI)

277 280 


317- `env` (optional): Environment variables to set for the server.320- `env` (optional): Environment variables to set for the server.

318- `env_vars` (optional): Environment variables to allow and forward.321- `env_vars` (optional): Environment variables to allow and forward.

319- `cwd` (optional): Working directory to start the server from.322- `cwd` (optional): Working directory to start the server from.

320- `experimental_environment` (optional): Set to `remote` to start the stdio

321 server through a remote executor environment when one is available.

322 323 

323`env_vars` can contain plain variable names or objects with a source:324`env_vars` can contain plain variable names or objects with a source:

324 325 


364 365 

365#### Other configuration options366#### Other configuration options

366 367 

368- `environment_id` selects the environment for a stdio or Streamable HTTP

369 server. It defaults to `local`. To connect through a remote executor, use

370 its registered environment ID.

367- `startup_timeout_sec` (optional): Timeout (seconds) for the server to start. Default: `10`.371- `startup_timeout_sec` (optional): Timeout (seconds) for the server to start. Default: `10`.

368- `tool_timeout_sec` (optional): Timeout (seconds) for the server to run a tool. Default: `60`.372- `tool_timeout_sec` (optional): Timeout (seconds) for the server to run a tool. Default: `60`.

369- `enabled` (optional): Set `false` to disable a server without deleting it.373- `enabled` (optional): Set `false` to disable a server without deleting it.

370- `required` (optional): Set `true` to make startup fail if this enabled server can't initialize.374- Set `required = true` to make startup fail if this enabled server isn't

375 ready. By default, `startup_readiness = "connection"` requires a live connection.

376 Set `startup_readiness = "catalog"` to let a valid cached tool catalog

377 satisfy startup while the server connects. Tool calls still need a live

378 connection.

371- `enabled_tools` (optional): Tool allow list.379- `enabled_tools` (optional): Tool allow list.

372- `disabled_tools` (optional): Tool deny list (applied after `enabled_tools`).380- `disabled_tools` (optional): Tool deny list (applied after `enabled_tools`).

373- `default_tools_approval_mode` (optional): Default approval behavior for381- `default_tools_approval_mode` (optional): Default approval behavior for


404`mcp_servers.example.oauth.client_secret` in `config.toml`. Keep that file412`mcp_servers.example.oauth.client_secret` in `config.toml`. Keep that file

405private and out of version control.413private and out of version control.

406 414 

407Codex displays the complete callback URL to register with your provider:415Register the exact callback URL that `codex mcp add` prints. When the

416authorization server advertises issuer support, the CLI can print this URL.

408 417 

409```text418```text

410OAuth callback URL: http://127.0.0.1/callback419OAuth callback URL: http://127.0.0.1/callback

411```420```

412 421 

413Codex saves the callback alongside the client ID in `config.toml` for later422For the public client in this example, Codex saves the callback and client ID

414logins:423in `config.toml` for later logins:

415 424 

416```toml425```toml

417[mcp_servers.example]426[mcp_servers.example]


477Set `mcp_servers.<server-name>.scopes` in `config.toml` to choose OAuth scopes486Set `mcp_servers.<server-name>.scopes` in `config.toml` to choose OAuth scopes

478for a server. To override them for one login, run487for a server. To override them for one login, run

479`codex mcp login <name> --scopes read,write`.488`codex mcp login <name> --scopes read,write`.

480If neither is set, Codex uses advertised OAuth scopes when available.489If neither is set, Codex requests the scopes in the server's initial

490`WWW-Authenticate` challenge. If the challenge omits scopes, Codex uses the

491scopes advertised in the protected resource metadata when available.

481 492 

482An empty list (`scopes = []`) still lets the OAuth library choose scopes.493An empty list (`scopes = []`) still lets the OAuth library choose scopes.

483The library can also add `offline_access` when the authorization server supports it.494The library can also add `offline_access` when the authorization server supports it.

memories.md +10 −2

Details

93`~/.codex`. See [Config and state locations](https://learn.chatgpt.com/docs/config-file/config-advanced#config-and-state-locations)93`~/.codex`. See [Config and state locations](https://learn.chatgpt.com/docs/config-file/config-advanced#config-and-state-locations)

94for how Codex uses `CODEX_HOME`.94for how Codex uses `CODEX_HOME`.

95 95 

96The main memory files live under `~/.codex/memories/` and include summaries,96When you enable memories in a fresh Codex home, the CLI uses

97durable entries, recent inputs, and supporting evidence from prior chats.97`$CODEX_HOME/memories_v2/` by default. If `$CODEX_HOME/memories/` already

98exists, the CLI continues to use that store by default. Set

99`memories.version` to choose a version explicitly. With no explicit version,

100`memories.dual_write = false` keeps even a fresh profile on v1.

101 

102In the desktop app, check both `$CODEX_HOME/memories/` and

103`$CODEX_HOME/memories_v2/` for generated summaries and supporting evidence

104from prior chats. During the migration, a new local chat with memories enabled

105can read from `memories/` and write to both directories, even on a fresh profile.

98 106 

99Treat these files as generated state. You can inspect them when troubleshooting107Treat these files as generated state. You can inspect them when troubleshooting

100or before sharing your Codex home directory, but don't rely on editing them by108or before sharing your Codex home directory, but don't rely on editing them by

Details

36codex exec --ephemeral "triage this repository and suggest next steps"36codex exec --ephemeral "triage this repository and suggest next steps"

37```37```

38 38 

39For workers with network-mounted home directories, see how to [keep job state local and retain the session rollout](https://learn.chatgpt.com/docs/environments/network-file-systems#run-independent-batch-jobs).

40 

39If stdin is piped and you also provide a prompt argument, Codex treats the prompt as the instruction and the piped content as additional context.41If stdin is piped and you also provide a prompt argument, Codex treats the prompt as the instruction and the piped content as additional context.

40 42 

41This lets you generate input with one command and hand it directly to Codex:43This lets you generate input with one command and hand it directly to Codex:

Details

36codex exec --ephemeral "triage this repository and suggest next steps"36codex exec --ephemeral "triage this repository and suggest next steps"

37```37```

38 38 

39For workers with network-mounted home directories, see how to [keep job state local and retain the session rollout](https://learn.chatgpt.com/docs/environments/network-file-systems#run-independent-batch-jobs).

40 

39If stdin is piped and you also provide a prompt argument, Codex treats the prompt as the instruction and the piped content as additional context.41If stdin is piped and you also provide a prompt argument, Codex treats the prompt as the instruction and the piped content as additional context.

40 42 

41This lets you generate input with one command and hand it directly to Codex:43This lets you generate input with one command and hand it directly to Codex:

rules.md +1 −1

Details

151. Create a `.rules` file under a `rules/` folder next to an active config layer (for example, `~/.codex/rules/default.rules`).151. Create a `.rules` file under a `rules/` folder next to an active config layer (for example, `~/.codex/rules/default.rules`).

162. Add a rule. This example prompts before allowing `gh pr view` to run outside the sandbox.162. Add a rule. This example prompts before allowing `gh pr view` to run outside the sandbox.

17 17 

18```python18```python snippet=configuration reason="Starlark policy configuration interpreted by Codex"

19 # Prompt before running commands with the prefix `gh pr view` outside the sandbox.19 # Prompt before running commands with the prefix `gh pr view` outside the sandbox.

20 prefix_rule(20 prefix_rule(

21 # The prefix to match.21 # The prefix to match.

sdk.md +40 −5

Details

37 38 

38Start a thread with Codex and run it with your prompt.39Start a thread with Codex and run it with your prompt.

39 40 

40```ts41```typescript

41 42import { Codex } from "@openai/codex-sdk";

42 43 

43const codex = new Codex();44const codex = new Codex();

44const thread = codex.startThread();45const thread = codex.startThread();


49console.log(result.finalResponse);50console.log(result.finalResponse);

50```51```

51 52 

53 

52Call `run()` again to continue on the same thread, or resume a past thread by providing a thread ID.54Call `run()` again to continue on the same thread, or resume a past thread by providing a thread ID.

53 55 

54```ts56```typescript

55// running the same thread57// running the same thread

56const result = await thread.run("Implement the plan");58const result = await thread.run("Implement the plan");

57 59 


59 61 

60// resuming past thread62// resuming past thread

61 63 

62const threadId = "<thread-id>";64const threadId = thread.id!;

63const thread2 = codex.resumeThread(threadId);65const thread2 = codex.resumeThread(threadId);

64const result2 = await thread2.run("Pick up where you left off");66const result2 = await thread2.run("Pick up where you left off");

65 67 

66console.log(result2.finalResponse);68console.log(result2.finalResponse);

67```69```

68 70 

71 

72To identify threads created by your integration, set `threadSource` when you create a thread.

73For example, `codex.startThread({ threadSource: "ci" })` labels the thread

74as `ci`. Resuming a thread preserves its original source.

75 

69### Configuration overrides76### Configuration overrides

70 77 

71Pass `config` to set structured Codex configuration. For keys that can't be78Pass `config` to set structured Codex configuration. For keys that can't be

72expressed as dotted paths, use `configOverrides` to pass raw TOML strings as79expressed as dotted paths, use `configOverrides` to pass raw TOML strings as

73separate `--config` arguments:80separate `--config` arguments:

74 81 

75```ts82```typescript

76const codex = new Codex({83const codex = new Codex({

77 config: { default_permissions: "audit" },84 config: { default_permissions: "audit" },

78 configOverrides: [85 configOverrides: [


138```151```

139 152 

140 153 

154### Pass content from another system

155 

156When a tool, application, or another agent supplies content, pass an

157`ExternalMessage` as the entire input to `thread.run()` or `thread.turn()`.

158For example, `ExternalMessage(tool_name="issue_tracker", content=issue_body)`

159identifies the tool that supplied an issue description. Codex treats the

160description as tool output, at a lower priority than user and developer instructions. The message

161can start a turn or join an active regular turn.

162 

163### Resume a thread without loading its history

164 

165Pass `include_turns=False` to `codex.thread_resume()` or `codex.thread_fork()`

166to skip loading old turns into the response. The model still has the thread's

167context. To retrieve the history later, call `thread.read(include_turns=True)`.

168 

169With Codex CLI 0.166.0 or later, use the thread's saved model provider to resume it. If you switch providers, call `codex.thread_fork(thread_id)` to

170continue from the same history on the new provider.

171 

172### Set the service tier for one turn

173 

174To choose the service tier for a single new turn, pass `turn_service_tier` to

175`run()` or `turn()`. For example, `turn_service_tier="default"` uses standard

176speed for that turn. To change the tier for this and later turns, pass

177`service_tier`. Joining an active turn leaves its tier unchanged.

178 

179If you supply your own Codex executable, `ExternalMessage`, explicit

180`include_turns` on resume or fork, and `turn_service_tier` require Codex CLI

1810.151.0 or later.

182 

141### Sandbox presets183### Sandbox presets

142 184 

143Use the same `Sandbox` presets when creating a thread or changing its filesystem185Use the same `Sandbox` presets when creating a thread or changing its filesystem

Details

190 │ └── attempt-1/190 │ └── attempt-1/

191 │ ├── scan-manifest.json191 │ ├── scan-manifest.json

192 │ ├── findings.json192 │ ├── findings.json

193 │ ├── coverage.json

194 │ └── report.md193 │ └── report.md

195 └── identity/194 └── identity/

196 └── attempt-1/195 └── attempt-1/

197 ├── scan-manifest.json196 ├── scan-manifest.json

198 ├── findings.json197 ├── findings.json

199 ├── coverage.json

200 └── report.md198 └── report.md

201```199```

202 200 


205- `results.jsonl` records each repository attempt, its status, artifact203- `results.jsonl` records each repository attempt, its status, artifact

206 directory, and any available cost or error details.204 directory, and any available cost or error details.

207- `report.md` provides a readable report for one repository attempt.205- `report.md` provides a readable report for one repository attempt.

208- `findings.json` and `coverage.json` record that attempt's findings and206- Open `findings.json` for the attempt's findings and `scan-manifest.json` for

209 reviewed scope.207 its configured scope and review exclusions.

210 208 

211Export one completed repository scan when you need a portable result:209Export one completed repository scan when you need a portable result:

212 210 

Details

65npx @openai/codex-security scans show SCAN_ID65npx @openai/codex-security scans show SCAN_ID

66```66```

67 67 

68Each completed scan keeps its report, findings, coverage, and supporting68Each completed scan keeps its report, findings, manifest, and supporting

69artifacts together. See [Scan69artifacts together. See [Scan

70artifacts](https://learn.chatgpt.com/docs/security/cli/reference#scan-artifacts) for the full layout.70artifacts](https://learn.chatgpt.com/docs/security/cli/reference#scan-artifacts) for the full layout.

71 71 


170 170 

171### What does incomplete coverage mean171### What does incomplete coverage mean

172 172 

173Review `coverage.json` for excluded paths, deferred surfaces, and open questions.173In `scan-manifest.json`, check `scan.status` to see whether the scan finished.

174New results don't include a coverage-completeness field. Check `scan.status` in174`scan.scope` records the configured scope. `scan.review.excludedPaths` lists

175`scan-manifest.json` for execution status.175path patterns the scan excluded from review. If an older manifest has

176`scan.coverageRef`, open the file it names for coverage details.

176 177 

177Coverage gaps don't change a completed scan's exit code. Exit `0` doesn't mean178Coverage gaps don't change a completed scan's exit code. Exit `0` doesn't mean

178every file was reviewed. A later scan can't establish that an earlier finding179every file was reviewed. A later scan can't establish that an earlier finding

Details

35| `codex-security scans` | List, inspect, compare, and retrieve saved scan logs. |35| `codex-security scans` | List, inspect, compare, and retrieve saved scan logs. |

36| `codex-security findings` | Review and update saved security findings. |36| `codex-security findings` | Review and update saved security findings. |

37| `codex-security export` | Export findings or a retained threat model. |37| `codex-security export` | Export findings or a retained threat model. |

38| `codex-security publish` | Publish findings to Linear or a custom findings service. |38| `codex-security publish` | Check or publish a saved scan, or import external findings. |

39| `codex-security classify-severity` | Apply a severity rubric to saved findings. |39| `codex-security classify-severity` | Apply a severity rubric to saved findings. |

40| `codex-security suggest-owners` | Suggest finding owners using CODEOWNERS and Git history. |40| `codex-security suggest-owners` | Suggest finding owners using CODEOWNERS and Git history. |

41| `codex-security dedupe` | Deduplicate saved findings. |41| `codex-security dedupe` | Deduplicate saved findings. |


676`codex-security validate /path/outside/repository/alerts.json` to assess them.676`codex-security validate /path/outside/repository/alerts.json` to assess them.

677Keep the full JSON without output filters or token limits when saving677Keep the full JSON without output filters or token limits when saving

678validation inputs. Use [`scan import`](#codex-security-scan-import) for678validation inputs. Use [`scan import`](#codex-security-scan-import) for

679findings already in the Codex Security schema.679findings already in the Codex Security schema. To import Dependabot alerts, use

680[`publish findings`](#codex-security-publish-findings).

680 681 

681## `codex-security install-hook`682## `codex-security install-hook`

682 683 


1210The CLI doesn't send model credentials to a custom service. Handle any required1211The CLI doesn't send model credentials to a custom service. Handle any required

1211authentication outside the CLI. See the [findings service guide](https://github.com/openai/codex-security/blob/main/sdk/typescript/docs/findings-service.md) for deployment and protocol details.1212authentication outside the CLI. See the [findings service guide](https://github.com/openai/codex-security/blob/main/sdk/typescript/docs/findings-service.md) for deployment and protocol details.

1212 1213 

1214## `codex-security publish findings`

1215 

1216Use `--to local` to save imported findings on your machine. With `--to cloud`,

1217even a preview contacts the service. It needs a file-backed ChatGPT login and

1218an authorized repository ID or URL with an existing Cloud environment. A Cloud

1219import can return a partial result if the service rejects individual records.

1220See the [GitHub import guide](https://github.com/openai/codex-security/blob/main/sdk/typescript/docs/cli.md#import-github-findings-locally-or-to-cloud) for both workflows.

1221 

1222To import Dependabot alerts for a local checkout, you need a saved export from

1223the same GitHub repository. Follow the [Dependabot export guide](https://github.com/openai/codex-security/blob/main/docs/scanner-imports/github-dependabot.md) to save all pages outside the checkout using a token with read access to Dependabot alerts.

1224 

1225Append `echo "$out/dependabot.jsonl"` to the export script before running it.

1226In a new shell, use the path it printed to preview the file. Replace `./project` and `OWNER/REPO` with your checkout and repository.

1227If the checkout has network remotes, one must match the alert repository.

1228Otherwise, verify that the export belongs to the checkout.

1229 

1230```bash

1231export CODEX_SECURITY_ENABLE_EXTERNAL_IMPORTS=1

1232npx @openai/codex-security publish findings /path/to/dependabot.jsonl \

1233 --to local --repository ./project --provider github \

1234 --source-key github.com/OWNER/REPO/dependabot --dry-run --format json

1235```

1236 

1237Check the destination and exclusions in the preview. A dry run exits with `0`

1238even if it lists excluded alerts. To save the accepted alerts, rerun without

1239`--dry-run` and confirm, or replace `--dry-run` with `--yes`. If the import

1240excludes any alerts, it saves the accepted ones and exits with `1`. Read the

1241stored alerts in the same shell.

1242 

1243```bash

1244npx @openai/codex-security findings imported ./project --format json

1245```

1246 

1247Imported alerts start with the assessment status `not_assessed`. With the same

1248source key, a later import updates the stored records for alerts in the file.

1249Omitted alerts keep their last imported state. Alerts that share an advisory remain

1250separate records.

1251 

1213## Finding review commands1252## Finding review commands

1214 1253 

1215These commands work with existing findings:1254These commands work with existing findings:


1525The CLI uses these exit codes:1564The CLI uses these exit codes:

1526 1565 

1527| Exit | Condition |1566| Exit | Condition |

1528| ----- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |1567| ----- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |

1529| `0` | A scan or bulk campaign completed and passed its severity policy, a publication completed without failures, or another command succeeded. |1568| `0` | A scan or bulk campaign completed and passed its severity policy, a publication completed without failures, or another command succeeded. |

1530| `1` | A completed scan or bulk campaign reports a finding at or above the configured severity, or `verify-fix` reports a finding as still vulnerable with no inconclusive results. |1569| `1` | A scan or bulk campaign meets its severity threshold, `verify-fix` reports an unfixed finding with no inconclusive results, or a confirmed import excludes local records or returns a partial Cloud result. |

1531| `2` | An input, execution, result-integrity, required-output, or export failure occurred, a publication has one or more failed findings, or `verify-fix` reports an inconclusive result. |1570| `2` | An input, execution, result-integrity, required-output, or export failure occurred, `publish scan` has one or more failed findings, or `verify-fix` reports an inconclusive result. |

1532| `130` | Ctrl-C interrupted a scan or publication. |1571| `130` | Ctrl-C interrupted a scan or publication. |

1533| `143` | SIGTERM terminated a scan or publication. |1572| `143` | SIGTERM terminated a scan or publication. |

1534 1573 

Details

277 277

278 278 

279 279 

280```groovy280```groovy snippet=configuration reason="Jenkins pipeline configuration for the documented CI integration"

281pipeline {281pipeline {

282 agent { label 'linux' }282 agent { label 'linux' }

283 stages {283 stages {

security/sdk.md +121 −77

Details

42before you start. See [Local scan42before you start. See [Local scan

43permissions](https://learn.chatgpt.com/docs/security/cli/reference#local-scan-permissions).43permissions](https://learn.chatgpt.com/docs/security/cli/reference#local-scan-permissions).

44 44 

45Save this example as `scan.mjs`. Replace the paths, run a standard repository45Save this example as `scan.mjs`. Pass the paths to the repository and results directory as command-line arguments. Run a standard repository scan and close the client

46scan, and close the client when the work completes. Pass `outputDir` to choose a private46when the work completes. Pass `outputDir` to choose a private

47results directory outside the enclosing Git worktree.47results directory outside the enclosing Git worktree.

48 48 

49If you omit `outputDir`, Codex Security saves results in its own persistent49If you omit `outputDir`, Codex Security saves results in its own persistent

50state directory. Results can include source excerpts and vulnerability50state directory. Results can include source excerpts and vulnerability

51details. Set who can read them and how long to keep them.51details. Set who can read them and how long to keep them.

52 52 

53```ts53```typescript

54 54import { CodexSecurity } from "@openai/codex-security";

55 55 

56const [repository, outputDir] = process.argv.slice(2);

57if (!repository || !outputDir) {

58 throw new Error("Usage: node scan.mjs <repository> <results-directory>");

59}

56const security = new CodexSecurity();60const security = new CodexSecurity();

57 61 

58try {62try {

59 const result = await security.run("/path/to/repository", {63 const result = await security.run(repository, {

60 outputDir: "/path/outside/repository/results",64 outputDir,

61 });65 });

62 66 

63 console.log(result.reportPath);67 console.log(result.reportPath);


71Run it with Node.js:76Run it with Node.js:

72 77 

73```bash78```bash

74node scan.mjs79node scan.mjs /path/to/repository /path/outside/repository/results

75```80```

76 81 

77The example prints the report path, scan status, and finding count.82The example prints the report path, scan status, and finding count.


90## Check inputs with preflight95## Check inputs with preflight

91 96 

92Use `preflight` to check a repository, target, mode, knowledge-base documents,97Use `preflight` to check a repository, target, mode, knowledge-base documents,

93output location, and Codex configuration before starting a scan:98output location, and Codex configuration before starting a scan. This example

99reads `security.md` from the repository root:

94 100 

95```ts101```typescript

96const plan = await security.preflight("/path/to/repository", {102import { join } from "node:path";

103 

104const knowledgeBase = join(repository, "security.md");

105 

106const plan = await security.preflight(repository, {

97 target: ["services/billing", "packages/auth"],107 target: ["services/billing", "packages/auth"],

98 knowledgeBasePaths: ["/path/to/architecture.md"],108 knowledgeBasePaths: [knowledgeBase],

99 outputDir: "/path/outside/repository/results",109 outputDir: outputDir,

100});110});

101 111 

102console.log(plan.repository);112console.log(plan.repository);


112To preview archival for an existing result directory, set123To preview archival for an existing result directory, set

113`archiveExisting: true`:124`archiveExisting: true`:

114 125 

115```ts126```typescript

116const plan = await security.preflight("/path/to/repository", {127const plan = await security.preflight(repository, {

117 outputDir: "/path/outside/repository/results",128 outputDir: outputDir,

118 archiveExisting: true,129 archiveExisting: true,

119});130});

120 131 


125differ because `run` generates its own unique destination. Capture the actual137differ because `run` generates its own unique destination. Capture the actual

126archive path with `onOutputArchived`:138archive path with `onOutputArchived`:

127 139 

128```ts140```typescript

129await security.run("/path/to/repository", {141await security.run(repository, {

130 outputDir: "/path/outside/repository/results",142 outputDir: outputDir,

131 archiveExisting: true,143 archiveExisting: true,

132 onOutputArchived(archiveDir) {144 onOutputArchived(archiveDir) {

133 console.log("Archived results:", archiveDir);145 console.log("Archived results:", archiveDir);


147 160 

148Pass an array of paths inside the repository:161Pass an array of paths inside the repository:

149 162 

150```ts163```typescript

151const result = await security.run("/path/to/repository", {164const result = await security.run(repository, {

152 target: ["services/billing", "packages/auth"],165 target: ["services/billing", "packages/auth"],

153});166});

154```167```


161Use `DiffTarget.refs` to scan committed changes between two locally available175Use `DiffTarget.refs` to scan committed changes between two locally available

162Git revisions:176Git revisions:

163 177 

164```ts178```typescript

165 179import { DiffTarget } from "@openai/codex-security";

166 180 

167const target = DiffTarget.refs({181const target = DiffTarget.refs({

168 base: "origin/main",182 base: "HEAD~1",

169 head: "HEAD",183 head: "HEAD",

170});184});

171 185 

172const result = await security.run("/path/to/repository", { target });186const result = await security.run(repository, { target });

173```187```

174 188 

189 

175The head defaults to `HEAD`. Pass the Git worktree root as the repository and190The head defaults to `HEAD`. Pass the Git worktree root as the repository and

176check out the requested head before scanning.191check out the requested head before scanning.

177 192 


180Use `DiffTarget.workingTree` to scan staged and unstaged changes against a base195Use `DiffTarget.workingTree` to scan staged and unstaged changes against a base

181revision:196revision:

182 197 

183```ts198```typescript

199import { DiffTarget } from "@openai/codex-security";

184const target = DiffTarget.workingTree({ base: "HEAD" });200const target = DiffTarget.workingTree({ base: "HEAD" });

185const result = await security.run("/path/to/repository", { target });201const result = await security.run(repository, { target });

186```202```

187 203 

204 

188The base defaults to `HEAD`. Fetch the selected revisions before starting a205The base defaults to `HEAD`. Fetch the selected revisions before starting a

189diff or working-tree scan.206diff or working-tree scan.

190 207 


192 209 

193Set `mode: "deep"` for a repository or path scan that needs broader review:210Set `mode: "deep"` for a repository or path scan that needs broader review:

194 211 

195```ts212```typescript

196const result = await security.run("/path/to/repository", {213const result = await security.run(repository, {

197 target: ["services/billing"],214 target: ["services/billing"],

198 mode: "deep",215 mode: "deep",

199 workers: 2,216 workers: 2,


221Pass architecture documents, threat models, or security policies through239Pass architecture documents, threat models, or security policies through

222`knowledgeBasePaths`:240`knowledgeBasePaths`:

223 241 

224```ts242```typescript

225const result = await security.run("/path/to/repository", {243import { join } from "node:path";

226 knowledgeBasePaths: [244 

227 "/path/to/architecture.md",245const knowledgeBase = join(repository, "security.md");

228 "/path/to/security-policies",246 

229 ],247const result = await security.run(repository, {

248 knowledgeBasePaths: [knowledgeBase],

230});249});

231```250```

232 251 


244 264 

245Use `scanPrompt` to focus the scan and `postScanPrompt` to request a follow-up:265Use `scanPrompt` to focus the scan and `postScanPrompt` to request a follow-up:

246 266 

247```ts267```typescript

248const result = await security.run("/path/to/repository", {268const result = await security.run(repository, {

249 scanPrompt: "Focus on tenant isolation and authorization checks.",269 scanPrompt: "Focus on tenant isolation and authorization checks.",

250 postScanPrompt: "Write confirmed findings to post-scan-summary.md.",270 postScanPrompt: "Write confirmed findings to post-scan-summary.md.",

251});271});


260 281 

261Pass `validationPrompt` to check candidate findings with your own test282Pass `validationPrompt` to check candidate findings with your own test

262procedure. For example, point the prompt at a script you control outside the283procedure. For example, point the prompt at a script you control outside the

263checkout and run it against your local test server:284checkout and run it against your local test server. Pass the validation script

285and server URL after the repository and results directory arguments:

264 286 

265```ts287```typescript

266const result = await security.run("/path/to/repository", {288const [validationScript, validationUrl] = process.argv.slice(4);

267 validationPrompt:289if (!validationScript || !validationUrl)

268 "Run /path/to/security-tests/validate.sh against http://localhost:3000 and report which findings reproduce.",290 throw new Error("Pass a validation script path and service URL.");

291const result = await security.run(repository, {

292 outputDir,

293 validationPrompt: `Run ${validationScript} against ${validationUrl} and report which findings reproduce.`,

269});294});

270```295```

271 296 

297 

298```bash

299node scan.mjs /path/to/repository /path/outside/repository/results /path/to/validate.sh http://localhost:3000

300```

301 

272Use `validationPrompt` with standard repository, path, committed-diff, or302Use `validationPrompt` with standard repository, path, committed-diff, or

273working-tree scans. To use the same procedure for each standard component303working-tree scans. To use the same procedure for each standard component

274scan, pass `scanOptions.validationPrompt` to `runComponentScans`. Deep scans304scan, pass `scanOptions.validationPrompt` to `runComponentScans`. Deep scans


279Set `maxCostUsd` to stop a scan when its estimated model cost exceeds a limit.309Set `maxCostUsd` to stop a scan when its estimated model cost exceeds a limit.

280Use `onCost` to track cost as the scan runs and report `estimatedUsdRange`:310Use `onCost` to track cost as the scan runs and report `estimatedUsdRange`:

281 311 

282```ts312```typescript

283const result = await security.run("/path/to/repository", {313const result = await security.run(repository, {

284 maxCostUsd: 5,314 maxCostUsd: 5,

285 onCost(cost) {315 onCost(cost) {

286 console.log(cost.estimatedUsdRange);316 console.log(cost.estimatedUsdRange);


308their findings. Give each component a name and one or more repository-relative339their findings. Give each component a name and one or more repository-relative

309paths. Choose a new or empty output directory outside the enclosing Git worktree.340paths. Choose a new or empty output directory outside the enclosing Git worktree.

310 341 

311```ts342```typescript

312 343import { runComponentScans } from "@openai/codex-security";

313 344 

314const result = await runComponentScans({345const result = await runComponentScans({

315 repository: "/path/to/project",346 repository: repository,

316 outputDir: "/path/outside/project/component-results",347 outputDir: outputDir,

317 components: [348 components: [

318 { name: "API", paths: ["apps/api", "packages/auth"] },349 { name: "API", paths: ["services/api", "packages/auth"] },

319 { name: "Web", paths: ["apps/web"] },350 { name: "Web", paths: ["services/billing"] },

320 ],351 ],

321 workers: 2,352 workers: 2,

322 onProgress: ({ name, status }) => console.log(name, status),353 onProgress: ({ name, status }) => console.log(name, status),


331Add `planOnly: true` to save the plan in `components.json` without running any363Add `planOnly: true` to save the plan in `components.json` without running any

332scans:364scans:

333 365 

334```ts366```typescript

367import { runComponentScans } from "@openai/codex-security";

368 

335const plan = await runComponentScans({369const plan = await runComponentScans({

336 repository: "/path/to/project",370 repository: repository,

337 outputDir: "/path/outside/project/component-plan",371 outputDir: outputDir,

338 auto: true,372 auto: true,

339 planOnly: true,373 planOnly: true,

340});374});


377 412 

378Read the severity and first source location for each finding:413Read the severity and first source location for each finding:

379 414 

380```ts415```typescript

381for (const finding of result.findings.findings) {416for (const finding of result.findings.findings) {

382 const location = finding.locations[0];417 const location = finding.locations[0];

383 if (location === undefined) continue;418 if (location === undefined) continue;


396For repository-wide findings, `confirmedInLatestScan` distinguishes findings432For repository-wide findings, `confirmedInLatestScan` distinguishes findings

397seen in the latest scan from earlier findings that remain open:433seen in the latest scan from earlier findings that remain open:

398 434 

399```ts435```typescript

400for (const finding of result.repositoryFindings ?? []) {436for (const finding of result.repositoryFindings ?? []) {

401 console.log(finding.title, finding.confirmedInLatestScan);437 console.log(finding.title, finding.confirmedInLatestScan);

402}438}


414### Export saved artifacts451### Export saved artifacts

415 452 

416Export saved results without starting Codex, loading credentials, or making a453Export saved results without starting Codex, loading credentials, or making a

417model call. This example exports a saved threat model to stdout. Replace454model call. This example exports a saved threat model to stdout. Pass an existing

418`/path/to/scan` with a saved result directory:455scan results directory as the first command-line argument:

419 456 

420```ts457```typescript

458import { exportArtifact } from "@openai/codex-security";

421 459 

460const directory = process.argv[2];

461if (!directory) {

462 throw new Error(

463 "Pass an existing scan results directory as the first argument."

464 );

465}

422 466 

423await exportArtifact({467await exportArtifact({

424 source: { directory: "/path/to/scan" },468 source: { directory },

425 artifact: "threat-model",469 artifact: "threat-model",

426 output: "-",470 output: "-",

427});471});


430To select a saved scan by ID, use `source: { scanId: "SCAN_ID" }` instead. Set475To select a saved scan by ID, use `source: { scanId: "SCAN_ID" }` instead. Set

431`output` to a destination path to save the artifact to a file.476`output` to a destination path to save the artifact to a file.

432 477 

433Use `artifact: "threat-model"` to export Markdown; the export returns an error478Threat models export as Markdown. The export returns an error if the scan has

434if no threat model was saved. For findings, use `artifact: "findings"` and choose479no saved threat model. For findings, set `artifact: "findings"` and choose

435`format: "csv"`, `"json"`, or `"sarif"` (the default).480`format: "sarif"` (the default), `"json"`, `"csv"`, or `"servicenow-avit"`.

436 481 

437The result includes the output `path` and, for a threat-model file export,482The result includes the output `path` and, for a threat-model file export,

438`provenance` from the same saved results. Both fields are `null` when483`provenance` from the same saved results. Both fields are `null` when

439`output: "-"` writes to stdout. Export requires Python 3.10 or later.484`output: "-"` writes to stdout. Export requires Python 3.10 or later.

440 485 

486For ServiceNow Manual AVIT Ingestion, [prepare the application template](https://learn.chatgpt.com/docs/security/cli/reference#export-findings-for-servicenow) and pass its path as `avitTemplate`.

487 

488```ts

489await exportArtifact({

490 source: { directory: "/path/to/scan" },

491 artifact: "findings",

492 format: "servicenow-avit",

493 avitTemplate: "/path/outside/repository/exports/app.csv",

494 output: "/path/outside/repository/exports/findings-avit.csv",

495});

496```

497 

441## Validate an existing finding498## Validate an existing finding

442 499 

443Use `validate` to check a finding from another tool or workflow against the500Use `validate` to check a finding from another tool or workflow against the

444source. It doesn't start a new scan, run the application, or execute its tests.501source. It doesn't start a new scan, run the application, or execute its tests.

445Run a separate reproduction if you need runtime evidence.502Run a separate reproduction if you need runtime evidence.

446 503 

447```ts504```typescript

448const validation = await security.validate({505const validation = await security.validate({

449 repositoryPath: "/path/to/repository",506 repositoryPath: repository,

450 finding: {507 finding: {

451 title: "Possible SQL injection",508 title: "Possible SQL injection",

452 location: "src/query.ts:42",509 location: "src/index.js:1",

453 },510 },

454});511});

455 512 


469Pass `ScanOptions` callbacks to report scan startup, worker progress, and527Pass `ScanOptions` callbacks to report scan startup, worker progress, and

470connection retries:528connection retries:

471 529 

472```ts530```typescript

473const result = await security.run("/path/to/repository", {531const result = await security.run(repository, {

474 outputDir: "/path/outside/repository/results",532 outputDir: outputDir,

475 onScanStarted() {533 onScanStarted() {

476 console.log("Scan started");534 console.log("Scan started");

477 },535 },


499If the scan is still running after 30 minutes, this example interrupts it and558If the scan is still running after 30 minutes, this example interrupts it and

500prints the directory containing any saved output:559prints the directory containing any saved output:

501 560 

502```ts561```typescript

503 562import { ScanInterruptedError } from "@openai/codex-security";

504 563 

505try {564try {

506 await security.run("/path/to/repository", {565 await security.run(repository, {

507 outputDir: "/path/outside/repository/results",566 outputDir: outputDir,

508 signal: AbortSignal.timeout(30 * 60 * 1000),567 signal: AbortSignal.timeout(30 * 60 * 1000),

509 });568 });

510} catch (error) {569} catch (error) {


552 612 

553```typescript613```typescript

554const security = new CodexSecurity({614const security = new CodexSecurity({

555 pluginPath: "/path/to/codex-security-plugin",615 // To override the bundled plugin, add pluginPath: "/path/to/plugin".

556 pythonPath: "/path/to/python",616 pythonPath: "python3",

557 codexOverrides: {617 codexOverrides: {

558 model: "gpt-6.1-sol",618 model: "gpt-6.1-sol",

559 model_reasoning_effort: "medium",619 model_reasoning_effort: "medium",


562```622```

563 623 

564 624 

565`pluginPath` accepts a plugin directory or ZIP. `pythonPath` selects the625Set `pluginPath` to a plugin directory or ZIP to override the bundled plugin.

626`pythonPath` selects the

566plugin interpreter. `codexOverrides` merges supported values into the isolated627plugin interpreter. `codexOverrides` merges supported values into the isolated

567Codex configuration. To use [Amazon628Codex configuration. To use [Amazon

568Bedrock](https://learn.chatgpt.com/docs/security/cli/reference#use-amazon-bedrock), set629Bedrock](https://learn.chatgpt.com/docs/security/cli/reference#use-amazon-bedrock), set


577provider configuration in `codexOverrides`. Set `OPENROUTER_API_KEY`638provider configuration in `codexOverrides`. Set `OPENROUTER_API_KEY`

578and pass an available OpenRouter model ID to this TypeScript function:639and pass an available OpenRouter model ID to this TypeScript function:

579 640 

580```ts641```typescript

581function createOpenRouterClient(model: string) {642function createOpenRouterClient(model: string) {

582 return new CodexSecurity({643 return new CodexSecurity({

583 codexOverrides: {644 codexOverrides: {


619When both an API key and a stored sign-in are available, the SDK uses the API681When both an API key and a stored sign-in are available, the SDK uses the API

620key by default. To use your ChatGPT sign-in instead, select it for the scan:682key by default. To use your ChatGPT sign-in instead, select it for the scan:

621 683 

622```ts684```typescript

623const result = await security.run("/path/to/repository", {685const result = await security.run(repository, {

624 auth: "chatgpt",686 auth: "chatgpt",

625});687});

626```688```

skills.md +14 −2

Details

144| `REPO` | `$REPO_ROOT/.agents/skills` <br /> The topmost root folder when you launch Codex inside a Git repository. | If you're in a repository with nested folders, organizations can check in skills relevant to everyone using the repository. These serve as root skills available to any subfolder in the repository. |144| `REPO` | `$REPO_ROOT/.agents/skills` <br /> The topmost root folder when you launch Codex inside a Git repository. | If you're in a repository with nested folders, organizations can check in skills relevant to everyone using the repository. These serve as root skills available to any subfolder in the repository. |

145| `USER` | `$HOME/.agents/skills` <br /> Any skills checked into the user's personal folder. | Use to curate skills relevant to a user that apply to any repository the user may work in. |145| `USER` | `$HOME/.agents/skills` <br /> Any skills checked into the user's personal folder. | Use to curate skills relevant to a user that apply to any repository the user may work in. |

146| `ADMIN` | `/etc/codex/skills` <br /> Any skills checked into the machine or container in a shared, system location. | Use for SDK scripts, automation, and for checking in default admin skills available to each user on the machine. |146| `ADMIN` | `/etc/codex/skills` <br /> Any skills checked into the machine or container in a shared, system location. | Use for SDK scripts, automation, and for checking in default admin skills available to each user on the machine. |

147| `SYSTEM` | Bundled with Codex by OpenAI. | Useful skills relevant to a broad audience such as the skill-creator and plan skills. Available to everyone when they start Codex. |147| `SYSTEM` | Bundled with Codex by OpenAI. | Includes `skill-creator` and `skill-installer`. Enabled by default. |

148 148 

149Codex supports symlinked skill folders and follows the symlink target when scanning these locations.149Codex supports symlinked skill folders and follows the symlink target when scanning these locations.

150 150 


188enabled = false188enabled = false

189```189```

190 190 

191Restart Codex after changing `~/.codex/config.toml`.191Use exactly one selector per entry. An absolute `path` matches one

192`SKILL.md` file. A `name` matches every skill with that name. When more than

193one entry matches a skill, the last matching entry wins.

194 

195To turn off all bundled system skills for the current project, add this setting

196to its trusted `.codex/config.toml`:

197 

198```toml

199[skills.bundled]

200enabled = false

201```

202 

203Restart Codex after changing the configuration.

192 204 

193## Optional metadata205## Optional metadata

194 206 

Details

113Prefer `NavigationSplitView` when the feature benefits from persistent navigation and a stable selected item. Keep sidebar rows native and lightweight, let the sidebar use system backgrounds, and reserve custom cards or dense metadata for the detail pane or inspector.113Prefer `NavigationSplitView` when the feature benefits from persistent navigation and a stable selected item. Keep sidebar rows native and lightweight, let the sidebar use system backgrounds, and reserve custom cards or dense metadata for the detail pane or inspector.

114 114 

115```swift115```swift

116import SwiftUI

117 

118struct Item: Identifiable, Hashable {

119 let id: String

120 let title: String

121 let systemImage: String

122}

123let items = [Item(id: "notes", title: "Notes", systemImage: "note.text"), Item(id: "photos", title: "Photos", systemImage: "photo")]

124 

125struct ItemDetailView: View {

126 let selection: String?

127 var body: some View { Text(selection ?? "Select an item").frame(maxWidth: .infinity, maxHeight: .infinity) }

128}

129struct ItemInspectorView: View {

130 let selection: String?

131 var body: some View { Text("Metadata: \(selection ?? "No selection")").padding().frame(minWidth: 220) }

132}

133@MainActor final class LibraryStore: ObservableObject {

134 @Published var entries = items

135 @Published var selection: String?

136 @Published var showInspector = true

137 func addItem() {

138 let item = Item(id: UUID().uuidString, title: "New Item", systemImage: "doc")

139 entries.append(item)

140 selection = item.id

141 }

142}

143 

116struct LibraryRootView: View {144struct LibraryRootView: View {

117 @SceneStorage("LibraryRootView.selection") private var selection: Item.ID?145 @StateObject private var store = LibraryStore()

118 @SceneStorage("LibraryRootView.showInspector") private var showInspector = true146 @SceneStorage("LibraryRootView.selection") private var savedSelection: Item.ID?

147 @SceneStorage("LibraryRootView.showInspector") private var savedShowInspector = true

119 148 

120 var body: some View {149 var body: some View {

121 NavigationSplitView {150 NavigationSplitView {

122 List(selection: $selection) {151 List(selection: $store.selection) {

123 ForEach(items) { item in152 ForEach(store.entries) { item in

124 Label(item.title, systemImage: item.systemImage)153 Label(item.title, systemImage: item.systemImage)

125 .tag(item.id)154 .tag(item.id)

126 }155 }


128 .listStyle(.sidebar)157 .listStyle(.sidebar)

129 .navigationTitle("Library")158 .navigationTitle("Library")

130 } detail: {159 } detail: {

131 ItemDetailView(selection: selection)160 ItemDetailView(selection: store.selection)

132 .inspector(isPresented: $showInspector) {161 .inspector(isPresented: $store.showInspector) {

133 ItemInspectorView(selection: selection)162 ItemInspectorView(selection: store.selection)

163 }

164 }

165 .focusedSceneObject(store)

166 .onAppear {

167 store.selection = savedSelection

168 store.showInspector = savedShowInspector

169 }

170 .onChange(of: store.selection) { _, selection in

171 savedSelection = selection

134 }172 }

173 .onChange(of: store.showInspector) { _, showInspector in

174 savedShowInspector = showInspector

135 }175 }

136 }176 }

137}177}


146```swift187```swift

147@main188@main

148struct LibraryApp: App {189struct LibraryApp: App {

190 @FocusedObject private var store: LibraryStore?

149 var body: some Scene {191 var body: some Scene {

150 WindowGroup {192 WindowGroup {

151 LibraryRootView()193 LibraryRootView()


153 .commands {195 .commands {

154 CommandMenu("Library") {196 CommandMenu("Library") {

155 Button("New Item") {197 Button("New Item") {

156 // Create a new item.198 store?.addItem()

157 }199 }

158 .keyboardShortcut("n")200 .keyboardShortcut("n")

201 .disabled(store == nil)

159 202 

160 Button("Toggle Inspector") {203 Button("Toggle Inspector") {

161 // Route this command to the focused window or selected item state.204 store?.showInspector.toggle()

162 }205 }

163 .keyboardShortcut("i", modifiers: [.command, .option])206 .keyboardShortcut("i", modifiers: [.command, .option])

207 .disabled(store == nil)

164 }208 }

165 }209 }

166 210 

Details

116Ask Codex for one logger per feature area, not one permanent log line for every state mutation. Feature categories such as `Windowing`, `Commands`, `MenuBar`, `Sidebar`, `Sync`, or `Import` make logs much easier to filter during the next debugging pass.116Ask Codex for one logger per feature area, not one permanent log line for every state mutation. Feature categories such as `Windowing`, `Commands`, `MenuBar`, `Sidebar`, `Sync`, or `Import` make logs much easier to filter during the next debugging pass.

117 117 

118```swift118```swift

119import SwiftUI

120 

121struct SidebarItem { let id: String }

122@MainActor private var selection: String?

119import OSLog123import OSLog

120 124 

121private let logger = Logger(125private let logger = Logger(

webmcp.md +11 −21

Details

11In the [built-in browser](https://learn.chatgpt.com/docs/browser) in the ChatGPT desktop app, ChatGPT11In the [built-in browser](https://learn.chatgpt.com/docs/browser) in the ChatGPT desktop app, ChatGPT

12Work and Codex can discover and use these tools when they are available.12Work and Codex can discover and use these tools when they are available.

13 13 

14Use GPT-5.6 Sol or GPT-6 Sol for site tools. GPT-5.6 Luna currently has WebMCP14Site tools require a supported model and a page that provides tools. Your

15 disabled. Update the ChatGPT desktop app to the latest version. In Enterprise15 account or your managed workspace's browser policy can grant access. Your

16 workspaces, an admin must allow **Site tools** through workspace policy. Site16 browser settings and site permissions still apply.

17 tools aren't available in Edu workspaces. Availability also depends on rollout

18 and the tools provided by the current page.

19 17 

20## WebMCP vs. MCP18## WebMCP vs. MCP

21 19 


112 110 

113## Limitations111## Limitations

114 112 

115ChatGPT's built-in browser currently supports a subset of the WebMCP APIs.113Site tools currently run only in the ChatGPT desktop app's built-in browser.

116The following features aren't supported:

117 

118- **Declarative API:** Tools defined through HTML form attributes aren't

119 available as site tools.

120- **Tools in iframes:** The browser doesn't discover tools registered inside

121 iframes, including same-origin and cross-origin iframes.

122 

123Use JavaScript to register tools in the top-level page, as shown in the

124[next section](#add-webmcp-to-your-website). ChatGPT Work and Codex may still

125interact with forms using regular browser capabilities, but those interactions

126aren't WebMCP tool calls.

127 

128The WebMCP specification and Chrome's developer guide describe the broader

129APIs, including features that aren't currently supported in the built-in browser.

130 114 

131## Add WebMCP to your website115## Add WebMCP to your website

132 116 


134[Site](https://learn.chatgpt.com/docs/sites) you're working on. Describe what an agent should be able118[Site](https://learn.chatgpt.com/docs/sites) you're working on. Describe what an agent should be able

135to do, and ask Codex to reuse the application's existing logic and permissions.119to do, and ask Codex to reuse the application's existing logic and permissions.

136 120 

121Register a tool with JavaScript or add WebMCP attributes to an HTML form. The

122built-in browser can discover tools in the top-level page and in same-origin

123and cross-origin iframes. Each frame must use a secure context. The browser

124checks access for the origin that provides the tool. You can omit `exposedTo`

125for agent discovery.

126 

137Start with an operation your application already supports. For example:127Start with an operation your application already supports. For example:

138 128 

139- A dashboard that lets the agent set a date range and inspect the data behind129- A dashboard that lets the agent set a date range and inspect the data behind


147for browser support and register a tool. This read-only example returns the137for browser support and register a tool. This read-only example returns the

148current page's title:138current page's title:

149 139 

150```javascript140```typescript

151if (typeof document.modelContext?.registerTool === "function") {141if (typeof document.modelContext?.registerTool === "function") {

152 await document.modelContext.registerTool({142 await document.modelContext.registerTool({

153 name: "get_page_title",143 name: "get_page_title",