SpyBara
Go Premium Account
2026
14 May 2026, 21:00
18 May 2026, 22:01 14 May 2026, 21:00 14 May 2026, 07:00 13 May 2026, 00:57 12 May 2026, 01:59 11 May 2026, 18:00 7 May 2026, 20:02 7 May 2026, 17:08 5 May 2026, 23:00 2 May 2026, 06:45 2 May 2026, 00:48 1 May 2026, 18:29 30 Apr 2026, 18:36 29 Apr 2026, 12:40 29 Apr 2026, 00:50 25 Apr 2026, 06:37 25 Apr 2026, 00:42 24 Apr 2026, 18:20 24 Apr 2026, 12:28 23 Apr 2026, 18:31 23 Apr 2026, 12:28 23 Apr 2026, 00:46 22 Apr 2026, 18:29 22 Apr 2026, 00:42 21 Apr 2026, 18:29 21 Apr 2026, 12:30 21 Apr 2026, 06:45 20 Apr 2026, 18:26 20 Apr 2026, 06:53 18 Apr 2026, 18:18 17 Apr 2026, 00:44 16 Apr 2026, 18:31 16 Apr 2026, 00:46 15 Apr 2026, 18:31 15 Apr 2026, 06:44 14 Apr 2026, 18:31 14 Apr 2026, 12:29 13 Apr 2026, 18:37 13 Apr 2026, 00:44 12 Apr 2026, 06:38 10 Apr 2026, 18:23 9 Apr 2026, 00:33 8 Apr 2026, 18:32 8 Apr 2026, 00:40 7 Apr 2026, 00:40 2 Apr 2026, 18:23 31 Mar 2026, 06:35 31 Mar 2026, 00:39 28 Mar 2026, 06:26 28 Mar 2026, 00:36 27 Mar 2026, 18:23 27 Mar 2026, 00:39 26 Mar 2026, 18:27 25 Mar 2026, 18:24 23 Mar 2026, 18:22 20 Mar 2026, 00:35 18 Mar 2026, 12:23 18 Mar 2026, 00:36 17 Mar 2026, 18:24 17 Mar 2026, 00:33 16 Mar 2026, 18:25 16 Mar 2026, 12:23 14 Mar 2026, 00:32 13 Mar 2026, 18:15 13 Mar 2026, 00:34 11 Mar 2026, 00:31 9 Mar 2026, 00:34 8 Mar 2026, 18:10 8 Mar 2026, 00:35 7 Mar 2026, 18:10 7 Mar 2026, 06:14 7 Mar 2026, 00:33 6 Mar 2026, 00:38 5 Mar 2026, 18:41 5 Mar 2026, 06:22 5 Mar 2026, 00:34 4 Mar 2026, 18:18 4 Mar 2026, 06:20 3 Mar 2026, 18:20 3 Mar 2026, 00:35 27 Feb 2026, 18:15 24 Feb 2026, 06:27 24 Feb 2026, 00:33 23 Feb 2026, 18:27 21 Feb 2026, 00:33 20 Feb 2026, 12:16 19 Feb 2026, 20:53 19 Feb 2026, 20:37
18 May 2026, 22:01
18 May 2026, 22:01 14 May 2026, 21:00 14 May 2026, 07:00 13 May 2026, 00:57 12 May 2026, 01:59 11 May 2026, 18:00 7 May 2026, 20:02 7 May 2026, 17:08 5 May 2026, 23:00 2 May 2026, 06:45 2 May 2026, 00:48 1 May 2026, 18:29 30 Apr 2026, 18:36 29 Apr 2026, 12:40 29 Apr 2026, 00:50 25 Apr 2026, 06:37 25 Apr 2026, 00:42 24 Apr 2026, 18:20 24 Apr 2026, 12:28 23 Apr 2026, 18:31 23 Apr 2026, 12:28 23 Apr 2026, 00:46 22 Apr 2026, 18:29 22 Apr 2026, 00:42 21 Apr 2026, 18:29 21 Apr 2026, 12:30 21 Apr 2026, 06:45 20 Apr 2026, 18:26 20 Apr 2026, 06:53 18 Apr 2026, 18:18 17 Apr 2026, 00:44 16 Apr 2026, 18:31 16 Apr 2026, 00:46 15 Apr 2026, 18:31 15 Apr 2026, 06:44 14 Apr 2026, 18:31 14 Apr 2026, 12:29 13 Apr 2026, 18:37 13 Apr 2026, 00:44 12 Apr 2026, 06:38 10 Apr 2026, 18:23 9 Apr 2026, 00:33 8 Apr 2026, 18:32 8 Apr 2026, 00:40 7 Apr 2026, 00:40 2 Apr 2026, 18:23 31 Mar 2026, 06:35 31 Mar 2026, 00:39 28 Mar 2026, 06:26 28 Mar 2026, 00:36 27 Mar 2026, 18:23 27 Mar 2026, 00:39 26 Mar 2026, 18:27 25 Mar 2026, 18:24 23 Mar 2026, 18:22 20 Mar 2026, 00:35 18 Mar 2026, 12:23 18 Mar 2026, 00:36 17 Mar 2026, 18:24 17 Mar 2026, 00:33 16 Mar 2026, 18:25 16 Mar 2026, 12:23 14 Mar 2026, 00:32 13 Mar 2026, 18:15 13 Mar 2026, 00:34 11 Mar 2026, 00:31 9 Mar 2026, 00:34 8 Mar 2026, 18:10 8 Mar 2026, 00:35 7 Mar 2026, 18:10 7 Mar 2026, 06:14 7 Mar 2026, 00:33 6 Mar 2026, 00:38 5 Mar 2026, 18:41 5 Mar 2026, 06:22 5 Mar 2026, 00:34 4 Mar 2026, 18:18 4 Mar 2026, 06:20 3 Mar 2026, 18:20 3 Mar 2026, 00:35 27 Feb 2026, 18:15 24 Feb 2026, 06:27 24 Feb 2026, 00:33 23 Feb 2026, 18:27 21 Feb 2026, 00:33 20 Feb 2026, 12:16 19 Feb 2026, 20:53 19 Feb 2026, 20:37
Fri 1 18:29 Sat 2 00:48 Sat 2 06:45 Tue 5 23:00 Thu 7 17:08 Thu 7 20:02 Mon 11 18:00 Tue 12 01:59 Wed 13 00:57 Thu 14 07:00 Thu 14 21:00 Mon 18 22:01
Details

41network_access = true41network_access = true

42```42```

43 43 

44### Network isolation

45 

46Network access is controlled through destination rules that apply to scripts,

47programs, and subprocesses spawned by commands. When command network access is

48already enabled, turn on the `network_proxy` feature to constrain that traffic

49to the network policy you configure.

50 

51```toml

52[features.network_proxy]

53enabled = true

54domains = { "api.openai.com" = "allow", "example.com" = "deny" }

55```

56 

57For a one-off CLI session, use the boolean shorthand when you only need the

58toggle, and the table form when you also set policy options:

59 

60```bash

61codex \

62 -c 'features.network_proxy=true' \

63 -c 'sandbox_workspace_write.network_access=true'

64 

65codex \

66 -c 'features.network_proxy.enabled=true' \

67 -c 'features.network_proxy.domains={ "api.openai.com" = "allow", "example.com" = "deny" }' \

68 -c 'sandbox_workspace_write.network_access=true'

69```

70 

71The feature changes how enabled network access is enforced; it does not grant

72network access by itself. Use `sandbox_workspace_write.network_access` with

73`workspace-write` config to decide whether commands have network access at all:

74 

75- Network off + `network_proxy` on: network stays off, and the feature does nothing.

76- Network on + `network_proxy` off: network stays on with unrestricted direct

77 outbound access.

78- Network on + `network_proxy` on: network stays on, and outbound traffic is

79 constrained by the configured network policy.

80 

81Admin-managed `experimental_network` requirements are separate from the user

82feature toggle. They can configure and start sandboxed networking without

83`features.network_proxy`, but they do not turn on network access when the active

84sandbox keeps it off. See [Managed configuration](https://developers.openai.com/codex/enterprise/managed-configuration#configure-network-access-requirements)

85for the administrator-side `requirements.toml` shape.

86 

87#### Network policy

88 

89Domain rules are allowlist-first:

90 

91- Exact hosts match only themselves.

92- `*.example.com` matches subdomains such as `api.example.com`, but not

93 `example.com`.

94- `**.example.com` matches both the apex and subdomains.

95- A global `*` allow rule matches any public host that is not denied. Treat `*`

96 as broad network access and prefer scoped rules when you can.

97- `deny` always wins over `allow`, and global `*` is only valid for allow rules.

98 

99#### Local and private destinations

100 

101By default, `allow_local_binding = false` blocks loopback, link-local, and

102private destinations:

103 

104- Specific exceptions: add an exact local IP literal or `localhost` allow rule

105 when a command needs one local target.

106- Broader access: set `allow_local_binding = true` only when you intentionally

107 want wider local/private reach.

108- Wildcards: wildcard rules do not count as explicit local exceptions.

109- Resolved addresses: hostnames that resolve to local/private IPs stay blocked

110 even if they match the allowlist.

111 

112#### DNS rebinding protections

113 

114Before allowing a hostname, Codex performs a best-effort DNS and IP

115classification check:

116 

117- Lookups that fail or time out are blocked.

118- Hostnames that resolve to non-public addresses are blocked.

119- The check reduces DNS rebinding risk, but it does not eliminate it. Preventing

120 rebinding completely would require pinning resolved IPs through the transport

121 layer.

122 

123If hostile DNS is in scope, enforce egress controls at a lower layer too.

124 

125#### Dangerous settings

126 

127Two settings deliberately widen the trust boundary:

128 

129- `dangerously_allow_non_loopback_proxy = true` can expose proxy listeners beyond

130 loopback.

131- `dangerously_allow_all_unix_sockets = true` bypasses the Unix socket allowlist.

132 

133Use them only in tightly controlled environments. When Unix socket proxying is

134enabled, listeners stay loopback-only even if non-loopback binding was requested,

135so sandboxed networking does not become a remote bridge into local daemons.

136 

137`network_proxy` is off by default. When you enable it:

138 

139| Setting | Default | Behavior |

140| -------------------------------------- | ------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |

141| `enabled` | `false` | Starts sandboxed networking only when command network access is already on. |

142| `domains` | unset | Uses allowlist behavior, so no external destinations are allowed until you add `allow` rules. Supports exact hosts, scoped wildcards, and global `*` allow rules; `deny` always wins. |

143| `unix_sockets` | unset | No Unix socket destinations are allowed until you add explicit `allow` rules. |

144| `allow_local_binding` | `false` | Blocks local and private-network destinations unless you add an exact local IP literal or `localhost` allow rule, or explicitly opt into broader local/private access. |

145| `enable_socks5` | `true` | Exposes SOCKS5 support when policy allows it. |

146| `enable_socks5_udp` | `true` | Allows UDP over SOCKS5 when SOCKS5 is available. |

147| `allow_upstream_proxy` | `true` | Lets sandboxed networking honor an upstream proxy from the environment. |

148| `dangerously_allow_non_loopback_proxy` | `false` | Keeps listener endpoints on loopback unless you deliberately expose them beyond localhost. |

149| `dangerously_allow_all_unix_sockets` | `false` | Keeps Unix socket access allowlist-based unless you deliberately bypass that protection. |

150 

44You can also control the [web search tool](https://platform.openai.com/docs/guides/tools-web-search) without granting full network access to spawned commands. Codex defaults to using a web search cache to access results. The cache is an OpenAI-maintained index of web results, so cached mode returns pre-indexed results instead of fetching live pages. This reduces exposure to prompt injection from arbitrary live content, but you should still treat web results as untrusted. If you are using `--yolo` or another [full access sandbox setting](#common-sandbox-and-approval-combinations), web search defaults to live results. Use `--search` or set `web_search = "live"` to allow live browsing, or set it to `"disabled"` to turn the tool off:151You can also control the [web search tool](https://platform.openai.com/docs/guides/tools-web-search) without granting full network access to spawned commands. Codex defaults to using a web search cache to access results. The cache is an OpenAI-maintained index of web results, so cached mode returns pre-indexed results instead of fetching live pages. This reduces exposure to prompt injection from arbitrary live content, but you should still treat web results as untrusted. If you are using `--yolo` or another [full access sandbox setting](#common-sandbox-and-approval-combinations), web search defaults to live results. Use `--search` or set `web_search = "live"` to allow live browsing, or set it to `"disabled"` to turn the tool off:

45 152 

46```toml153```toml

app-server.md +140 −18

Details

12Supported transports:12Supported transports:

13 13 

14- `stdio` (`--listen stdio://`, default): newline-delimited JSON (JSONL).14- `stdio` (`--listen stdio://`, default): newline-delimited JSON (JSONL).

15- `websocket` (`--listen ws://IP:PORT`, experimental and unsupported): one JSON-RPC message per WebSocket text frame.15- `websocket` (`--listen ws://IP:PORT`, experimental and unsupported): one

16 JSON-RPC message per WebSocket text frame.

17- Unix socket (`--listen unix://` or `--listen unix://PATH`): WebSocket

18 connections over Codex's default app-server control socket or a custom Unix

19 socket path, using the standard HTTP Upgrade handshake.

16- `off` (`--listen off`): don't expose a local transport.20- `off` (`--listen off`): don't expose a local transport.

17 21 

18When you run with `--listen ws://IP:PORT`, the same listener also serves basic HTTP health probes:22When you run with `--listen ws://IP:PORT`, the same listener also serves basic

23HTTP health probes:

19 24 

20- `GET /readyz` returns `200 OK` once the listener accepts new connections.25- `GET /readyz` returns `200 OK` once the listener accepts new connections.

21- `GET /healthz` returns `200 OK` when the request doesn't include an `Origin` header.26- `GET /healthz` returns `200 OK` when the request doesn't include an `Origin`

27 header.

22- Requests with an `Origin` header are rejected with `403 Forbidden`.28- Requests with an `Origin` header are rejected with `403 Forbidden`.

23 29 

24WebSocket transport is experimental and unsupported. Loopback listeners such as `ws://127.0.0.1:PORT` are appropriate for localhost and SSH port-forwarding workflows. Non-loopback WebSocket listeners currently allow unauthenticated connections by default during rollout, so configure WebSocket auth before exposing one remotely.30WebSocket transport is experimental and unsupported. Local listeners such as

31`ws://127.0.0.1:PORT` are appropriate for localhost and SSH port-forwarding

32workflows. Non-loopback WebSocket listeners currently allow unauthenticated

33connections by default during rollout, so configure WebSocket auth before

34exposing one remotely.

25 35 

26Supported WebSocket auth flags:36Supported WebSocket auth flags:

27 37 


29- `--ws-auth capability-token --ws-token-sha256 HEX`39- `--ws-auth capability-token --ws-token-sha256 HEX`

30- `--ws-auth signed-bearer-token --ws-shared-secret-file /absolute/path`40- `--ws-auth signed-bearer-token --ws-shared-secret-file /absolute/path`

31 41 

32For signed bearer tokens, you can also set `--ws-issuer`, `--ws-audience`, and `--ws-max-clock-skew-seconds`. Clients present the credential as `Authorization: Bearer <token>` during the WebSocket handshake, and app-server enforces auth before JSON-RPC `initialize`.42For signed bearer tokens, you can also set `--ws-issuer`, `--ws-audience`, and

43`--ws-max-clock-skew-seconds`. Clients present the credential as

44`Authorization: Bearer <token>` during the WebSocket handshake, and app-server

45enforces auth before JSON-RPC `initialize`.

33 46 

34Prefer `--ws-token-file` over passing raw bearer tokens on the command line. Use `--ws-token-sha256` only when the client keeps the raw high-entropy token in a separate local secret store; the hash is only a verifier, and clients still need the original token.47Prefer `--ws-token-file` over passing raw bearer tokens on the command line. Use

48`--ws-token-sha256` only when the client keeps the raw high-entropy token in a

49separate local secret store; the hash is only a verifier, and clients still need

50the original token.

35 51 

36In WebSocket mode, app-server uses bounded queues. When request ingress is full, the server rejects new requests with JSON-RPC error code `-32001` and message `"Server overloaded; retry later."` Clients should retry with an exponentially increasing delay and jitter.52In WebSocket mode, app-server uses bounded queues. When request ingress is full,

53the server rejects new requests with JSON-RPC error code `-32001` and message

54`"Server overloaded; retry later."` Clients should retry with an exponentially

55increasing delay and jitter.

37 56 

38## Message schema57## Message schema

39 58 


68 87 

69## Getting started88## Getting started

70 89 

711. Start the server with `codex app-server` (default stdio transport) or `codex app-server --listen ws://127.0.0.1:4500` (experimental WebSocket transport).901. Start the server with `codex app-server` (default stdio transport),

91 `codex app-server --listen ws://127.0.0.1:4500` (TCP WebSocket), or

92 `codex app-server --listen unix://` (default Unix socket).

722. Connect a client over the selected transport, then send `initialize` followed by the `initialized` notification.932. Connect a client over the selected transport, then send `initialize` followed by the `initialized` notification.

733. Start a thread and a turn, then keep reading notifications from the active transport stream.943. Start a thread and a turn, then keep reading notifications from the active transport stream.

74 95 


216 237 

217- `thread/start` - create a new thread; emits `thread/started` and automatically subscribes you to turn/item events for that thread.238- `thread/start` - create a new thread; emits `thread/started` and automatically subscribes you to turn/item events for that thread.

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

219- `thread/fork` - fork a thread into a new thread id by copying stored history; emits `thread/started` for the new thread.240- `thread/fork` - fork a thread into a new thread id by copying stored history; emits `thread/started` for the new thread. Returned threads include `forkedFromId` when available.

220- `thread/read` - read a stored thread by id without resuming it; set `includeTurns` to return full turn history. Returned `thread` objects include runtime `status`.241- `thread/read` - read a stored thread by id without resuming it; set `includeTurns` to return full turn history. Returned `thread` objects include runtime `status`.

221- `thread/list` - page through stored thread logs; supports cursor-based pagination plus `modelProviders`, `sourceKinds`, `archived`, `cwd`, and `searchTerm` filters. Returned `thread` objects include runtime `status`.242- `thread/list` - page through stored thread logs; supports cursor-based pagination plus `modelProviders`, `sourceKinds`, `archived`, `cwd`, and `searchTerm` filters. Returned `thread` objects include runtime `status`.

222- `thread/turns/list` - page through a stored thread's turn history without resuming it.243- `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.

244- `thread/turns/items/list` - reserved for paged turn-item loading; currently returns unsupported.

223- `thread/loaded/list` - list the thread ids currently loaded in memory.245- `thread/loaded/list` - list the thread ids currently loaded in memory.

224- `thread/name/set` - set or update a thread's user-facing name for a loaded thread or a persisted rollout; emits `thread/name/updated`.246- `thread/name/set` - set or update a thread's user-facing name for a loaded thread or a persisted rollout; emits `thread/name/updated`.

225- `thread/goal/set` - set the goal for a loaded thread (experimental; requires `capabilities.experimentalApi`); emits `thread/goal/updated`.247- `thread/goal/set` - set the goal for a loaded thread (experimental; requires `capabilities.experimentalApi`); emits `thread/goal/updated`.


244- `command/exec/resize` - resize a running PTY-backed `command/exec` session.266- `command/exec/resize` - resize a running PTY-backed `command/exec` session.

245- `command/exec/terminate` - stop a running `command/exec` session.267- `command/exec/terminate` - stop a running `command/exec` session.

246- `command/exec/outputDelta` (notify) - emitted for base64-encoded stdout/stderr chunks from a streaming `command/exec` session.268- `command/exec/outputDelta` (notify) - emitted for base64-encoded stdout/stderr chunks from a streaming `command/exec` session.

269- `process/spawn` - start an explicit process session outside Codex's sandbox (experimental; requires `capabilities.experimentalApi`).

270- `process/writeStdin` - write stdin bytes to a running `process/spawn` session or close stdin (experimental).

271- `process/resizePty` - resize a running PTY-backed process session (experimental).

272- `process/kill` - terminate a running process session (experimental).

273- `process/outputDelta` and `process/exited` (notify) - emitted for streaming process output and process exit status (experimental).

247- `model/list` - list available models (set `includeHidden: true` to include entries with `hidden: true`) with effort options, optional `upgrade`, and `inputModalities`.274- `model/list` - list available models (set `includeHidden: true` to include entries with `hidden: true`) with effort options, optional `upgrade`, and `inputModalities`.

248- `modelProvider/capabilities/read` - read provider capability bounds for model/provider combinations (experimental; requires `capabilities.experimentalApi`).275- `modelProvider/capabilities/read` - read provider capability bounds for model/provider combinations (experimental; requires `capabilities.experimentalApi`).

249- `experimentalFeature/list` - list feature flags with lifecycle stage metadata and cursor pagination.276- `experimentalFeature/list` - list feature flags with lifecycle stage metadata and cursor pagination.

250- `experimentalFeature/enablement/set` - patch in-memory runtime enablement for supported feature keys such as `apps` and `plugins`.277- `experimentalFeature/enablement/set` - patch in-memory runtime settings for supported feature keys such as `apps` and `plugins`.

251- `collaborationMode/list` - list collaboration mode presets (experimental, no pagination).278- `collaborationMode/list` - list collaboration mode presets (experimental, no pagination).

252- `skills/list` - list skills for one or more `cwd` values (supports `forceReload` and optional `perCwdExtraUserRoots`).279- `skills/list` - list skills for one or more `cwd` values (supports `forceReload` and optional `perCwdExtraUserRoots`).

253- `skills/changed` (notify) - emitted when watched local skill files change.280- `skills/changed` (notify) - emitted when watched local skill files change.


351## Threads378## Threads

352 379 

353- `thread/read` reads a stored thread without subscribing to it; set `includeTurns` to include turns.380- `thread/read` reads a stored thread without subscribing to it; set `includeTurns` to include turns.

354- `thread/turns/list` pages through a stored thread's turn history without resuming it.381- `thread/turns/list` pages through a stored thread's turn history without

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

383 summarized, or fully loaded.

355- `thread/list` supports cursor pagination plus `modelProviders`, `sourceKinds`, `archived`, `cwd`, and `searchTerm` filtering.384- `thread/list` supports cursor pagination plus `modelProviders`, `sourceKinds`, `archived`, `cwd`, and `searchTerm` filtering.

356- `thread/loaded/list` returns the thread IDs currently in memory.385- `thread/loaded/list` returns the thread IDs currently in memory.

357- `thread/archive` moves the thread's persisted JSONL log into the archived directory.386- `thread/archive` moves the thread's persisted JSONL log into the archived directory.


378{ "id": 10, "result": {407{ "id": 10, "result": {

379 "thread": {408 "thread": {

380 "id": "thr_123",409 "id": "thr_123",

410 "sessionId": "thr_123",

381 "preview": "",411 "preview": "",

382 "ephemeral": false,412 "ephemeral": false,

383 "modelProvider": "openai",413 "modelProvider": "openai",


389 419 

390`serviceName` is optional. Set it when you want app-server to tag thread-level metrics with your integration's service name.420`serviceName` is optional. Set it when you want app-server to tag thread-level metrics with your integration's service name.

391 421 

422`thread.sessionId` identifies the current live session tree root. Root threads

423use their own thread id as the session id; forked threads keep the session id

424of the root they came from. Clients should read the session id from

425`thread.sessionId` instead of deriving it from the thread id.

426 

392To continue a stored session, call `thread/resume` with the `thread.id` you recorded earlier. The response shape matches `thread/start`. You can also pass the same configuration overrides supported by `thread/start`, such as `personality`:427To continue a stored session, call `thread/resume` with the `thread.id` you recorded earlier. The response shape matches `thread/start`. You can also pass the same configuration overrides supported by `thread/start`, such as `personality`:

393 428 

394```json429```json


407 442 

408If 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.443If 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.

409 444 

445### Manage a thread goal

446 

447`thread/goal/set`, `thread/goal/get`, and `thread/goal/clear` are experimental

448and require `capabilities.experimentalApi = true` plus the `goals` feature. Use

449them for the same persisted goal state surfaced by `/goal` in the TUI.

450 

451```json

452{ "method": "thread/goal/set", "id": 13, "params": {

453 "threadId": "thr_123",

454 "objective": "Finish the migration and keep tests green",

455 "status": "active",

456 "tokenBudget": 40000

457} }

458{ "id": 13, "result": { "goal": {

459 "threadId": "thr_123",

460 "objective": "Finish the migration and keep tests green",

461 "status": "active",

462 "tokenBudget": 40000,

463 "tokensUsed": 0,

464 "timeUsedSeconds": 0

465} } }

466{ "method": "thread/goal/updated", "params": {

467 "threadId": "thr_123",

468 "goal": {

469 "threadId": "thr_123",

470 "objective": "Finish the migration and keep tests green",

471 "status": "active",

472 "tokenBudget": 40000,

473 "tokensUsed": 0,

474 "timeUsedSeconds": 0

475 }

476} }

477```

478 

479Goal objectives must be non-empty and at most 4,000 characters. Supplying a new

480objective replaces the goal and resets usage accounting. Supplying the current

481non-terminal objective, or omitting `objective`, updates status or token budget

482while preserving usage history.

483 

410To branch from a stored session, call `thread/fork` with the `thread.id`. This creates a new thread id and emits a `thread/started` notification for it:484To branch from a stored session, call `thread/fork` with the `thread.id`. This creates a new thread id and emits a `thread/started` notification for it:

411 485 

412```json486```json

413{ "method": "thread/fork", "id": 12, "params": { "threadId": "thr_123" } }487{ "method": "thread/fork", "id": 12, "params": { "threadId": "thr_123" } }

414{ "id": 12, "result": { "thread": { "id": "thr_456" } } }488{ "id": 12, "result": { "thread": { "id": "thr_456", "sessionId": "thr_123", "forkedFromId": "thr_123" } } }

415{ "method": "thread/started", "params": { "thread": { "id": "thr_456" } } }489{ "method": "thread/started", "params": { "thread": { "id": "thr_456" } } }

416```490```

417 491 


435 509 

436Use `thread/turns/list` to page a stored thread's turn history without resuming it. Results default to newest-first so clients can fetch older turns with `nextCursor`. The response also includes `backwardsCursor`; pass it as `cursor` with `sortDirection: "asc"` to fetch turns newer than the first item from the earlier page.510Use `thread/turns/list` to page a stored thread's turn history without resuming it. Results default to newest-first so clients can fetch older turns with `nextCursor`. The response also includes `backwardsCursor`; pass it as `cursor` with `sortDirection: "asc"` to fetch turns newer than the first item from the earlier page.

437 511 

512`itemsView` controls how much turn-item data the response includes:

513 

514- `notLoaded` omits items.

515- `summary` returns summarized item data and is the default when omitted.

516- `full` returns full item data.

517 

438```json518```json

439{ "method": "thread/turns/list", "id": 20, "params": {519{ "method": "thread/turns/list", "id": 20, "params": {

440 "threadId": "thr_123",520 "threadId": "thr_123",

441 "limit": 50,521 "limit": 50,

442 "sortDirection": "desc"522 "sortDirection": "desc",

523 "itemsView": "summary"

443} }524} }

444{ "id": 20, "result": {525{ "id": 20, "result": {

445 "data": [],526 "data": [],


448} }529} }

449```530```

450 531 

532`thread/turns/items/list` is reserved for paged turn-item loading, but the

533current server returns an unsupported-method error.

534 

451### List threads (with pagination & filters)535### List threads (with pagination & filters)

452 536 

453`thread/list` lets you render a history UI. Results default to newest-first by `createdAt`. Filters apply before pagination. Pass any combination of:537`thread/list` lets you render a history UI. Results default to newest-first by `createdAt`. Filters apply before pagination. Pass any combination of:


825 909 

826Use this notification to render the reviewer output in your client.910Use this notification to render the reviewer output in your client.

827 911 

912## Process execution

913 

914`process/*` is an experimental, explicit process-control API. It requires

915`capabilities.experimentalApi = true` and runs outside Codex's sandbox. Use it

916only when your client intentionally exposes local process control without a

917sandbox.

918 

919Start a process with `process/spawn` and provide a `processHandle`, then use

920that handle for stdin, resize, and kill requests. Output streams through

921`process/outputDelta` notifications and completion streams through

922`process/exited`.

923 

924```json

925{ "method": "process/spawn", "id": 48, "params": {

926 "command": ["python3", "-m", "pytest", "-q"],

927 "processHandle": "pytest-1",

928 "cwd": "/Users/me/project",

929 "tty": true

930} }

931{ "id": 48, "result": {} }

932{ "method": "process/outputDelta", "params": {

933 "processHandle": "pytest-1",

934 "stream": "stdout",

935 "deltaBase64": "Li4u"

936} }

937{ "method": "process/exited", "params": {

938 "processHandle": "pytest-1",

939 "exitCode": 0

940} }

941```

942 

943Use `process/writeStdin` with `deltaBase64`, `closeStdin`, or both to send

944input. Use `process/resizePty` for PTY resize events and `process/kill` to

945terminate a running process.

946 

828## Command execution947## Command execution

829 948 

830`command/exec` runs a single command (`argv` array) under the server sandbox without creating a thread.949`command/exec` runs a single command (`argv` array) under the server sandbox without creating a thread.


990- `item/reasoning/summaryPartAdded` - marks a boundary between reasoning summary sections.1109- `item/reasoning/summaryPartAdded` - marks a boundary between reasoning summary sections.

991- `item/reasoning/textDelta` - streams raw reasoning text (when supported by the model).1110- `item/reasoning/textDelta` - streams raw reasoning text (when supported by the model).

992- `item/commandExecution/outputDelta` - streams stdout/stderr for a command; append deltas in order.1111- `item/commandExecution/outputDelta` - streams stdout/stderr for a command; append deltas in order.

993- `item/fileChange/outputDelta` - contains the tool call response of the underlying `apply_patch` tool call.1112- `item/fileChange/outputDelta` - deprecated compatibility notification for legacy `apply_patch` text output. Current app-server versions no longer emit it; use `fileChange` items and `turn/diff/updated` instead.

994 1113 

995## Errors1114## Errors

996 1115 


1050 1169 

1051`dynamicTools` on `thread/start` and the corresponding `item/tool/call` request or response flow are experimental APIs.1170`dynamicTools` on `thread/start` and the corresponding `item/tool/call` request or response flow are experimental APIs.

1052 1171 

1172Dynamic tool names and namespace names must follow Responses API naming

1173constraints. Avoid reserved namespace names used by built-in Codex tools.

1174 

1053When a dynamic tool is invoked during a turn, app-server emits:1175When a dynamic tool is invoked during a turn, app-server emits:

1054 1176 

10551. `item/started` with `item.type = "dynamicToolCall"`, `status = "inProgress"`, plus `tool` and `arguments`.11771. `item/started` with `item.type = "dynamicToolCall"`, `status = "inProgress"`, plus `tool` and `arguments`.


1662- `usedPercent` is current usage within the quota window.1784- `usedPercent` is current usage within the quota window.

1663- `windowDurationMins` is the quota window length.1785- `windowDurationMins` is the quota window length.

1664- `resetsAt` is a Unix timestamp (seconds) for the next reset.1786- `resetsAt` is a Unix timestamp (seconds) for the next reset.

1665- `planType` is included when the backend returns the ChatGPT plan associated with a bucket.1787- `planType` is included when the server returns the ChatGPT plan associated with a bucket.

1666- `credits` is included when the backend returns remaining workspace credit details.1788- `credits` is included when the server returns remaining workspace credit details.

1667- `rateLimitReachedType` identifies the backend-classified limit state when one has been reached.1789- `rateLimitReachedType` identifies the server-classified limit state when one has been reached.

1668 1790 

1669### 7) Notify a workspace owner about a limit1791### 7) Notify a workspace owner about a limit

1670 1792 

auth.md +8 −1

Details

20 20 

21When you sign in with ChatGPT from the Codex app, CLI, or IDE Extension, Codex opens a browser window for you to complete the login flow. After you sign in, the browser returns an access token to the CLI or IDE extension.21When you sign in with ChatGPT from the Codex app, CLI, or IDE Extension, Codex opens a browser window for you to complete the login flow. After you sign in, the browser returns an access token to the CLI or IDE extension.

22 22 

23If your environment already provides a ChatGPT access token, the CLI can read

24it from stdin:

25 

26```shell

27printenv CODEX_ACCESS_TOKEN | codex login --with-access-token

28```

29 

23### Sign in with an API key30### Sign in with an API key

24 31 

25You can also sign in to the Codex app, CLI, or IDE Extension with an API key. Get your API key from the [OpenAI dashboard](https://platform.openai.com/api-keys).32You can also sign in to the Codex app, CLI, or IDE Extension with an API key. Get your API key from the [OpenAI dashboard](https://platform.openai.com/api-keys).


116If your network uses a corporate TLS proxy or private root CA, set123If your network uses a corporate TLS proxy or private root CA, set

117`CODEX_CA_CERTIFICATE` to a PEM bundle before logging in. When124`CODEX_CA_CERTIFICATE` to a PEM bundle before logging in. When

118`CODEX_CA_CERTIFICATE` is unset, Codex falls back to `SSL_CERT_FILE`. The same125`CODEX_CA_CERTIFICATE` is unset, Codex falls back to `SSL_CERT_FILE`. The same

119custom CA settings apply to login, normal HTTPS requests, and secure websocket126custom CA settings apply to login, normal HTTPS requests, and secure WebSocket

120connections.127connections.

121 128 

122```shell129```shell

cli/features.md +32 −38

Details

48 48 

49## Connect the TUI to a remote app server49## Connect the TUI to a remote app server

50 50 

51Remote TUI mode lets you run the Codex app server on one machine and use the Codex terminal UI from another machine. This is useful when the code, credentials, or execution environment live on a remote host, but you want the local interactive TUI experience.51Remote TUI mode lets you run the Codex app server on one machine and use the

52 52Codex terminal UI from another machine. Start the app server with a WebSocket

53Start the app server on the machine that should own the workspace and run commands:53listener:

54 54 

55```bash55```bash

56codex app-server --listen ws://127.0.0.1:450056codex app-server --listen ws://127.0.0.1:4500

57```57```

58 58 

59Then connect from the machine running the TUI:59Then connect the TUI to that endpoint:

60 60 

61```bash61```bash

62codex --remote ws://127.0.0.1:450062codex --remote ws://127.0.0.1:4500

63```63```

64 64 

65For access from another machine, bind the app server to a reachable interface, for example:65For access from another machine, bind the app server to a reachable interface

66 66and configure WebSocket auth before remote use:

67```bash

68codex app-server --listen ws://0.0.0.0:4500

69```

70 

71`--remote` accepts explicit `ws://host:port` and `wss://host:port` addresses only. For plain WebSocket connections, prefer local-host addresses or SSH port forwarding. If you expose the listener beyond the local host, configure authentication before real remote use and put authenticated non-local connections behind TLS.

72 

73Codex supports these WebSocket authentication modes for remote TUI connections:

74 

75- **No WebSocket auth**: Best for local-host listeners or SSH port-forwarded connections. Codex can start non-local listeners without auth, but logs a warning and the startup banner reminds you to configure auth before real remote use.

76- **Capability token**: Store a shared token in a file on the app-server host, start the server with `--ws-auth capability-token --ws-token-file /abs/path/to/token`, then set the same token in an environment variable on the TUI host and pass `--remote-auth-token-env <ENV_VAR>`.

77- **Signed bearer token**: Store an HMAC shared secret in a file on the app-server host, start the server with `--ws-auth signed-bearer-token --ws-shared-secret-file /abs/path/to/secret`, and have the TUI send a signed JWT bearer token through `--remote-auth-token-env <ENV_VAR>`. The shared secret must be at least 32 bytes. Signed tokens use HS256 and must include `exp`; Codex also validates `nbf`, `iss`, and `aud` when those claims or server options are present.

78 

79To create a capability token on the app-server host, generate a random token file with permissions that only your user can read:

80 67 

81```bash68```bash

82TOKEN_FILE="$HOME/.codex/codex-app-server-token"69TOKEN_FILE="$HOME/.codex/app-server-token"

83install -d -m 700 "$(dirname "$TOKEN_FILE")"

84openssl rand -base64 32 > "$TOKEN_FILE"70openssl rand -base64 32 > "$TOKEN_FILE"

85chmod 600 "$TOKEN_FILE"71chmod 600 "$TOKEN_FILE"

72codex app-server --listen ws://0.0.0.0:4500 --ws-auth capability-token --ws-token-file "$TOKEN_FILE"

86```73```

87 74 

88Treat the token file like a password, and regenerate it if it leaks.75`--remote` accepts explicit `ws://host:port` and `wss://host:port` addresses.

76Plain WebSocket connections are appropriate for localhost and SSH

77port-forwarding workflows. For non-local clients, use WebSocket auth and put the

78connection behind TLS.

79 

80Codex supports these WebSocket authentication modes:

81 

82- Capability token: start the server with `--ws-auth capability-token` and

83 either `--ws-token-file /absolute/path` or `--ws-token-sha256 HEX`.

84- Signed bearer token: start the server with

85 `--ws-auth signed-bearer-token --ws-shared-secret-file /absolute/path`, plus

86 optional `--ws-issuer`, `--ws-audience`, and `--ws-max-clock-skew-seconds`.

89 87 

90Then start the app server with that token file. For example, with a capability token behind a TLS proxy:88The TUI sends the remote auth token as an `Authorization: Bearer <token>` header

89during the WebSocket handshake. Codex only accepts remote auth tokens over

90`wss://` URLs or loopback `ws://` URLs.

91 91 

92```bash92```bash

93# Remote host93export CODEX_REMOTE_TOKEN="$(cat "$TOKEN_FILE")"

94TOKEN_FILE="$HOME/.codex/codex-app-server-token"94codex --remote wss://remote-host:4500 --remote-auth-token-env CODEX_REMOTE_TOKEN

95codex app-server \

96 --listen ws://0.0.0.0:4500 \

97 --ws-auth capability-token \

98 --ws-token-file "$TOKEN_FILE"

99 

100# TUI host

101export CODEX_REMOTE_AUTH_TOKEN="$(ssh devbox 'cat ~/.codex/codex-app-server-token')"

102codex --remote wss://codex-devbox.example.com:4500 \

103 --remote-auth-token-env CODEX_REMOTE_AUTH_TOKEN

104```95```

105 96 

106The TUI sends remote auth tokens as `Authorization: Bearer <token>` during the WebSocket handshake. Codex only sends those tokens over `wss://` URLs or `ws://` URLs whose host is `localhost`, `127.0.0.1`, or `::1`, so put non-local remote listeners behind TLS if clients need to authenticate over the network.97For SSH remote projects in the Codex app, use

98[Remote connections](https://developers.openai.com/codex/remote-connections). For managed remote-control

99clients, `codex remote-control` starts an app-server process with

100remote-control support enabled.

107 101 

108## Models and reasoning102## Models and reasoning

109 103 

110For most tasks in Codex, `gpt-5.5` is the recommended model when it is104For most tasks in Codex, `gpt-5.5` is the recommended model when it's

111available. It is OpenAI's newest frontier model for complex coding, computer105available. It's OpenAI's newest frontier model for complex coding, computer

112use, knowledge work, and research workflows, with stronger planning, tool use,106use, knowledge work, and research workflows, with stronger planning, tool use,

113and follow-through on multi-step tasks. If `gpt-5.5` is not yet available,107and follow-through on multi-step tasks. If `gpt-5.5` isn't yet available,

114continue using `gpt-5.4`. For extra fast tasks, ChatGPT Pro subscribers have108continue using `gpt-5.4`. For extra fast tasks, ChatGPT Pro subscribers have

115access to the GPT-5.3-Codex-Spark model in research preview.109access to the GPT-5.3-Codex-Spark model in research preview.

116 110 

cli/reference.md +34 −7

Details

122 href: "/codex/cli/reference#codex-app-server",122 href: "/codex/cli/reference#codex-app-server",

123 type: "experimental",123 type: "experimental",

124 description:124 description:

125 "Launch the Codex app server for local development or debugging.",125 "Launch the Codex app server for local development or debugging over stdio, WebSocket, or a Unix socket.",

126 },

127 {

128 key: "codex remote-control",

129 href: "/codex/cli/reference#codex-remote-control",

130 type: "experimental",

131 description:

132 "Ensure the local app-server daemon is running with remote-control support enabled.",

126 },133 },

127 {134 {

128 key: "codex app",135 key: "codex app",


192 href: "/codex/cli/reference#codex-login",199 href: "/codex/cli/reference#codex-login",

193 type: "stable",200 type: "stable",

194 description:201 description:

195 "Authenticate Codex using ChatGPT OAuth, device auth, or an API key piped over stdin.",202 "Authenticate Codex using ChatGPT OAuth, device auth, an API key, or an access token piped over stdin.",

196 },203 },

197 {204 {

198 key: "codex logout",205 key: "codex logout",


375export const appServerOptions = [382export const appServerOptions = [

376 {383 {

377 key: "--listen",384 key: "--listen",

378 type: "stdio:// | ws://IP:PORT",385 type: "stdio:// | ws://IP:PORT | unix:// | unix://PATH | off",

379 defaultValue: "stdio://",386 defaultValue: "stdio://",

380 description:387 description:

381 "Transport listener URL. Use `ws://IP:PORT` to expose a WebSocket endpoint for remote clients.",388 "Transport listener URL. Use `stdio://` for JSONL, `ws://IP:PORT` for a TCP WebSocket endpoint, `unix://` for the default Unix socket, `unix://PATH` for a custom Unix socket, or `off` to disable the local transport.",

382 },389 },

383 {390 {

384 key: "--ws-auth",391 key: "--ws-auth",


417 description:424 description:

418 "Clock skew allowance when validating signed bearer token `exp` and `nbf` claims. Requires `--ws-auth signed-bearer-token`.",425 "Clock skew allowance when validating signed bearer token `exp` and `nbf` claims. Requires `--ws-auth signed-bearer-token`.",

419 },426 },

427 {

428 key: "--analytics-default-enabled",

429 type: "boolean",

430 defaultValue: "false",

431 description:

432 "Defaults analytics to enabled for first-party app-server clients unless the user opts out in config.",

433 },

420];434];

421 435 

422export const appOptions = [436export const appOptions = [


583 description:597 description:

584 "Read an API key from stdin (for example `printenv OPENAI_API_KEY | codex login --with-api-key`).",598 "Read an API key from stdin (for example `printenv OPENAI_API_KEY | codex login --with-api-key`).",

585 },599 },

600 {

601 key: "--with-access-token",

602 type: "boolean",

603 description:

604 "Read an access token from stdin (for example `printenv CODEX_ACCESS_TOKEN | codex login --with-access-token`).",

605 },

586 {606 {

587 key: "--device-auth",607 key: "--device-auth",

588 type: "boolean",608 type: "boolean",


893 913 

894Running `codex` with no subcommand launches the interactive terminal UI (TUI). The agent accepts the global flags above plus image attachments. Web search defaults to cached mode; use `--search` to switch to live browsing. For low-friction local work, use `--sandbox workspace-write --ask-for-approval on-request`.914Running `codex` with no subcommand launches the interactive terminal UI (TUI). The agent accepts the global flags above plus image attachments. Web search defaults to cached mode; use `--search` to switch to live browsing. For low-friction local work, use `--sandbox workspace-write --ask-for-approval on-request`.

895 915 

896Use `--remote ws://host:port` or `--remote wss://host:port` to connect the TUI to an app server started with `codex app-server --listen ws://IP:PORT`. Add `--remote-auth-token-env <ENV_VAR>` when the server requires a bearer token for WebSocket authentication. See [Codex CLI features](https://developers.openai.com/codex/cli/features#connect-the-tui-to-a-remote-app-server) for setup examples and authentication guidance.916Use `--remote ws://host:port` or `--remote wss://host:port` to connect the TUI to an app server started with `codex app-server --listen ws://IP:PORT`. Add `--remote-auth-token-env <ENV_VAR>` when the server requires a bearer token for WebSocket authentication.

897 917 

898### `codex app-server`918### `codex app-server`

899 919 


901 921 

902<ConfigTable client:load options={appServerOptions} />922<ConfigTable client:load options={appServerOptions} />

903 923 

904`codex app-server --listen stdio://` keeps the default JSONL-over-stdio behavior. `--listen ws://IP:PORT` enables WebSocket transport for app-server clients. The server accepts `ws://` listen URLs; use TLS termination or a secure proxy when clients connect with `wss://`. If you generate schemas for client bindings, add `--experimental` to include gated fields and methods.924`codex app-server --listen stdio://` keeps the default JSONL-over-stdio behavior. `--listen ws://IP:PORT` enables WebSocket transport for app-server clients. The server accepts `ws://` listen URLs; use TLS termination or a secure proxy when clients connect with `wss://`. Use `--listen unix://` to accept WebSocket handshakes on Codex's default Unix socket, or `--listen unix:///absolute/path.sock` to choose a socket path. If you generate schemas for client bindings, add `--experimental` to include gated fields and methods.

925 

926### `codex remote-control`

927 

928Ensure the app-server daemon is running with remote-control support enabled.

929Managed remote-control clients and SSH remote workflows use this command; it's

930not a replacement for `codex app-server --listen` when you are building a local

931protocol client.

905 932 

906### `codex app`933### `codex app`

907 934 


983 1010 

984### `codex login`1011### `codex login`

985 1012 

986Authenticate the CLI with a ChatGPT account or API key. With no flags, Codex opens a browser for the ChatGPT OAuth flow.1013Authenticate the CLI with a ChatGPT account, API key, or access token. With no flags, Codex opens a browser for the ChatGPT OAuth flow.

987 1014 

988<ConfigTable client:load options={loginOptions} />1015<ConfigTable client:load options={loginOptions} />

989 1016 

Details

9 9 

10- Find the right built-in slash command for a task10- Find the right built-in slash command for a task

11- Steer an active session with commands like `/model`, `/fast`,11- Steer an active session with commands like `/model`, `/fast`,

12 `/personality`, `/permissions`, `/agent`, and `/status`12 `/personality`, `/permissions`, `/approve`, `/raw`, `/agent`, and `/status`

13 13 

14## Built-in slash commands14## Built-in slash commands

15 15 


24| Command | Purpose | When to use it |24| Command | Purpose | When to use it |

25| ------------------------------------------------------------------------------- | --------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------- |25| ------------------------------------------------------------------------------- | --------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------- |

26| [`/permissions`](#update-permissions-with-permissions) | Set what Codex can do without asking first. | Relax or tighten approval requirements mid-session, such as switching between Auto and Read Only. |26| [`/permissions`](#update-permissions-with-permissions) | Set what Codex can do without asking first. | Relax or tighten approval requirements mid-session, such as switching between Auto and Read Only. |

27| [`/ide`](#include-ide-context-with-ide) | Include open files, current selection, and other IDE context. | Pull editor context into the next prompt without re-explaining what's open in your IDE. |

28| [`/keymap`](#remap-tui-shortcuts-with-keymap) | Remap TUI keyboard shortcuts. | Inspect and persist custom shortcut bindings in `config.toml`. |

29| [`/vim`](#toggle-vim-mode-with-vim) | Toggle Vim mode for the composer. | Switch between Vim normal/insert behavior and the default composer editing mode. |

27| [`/sandbox-add-read-dir`](#grant-sandbox-read-access-with-sandbox-add-read-dir) | Grant sandbox read access to an extra directory (Windows only). | Unblock commands that need to read an absolute directory path outside the current readable roots. |30| [`/sandbox-add-read-dir`](#grant-sandbox-read-access-with-sandbox-add-read-dir) | Grant sandbox read access to an extra directory (Windows only). | Unblock commands that need to read an absolute directory path outside the current readable roots. |

28| [`/agent`](#switch-agent-threads-with-agent) | Switch the active agent thread. | Inspect or continue work in a spawned subagent thread. |31| [`/agent`](#switch-agent-threads-with-agent) | Switch the active agent thread. | Inspect or continue work in a spawned subagent thread. |

29| [`/apps`](#browse-apps-with-apps) | Browse apps (connectors) and insert them into your prompt. | Attach an app as `$app-slug` before asking Codex to use it. |32| [`/apps`](#browse-apps-with-apps) | Browse apps (connectors) and insert them into your prompt. | Attach an app as `$app-slug` before asking Codex to use it. |

30| [`/plugins`](#browse-plugins-with-plugins) | Browse installed and discoverable plugins. | Inspect plugin tools, install suggested plugins, or manage plugin availability. |33| [`/plugins`](#browse-plugins-with-plugins) | Browse installed and discoverable plugins. | Inspect plugin tools, install suggested plugins, or manage plugin availability. |

34| [`/hooks`](#review-hooks-with-hooks) | Review lifecycle hooks. | Inspect configured hooks, trust new or changed hooks, or disable non-managed hooks before they run. |

31| [`/clear`](#clear-the-terminal-and-start-a-new-chat-with-clear) | Clear the terminal and start a fresh chat. | Reset the visible UI and conversation together when you want a fresh start. |35| [`/clear`](#clear-the-terminal-and-start-a-new-chat-with-clear) | Clear the terminal and start a fresh chat. | Reset the visible UI and conversation together when you want a fresh start. |

32| [`/compact`](#keep-transcripts-lean-with-compact) | Summarize the visible conversation to free tokens. | Use after long runs so Codex retains key points without blowing the context window. |36| [`/compact`](#keep-transcripts-lean-with-compact) | Summarize the visible conversation to free tokens. | Use after long runs so Codex retains key points without blowing the context window. |

33| [`/copy`](#copy-the-latest-response-with-copy) | Copy the latest completed Codex output. | Grab the latest finished response or plan text without manually selecting it. You can also press `Ctrl+O`. |37| [`/copy`](#copy-the-latest-response-with-copy) | Copy the latest completed Codex output. | Grab the latest finished response or plan text without manually selecting it. You can also press `Ctrl+O`. |

34| [`/diff`](#review-changes-with-diff) | Show the Git diff, including files Git isn't tracking yet. | Review Codex's edits before you commit or run tests. |38| [`/diff`](#review-changes-with-diff) | Show the Git diff, including files Git isn't tracking yet. | Review Codex's edits before you commit or run tests. |

35| [`/exit`](#exit-the-cli-with-quit-or-exit) | Exit the CLI (same as `/quit`). | Alternative spelling; both commands exit the session. |39| [`/exit`](#exit-the-cli-with-quit-or-exit) | Exit the CLI (same as `/quit`). | Alternative spelling; both commands exit the session. |

36| [`/experimental`](#toggle-experimental-features-with-experimental) | Toggle experimental features. | Enable optional features such as subagents from the CLI. |40| [`/experimental`](#toggle-experimental-features-with-experimental) | Toggle experimental features. | Enable optional features such as subagents from the CLI. |

41| [`/approve`](#approve-an-auto-review-denial-with-approve) | Approve one retry of a recent auto review denial. | Retry a command or action that the auto reviewer denied. |

42| [`/memories`](#configure-memories-with-memories) | Configure memory use and generation. | Turn memory injection or memory generation on or off without leaving the TUI. |

43| [`/skills`](#use-skills-with-skills) | Browse and use skills. | Improve task-specific behavior by selecting a relevant local skill. |

44| [`/hooks`](#view-lifecycle-hooks-with-hooks) | View and manage lifecycle hooks. | Inspect hook configuration loaded into the current session. |

37| [`/feedback`](#send-feedback-with-feedback) | Send logs to the Codex maintainers. | Report issues or share diagnostics with support. |45| [`/feedback`](#send-feedback-with-feedback) | Send logs to the Codex maintainers. | Report issues or share diagnostics with support. |

38| [`/init`](#generate-agentsmd-with-init) | Generate an `AGENTS.md` scaffold in the current directory. | Capture persistent instructions for the repository or subdirectory you're working in. |46| [`/init`](#generate-agentsmd-with-init) | Generate an `AGENTS.md` scaffold in the current directory. | Capture persistent instructions for the repository or subdirectory you're working in. |

39| [`/logout`](#sign-out-with-logout) | Sign out of Codex. | Clear local credentials when using a shared machine. |47| [`/logout`](#sign-out-with-logout) | Sign out of Codex. | Clear local credentials when using a shared machine. |

40| [`/mcp`](#list-mcp-tools-with-mcp) | List configured Model Context Protocol (MCP) tools. | Check which external tools Codex can call during the session; add `verbose` for server details. |48| [`/mcp`](#list-mcp-tools-with-mcp) | List configured Model Context Protocol (MCP) tools. | Check which external tools Codex can call during the session; add `verbose` for server details. |

41| [`/mention`](#highlight-files-with-mention) | Attach a file to the conversation. | Point Codex at specific files or folders you want it to inspect next. |49| [`/mention`](#highlight-files-with-mention) | Attach a file to the conversation. | Point Codex at specific files or folders you want it to inspect next. |

42| [`/model`](#set-the-active-model-with-model) | Choose the active model (and reasoning effort, when available). | Switch between general-purpose models (`gpt-4.1-mini`) and deeper reasoning models before running a task. |50| [`/model`](#set-the-active-model-with-model) | Choose the active model (and reasoning effort, when available). | Switch between general-purpose models (`gpt-4.1-mini`) and deeper reasoning models before running a task. |

43| [`/fast`](#toggle-fast-mode-with-fast) | Toggle Fast mode for supported models. | Turn Fast mode on or off, or check whether the current thread is using it. |51| [`/fast`](#toggle-fast-mode-with-fast) | Toggle a Fast service tier when the model catalog exposes one. | Turn the current model's Fast tier on or off, or check whether the thread is using it. |

44| [`/plan`](#switch-to-plan-mode-with-plan) | Switch to plan mode and optionally send a prompt. | Ask Codex to propose an execution plan before implementation work starts. |52| [`/plan`](#switch-to-plan-mode-with-plan) | Switch to plan mode and optionally send a prompt. | Ask Codex to propose an execution plan before implementation work starts. |

45| [`/goal`](#set-or-view-an-experimental-task-goal-with-goal) | Set or view an experimental goal for a long-running task. | Give Codex a persistent target to track while a larger task runs. Requires `features.goals`. |53| [`/goal`](#set-or-view-an-experimental-task-goal-with-goal) | Set, pause, resume, view, or clear a task goal. | Give Codex a persistent target to track while a larger task runs. Requires `features.goals`. |

46| [`/personality`](#set-a-communication-style-with-personality) | Choose a communication style for responses. | Make Codex more concise, more explanatory, or more collaborative without changing your instructions. |54| [`/personality`](#set-a-communication-style-with-personality) | Choose a communication style for responses. | Make Codex more concise, more explanatory, or more collaborative without changing your instructions. |

47| [`/ps`](#check-background-terminals-with-ps) | Show experimental background terminals and their recent output. | Check long-running commands without leaving the main transcript. |55| [`/ps`](#check-background-terminals-with-ps) | Show experimental background terminals and their recent output. | Check long-running commands without leaving the main transcript. |

48| [`/stop`](#stop-background-terminals-with-stop) | Stop all background terminals. | Cancel background terminal work started by the current session. |56| [`/stop`](#stop-background-terminals-with-stop) | Stop all background terminals. | Cancel background terminal work started by the current session. |

49| [`/fork`](#fork-the-current-conversation-with-fork) | Fork the current conversation into a new thread. | Branch the active session to explore a new approach without losing the current transcript. |57| [`/fork`](#fork-the-current-conversation-with-fork) | Fork the current conversation into a new thread. | Branch the active session to explore a new approach without losing the current transcript. |

50| [`/side`](#start-a-side-conversation-with-side) | Start an ephemeral side conversation. | Ask a focused follow-up without disrupting the main thread's transcript. |58| [`/side`](#start-a-side-conversation-with-side) | Start an ephemeral side conversation. | Ask a focused follow-up without disrupting the main thread's transcript. |

59| [`/raw`](#toggle-raw-scrollback-with-raw) | Toggle raw scrollback mode. | Make terminal selection and copying less formatted while reviewing long output. |

51| [`/resume`](#resume-a-saved-conversation-with-resume) | Resume a saved conversation from your session list. | Continue work from a previous CLI session without starting over. |60| [`/resume`](#resume-a-saved-conversation-with-resume) | Resume a saved conversation from your session list. | Continue work from a previous CLI session without starting over. |

52| [`/new`](#start-a-new-conversation-with-new) | Start a new conversation inside the same CLI session. | Reset the chat context without leaving the CLI when you want a fresh prompt in the same repo. |61| [`/new`](#start-a-new-conversation-with-new) | Start a new conversation inside the same CLI session. | Reset the chat context without leaving the CLI when you want a fresh prompt in the same repo. |

53| [`/quit`](#exit-the-cli-with-quit-or-exit) | Exit the CLI. | Leave the session immediately. |62| [`/quit`](#exit-the-cli-with-quit-or-exit) | Exit the CLI. | Leave the session immediately. |


56| [`/debug-config`](#inspect-config-layers-with-debug-config) | Print config layer and requirements diagnostics. | Debug precedence and policy requirements, including experimental network constraints. |65| [`/debug-config`](#inspect-config-layers-with-debug-config) | Print config layer and requirements diagnostics. | Debug precedence and policy requirements, including experimental network constraints. |

57| [`/statusline`](#configure-footer-items-with-statusline) | Configure TUI status-line fields interactively. | Pick and reorder footer items (model/context/limits/git/tokens/session) and persist in config.toml. |66| [`/statusline`](#configure-footer-items-with-statusline) | Configure TUI status-line fields interactively. | Pick and reorder footer items (model/context/limits/git/tokens/session) and persist in config.toml. |

58| [`/title`](#configure-terminal-title-items-with-title) | Configure terminal window or tab title fields interactively. | Pick and reorder title items such as project, status, thread, branch, model, and task progress. |67| [`/title`](#configure-terminal-title-items-with-title) | Configure terminal window or tab title fields interactively. | Pick and reorder title items such as project, status, thread, branch, model, and task progress. |

59| [`/keymap`](#remap-tui-shortcuts-with-keymap) | Remap TUI keyboard shortcuts. | Inspect and persist custom shortcut bindings in `config.toml`. |68| [`/theme`](#choose-a-syntax-theme-with-theme) | Choose a syntax-highlighting theme. | Preview and persist a terminal syntax-highlighting theme. |

60 69 

61`/quit` and `/exit` both exit the CLI. Use them only after you have saved or70`/quit` and `/exit` both exit the CLI. Use them only after you have saved or

62committed any important work.71committed any important work.

63 72 

64The `/approvals` command still works as an alias, but it no longer appears in the slash popup list.73Use `/permissions` to adjust what Codex can do without asking first. Use

74`/approve` only when you need to retry a recent action that automatic review

75denied.

65 76 

66## Control your session with slash commands77## Control your session with slash commands

67 78 


801. Type `/fast on`, `/fast off`, or `/fast status`.911. Type `/fast on`, `/fast off`, or `/fast status`.

812. If you want the setting to persist, confirm the update when Codex offers to save it.922. If you want the setting to persist, confirm the update when Codex offers to save it.

82 93 

83Expected: Codex reports whether Fast mode is on or off for the current thread. In the TUI footer, you can also show a Fast mode status-line item with `/statusline`.94Expected: Codex reports whether the current model's Fast service tier is on or

95off for the current thread. In the TUI footer, you can also show a Fast mode

96status-line item with `/statusline`.

97 

98Fast tier commands are catalog-driven. If the current model doesn't advertise a

99Fast tier, Codex won't show `/fast`.

84 100 

85### Set a communication style with `/personality`101### Set a communication style with `/personality`

86 102 


119 135 

120Expected: Codex keeps the goal attached to the active thread while work continues.136Expected: Codex keeps the goal attached to the active thread while work continues.

121 137 

138Goal objectives must be non-empty and at most 4,000 characters. For longer

139instructions, put the details in a file and point the goal at that file.

140 

122### Toggle experimental features with `/experimental`141### Toggle experimental features with `/experimental`

123 142 

1241. Type `/experimental` and press Enter.1431. Type `/experimental` and press Enter.


126 145 

127Expected: Codex saves your feature choices to config and applies them on restart.146Expected: Codex saves your feature choices to config and applies them on restart.

128 147 

148### Approve an auto review denial with `/approve`

149 

150Use `/approve` when the automatic reviewer denied a recent action and you want

151Codex to retry it once.

152 

1531. Type `/approve`.

1542. Confirm the retry when Codex shows the relevant denied action.

155 

156Expected: Codex retries that denied action once under the current session

157policy.

158 

159### Configure memories with `/memories`

160 

1611. Type `/memories`.

1622. Choose whether Codex should use existing memories, generate new memories, or

163 keep memory behavior disabled.

164 

165Expected: Codex updates the relevant memory settings for future sessions.

166 

167### Use skills with `/skills`

168 

1691. Type `/skills`.

1702. Pick the skill you want Codex to apply.

171 

172Expected: Codex inserts the selected skill context so the next request follows

173that skill's instructions.

174 

175### View lifecycle hooks with `/hooks`

176 

1771. Type `/hooks`.

1782. Review the loaded lifecycle hook configuration.

179 

180Expected: Codex shows the hooks that can run in the current session.

181 

129### Clear the terminal and start a new chat with `/clear`182### Clear the terminal and start a new chat with `/clear`

130 183 

1311. Type `/clear` and press Enter.1841. Type `/clear` and press Enter.


147Expected: Codex announces the updated policy. Future actions respect the200Expected: Codex announces the updated policy. Future actions respect the

148updated approval mode until you change it again.201updated approval mode until you change it again.

149 202 

203### Include IDE context with `/ide`

204 

2051. Type `/ide`.

2062. Add optional inline text if you want to explain what Codex should do with the

207 current IDE selection or open files.

208 

209Expected: Codex includes available IDE context in the next prompt.

210 

211### Toggle Vim mode with `/vim`

212 

2131. Type `/vim`.

2142. Continue editing in the composer.

215 

216Expected: Codex toggles composer Vim mode for the current session. To make Vim

217mode the default for new sessions, set `tui.vim_mode_default = true` in

218`config.toml`.

219 

150### Copy the latest response with `/copy`220### Copy the latest response with `/copy`

151 221 

1521. Type `/copy` and press Enter.2221. Type `/copy` and press Enter.


160You can also press <kbd>Ctrl</kbd>+<kbd>O</kbd> from the main TUI to copy the230You can also press <kbd>Ctrl</kbd>+<kbd>O</kbd> from the main TUI to copy the

161latest completed response without opening the slash command menu.231latest completed response without opening the slash command menu.

162 232 

233### Toggle raw scrollback with `/raw`

234 

2351. Type `/raw`, `/raw on`, or `/raw off`.

236 

237Expected: Codex toggles raw scrollback mode, which makes terminal selection and

238copying more direct. You can also use the default <kbd>Alt</kbd>+<kbd>R</kbd>

239binding or persist the default with `tui.raw_output_mode = true`.

240 

163### Grant sandbox read access with `/sandbox-add-read-dir`241### Grant sandbox read access with `/sandbox-add-read-dir`

164 242 

165This command is available only when running the CLI natively on Windows.243This command is available only when running the CLI natively on Windows.


213Available title items include app name, project, spinner, status, thread, git291Available title items include app name, project, spinner, status, thread, git

214branch, model, and task progress.292branch, model, and task progress.

215 293 

294### Choose a syntax theme with `/theme`

295 

2961. Type `/theme`.

2972. Preview a theme from the picker, then confirm.

298 

299Expected: Codex updates syntax highlighting and persists the choice to

300`tui.theme` in `config.toml`.

301 

216### Remap TUI shortcuts with `/keymap`302### Remap TUI shortcuts with `/keymap`

217 303 

218Use `/keymap` to inspect, update, and persist keyboard shortcut bindings for the TUI.304Use `/keymap` to inspect, update, and persist keyboard shortcut bindings for the TUI.


349discoverable plugins that your configuration allows, and installed plugin state.435discoverable plugins that your configuration allows, and installed plugin state.

350Press <kbd>Space</kbd> on an installed plugin to toggle its enabled state.436Press <kbd>Space</kbd> on an installed plugin to toggle its enabled state.

351 437 

438### Review hooks with `/hooks`

439 

4401. Type `/hooks`.

4412. Choose a hook event to inspect the matching handlers.

4423. Trust, disable, or re-enable non-managed hooks as needed.

443 

444Expected: Codex opens the hook browser so you can review configured lifecycle

445hooks. Managed hooks appear as managed and can't be disabled from the user hook

446browser.

447 

352### Switch agent threads with `/agent`448### Switch agent threads with `/agent`

353 449 

3541. Type `/agent` and press Enter.4501. Type `/agent` and press Enter.

config-advanced.md +13 −12

Details

88 88 

89Relative paths inside a project config (for example, `model_instructions_file`) are resolved relative to the `.codex/` folder that contains the `config.toml`.89Relative paths inside a project config (for example, `model_instructions_file`) are resolved relative to the `.codex/` folder that contains the `config.toml`.

90 90 

91## Hooks (experimental)91Project config files can't override settings that redirect credentials, change

92provider auth, or run machine-local notification/telemetry commands.

93Codex ignores the following keys in project-local `.codex/config.toml` and

94prints a startup warning when it sees them: `openai_base_url`,

95`chatgpt_base_url`, `model_provider`, `model_providers`, `notify`, `profile`,

96`profiles`, `experimental_realtime_ws_base_url`, and `otel`. Set those keys in

97your user-level `~/.codex/config.toml` instead.

98 

99## Hooks

92 100 

93Codex can also load lifecycle hooks from either `hooks.json` files or inline101Codex can also load lifecycle hooks from either `hooks.json` files or inline

94`[hooks]` tables in `config.toml` files that sit next to active config layers.102`[hooks]` tables in `config.toml` files that sit next to active config layers.

95 103 

96In practice, the two most useful locations are:104In practice, the four most useful locations are:

97 105 

98- `~/.codex/hooks.json`106- `~/.codex/hooks.json`

99- `~/.codex/config.toml`107- `~/.codex/config.toml`


103Project-local hooks load only when the project `.codex/` layer is trusted.111Project-local hooks load only when the project `.codex/` layer is trusted.

104User-level hooks remain independent of project trust.112User-level hooks remain independent of project trust.

105 113 

106Turn hooks on with:

107 

108```toml

109[features]

110codex_hooks = true

111```

112 

113Inline TOML hooks use the same event structure as `hooks.json`:114Inline TOML hooks use the same event structure as `hooks.json`:

114 115 

115```toml116```toml


469| `websocket.request.duration_ms` | histogram | `success` | WebSocket request duration in milliseconds. |470| `websocket.request.duration_ms` | histogram | `success` | WebSocket request duration in milliseconds. |

470| `websocket.event` | counter | `kind`, `success` | WebSocket message/event count by type and success/failure. |471| `websocket.event` | counter | `kind`, `success` | WebSocket message/event count by type and success/failure. |

471| `websocket.event.duration_ms` | histogram | `kind`, `success` | WebSocket message/event processing duration in milliseconds. |472| `websocket.event.duration_ms` | histogram | `kind`, `success` | WebSocket message/event processing duration in milliseconds. |

472| `responses_api_overhead.duration_ms` | histogram | | Responses API overhead timing from websocket responses. |473| `responses_api_overhead.duration_ms` | histogram | | Responses API overhead timing from WebSocket responses. |

473| `responses_api_inference_time.duration_ms` | histogram | | Responses API inference timing from websocket responses. |474| `responses_api_inference_time.duration_ms` | histogram | | Responses API inference timing from WebSocket responses. |

474| `responses_api_engine_iapi_ttft.duration_ms` | histogram | | Responses API engine IAPI time-to-first-token timing. |475| `responses_api_engine_iapi_ttft.duration_ms` | histogram | | Responses API engine IAPI time-to-first-token timing. |

475| `responses_api_engine_service_ttft.duration_ms` | histogram | | Responses API engine service time-to-first-token timing. |476| `responses_api_engine_service_ttft.duration_ms` | histogram | | Responses API engine service time-to-first-token timing. |

476| `responses_api_engine_iapi_tbt.duration_ms` | histogram | | Responses API engine IAPI time-between-token timing. |477| `responses_api_engine_iapi_tbt.duration_ms` | histogram | | Responses API engine IAPI time-between-token timing. |


505| `mcp.call` | counter | See note | MCP tool invocation result. |506| `mcp.call` | counter | See note | MCP tool invocation result. |

506| `mcp.call.duration_ms` | histogram | See note | MCP tool invocation duration. |507| `mcp.call.duration_ms` | histogram | See note | MCP tool invocation duration. |

507| `mcp.tools.list.duration_ms` | histogram | `cache` | MCP tool-list duration, including cache hit/miss state. |508| `mcp.tools.list.duration_ms` | histogram | `cache` | MCP tool-list duration, including cache hit/miss state. |

508| `mcp.tools.fetch_uncached.duration_ms` | histogram | | Duration of uncached MCP tool fetches. |509| `mcp.tools.fetch_uncached.duration_ms` | histogram | | Duration of MCP tool fetches that miss the cache. |

509| `mcp.tools.cache_write.duration_ms` | histogram | | Duration of Codex Apps MCP tool-cache writes. |510| `mcp.tools.cache_write.duration_ms` | histogram | | Duration of Codex Apps MCP tool-cache writes. |

510| `hooks.run` | counter | `hook_name`, `source`, `status` | Hook run count by hook name, source, and status. |511| `hooks.run` | counter | `hook_name`, `source`, `status` | Hook run count by hook name, source, and status. |

511| `hooks.run.duration_ms` | histogram | `hook_name`, `source`, `status` | Hook run duration in milliseconds. |512| `hooks.run.duration_ms` | histogram | `hook_name`, `source`, `status` | Hook run duration in milliseconds. |

config-basic.md +4 −3

Details

168### Supported features168### Supported features

169 169 

170| Key | Default | Maturity | Description |170| Key | Default | Maturity | Description |

171| -------------------- | :-------------------: | ------------ | ---------------------------------------------------------------------------------------- |171| -------------------- | :-------------------: | ----------------- | ---------------------------------------------------------------------------------------------- |

172| `apps` | false | Experimental | Enable ChatGPT Apps/connectors support |172| `apps` | false | Experimental | Enable ChatGPT Apps/connectors support |

173| `codex_git_commit` | false | Experimental | Enable Codex-generated git commits and commit attribution trailers |173| `codex_git_commit` | false | Experimental | Enable Codex-generated git commits and commit attribution trailers |

174| `codex_hooks` | true | Stable | Enable lifecycle hooks from `hooks.json` or inline `[hooks]`. See [Hooks](https://developers.openai.com/codex/hooks). |174| `hooks` | true | Stable | Enable lifecycle hooks from `hooks.json` or inline `[hooks]`. See [Hooks](https://developers.openai.com/codex/hooks). |

175| `plugin_hooks` | false | Under development | Opt into lifecycle hooks bundled with plugins. See [Hooks](https://developers.openai.com/codex/hooks#plugin-bundled-hooks). |

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

176| `memories` | false | Stable | Enable [Memories](https://developers.openai.com/codex/memories) |177| `memories` | false | Stable | Enable [Memories](https://developers.openai.com/codex/memories) |

177| `multi_agent` | true | Stable | Enable subagent collaboration tools |178| `multi_agent` | true | Stable | Enable subagent collaboration tools |


190 191 

191Omit feature keys to keep their defaults.192Omit feature keys to keep their defaults.

192 193 

193For the current lifecycle hooks MVP, see [Hooks](https://developers.openai.com/codex/hooks).194For lifecycle hook configuration, see [Hooks](https://developers.openai.com/codex/hooks).

194 195 

195### Enabling features196### Enabling features

196 197 

config-reference.md +231 −21

Details

6 6 

7User-level configuration lives in `~/.codex/config.toml`. You can also add project-scoped overrides in `.codex/config.toml` files. Codex loads project-scoped config files only when you trust the project.7User-level configuration lives in `~/.codex/config.toml`. You can also add project-scoped overrides in `.codex/config.toml` files. Codex loads project-scoped config files only when you trust the project.

8 8 

9Project-scoped config can't override machine-local provider, auth,

10notification, profile, or telemetry routing keys. Codex ignores

11`openai_base_url`, `chatgpt_base_url`, `model_provider`, `model_providers`,

12`notify`, `profile`, `profiles`, `experimental_realtime_ws_base_url`, and

13`otel` when they appear in a project-local `.codex/config.toml`; put those in

14user-level config instead.

15 

9For sandbox and approval keys (`approval_policy`, `sandbox_mode`, and `sandbox_workspace_write.*`), pair this reference with [Sandbox and approvals](https://developers.openai.com/codex/agent-approvals-security#sandbox-and-approvals), [Protected paths in writable roots](https://developers.openai.com/codex/agent-approvals-security#protected-paths-in-writable-roots), and [Network access](https://developers.openai.com/codex/agent-approvals-security#network-access).16For sandbox and approval keys (`approval_policy`, `sandbox_mode`, and `sandbox_workspace_write.*`), pair this reference with [Sandbox and approvals](https://developers.openai.com/codex/agent-approvals-security#sandbox-and-approvals), [Protected paths in writable roots](https://developers.openai.com/codex/agent-approvals-security#protected-paths-in-writable-roots), and [Network access](https://developers.openai.com/codex/agent-approvals-security#network-access).

10 17 

11<ConfigTable18<ConfigTable


224 },231 },

225 {232 {

226 key: "service_tier",233 key: "service_tier",

227 type: "flex | fast",234 type: "string",

228 description: "Preferred service tier for new turns.",235 description:

236 "Preferred service tier for new turns. Built-in values include `flex` and `fast`; legacy `fast` config maps to the request value `priority`, and catalog-provided tier IDs can also be stored.",

229 },237 },

230 {238 {

231 key: "experimental_compact_prompt_file",239 key: "experimental_compact_prompt_file",


325 description: "Enable ChatGPT Apps/connectors support (experimental).",333 description: "Enable ChatGPT Apps/connectors support (experimental).",

326 },334 },

327 {335 {

328 key: "features.codex_hooks",336 key: "features.hooks",

329 type: "boolean",337 type: "boolean",

330 description:338 description:

331 "Enable lifecycle hooks loaded from `hooks.json` or inline `[hooks]` config.",339 "Enable lifecycle hooks loaded from `hooks.json` or inline `[hooks]` config. `features.codex_hooks` is a deprecated alias.",

332 },340 },

333 {341 {

334 key: "features.codex_git_commit",342 key: "features.codex_git_commit",


342 description:350 description:

343 "Lifecycle hooks configured inline in `config.toml`. Uses the same event schema as `hooks.json`; see the Hooks guide for examples and supported events.",351 "Lifecycle hooks configured inline in `config.toml`. Uses the same event schema as `hooks.json`; see the Hooks guide for examples and supported events.",

344 },352 },

353 {

354 key: "features.plugin_hooks",

355 type: "boolean",

356 description:

357 "Opt into lifecycle hooks bundled with enabled plugins. Off by default in this release; set to `true` to opt in.",

358 },

345 {359 {

346 key: "features.memories",360 key: "features.memories",

347 type: "boolean",361 type: "boolean",


434 description:448 description:

435 "Deny list applied after `enabled_tools` for the MCP server.",449 "Deny list applied after `enabled_tools` for the MCP server.",

436 },450 },

451 {

452 key: "mcp_servers.<id>.default_tools_approval_mode",

453 type: "auto | prompt | approve",

454 description:

455 "Default approval behavior for MCP tools on this server unless a per-tool override exists.",

456 },

457 {

458 key: "mcp_servers.<id>.tools.<tool>.approval_mode",

459 type: "auto | prompt | approve",

460 description:

461 "Per-tool approval behavior override for one MCP tool on this server.",

462 },

437 {463 {

438 key: "mcp_servers.<id>.scopes",464 key: "mcp_servers.<id>.scopes",

439 type: "array<string>",465 type: "array<string>",


581 description:607 description:

582 "Enable personality selection controls (stable; on by default).",608 "Enable personality selection controls (stable; on by default).",

583 },609 },

610 {

611 key: "features.network_proxy",

612 type: "boolean | table",

613 description:

614 "Enable sandboxed networking. Use a table form when setting network policy options such as `domains` (experimental; off by default).",

615 },

616 {

617 key: "features.network_proxy.enabled",

618 type: "boolean",

619 description: "Enable sandboxed networking. Defaults to `false`.",

620 },

621 {

622 key: "features.network_proxy.domains",

623 type: "map<string, allow | deny>",

624 description:

625 "Domain policy for sandboxed networking. Unset by default, which means no external destinations are allowed until you add `allow` rules. 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. Add `deny` rules for blocked destinations; `deny` wins on conflicts.",

626 },

627 {

628 key: "features.network_proxy.unix_sockets",

629 type: "map<string, allow | none>",

630 description:

631 "Unix socket policy for sandboxed networking. Unset by default; add `allow` entries for permitted sockets.",

632 },

633 {

634 key: "features.network_proxy.allow_local_binding",

635 type: "boolean",

636 description:

637 "Allow broader local/private-network access. Defaults to `false`; exact local IP literal or `localhost` allow rules can still permit specific local targets.",

638 },

639 {

640 key: "features.network_proxy.enable_socks5",

641 type: "boolean",

642 description: "Expose SOCKS5 support. Defaults to `true`.",

643 },

644 {

645 key: "features.network_proxy.enable_socks5_udp",

646 type: "boolean",

647 description: "Allow UDP over SOCKS5. Defaults to `true`.",

648 },

649 {

650 key: "features.network_proxy.allow_upstream_proxy",

651 type: "boolean",

652 description:

653 "Allow chaining through an upstream proxy from the environment. Defaults to `true`.",

654 },

655 {

656 key: "features.network_proxy.dangerously_allow_non_loopback_proxy",

657 type: "boolean",

658 description:

659 "Permit non-loopback listener addresses. Defaults to `false`; enabling it can expose proxy listeners beyond localhost.",

660 },

661 {

662 key: "features.network_proxy.dangerously_allow_all_unix_sockets",

663 type: "boolean",

664 description:

665 "Permit arbitrary Unix socket destinations instead of allowlist-only access. Defaults to `false`; use only in tightly controlled environments.",

666 },

667 {

668 key: "features.network_proxy.proxy_url",

669 type: "string",

670 description:

671 'HTTP listener URL for sandboxed networking. Defaults to `"http://127.0.0.1:3128"`.',

672 },

673 {

674 key: "features.network_proxy.socks_url",

675 type: "string",

676 description:

677 'SOCKS5 listener URL. Defaults to `"http://127.0.0.1:8081"`.',

678 },

584 {679 {

585 key: "features.web_search",680 key: "features.web_search",

586 type: "boolean",681 type: "boolean",


621 key: "features.fast_mode",716 key: "features.fast_mode",

622 type: "boolean",717 type: "boolean",

623 description:718 description:

624 'Enable Fast mode selection and the `service_tier = "fast"` path (stable; on by default).',719 "Enable model-catalog service tier selection in the TUI, including Fast-tier commands when the active model advertises them (stable; on by default).",

625 },720 },

626 {721 {

627 key: "features.prevent_idle_sleep",722 key: "features.prevent_idle_sleep",


858 },953 },

859 {954 {

860 key: "profiles.<name>.service_tier",955 key: "profiles.<name>.service_tier",

861 type: "flex | fast",956 type: "string",

862 description: "Profile-scoped service tier preference for new turns.",957 description: "Profile-scoped service tier preference for new turns.",

863 },958 },

864 {959 {


1072 description:1167 description:

1073 "Control alternate screen usage for the TUI (default: auto; auto skips it in Zellij to preserve scrollback).",1168 "Control alternate screen usage for the TUI (default: auto; auto skips it in Zellij to preserve scrollback).",

1074 },1169 },

1170 {

1171 key: "tui.vim_mode_default",

1172 type: "boolean",

1173 description:

1174 "Start the composer in Vim normal mode instead of insert mode (default: false). You can still toggle it per session with `/vim`.",

1175 },

1176 {

1177 key: "tui.raw_output_mode",

1178 type: "boolean",

1179 description:

1180 "Start the TUI in raw scrollback mode for copy-friendly terminal selection (default: false). You can toggle it with `/raw` or the default `alt-r` key binding.",

1181 },

1075 {1182 {

1076 key: "tui.show_tooltips",1183 key: "tui.show_tooltips",

1077 type: "boolean",1184 type: "boolean",


1106 key: "tui.keymap.<context>.<action> = []",1213 key: "tui.keymap.<context>.<action> = []",

1107 type: "empty array",1214 type: "empty array",

1108 description:1215 description:

1109 "Unbind the action in that keymap context. Key names use normalized strings such as `ctrl-a`, `shift-enter`, or `page-down`.",1216 "Unbind the action in that keymap context. Key names use normalized strings such as `ctrl-a`, `shift-enter`, `page-down`, or `minus`.",

1217 },

1218 {

1219 key: "plugins.<plugin>.mcp_servers.<server>.enabled",

1220 type: "boolean",

1221 description:

1222 "Enable or disable an MCP server bundled by an installed plugin without changing the plugin manifest.",

1223 },

1224 {

1225 key: "plugins.<plugin>.mcp_servers.<server>.default_tools_approval_mode",

1226 type: "auto | prompt | approve",

1227 description:

1228 "Default approval behavior for tools on a plugin-provided MCP server.",

1229 },

1230 {

1231 key: "plugins.<plugin>.mcp_servers.<server>.enabled_tools",

1232 type: "array<string>",

1233 description:

1234 "Allow list of tools exposed from a plugin-provided MCP server.",

1235 },

1236 {

1237 key: "plugins.<plugin>.mcp_servers.<server>.disabled_tools",

1238 type: "array<string>",

1239 description:

1240 "Deny list applied after `enabled_tools` for a plugin-provided MCP server.",

1241 },

1242 {

1243 key: "plugins.<plugin>.mcp_servers.<server>.tools.<tool>.approval_mode",

1244 type: "auto | prompt | approve",

1245 description:

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

1110 },1247 },

1111 {1248 {

1112 key: "tui.model_availability_nux.<model>",1249 key: "tui.model_availability_nux.<model>",


1225 key: "permissions.<name>.network.proxy_url",1362 key: "permissions.<name>.network.proxy_url",

1226 type: "string",1363 type: "string",

1227 description:1364 description:

1228 "HTTP proxy endpoint used when this permissions profile enables the managed network proxy.",1365 "HTTP listener URL used when this permissions profile enables sandboxed networking.",

1229 },1366 },

1230 {1367 {

1231 key: "permissions.<name>.network.enable_socks5",1368 key: "permissions.<name>.network.enable_socks5",

1232 type: "boolean",1369 type: "boolean",

1233 description:1370 description:

1234 "Expose a SOCKS5 listener when this permissions profile enables the managed network proxy.",1371 "Expose SOCKS5 support when this permissions profile enables sandboxed networking.",

1235 },1372 },

1236 {1373 {

1237 key: "permissions.<name>.network.socks_url",1374 key: "permissions.<name>.network.socks_url",


1247 key: "permissions.<name>.network.allow_upstream_proxy",1384 key: "permissions.<name>.network.allow_upstream_proxy",

1248 type: "boolean",1385 type: "boolean",

1249 description:1386 description:

1250 "Allow the managed proxy to chain to another upstream proxy.",1387 "Allow sandboxed networking to chain through another upstream proxy.",

1251 },1388 },

1252 {1389 {

1253 key: "permissions.<name>.network.dangerously_allow_non_loopback_proxy",1390 key: "permissions.<name>.network.dangerously_allow_non_loopback_proxy",

1254 type: "boolean",1391 type: "boolean",

1255 description:1392 description:

1256 "Permit non-loopback bind addresses for the managed proxy listener.",1393 "Permit non-loopback bind addresses for sandboxed networking listeners. Enabling it can expose listeners beyond localhost.",

1257 },1394 },

1258 {1395 {

1259 key: "permissions.<name>.network.dangerously_allow_all_unix_sockets",1396 key: "permissions.<name>.network.dangerously_allow_all_unix_sockets",

1260 type: "boolean",1397 type: "boolean",

1261 description:1398 description:

1262 "Allow the proxy to use arbitrary Unix sockets instead of the default restricted set.",1399 "Allow arbitrary Unix socket destinations instead of the default restricted set. Use only in tightly controlled environments.",

1263 },

1264 {

1265 key: "permissions.<name>.network.mode",

1266 type: "limited | full",

1267 description: "Network proxy mode used for subprocess traffic.",

1268 },1400 },

1269 {1401 {

1270 key: "permissions.<name>.network.domains",1402 key: "permissions.<name>.network.domains",

1271 type: "map<string, allow | deny>",1403 type: "map<string, allow | deny>",

1272 description:1404 description:

1273 "Domain rules for the managed proxy. Use domain names or wildcard patterns as keys, with `allow` or `deny` values.",1405 "Domain rules for sandboxed networking. Supports exact hosts, `*.example.com` for subdomains only, `**.example.com` for apex plus subdomains, and global `*` allow rules. `deny` wins on conflicts.",

1274 },1406 },

1275 {1407 {

1276 key: "permissions.<name>.network.unix_sockets",1408 key: "permissions.<name>.network.unix_sockets",

1277 type: "map<string, allow | none>",1409 type: "map<string, allow | none>",

1278 description:1410 description:

1279 "Unix socket rules for the managed proxy. Use socket paths as keys, with `allow` or `none` values.",1411 "Unix socket rules for sandboxed networking. Use socket paths as keys, with `allow` or `none` values.",

1280 },1412 },

1281 {1413 {

1282 key: "permissions.<name>.network.allow_local_binding",1414 key: "permissions.<name>.network.allow_local_binding",

1283 type: "boolean",1415 type: "boolean",

1284 description:1416 description:

1285 "Permit local bind/listen operations through the managed proxy.",1417 "Permit broader local/private-network access through sandboxed networking. Exact local IP literal or `localhost` allow rules can still permit specific local targets when this stays `false`.",

1286 },1418 },

1287 {1419 {

1288 key: "projects.<path>.trust_level",1420 key: "projects.<path>.trust_level",


1435 description:1567 description:

1436 "Set to `false` in `requirements.toml` to disable Computer Use availability and related install or enablement flows.",1568 "Set to `false` in `requirements.toml` to disable Computer Use availability and related install or enablement flows.",

1437 },1569 },

1570 {

1571 key: "experimental_network",

1572 type: "table",

1573 description:

1574 "Network access requirements enforced from `requirements.toml`. These constraints are separate from `features.network_proxy` and can configure sandboxed networking without the user feature flag.",

1575 },

1576 {

1577 key: "experimental_network.enabled",

1578 type: "boolean",

1579 description:

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

1581 },

1582 {

1583 key: "experimental_network.http_port",

1584 type: "integer",

1585 description:

1586 "Loopback HTTP listener port to use for `[experimental_network]` requirements.",

1587 },

1588 {

1589 key: "experimental_network.socks_port",

1590 type: "integer",

1591 description:

1592 "Loopback SOCKS5 listener port to use for `[experimental_network]` requirements.",

1593 },

1594 {

1595 key: "experimental_network.allow_upstream_proxy",

1596 type: "boolean",

1597 description:

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

1599 },

1600 {

1601 key: "experimental_network.dangerously_allow_non_loopback_proxy",

1602 type: "boolean",

1603 description:

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

1605 },

1606 {

1607 key: "experimental_network.dangerously_allow_all_unix_sockets",

1608 type: "boolean",

1609 description:

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

1611 },

1612 {

1613 key: "experimental_network.domains",

1614 type: "map<string, allow | deny>",

1615 description:

1616 "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. `deny` wins on conflicts. Do not combine this with `experimental_network.allowed_domains` or `experimental_network.denied_domains`.",

1617 },

1618 {

1619 key: "experimental_network.allowed_domains",

1620 type: "array<string>",

1621 description:

1622 "List-shaped administrator allow rules for sandboxed networking. Do not combine this with `experimental_network.domains`.",

1623 },

1624 {

1625 key: "experimental_network.denied_domains",

1626 type: "array<string>",

1627 description:

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

1629 },

1630 {

1631 key: "experimental_network.managed_allowed_domains_only",

1632 type: "boolean",

1633 description:

1634 "When `true`, only administrator-managed allow rules remain effective while sandboxed networking requirements are active; user allowlist additions are ignored. Without managed allow rules, user-added domain allow rules do not remain effective.",

1635 },

1636 {

1637 key: "experimental_network.unix_sockets",

1638 type: "map<string, allow | none>",

1639 description:

1640 "Administrator-managed Unix socket policy for sandboxed networking.",

1641 },

1642 {

1643 key: "experimental_network.allow_local_binding",

1644 type: "boolean",

1645 description:

1646 "Permit broader local/private-network access for sandboxed networking. Exact local IP literal or `localhost` allow rules can still permit specific local targets when this stays `false`.",

1647 },

1438 {1648 {

1439 key: "hooks",1649 key: "hooks",

1440 type: "table",1650 type: "table",


1457 key: "hooks.<Event>",1667 key: "hooks.<Event>",

1458 type: "array<table>",1668 type: "array<table>",

1459 description:1669 description:

1460 "Matcher groups for a hook event such as `PreToolUse`, `PostToolUse`, `PermissionRequest`, `SessionStart`, `UserPromptSubmit`, or `Stop`.",1670 "Matcher groups for a hook event such as `PreToolUse`, `PermissionRequest`, `PostToolUse`, `SessionStart`, `UserPromptSubmit`, or `Stop`.",

1461 },1671 },

1462 {1672 {

1463 key: "hooks.<Event>[].hooks",1673 key: "hooks.<Event>[].hooks",

config-sample.md +18 −6

Details

42# Default OSS provider for --oss sessions. When unset, Codex prompts. Default: unset.42# Default OSS provider for --oss sessions. When unset, Codex prompts. Default: unset.

43# oss_provider = "ollama"43# oss_provider = "ollama"

44 44 

45# Preferred service tier. `fast` is honored only when enabled in [features].45# Preferred service tier. Built-in examples: fast | flex; model catalogs can add more.

46# service_tier = "flex" # fast | flex46# service_tier = "flex"

47 47 

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

49# model_context_window = 128000 # tokens; default: auto for model49# model_context_window = 128000 # tokens; default: auto for model


288experimental_use_profile = false288experimental_use_profile = false

289 289 

290################################################################################290################################################################################

291# Managed network proxy settings291# Sandboxed networking settings

292################################################################################292################################################################################

293 293 

294# Enable the feature before configuring sandboxed networking rules.

295# [features.network_proxy]

296# enabled = true

297# domains = { "api.openai.com" = "allow", "example.com" = "deny" }

298#

299# Exact hosts match only themselves.

300# "*.example.com" matches subdomains only; "**.example.com" matches the apex plus subdomains.

301# "*" allows any public host that is not denied, so prefer scoped rules when possible.

302# `allow_local_binding = false` blocks loopback and private destinations by default.

303# Add an exact local IP literal or `localhost` allow rule for one target, or set it to true only when broader local access is required.

304#

294# Set `default_permissions = "workspace"` before enabling this profile.305# Set `default_permissions = "workspace"` before enabling this profile.

295# [permissions.workspace.network]306# [permissions.workspace.network]

296# enabled = true307# enabled = true


303# dangerously_allow_non_loopback_proxy = false314# dangerously_allow_non_loopback_proxy = false

304# dangerously_allow_non_loopback_admin = false315# dangerously_allow_non_loopback_admin = false

305# dangerously_allow_all_unix_sockets = false316# dangerously_allow_all_unix_sockets = false

306# mode = "limited" # limited | full

307# allow_local_binding = false317# allow_local_binding = false

308#318#

309# [permissions.workspace.network.domains]319# [permissions.workspace.network.domains]


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

401# shell_tool = true411# shell_tool = true

402# apps = false412# apps = false

413# hooks = false

414# plugin_hooks = false # Default off; set true to opt into plugin-bundled hooks.

403# codex_git_commit = false415# codex_git_commit = false

404# codex_hooks = false

405# unified_exec = true416# unified_exec = true

406# shell_snapshot = true417# shell_snapshot = true

407# multi_agent = true418# multi_agent = true

408# personality = true419# personality = true

420# network_proxy = false

409# fast_mode = true421# fast_mode = true

410# enable_request_compression = true422# enable_request_compression = true

411# skill_mcp_dependency_install = true423# skill_mcp_dependency_install = true


580# model_provider = "openai"592# model_provider = "openai"

581# approval_policy = "on-request"593# approval_policy = "on-request"

582# sandbox_mode = "read-only"594# sandbox_mode = "read-only"

583# service_tier = "flex"595# service_tier = "flex" # or another supported service tier id

584# oss_provider = "ollama"596# oss_provider = "ollama"

585# model_reasoning_effort = "medium"597# model_reasoning_effort = "medium"

586# plan_mode_reasoning_effort = "high"598# plan_mode_reasoning_effort = "high"

Details

163 163 

164Codex Admins can deploy admin-enforced `requirements.toml` policies from the Codex [Policies page](https://chatgpt.com/codex/settings/policies).164Codex Admins can deploy admin-enforced `requirements.toml` policies from the Codex [Policies page](https://chatgpt.com/codex/settings/policies).

165 165 

166Use this page when you want to apply different local Codex constraints to different groups without distributing device-level files first. The managed policy uses the same `requirements.toml` format described in [Managed configuration](https://developers.openai.com/codex/enterprise/managed-configuration), so you can define allowed approval policies, sandbox modes, web search behavior, MCP server allowlists, feature pins, and restrictive command rules. To disable Browser Use, the in-app browser, or Computer Use, see [Pin feature flags](https://developers.openai.com/codex/enterprise/managed-configuration#pin-feature-flags).166Use this page when you want to apply different local Codex constraints to different groups without distributing device-level files first. The managed policy uses the same `requirements.toml` format described in [Managed configuration](https://developers.openai.com/codex/enterprise/managed-configuration), so you can define allowed approval policies, sandbox modes, web search behavior, network access requirements, MCP server allowlists, feature pins, and restrictive command rules. To disable Browser Use, the in-app browser, or Computer Use, see [Pin feature flags](https://developers.openai.com/codex/enterprise/managed-configuration#pin-feature-flags).

167 167 

168<div class="max-w-1xl mx-auto py-1">168<div class="max-w-1xl mx-auto py-1">

169 <img src="https://developers.openai.com/images/codex/enterprise/policies_and_configurations_page.png"169 <img src="https://developers.openai.com/images/codex/enterprise/policies_and_configurations_page.png"


209computer_use = false209computer_use = false

210```210```

211 211 

212Example: define administrator-owned network requirements:

213 

214```toml

215experimental_network.enabled = true

216experimental_network.dangerously_allow_all_unix_sockets = true

217experimental_network.allow_local_binding = true

218experimental_network.allowed_domains = [

219 "api.openai.com",

220 "*.example.com",

221]

222experimental_network.denied_domains = [

223 "blocked.example.com",

224 "*.exfil.example.com",

225]

226```

227 

212Example: add a restrictive command rule when you want admins to block or gate specific commands:228Example: add a restrictive command rule when you want admins to block or gate specific commands:

213 229 

214```toml230```toml


218]234]

219```235```

220 236 

221You can use either example on its own or combine them in a single managed policy for a group. For exact keys, precedence, and more examples, see [Managed configuration](https://developers.openai.com/codex/enterprise/managed-configuration) and [Agent approvals & security](https://developers.openai.com/codex/agent-approvals-security).237You can use any example on its own or combine them in a single managed policy for a group. For exact keys, precedence, and more examples, see [Managed configuration](https://developers.openai.com/codex/enterprise/managed-configuration) and [Agent approvals & security](https://developers.openai.com/codex/agent-approvals-security).

222 238 

223### Checking user policies239### Checking user policies

224 240 

Details

76 76 

77Use `[[remote_sandbox_config]]` when one managed policy should apply different77Use `[[remote_sandbox_config]]` when one managed policy should apply different

78sandbox requirements on different hosts. For example, you can keep a stricter78sandbox requirements on different hosts. For example, you can keep a stricter

79default for laptops while allowing workspace writes on matching devboxes or CI79default for laptops while allowing workspace writes on matching dev boxes or CI

80runners. Host-specific entries currently override `allowed_sandbox_modes` only:80runners. Host-specific entries currently override `allowed_sandbox_modes` only:

81 81 

82```toml82```toml


94 94 

95The first matching `[[remote_sandbox_config]]` entry wins within the same95The first matching `[[remote_sandbox_config]]` entry wins within the same

96requirements source. If no entry matches, Codex keeps the top-level96requirements source. If no entry matches, Codex keeps the top-level

97`allowed_sandbox_modes`. Hostname matching is for policy selection only; don't97`allowed_sandbox_modes`. Host name matching is for policy selection only; don't

98treat it as authenticated device proof.98treat it as authenticated device proof.

99 99 

100You can also constrain web search mode:100You can also constrain web search mode:


106`allowed_web_search_modes = []` allows only `"disabled"`.106`allowed_web_search_modes = []` allows only `"disabled"`.

107For example, `allowed_web_search_modes = ["cached"]` prevents live web search even in `danger-full-access` sessions.107For example, `allowed_web_search_modes = ["cached"]` prevents live web search even in `danger-full-access` sessions.

108 108 

109### Configure network access requirements

110 

111Use `[experimental_network]` in `requirements.toml` when administrators should

112define network access requirements centrally. These requirements are separate

113from the user `features.network_proxy` toggle: they can configure sandboxed

114networking without that feature flag, but they do not grant command network

115access when the active sandbox keeps networking off.

116 

117```toml

118experimental_network.enabled = true

119experimental_network.dangerously_allow_all_unix_sockets = true

120experimental_network.allow_local_binding = true

121experimental_network.allowed_domains = [

122 "api.openai.com",

123 "*.example.com",

124]

125experimental_network.denied_domains = [

126 "blocked.example.com",

127 "*.exfil.example.com",

128]

129```

130 

131Use `experimental_network.managed_allowed_domains_only = true` only when you

132also define administrator-owned `allowed_domains` and want that allowlist to be

133exclusive. If it is `true` without managed allow rules, user-added domain allow

134rules do not remain effective.

135 

136The domain syntax, local/private destination rules, deny-over-allow behavior,

137and DNS rebinding limitations are the same as the sandboxed networking behavior

138described in [Agent approvals & security](https://developers.openai.com/codex/agent-approvals-security#network-isolation).

139 

109### Pin feature flags140### Pin feature flags

110 141 

111You can also pin [feature flags](https://developers.openai.com/codex/config-basic/#feature-flags) for users142You can also pin [feature flags](https://developers.openai.com/codex/config-basic/#feature-flags) for users


129- `in_app_browser = false` disables the in-app browser pane.160- `in_app_browser = false` disables the in-app browser pane.

130- `browser_use = false` disables Browser Use and Browser Agent availability.161- `browser_use = false` disables Browser Use and Browser Agent availability.

131- `computer_use = false` disables Computer Use availability and related162- `computer_use = false` disables Computer Use availability and related

132 install or enablement flows.163 install or setup flows.

133 164 

134If omitted, these features are allowed by policy, subject to normal client,165If omitted, these features are allowed by policy, subject to normal client,

135platform, and rollout availability.166platform, and rollout availability.


187directory where your MDM or endpoint-management tooling installs the referenced218directory where your MDM or endpoint-management tooling installs the referenced

188scripts.219scripts.

189 220 

221To enforce managed hooks even for users who disabled hooks locally, pin

222`[features].hooks = true` alongside `[hooks]`.

223 

190```toml224```toml

191[features]225[features]

192codex_hooks = true226hooks = true

193 227 

194[hooks]228[hooks]

195managed_dir = "/enterprise/hooks"229managed_dir = "/enterprise/hooks"

hooks.md +117 −25

Details

9- Run a custom validation check when a conversation turn stops, enforcing standards9- Run a custom validation check when a conversation turn stops, enforcing standards

10- Customize prompting when in a certain directory10- Customize prompting when in a certain directory

11 11 

12Hooks are behind a feature flag in `config.toml`:12Hooks are enabled by default. If you need to turn them off in `config.toml`,

13set:

13 14 

14```toml15```toml

15[features]16[features]

16codex_hooks = true17hooks = false

17```18```

18 19 

20Use `hooks` as the canonical feature key. `codex_hooks` still works as a

21deprecated alias.

22 

23Admins can force hooks off the same way in `requirements.toml` with

24`[features].hooks = false`.

25 

19Runtime behavior to keep in mind:26Runtime behavior to keep in mind:

20 27 

21- Matching hooks from multiple files all run.28- Matching hooks from multiple files all run.

22- Multiple matching command hooks for the same event are launched concurrently,29- Multiple matching command hooks for the same event are launched concurrently,

23 so one hook cannot prevent another matching hook from starting.30 so one hook cannot prevent another matching hook from starting.

31- Non-managed command hooks must be reviewed and trusted before they run.

24- `PreToolUse`, `PermissionRequest`, `PostToolUse`, `UserPromptSubmit`, and32- `PreToolUse`, `PermissionRequest`, `PostToolUse`, `UserPromptSubmit`, and

25 `Stop` run at turn scope.33 `Stop` run at turn scope.

26 34 


44- `<repo>/.codex/config.toml`52- `<repo>/.codex/config.toml`

45 53 

46If more than one hook source exists, Codex loads all matching hooks.54If more than one hook source exists, Codex loads all matching hooks.

47Higher-precedence config layers do not replace lower-precedence hooks.55Higher-precedence config layers don't replace lower-precedence hooks.

48If a single layer contains both `hooks.json` and inline `[hooks]`, Codex56If a single layer contains both `hooks.json` and inline `[hooks]`, Codex

49merges them and warns at startup. Prefer one representation per layer.57merges them and warns at startup. Prefer one representation per layer.

50 58 

59Plugin hooks are off by default in this release. If

60`[features].plugin_hooks = true`, Codex can also discover hooks bundled with

61enabled plugins. Otherwise, enabled plugins won't run bundled hooks.

62 

51Project-local hooks load only when the project `.codex/` layer is trusted. In63Project-local hooks load only when the project `.codex/` layer is trusted. In

52untrusted projects, Codex still loads user and system hooks from their own64untrusted projects, Codex still loads user and system hooks from their own

53active config layers.65active config layers.

54 66 

67## Review and manage hooks

68 

69Codex lists configured hooks before deciding which ones can run. Use `/hooks`

70in the CLI to inspect hook sources, review new or changed hooks, trust hooks, or

71disable individual non-managed hooks. If hooks need review at startup, Codex

72prints a warning that tells you to open `/hooks`.

73 

74Managed hooks from system, MDM, cloud, or `requirements.toml` sources are marked

75as managed, trusted by policy, and can't be disabled from the user hook browser.

76 

55## Config shape77## Config shape

56 78 

57Hooks are organized in three levels:79Hooks are organized in three levels:


141- `timeout` is in seconds.163- `timeout` is in seconds.

142- If `timeout` is omitted, Codex uses `600` seconds.164- If `timeout` is omitted, Codex uses `600` seconds.

143- `statusMessage` is optional.165- `statusMessage` is optional.

166- `async` is parsed, but async command hooks aren't supported yet. Codex skips

167 handlers with `async: true`.

168- Only `type: "command"` handlers run today. `prompt` and `agent` handlers are

169 parsed but skipped.

144- Commands run with the session `cwd` as their working directory.170- Commands run with the session `cwd` as their working directory.

145- For repo-local hooks, prefer resolving from the git root instead of using a171- For repo-local hooks, prefer resolving from the git root instead of using a

146 relative path such as `.codex/hooks/...`. Codex may be started from a172 relative path such as `.codex/hooks/...`. Codex may be started from a


149Equivalent inline TOML in `config.toml`:175Equivalent inline TOML in `config.toml`:

150 176 

151```toml177```toml

152[features]

153codex_hooks = true

154 

155[[hooks.PreToolUse]]178[[hooks.PreToolUse]]

156matcher = "^Bash$"179matcher = "^Bash$"

157 180 


176Enterprise-managed requirements can also define hooks inline under `[hooks]`.199Enterprise-managed requirements can also define hooks inline under `[hooks]`.

177This is useful when admins want to enforce the hook configuration while200This is useful when admins want to enforce the hook configuration while

178delivering the actual scripts through MDM or another device-management system.201delivering the actual scripts through MDM or another device-management system.

202To enforce managed hooks even for users who disabled hooks locally, pin

203`[features].hooks = true` in `requirements.toml` alongside `[hooks]`.

179 204 

180```toml205```toml

181[features]206[features]

182codex_hooks = true207hooks = true

183 208 

184[hooks]209[hooks]

185managed_dir = "/enterprise/hooks"210managed_dir = "/enterprise/hooks"


199 224 

200- `managed_dir` is used on macOS and Linux.225- `managed_dir` is used on macOS and Linux.

201- `windows_managed_dir` is used on Windows.226- `windows_managed_dir` is used on Windows.

202- Codex does not distribute the scripts in `managed_dir`; your enterprise227- Codex doesn't distribute the scripts in `managed_dir`; your enterprise

203 tooling must install and update them separately.228 tooling must install and update them separately.

204- Managed hook commands should use absolute script paths under the configured229- Managed hook commands should use absolute script paths under the configured

205 managed directory.230 managed directory.

206 231 

232## Plugin-bundled hooks

233 

234Plugin-bundled hooks are opt-in for this release. When

235`[features].plugin_hooks = true` and a plugin is enabled, Codex can load

236lifecycle hooks from that plugin alongside user, project, and managed hooks.

237 

238```toml

239[features]

240plugin_hooks = true

241```

242 

243By default, Codex looks for `hooks/hooks.json` inside the plugin root. A plugin

244manifest can override that default with a `hooks` entry in

245`.codex-plugin/plugin.json`. The manifest entry can be a `./`-prefixed path, an

246array of `./`-prefixed paths, an inline hooks object, or an array of inline

247hooks objects.

248 

249```json

250{

251 "name": "repo-policy",

252 "hooks": "./hooks/hooks.json"

253}

254```

255 

256Manifest hook paths are resolved relative to the plugin root and must stay

257inside that root. If a manifest defines `hooks`, Codex uses those manifest

258entries instead of the default `hooks/hooks.json`.

259 

260Plugin hook commands receive these environment variables:

261 

262- `PLUGIN_ROOT` is a Codex-specific extension that points to the installed

263 plugin root.

264- `PLUGIN_DATA` is a Codex-specific extension that points to the plugin's

265 writable data directory.

266- Codex also sets `CLAUDE_PLUGIN_ROOT` and `CLAUDE_PLUGIN_DATA` for

267 compatibility with existing plugin hooks.

268 

269Plugin hooks use the same event schema as other hooks. They are non-managed

270hooks, so they require trust review before they run.

271 

207## Matcher patterns272## Matcher patterns

208 273 

209The `matcher` field is a regex string that filters when hooks fire. Use `"*"`,274The `matcher` field is a regex string that filters when hooks fire. Use `"*"`,


221| `UserPromptSubmit` | not supported | Any configured `matcher` is ignored for this event |286| `UserPromptSubmit` | not supported | Any configured `matcher` is ignored for this event |

222| `Stop` | not supported | Any configured `matcher` is ignored for this event |287| `Stop` | not supported | Any configured `matcher` is ignored for this event |

223 288 

224\*For `apply_patch`, matchers can also use `Edit` or `Write`.289\*For `apply_patch`, `matcher` values can also use `Edit` or `Write`.

225 290 

226Examples:291Examples:

227 292 


244| `transcript_path` | `string \| null` | Path to the session transcript file, if any |309| `transcript_path` | `string \| null` | Path to the session transcript file, if any |

245| `cwd` | `string` | Working directory for the session |310| `cwd` | `string` | Working directory for the session |

246| `hook_event_name` | `string` | Current hook event name |311| `hook_event_name` | `string` | Current hook event name |

247| `model` | `string` | Active model slug |312| `model` | `string` | Codex-specific extension. Active model slug |

313 

314Turn-scoped hooks list `turn_id` as a Codex-specific extension in their

315event-specific tables.

316 

317`SessionStart`, `PreToolUse`, `PermissionRequest`, `PostToolUse`,

318`UserPromptSubmit`, and `Stop` also include `permission_mode`, which describes

319the current permission mode as `default`, `acceptEdits`, `plan`, `dontAsk`, or

320`bypassPermissions`.

248 321 

249Turn-scoped hooks list `turn_id` in their event-specific tables.322`transcript_path` points to a conversation transcript for convenience, but the

323transcript format is not a stable interface for hooks and may change over time.

250 324 

251If you need the full wire format, see [Schemas](#schemas).325If you need the full wire format, see [Schemas](#schemas).

252 326 


288Fields in addition to [Common input fields](#common-input-fields):362Fields in addition to [Common input fields](#common-input-fields):

289 363 

290| Field | Type | Meaning |364| Field | Type | Meaning |

291| -------- | -------- | ---------------------------------------------- |365| -------- | -------- | -------------------------------------------------------- |

292| `source` | `string` | How the session started: `startup` or `resume` |366| `source` | `string` | How the session started: `startup`, `resume`, or `clear` |

293 367 

294Plain text on `stdout` is added as extra developer context.368Plain text on `stdout` is added as extra developer context.

295 369 


310### PreToolUse384### PreToolUse

311 385 

312`PreToolUse` can intercept Bash, file edits performed through `apply_patch`,386`PreToolUse` can intercept Bash, file edits performed through `apply_patch`,

313and MCP tool calls. It is still a guardrail rather than a complete enforcement387and MCP tool calls. It's still a guardrail rather than a complete enforcement

314boundary because Codex can often perform equivalent work through another388boundary because Codex can often perform equivalent work through another

315supported tool path.389supported tool path.

316 390 


320 `WebSearch` or other non-shell, non-MCP tool calls.394 `WebSearch` or other non-shell, non-MCP tool calls.

321 395 

322`matcher` is applied to `tool_name` and matcher aliases. For file edits through396`matcher` is applied to `tool_name` and matcher aliases. For file edits through

323`apply_patch`, matchers can use `apply_patch`, `Edit`, or `Write`; hook input397`apply_patch`, `matcher` values can use `apply_patch`, `Edit`, or `Write`; hook input

324still reports `tool_name: "apply_patch"`.398still reports `tool_name: "apply_patch"`.

325 399 

326Fields in addition to [Common input fields](#common-input-fields):400Fields in addition to [Common input fields](#common-input-fields):

327 401 

328| Field | Type | Meaning |402| Field | Type | Meaning |

329| ------------- | ------------ | --------------------------------------------------------------------------------------------------------- |403| ------------- | ------------ | ---------------------------------------------------------------------------------------------------------- |

330| `turn_id` | `string` | Codex-specific extension. Active Codex turn id |404| `turn_id` | `string` | Codex-specific extension. Active Codex turn id |

331| `tool_name` | `string` | Canonical hook tool name, such as `Bash`, `apply_patch`, or an MCP name like `mcp__fs__read` |405| `tool_name` | `string` | Canonical hook tool name, such as `Bash`, `apply_patch`, or an MCP name like `mcp__fs__read` |

332| `tool_use_id` | `string` | Tool-call id for this invocation |406| `tool_use_id` | `string` | Tool-call id for this invocation |

333| `tool_input` | `JSON value` | Tool-specific input. `Bash` and `apply_patch` use `tool_input.command` while MCP tools send all the args. |407| `tool_input` | `JSON value` | Tool-specific input. `Bash` and `apply_patch` use `tool_input.command` while MCP tools send all arguments. |

334 408 

335Plain text on `stdout` is ignored.409Plain text on `stdout` is ignored.

336 410 

337JSON on `stdout` can use `systemMessage` and can block a Bash command with this411JSON on `stdout` can use `systemMessage`. To deny a supported tool call, return

338hook-specific shape:412this hook-specific shape:

339 413 

340```json414```json

341{415{


358 432 

359You can also use exit code `2` and write the blocking reason to `stderr`.433You can also use exit code `2` and write the blocking reason to `stderr`.

360 434 

361`permissionDecision: "allow"` and `"ask"`, legacy `decision: "approve"`,435To add model-visible context without blocking, return

362`updatedInput`, `additionalContext`, `continue: false`, `stopReason`, and436`hookSpecificOutput.additionalContext`:

363`suppressOutput` are parsed but not supported yet, so they fail open.437 

438```json

439{

440 "hookSpecificOutput": {

441 "hookEventName": "PreToolUse",

442 "additionalContext": "The pending command touches generated files."

443 }

444}

445```

446 

447`permissionDecision: "ask"`, legacy `decision: "approve"`, `updatedInput`,

448`continue: false`, `stopReason`, and `suppressOutput` are parsed but not

449supported yet, so they fail open.

364 450 

365### PermissionRequest451### PermissionRequest

366 452 


384 470 

385Plain text on `stdout` is ignored.471Plain text on `stdout` is ignored.

386 472 

473Some tool inputs may include a human-readable description, but don't rely on a

474`tool_input.description` field for every tool.

475 

387To approve the request, return:476To approve the request, return:

388 477 

389```json478```json


432 `WebSearch` or other non-shell, non-MCP tool calls.521 `WebSearch` or other non-shell, non-MCP tool calls.

433 522 

434`matcher` is applied to `tool_name` and matcher aliases. For file edits through523`matcher` is applied to `tool_name` and matcher aliases. For file edits through

435`apply_patch`, matchers can use `apply_patch`, `Edit`, or `Write`; hook input524`apply_patch`, `matcher` values can use `apply_patch`, `Edit`, or `Write`; hook input

436still reports `tool_name: "apply_patch"`.525still reports `tool_name: "apply_patch"`.

437 526 

438Fields in addition to [Common input fields](#common-input-fields):527Fields in addition to [Common input fields](#common-input-fields):

439 528 

440| Field | Type | Meaning |529| Field | Type | Meaning |

441| --------------- | ------------ | --------------------------------------------------------------------------------------------------------- |530| --------------- | ------------ | ---------------------------------------------------------------------------------------------------------- |

442| `turn_id` | `string` | Codex-specific extension. Active Codex turn id |531| `turn_id` | `string` | Codex-specific extension. Active Codex turn id |

443| `tool_name` | `string` | Canonical hook tool name, such as `Bash`, `apply_patch`, or an MCP name like `mcp__fs__read` |532| `tool_name` | `string` | Canonical hook tool name, such as `Bash`, `apply_patch`, or an MCP name like `mcp__fs__read` |

444| `tool_use_id` | `string` | Tool-call id for this invocation |533| `tool_use_id` | `string` | Tool-call id for this invocation |

445| `tool_input` | `JSON value` | Tool-specific input. `Bash` and `apply_patch` use `tool_input.command` while MCP tools send all the args. |534| `tool_input` | `JSON value` | Tool-specific input. `Bash` and `apply_patch` use `tool_input.command` while MCP tools send all arguments. |

446| `tool_response` | `JSON value` | Tool-specific output. For MCP tools, this is the MCP call result. |535| `tool_response` | `JSON value` | Tool-specific output. For MCP tools, this is the MCP call result. |

447 536 

448Plain text on `stdout` is ignored.537Plain text on `stdout` is ignored.


549 638 

550## Schemas639## Schemas

551 640 

641The linked `main` branch schemas may include hook fields that are not in the

642 current release. Use this page as the release behavior reference.

643 

552If you need the exact current wire format, see the generated schemas in the644If you need the exact current wire format, see the generated schemas in the

553[Codex GitHub repository](https://github.com/openai/codex/tree/main/codex-rs/hooks/schema/generated).645[Codex GitHub repository](https://github.com/openai/codex/tree/main/codex-rs/hooks/schema/generated).

mcp.md +25 −0

Details

86- `required` (optional): Set `true` to make startup fail if this enabled server can't initialize.86- `required` (optional): Set `true` to make startup fail if this enabled server can't initialize.

87- `enabled_tools` (optional): Tool allow list.87- `enabled_tools` (optional): Tool allow list.

88- `disabled_tools` (optional): Tool deny list (applied after `enabled_tools`).88- `disabled_tools` (optional): Tool deny list (applied after `enabled_tools`).

89- `default_tools_approval_mode` (optional): Default approval behavior for

90 tools from this server. Supported values are `auto`, `prompt`, and

91 `approve`.

92- `tools.<tool>.approval_mode` (optional): Per-tool approval behavior override.

89 93 

90If your OAuth provider requires a fixed callback port, set the top-level `mcp_oauth_callback_port` in `config.toml`. If unset, Codex binds to an ephemeral port.94If your OAuth provider requires a fixed callback port, set the top-level `mcp_oauth_callback_port` in `config.toml`. If unset, Codex binds to an ephemeral port.

91 95 


125url = "http://localhost:3000/mcp"129url = "http://localhost:3000/mcp"

126enabled_tools = ["open", "screenshot"]130enabled_tools = ["open", "screenshot"]

127disabled_tools = ["screenshot"] # applied after enabled_tools131disabled_tools = ["screenshot"] # applied after enabled_tools

132default_tools_approval_mode = "prompt"

128startup_timeout_sec = 20133startup_timeout_sec = 20

129tool_timeout_sec = 45134tool_timeout_sec = 45

130enabled = true135enabled = true

136 

137[mcp_servers.chrome_devtools.tools.open]

138approval_mode = "approve"

139```

140 

141### Plugin-provided MCP servers

142 

143Installed plugins can bundle MCP servers in their plugin manifest. Those

144servers are launched from the plugin, so user config doesn't set their

145transport command. User config can still control on/off state and tool policy

146under `plugins.<plugin>.mcp_servers.<server>`.

147 

148```toml

149[plugins."sample@test".mcp_servers.sample]

150enabled = true

151default_tools_approval_mode = "prompt"

152enabled_tools = ["read", "search"]

153 

154[plugins."sample@test".mcp_servers.sample.tools.search]

155approval_mode = "approve"

131```156```

132 157 

133## Examples of useful MCP servers158## Examples of useful MCP servers

plugins/build.md +92 −25

Details

4plugins in Codex, see [Plugins](https://developers.openai.com/codex/plugins). If you are still iterating on4plugins in Codex, see [Plugins](https://developers.openai.com/codex/plugins). If you are still iterating on

5one repo or one personal workflow, start with a local skill. Build a plugin5one repo or one personal workflow, start with a local skill. Build a plugin

6when you want to share that workflow across teams, bundle app integrations or6when you want to share that workflow across teams, bundle app integrations or

7MCP config, or publish a stable package.7MCP config, package lifecycle hooks, or publish a stable package.

8 8 

9## Create a plugin with `$plugin-creator`9## Create a plugin with `$plugin-creator`

10 10 


320 320 

321- the curated marketplace that powers the official Plugin Directory321- the curated marketplace that powers the official Plugin Directory

322- a repo marketplace at `$REPO_ROOT/.agents/plugins/marketplace.json`322- a repo marketplace at `$REPO_ROOT/.agents/plugins/marketplace.json`

323- a Claude-style marketplace at `$REPO_ROOT/.claude-plugin/marketplace.json`323- a legacy-compatible marketplace at `$REPO_ROOT/.claude-plugin/marketplace.json`

324- a personal marketplace at `~/.agents/plugins/marketplace.json`324- a personal marketplace at `~/.agents/plugins/marketplace.json`

325 325 

326You can install any plugin exposed through a marketplace. Codex installs326You can install any plugin exposed through a marketplace. Codex installs


337### Plugin structure337### Plugin structure

338 338 

339Every plugin has a manifest at `.codex-plugin/plugin.json`. It can also include339Every plugin has a manifest at `.codex-plugin/plugin.json`. It can also include

340a `skills/` directory, an `.app.json` file that points at one or more apps or340a `skills/` directory, a `hooks/` directory for lifecycle hooks, an `.app.json`

341connectors, an `.mcp.json` file that configures MCP servers, lifecycle config,341file that points at one or more apps or connectors, an `.mcp.json` file that

342and assets used to present the plugin across supported surfaces.342configures MCP servers, and assets used to present the plugin across supported

343surfaces.

343 344 

344<FileTree345<FileTree

345 class="mt-4"346 class="mt-4"


374 },375 },

375 ],376 ],

376 },377 },

377 {

378 name: ".app.json",

379 comment: "Optional: app or connector mappings",

380 },

381 {

382 name: ".mcp.json",

383 comment: "Optional: MCP server configuration",

384 },

385 {378 {

386 name: "hooks/",379 name: "hooks/",

387 open: true,380 open: true,

388 children: [381 children: [

389 {382 {

390 name: "hooks.json",383 name: "hooks.json",

391 comment: "Optional: lifecycle configuration",384 comment: "Optional: lifecycle hooks",

392 },385 },

393 ],386 ],

394 },387 },

388 {

389 name: ".app.json",

390 comment: "Optional: app or connector mappings",

391 },

392 {

393 name: ".mcp.json",

394 comment: "Optional: MCP server configuration",

395 },

395 {396 {

396 name: "assets/",397 name: "assets/",

397 comment: "Optional: icons, logos, screenshots",398 comment: "Optional: icons, logos, screenshots",


401 ]}402 ]}

402/>403/>

403 404 

404Only `plugin.json` belongs in `.codex-plugin/`. Keep `skills/`, `assets/`,405Only `plugin.json` belongs in `.codex-plugin/`. Keep `skills/`, `hooks/`,

405`.mcp.json`, `.app.json`, and lifecycle config files at the plugin root.406`assets/`, `.mcp.json`, and `.app.json` at the plugin root.

406 407 

407Published plugins typically use a richer manifest than the minimal example that408Published plugins typically use a richer manifest than the minimal example that

408appears in quick-start scaffolds. The manifest has three jobs:409appears in quick-start scaffolds. The manifest has three jobs:

409 410 

410- Identify the plugin.411- Identify the plugin.

411- Point to bundled components such as skills, apps, or MCP servers.412- Point to bundled components such as skills, apps, MCP servers, or hooks.

412- Provide install-surface metadata such as descriptions, icons, and legal413- Provide install-surface metadata such as descriptions, icons, and legal

413 links.414 links.

414 415 


486- Store visual assets such as `composerIcon`, `logo`, and `screenshots` under487- Store visual assets such as `composerIcon`, `logo`, and `screenshots` under

487 `./assets/` when possible.488 `./assets/` when possible.

488- Use `skills` for bundled skill folders, `apps` for `.app.json`,489- Use `skills` for bundled skill folders, `apps` for `.app.json`,

489 `mcpServers` for `.mcp.json`, and `hooks` for lifecycle config.490 `mcpServers` for `.mcp.json`, and `hooks` for lifecycle hooks.

490- If you omit `hooks` and the plugin includes `./hooks/hooks.json`, Codex loads491- Plugin hooks are off by default in this release; bundled hooks won't run

491 that default lifecycle config automatically.492 unless `[features].plugin_hooks = true`.

493- When plugin hooks are enabled, omit `hooks` to use the default

494 `./hooks/hooks.json` file when present.

492 495 

493### Bundled MCP servers and lifecycle config496### Bundled MCP servers and lifecycle hooks

494 497 

495`mcpServers` can point to an `.mcp.json` file that contains either a direct498`mcpServers` can point to an `.mcp.json` file that contains either a direct

496server map or a wrapped `mcp_servers` object.499server map or a wrapped `mcp_servers` object.


519}522}

520```523```

521 524 

522`hooks` can point to one lifecycle JSON file, an array of lifecycle JSON files,525After installation, users can enable or disable a bundled MCP server and tune

523an inline lifecycle object, or an array of inline lifecycle objects. File paths526tool approval policy from their Codex config without editing the plugin. Use

524must follow the same `./`-prefixed plugin-root path rules as other manifest527`plugins.<plugin>.mcp_servers.<server>` for plugin-scoped MCP server policy:

525paths. If you omit the manifest field, Codex still checks `./hooks/hooks.json`.528 

529```toml

530[plugins."my-plugin".mcp_servers.docs]

531enabled = true

532default_tools_approval_mode = "prompt"

533enabled_tools = ["search"]

534 

535[plugins."my-plugin".mcp_servers.docs.tools.search]

536approval_mode = "approve"

537```

538 

539Plugin hooks are off by default in this release. When

540`[features].plugin_hooks = true` and your plugin is enabled, Codex can load

541lifecycle hooks from your plugin alongside user, project, and managed hooks.

542 

543```toml

544[features]

545plugin_hooks = true

546```

547 

548The default plugin hook file is `hooks/hooks.json`:

549 

550```json

551{

552 "hooks": {

553 "SessionStart": [

554 {

555 "hooks": [

556 {

557 "type": "command",

558 "command": "python3 ${PLUGIN_ROOT}/hooks/session_start.py",

559 "statusMessage": "Loading plugin context"

560 }

561 ]

562 }

563 ]

564 }

565}

566```

567 

568If you define `hooks` in `.codex-plugin/plugin.json`, Codex uses that manifest

569entry instead of the default `hooks/hooks.json`. The manifest field can be a

570single path, an array of paths, an inline hooks object, or an array of inline

571hooks objects.

572 

573```json

574{

575 "name": "repo-policy",

576 "hooks": ["./hooks/session.json", "./hooks/tools.json"]

577}

578```

579 

580Hook paths follow the same manifest path rules as `skills`, `apps`, and

581`mcpServers`: start with `./`, resolve relative to the plugin root, and stay

582inside the plugin root.

583 

584Plugin hook commands receive the Codex-specific environment variables

585`PLUGIN_ROOT` and `PLUGIN_DATA`. `PLUGIN_ROOT` points to the installed plugin

586root, and `PLUGIN_DATA` points to the plugin's writable data directory. Codex

587also sets `CLAUDE_PLUGIN_ROOT` and `CLAUDE_PLUGIN_DATA` for compatibility with

588existing plugin hooks.

589 

590Plugin hooks use the same event schema as regular hooks. See

591[Hooks](https://developers.openai.com/codex/hooks) for supported events, inputs, outputs, trust review, and

592current limitations.

526 593 

527### Publish official public plugins594### Publish official public plugins

528 595 

Details

6 Terminal,6 Terminal,

7} from "@components/react/oai/platform/ui/Icon.react";7} from "@components/react/oai/platform/ui/Icon.react";

8 8 

9Remote connections let you use Codex when you are away from the machine that9Remote connections let you use Codex from another device or another machine.

10runs it, or when your project lives on another machine. Connect the ChatGPT10Use Codex in the ChatGPT mobile app to work with Codex on a connected Mac,

11mobile app to a Codex App host, pick up work from another device, or configure11continue work from another Codex App device, or connect the Codex App to

12Codex to work on an SSH host.12projects on an SSH host.

13 13 

14Remote access uses the connected host's projects, threads, files, credentials,14Remote access uses the connected host's projects, threads, files, credentials,

15permissions, plugins, Computer Use, browser setup, and local tools.15permissions, plugins, Computer Use, browser setup, and local tools.


23- Get notified when Codex completes a task or needs your attention.23- Get notified when Codex completes a task or needs your attention.

24- Switch between connected hosts and threads.24- Switch between connected hosts and threads.

25 25 

26The next sections cover using the ChatGPT mobile app to control a Codex App26The next sections cover using Codex in the ChatGPT mobile app to control a Codex

27host. To connect Codex to a project on an SSH host, see27App host. To connect Codex to a project on an SSH host, see

28[connect to an SSH host](#connect-to-an-ssh-host).28[connect to an SSH host](#connect-to-an-ssh-host).

29 29 

30<div class="not-prose my-6 max-w-4xl rounded-xl bg-[url('/images/codex/codex-wallpaper-1.webp')] bg-cover bg-center p-4 md:p-8">30<div class="not-prose my-6 max-w-4xl rounded-xl bg-[url('/images/codex/codex-wallpaper-1.webp')] bg-cover bg-center p-4 md:p-8">


44 44 

45- Codex access in the ChatGPT account and workspace you want to use.45- Codex access in the ChatGPT account and workspace you want to use.

46- The latest ChatGPT mobile app on an iOS or Android device. If you do not see46- The latest ChatGPT mobile app on an iOS or Android device. If you do not see

47 Codex in the app, update ChatGPT first.47 Codex in the ChatGPT mobile app, update ChatGPT first.

48- A Mac host that is awake, online, running the Codex App, and signed in to the48- The latest Codex App for macOS running on a Mac host that is awake, online,

49 same account and workspace. Mobile setup and device control currently require49 and signed in to the same account and workspace. Mobile setup starts from the

50 the Codex App for macOS on the host; the setup flow isn't available from the50 Codex App; you cannot set it up from the Codex CLI or IDE Extension.

51 Codex CLI or IDE Extension.

52- Any required multi-factor authentication, SSO, or passkey configuration for51- Any required multi-factor authentication, SSO, or passkey configuration for

53 that account or workspace.52 that account or workspace.

54 53 


115it plugged in and turn on **Keep this Mac awake** in the host's connection114it plugged in and turn on **Keep this Mac awake** in the host's connection

116settings.115settings.

117 116 

117On a Mac laptop, remote access can stay available with the lid open while the

118computer is plugged in. With the lid closed, connect an external display as

119well. Choosing **Sleep** still stops remote access.

120 

118### <span class="not-prose inline-flex items-center gap-3 align-middle"><span class="inline-flex h-7 w-7 shrink-0 items-center justify-center rounded-md bg-surface-secondary text-secondary"><Storage width={17} height={17} /></span><span>A dedicated always-on Mac</span></span>121### <span class="not-prose inline-flex items-center gap-3 align-middle"><span class="inline-flex h-7 w-7 shrink-0 items-center justify-center rounded-md bg-surface-secondary text-secondary"><Storage width={17} height={17} /></span><span>A dedicated always-on Mac</span></span>

119 122 

120Use a dedicated always-on Mac when you want Codex to stay reachable for123Use a dedicated always-on Mac when you want Codex to stay reachable for


132 135 

133For SSH setup details, see [connect to an SSH host](#connect-to-an-ssh-host).136For SSH setup details, see [connect to an SSH host](#connect-to-an-ssh-host).

134 137 

138For browser or desktop tasks on an always-on Mac or remote host, enable

139 Computer Use and install the Chrome extension on that host.

140 

135## What comes from the connected host141## What comes from the connected host

136 142 

137Your phone sends prompts, approvals, and follow-up messages to Codex. The143Your phone sends prompts, approvals, and follow-up messages to Codex. The


155 161 

156## Pick up work from another device162## Pick up work from another device

157 163 

158You can also connect one Codex App host to another. For example, if your laptop164You can continue work from another signed-in Codex App device. For example, if

159is unavailable, you can start a thread from your phone on an always-on host,165your laptop is unavailable, you can start a thread from your phone on an

160then later open Codex on your laptop and continue that thread from there.166always-on host, then later open Codex on your laptop and continue that same

167thread there.

161 168 

162In Codex on the laptop, use **Settings > Connections > Control other devices**169In Codex on the laptop, use **Settings > Connections > Control other devices**

163to add the other host. A device can allow remote access and control another170to add the other host. A device can allow remote access and control another


215 222 

216</WorkflowSteps>223</WorkflowSteps>

217 224 

218If remote connections don't appear yet, enable the alpha feature flag in

219`~/.codex/config.toml`:

220 

221```toml

222[features]

223remote_connections = true

224```

225 

226<CodexScreenshot225<CodexScreenshot

227 alt="Codex app settings showing SSH remote connections"226 alt="Codex app settings showing SSH remote connections"

228 lightSrc="/images/codex/app/remote-connections-light.webp"227 lightSrc="/images/codex/app/remote-connections-light.webp"


234 233 

235## Authentication and network exposure234## Authentication and network exposure

236 235 

237Use SSH port forwarding with local-host WebSocket listeners. Don't expose an236Remote connections use SSH to start and manage the remote Codex app server.

238unauthenticated app-server listener on a shared or public network.237Don't expose app-server transports directly on a shared or public network.

239 238 

240If you need to reach a remote machine outside your current network, use a VPN or239If you need to reach a remote machine outside your current network, use a VPN

241mesh networking tool such as Tailscale instead of exposing the app server240or mesh networking tool instead of exposing the app server directly to the

242directly to the internet.241internet.

243 242 

244## Troubleshooting243## Troubleshooting

245 244 


251 250 

252### The approval request does not appear251### The approval request does not appear

253 252 

254Open the ChatGPT mobile app and go to Codex. Confirm that the phone and host use253Open Codex in the ChatGPT mobile app. Confirm that the phone and host use the

255the same ChatGPT account and workspace, then scan the QR code again or restart254same ChatGPT account and workspace, then scan the QR code again or restart setup

256setup from the host. If you use a ChatGPT workspace, ask your admin to confirm255from the host. If you use a ChatGPT workspace, ask your admin to confirm that

257that Remote Control access is enabled.256Remote Control access is enabled.

258 257 

259### The remote session disconnects258### The remote session disconnects

260 259 

subagents.md +1 −1

Details

60 60 

61Codex also reapplies the parent turn's live runtime overrides when it spawns a61Codex also reapplies the parent turn's live runtime overrides when it spawns a

62child. That includes sandbox and approval choices you set interactively during62child. That includes sandbox and approval choices you set interactively during

63the session, such as `/approvals` changes or `--yolo`, even if the selected63the session, such as `/permissions` changes or `--yolo`, even if the selected

64custom agent file sets different defaults.64custom agent file sets different defaults.

65 65 

66You can also override the sandbox configuration for individual [custom agents](#custom-agents), such as explicitly marking one to work in read-only mode.66You can also override the sandbox configuration for individual [custom agents](#custom-agents), such as explicitly marking one to work in read-only mode.