Decodex

One control loop for projects, retained lanes, signed delivery, upstream radar, and public updates.

Upstream · 103 commits 0.130.0 0.131.0-alpha.9
54 curated signals
30 try paths
0 high impact
May 13, 2026 latest analysis

Automation map

Four loops behind the product surface.

Decodex software Operate work, track impact, and keep delivery policy explicit.
  1. 01

    Control plane

    Project registry, identity routing, signing policy, review handoff, and landing rules.

  2. 02

    Retained execution

    Issue intake, context preservation, progress checkpoints, and verified handoff.

  3. 03

    Upstream radar

    Commit and PR analysis translated into product follow-up.

  4. 04

    Publisher

    X posts, release rollups, and migration notes with source links intact.

Decodex radar

Prioritized changes with an action path or watch note attached.

#22414 Capability Medium impact

Remote Codex can use Unix socket endpoints

This is directly useful for Decodex Control Plane work built on the Codex app-server: local Unix sockets can reduce exposed loopback surface area and make daemon-style local integrations cleaner without changing the JSON-RPC protocol shape.

Try path

On a Codex build that includes PR #22414, point the remote client at a Unix socket endpoint with codex --remote unix://PATH, or use unix:// for the default daemon socket path when the daemon is configured for UDS.

Open evidence

Next useful reads

  1. #22414 Remote Codex can use Unix socket endpoints
  2. #16946 Danger-full-access can now run under a managed denylist-only network policy
  3. #16082 App-server v2 can now read MCP resources directly

Watch notes

  • #22414

    Track when this lands in a public prerelease, because Decodex Control Plane and app-server integrations may be able to prefer local UDS transport over loopback WebSocket wiring.

  • #16946

    Watch for follow-up hardening around bypass paths and non-loopback proxy listener behavior, since this mode deliberately trades strict isolation for broader connectivity.

  • #16082

    Watch for follow-up MCP Apps work that builds on resource reads with richer UI wiring, resource-template flows, or higher-level client helpers.

Publisher output

Source-backed updates for the community channel.

Output path

Commit evidence becomes short X posts, release rollups, and B-side follow-up notes. Bot channel: @decodexspace.

Commit evidence Human-grade analysis X post Release rollup

Evidence feed

Source-backed cards. Filter for try paths or high-impact shifts.

May 2026

#22414
Capability Medium impact Confirmed

Remote Codex can use Unix socket endpoints

Merged PR #22414 adds Unix domain socket endpoints to codex --remote. The remote app-server client can now use unix:// or unix://PATH in addition to WebSocket URLs, while the TUI probes the default daemon socket before falling back to an embedded app-server.

Why it matters

This is directly useful for Decodex Control Plane work built on the Codex app-server: local Unix sockets can reduce exposed loopback surface area and make daemon-style local integrations cleaner without changing the JSON-RPC protocol shape.

Try path

On a Codex build that includes PR #22414, point the remote client at a Unix socket endpoint with codex --remote unix://PATH, or use unix:// for the default daemon socket path when the daemon is configured for UDS.

Expected effect The remote Codex client connects to the app-server over the Unix socket while reusing the same JSON-RPC protocol; the TUI can also prefer the local daemon socket and fall back to its embedded app-server if the daemon is absent or unresponsive.

--remote
Evidence 5 proof points
  • The PR body says codex --remote now accepts ws://host:port, wss://host:port, unix://, and unix://PATH.
  • codex-rs/app-server-client/src/remote.rs adds endpoint parsing and transport handling for WebSocket and Unix socket app-server endpoints.
  • codex-rs/app-server-client/src/lib.rs reuses the existing JSON-RPC client protocol over either a WebSocket stream or a Unix socket stream.
  • codex-rs/tui/src/lib.rs adds a fast startup probe for the default daemon socket and falls back to the embedded app-server when the daemon is missing or unresponsive.
  • The PR records focused coverage for UDS remote round trips, WebSocket auth headers, auth-token transport policy, remote address parsing, and missing-daemon fallback.

Caveats

  • This is upstream merged code evidence; availability still depends on the Codex build or prerelease channel that includes PR #22414.
  • The PR keeps remote auth-token transport restricted to wss:// and loopback ws:// endpoints, so UDS support should not be framed as broad remote-auth relaxation.

Watch state Track when this lands in a public prerelease, because Decodex Control Plane and app-server integrations may be able to prefer local UDS transport over loopback WebSocket wiring.

  1. PR Add support for UDS in `codex --remote` #22414
  2. Commit Support UDS and websocket remotes f31f1b6

April 2026

#16946
Behavior change Medium impact Confirmed

Danger-full-access can now run under a managed denylist-only network policy

Merged PR #16946 adds experimental_network.danger_full_access_denylist_only, letting danger-full-access sessions keep broad network access while still enforcing centrally managed deny entries.

Why it matters

This is aimed at org-managed Codex deployments that want a less restrictive yolo mode without dropping network policy entirely. It gives administrators a middle ground between full allowlist enforcement and completely unmanaged network access.

Try path

In a Codex build that includes PR #16946, add danger_full_access_denylist_only = true under [experimental_network] together with one or more denied domains, start a danger-full-access session, and verify allowed outbound access still works while the denied domains are blocked by policy.

Expected effect Danger-full-access sessions should retain broad network reach, but requests to managed denied domains should still be refused by the proxy policy surface.

experimental_network.danger_full_access_denylist_only = true
Evidence 4 proof points
  • The PR summary explicitly introduces experimental_network.danger_full_access_denylist_only and says it applies only to SandboxPolicy::DangerFullAccess sessions.
  • The bundle shows the new field wired through config requirements parsing, app-server protocol/schema output, config API mapping, and the TUI debug config surface, which confirms this is a real operator-facing config addition rather than an internal constant.
  • The core network proxy spec changes add a wildcard allowlist path plus dedicated tests for enforcing managed denied domains in danger-full-access mode.
  • The PR body includes a concrete TOML example under [experimental_network] and repeatedly warns that the denylist remains best effort only, which is the key behavioral caveat for anyone enabling it.

Caveats

  • The PR is explicit that this is not a hard security boundary: a danger-full-access session may still bypass the proxy denylist through allowed sockets or other local/private paths.
  • Read-only and workspace-write sandbox modes keep their existing network behavior; this flag is intentionally scoped to danger-full-access only.

Watch state Watch for follow-up hardening around bypass paths and non-loopback proxy listener behavior, since this mode deliberately trades strict isolation for broader connectivity.

  1. PR [codex] Add danger-full-access denylist-only network mode #16946
  2. Commit feat(network): add danger-full-access denylist-only mode 9d93253
  3. Commit fix(network): broaden danger-full-access denylist-only mode 4df276f
#16082
Capability Medium impact Confirmed

App-server v2 can now read MCP resources directly

Merged PR #16082 adds the mcpServer/resource/read request to the app-server protocol, so clients can fetch MCP resource contents by threadId, server name, and URI instead of only listing servers, tools, and templates.

Why it matters

This fills a real MCP Apps integration gap. Client builders can now move from discovering MCP resources to actually reading them through the same app-server surface, which makes richer MCP-backed UIs and workflows easier to build.

Try path

Start an app-server-backed Codex session with an MCP server that exposes resources, then issue mcpServer/resource/read with a live threadId, the MCP server name, and a known resource URI.

Expected effect The response should include a contents array with text or blob resource payloads for the requested MCP resource instead of only metadata about the server.

Evidence 4 proof points
  • The PR body states the new goal directly: add an mcpResource/read method to read an MCP resource.
  • The protocol bundle adds McpResourceReadParams, McpResourceReadResponse, and ResourceContent types plus a new mcpServer/resource/read request shape in both JSON schema and generated TypeScript outputs.
  • The app-server implementation gains request handling in codex_message_processor.rs, and the shared test harness adds a dedicated send_mcp_resource_read_request helper for the new method.
  • A new integration suite file, codex-rs/app-server/tests/suite/v2/mcp_resource.rs, provides focused end-to-end coverage for reading MCP resources through the v2 app-server path.

Caveats

  • This is app-server protocol work, so the immediate payoff is strongest for client and integration developers rather than ordinary chat-only usage.
  • The PR is labeled part 1, which suggests more MCP Apps work is expected on top of this read path.

Watch state Watch for follow-up MCP Apps work that builds on resource reads with richer UI wiring, resource-template flows, or higher-level client helpers.

  1. PR [mcp] Support MCP Apps part 1. #16082
  2. Commit update 9d85fa8
#16153
Behavior change Medium impact Confirmed

Code mode now supports setTimeout and clearTimeout

Merged PR #16153 adds timer support to code mode by exposing setTimeout and clearTimeout, so scripts can schedule delayed callbacks inside an exec run.

Why it matters

This makes code mode feel more like a real scripting runtime for lightweight orchestration. Delayed retries, timeout-backed promises, and simple event-loop style flows no longer need awkward manual polling just to wait a few milliseconds.

Try path

In code mode, run something like await new Promise((resolve) => setTimeout(resolve, 10)); text("timer done"); inside exec and confirm the delayed callback resumes the script.

Expected effect The script should pause briefly, then continue and emit the final output after the timeout callback fires.

Evidence 4 proof points
  • The code-mode description string now documents setTimeout(callback, delayMs?) and clearTimeout(timeoutId?) as built-in helpers available to runtime scripts.
  • The runtime adds dedicated timeout callbacks, installs both globals, and introduces a new timers.rs module that schedules callbacks and tracks timeout IDs.
  • Core integration coverage adds code_mode_can_resume_after_set_timeout, which awaits a promise built on setTimeout and verifies the exec call returns the expected output.
  • The PR body notes the current implementation uses one thread per timer, which supports reading this as a real new capability with an acknowledged implementation tradeoff rather than a docs-only change.

Caveats

  • The PR body explicitly says the current implementation starts a thread per timer, so this should be treated as functional support rather than the final scalability story.
  • Pending timeouts do not keep exec alive by themselves; the script still needs an explicit promise or other wait path if it wants to pause for the timer.

Watch state Watch for a follow-up runtime implementation that moves timers onto a shared async scheduler instead of per-timeout threads.

  1. PR Add setTimeout support to code mode #16153
  2. Commit Add setTimeout support to code mode ee42b49
  3. Commit Merge remote-tracking branch 'origin/main' into pakrym/add-settimeout-to-codemode 9113313
  4. Commit codex: fix CI failure on PR #16153 9abf7ea
#16508
Behavior change Medium impact Confirmed

Model and provider ownership moves out of codex-core

Merged PR #16508 splits models-manager out of core, moves several auth/provider/protocol helpers to owner crates, and keeps temporary re-exports so the workspace can adopt the new boundaries without one giant import rewrite.

Why it matters

This is primarily a contributor-facing architecture shift. Codex model metadata, provider config, auth glue, and response-debug helpers now have clearer crate ownership, which should make follow-on work in those areas less entangled with codex-core.

Watch state

Watch for follow-up PRs that remove the temporary re-exports and finish migrating imports to the new crate owners, since this change is deliberately staged.

Evidence 4 proof points
  • The PR summary explicitly says model metadata paths stop depending on core::Config and lists new owners such as codex-models-manager, codex-model-provider-info, codex-api, codex-protocol, and codex-response-debug-context.
  • The patch adds new workspace members and rewires Cargo manifests plus moved source files, which matches the claim that crate ownership is being redistributed rather than just lightly renamed.
  • Follow-up commits in the same PR restore bundled-model fallback behavior and avoid a giant import-only rewrite, which supports reading the change as a staged ownership extraction instead of a breaking immediate surface reset.
  • The touched files span core, api, app-server, protocol-adjacent code, and multiple new crates, so the main value is structural decoupling across the Codex Rust workspace.

Caveats

  • Most readers will not see an immediate CLI behavior change from this PR alone; the payoff is cleaner crate boundaries for later work.
  • The PR intentionally keeps temporary re-exports and defers some mechanical import cleanup to follow-up changes.
  1. PR extract models manager and related ownership from core #16508
  2. Commit Extract models manager ownership from core e67d682
  3. Commit codex: allow bundled models expect in PR #16508 2e105a9
  4. Commit codex: restore bundled models fallback 4dd6b8e
  5. Commit Address review style nits 22ddcb4
#16633
Behavior change Low impact Confirmed

Windows TUI builds stop tripping a cfg-mismatched local binding

Merged PR #16633 moves a terminal.viewport_area binding inside the Unix-only branch in tui.rs, so Windows builds no longer see an unused local introduced by the earlier zellij redraw work.

Why it matters

This is a small Windows-only build hygiene fix, but it removes avoidable compiler noise from the TUI path while broader Bazel-on-Windows work is still being stabilized.

Watch state

Watch for more cfg(unix) and Windows-specific TUI follow-ups near the redraw and viewport code paths as the cross-platform polish continues.

Evidence 3 proof points
  • The PR body says the unused-variable issue slipped in during PR #16578 and explicitly frames this as part of ongoing Windows bring-up work.
  • The bundle contains a single-file diff in codex-rs/tui/src/tui.rs where let area = terminal.viewport_area; is moved under #[cfg(unix)], which directly matches the stated fix.
  • No runtime logic, command paths, or user-visible rendering branches changed outside that binding placement, so the evidence supports calling this a narrow compile-path correction rather than a new TUI feature.

Caveats

  • This does not change TUI behavior at runtime for ordinary users; it only prevents a Windows-side compile warning/error path.
  • The broader Windows and Bazel compatibility work remains in flight, so this should be read as one cleanup step, not the whole story.
  1. PR fix: address unused variable on windows #16633
  2. Commit fix: address unused variable on windows 14da169
#16631
Behavior change Medium impact Confirmed

codex-core SessionTask builds get materially lighter

Merged PR #16631 replaces async_trait on SessionTask with native async futures plus a boxed adapter at the storage boundary, and the PR reports about a 48% package-clean codex-core rebuild reduction.

Why it matters

This is mainly a contributor-facing change, not a new CLI feature. People working in Codex core task execution should see faster rebuilds and less async-trait-generated glue when touching the session task path.

Watch state

Watch for follow-up core task-trait cleanups around the remaining boxed adapter boundary, since this PR deliberately keeps the heterogeneous dyn storage model.

Evidence 4 proof points
  • The PR body says this change continues the compile-time cleanup from #16630 and cites package-clean codex-core rebuilds as the benchmark that showed the real gain.
  • The patch removes #[async_trait] from SessionTask and concrete task implementations, switches the trait to native RPITIT futures, and adds an AnySessionTask adapter to keep boxing only at the heterogeneous storage boundary.
  • The state layer changes RunningTask from Arc<dyn SessionTask> to Arc<dyn AnySessionTask>, which matches the PR narrative that task lifecycle semantics stay the same while the abstraction boundary moves.
  • The touched files are all in the core task/state/test surface, which supports reading this as a scoped compile-time and maintainability change rather than a new end-user workflow.

Caveats

  • The PR body notes the win showed up on package-clean codex-core rebuilds, not on a warm incremental benchmark based on touching one task module.
  • This does not claim a runtime speedup for normal Codex usage; the main payoff is contributor build latency and trait-bound simplification.
  1. PR core: cut codex-core compile time 48% with native async SessionTask #16631
  2. Commit core: use native async SessionTask trait 2cafd78

March 2026

#16010
Behavior change Low impact Confirmed

wait_agent no longer needs target lists in MultiAgentV2

Merged PR #16010 changes multi-agent wait_agent so it wakes on new mailbox activity instead of requiring callers to name specific child targets.

Why it matters

This trims orchestration bookkeeping for advanced Codex users. If workers are spawned dynamically, the caller can now wait for the next inter-agent reply without first resolving thread IDs or task names.

Try path

In a Codex build that includes PR #16010 with MultiAgentV2 enabled, spawn a child agent, call wait_agent({"timeout_ms":1000}) from the root, then have any child send a message back without passing targets.

Expected effect wait_agent should return a simple completion result once fresh mailbox traffic arrives after the wait begins, even though no target list was provided.

Evidence 4 proof points
  • The PR narrative says a mailbox now backs inter-agent communication and that wait no longer takes a target argument.
  • The wait.rs handler removes targets from WaitArgs and replaces per-agent status waiting with a mailbox-sequence watch, so fresh mailbox traffic becomes the completion signal.
  • Session/task wiring was updated to treat mailbox items as pending input, which is the runtime path that makes the new wait behavior observable.
  • Tests were rewritten to accept timeout-only wait_agent calls and to confirm that new mailbox activity after the wait starts completes the call, while already-queued mail does not.

Caveats

  • This is mainly relevant to advanced multi-agent orchestration flows, not ordinary single-agent Codex usage.
  • The wait result is still only a completion-or-timeout summary; it does not surface the child message body itself.
  1. PR feat: add mailbox concept for wait #16010
  2. Commit feat: add mailbox concept for wait ddcdd1a
  3. Commit clippy 3670d0e
  4. Commit Merge remote-tracking branch 'origin/main' into jif/wait-mail-box 2fc9d2f
  5. Commit nit fixes 89fa34b
#15785
Behavior change Low impact Confirmed

Remote exec-server routing now uses CODEX_EXEC_SERVER_URL

Merged PR #15785 replaces the old experimental config-based exec-server override with a cached EnvironmentManager and the CODEX_EXEC_SERVER_URL environment variable, so app-server and TUI flows can reuse the same running exec server more consistently.

Why it matters

If you run Codex against a separate exec server, the setup path is simpler and more reliable: the override moves out of config.toml, the app-server creates the environment manager early, and delegated work inherits the same exec-server URL instead of rebuilding that routing piecemeal.

Try path

Run a Codex build that includes PR #15785 by starting codex-exec-server manually and launching the TUI or app-server path with CODEX_EXEC_SERVER_URL=ws://..., or use the new scripts/run_tui_with_exec_server.sh helper to do the handoff automatically.

Expected effect Codex should connect through the already running exec server without relying on the removed experimental_exec_server_url config key, and spawned or delegated work should stay pointed at that same remote execution endpoint.

Evidence 5 proof points
  • The PR body says the change adds a singleton environment manager created early in app-server startup and uses an environment variable to point Codex at a running exec server.
  • codex-rs/exec-server/src/environment.rs adds CODEX_EXEC_SERVER_URL_ENV_VAR = "CODEX_EXEC_SERVER_URL" plus an EnvironmentManager backed by OnceCell, which is direct evidence that exec-server selection is now cached and env-driven.
  • codex-rs/core/src/config/mod.rs and codex-rs/core/config.schema.json remove experimental_exec_server_url, showing the old config-surface override is no longer the supported path.
  • codex-rs/app-server/src/lib.rs, codex-rs/app-server/src/in_process.rs, and codex-rs/tui/src/app.rs now construct EnvironmentManager::from_env() early, while codex-rs/core/src/codex_delegate.rs passes the parent exec-server URL into delegated threads.
  • The new scripts/run_tui_with_exec_server.sh helper starts codex-exec-server, and the bundle's extracted flags include CODEX_EXEC_SERVER_URL="$exec_server_url", which supports the new env-based TUI handoff workflow.

Caveats

  • This is mainly relevant for remote or standalone exec-server setups; users on the default local execution path may not notice a visible difference.
  • Any workflow still relying on experimental_exec_server_url in config will need to migrate to the CODEX_EXEC_SERVER_URL environment variable.

Watch state Whether operator docs and surrounding tooling fully migrate from the removed experimental_exec_server_url knob to CODEX_EXEC_SERVER_URL, especially outside the new helper script.

  1. PR Add cached environment manager for exec server URL #15785
  2. Commit Add environment manager setup 2fdf36b
  3. Commit Add environment manager for exec url 9524bd2
  4. Commit codex: fix CI failure on PR #15785 8606dd1
  5. Commit codex: route tui app server through env manager 9c07e68
  6. Commit codex: drop broken remote-aware shell test 8986e44
#15802
Behavior change Low impact Confirmed

TUI plugin flows now use OpenAI Curated and drop the /apps command

Merged PR #15802 makes a small but visible plugin-UI cleanup in tui and tui_app_server: the curated marketplace gets a clearer name, /apps is hidden from the command menu, and uninstalled plugin states now show a more actionable ChatGPT install prompt.

Why it matters

This reduces terminology friction in the plugin experience. Users see a clearer curated marketplace label, less mixed app-versus-plugin wording in the TUI, and a better hint about what to do when a plugin depends on ChatGPT-side app installs.

Try path

Run a build that includes PR #15802 with plugins enabled, open the TUI or tui_app_server plugin flow, inspect the curated marketplace label and an uninstalled plugin state, and check the slash-command picker for /apps.

Expected effect The UI should show OpenAI Curated instead of the raw openai-curated name, the slash-command menu should no longer surface /apps, and uninstalled plugin states should tell you to install the required Apps in ChatGPT.

Evidence 3 proof points
  • The PR body frames the change as three user-facing polish items: rename the openai-curated marketplace to OpenAI Curated, hide the /apps menu entry, and change the app-install-phase display text.
  • Both codex-rs/tui and codex-rs/tui_app_server update bottom_pane/command_popup.rs to filter out SlashCommand::Apps, and both chatwidget/plugins.rs files replace Not installed yet. with Install the required Apps in ChatGPT to continue:.
  • codex-rs/core/src/plugins/manager.rs adds OPENAI_CURATED_MARKETPLACE_DISPLAY_NAME = "OpenAI Curated" and uses it when the marketplace name is openai-curated, while manager_tests.rs is updated to expect that display name.

Caveats

  • This is limited to tui and tui_app_server polish; it does not add new plugin capabilities or change backend install mechanics.

Watch state Whether any remaining plugin surfaces or docs still reference the older /apps command or the raw openai-curated marketplace name.

  1. PR TUI plugin menu polish #15802
  2. Commit Change label at app instalp step, hide /apps command c61d828
  3. Commit Cleaner display name for OpenAI Curated plugins marketplace 9ede25d
  4. Commit fmt 982b96d
#15759
Behavior change Low impact Confirmed

App-server TUI now keeps streamed transcript output intact under backpressure

PR #15759 changes the app-server TUI transport so transcript-bearing events are treated as must-deliver under backpressure, preventing large streamed responses from degrading into corrupted or incomplete paragraphs.

Why it matters

If you use Codex with the app-server TUI, long streamed answers are less likely to end up visibly broken when the UI falls behind. The fix prioritizes preserving the assistant’s actual transcript over dropping text fragments just to keep the queue moving.

Try path

Run a Codex build that includes PR #15759 with features.tui_app_server = true, trigger a response that streams a large amount of markdown or text, and watch the output while the UI is under load.

Expected effect The streamed answer should stay readable and complete instead of ending with mangled or missing paragraphs even if the app-server TUI briefly falls behind.

Add to $CODEX_HOME/config.toml features.tui_app_server = true
Evidence 4 proof points
  • The PR description explicitly says -c features.tui_app_server=true could corrupt large streamed output because AgentMessageDelta and ItemCompleted were previously droppable under backpressure, leaving incomplete markdown on screen.
  • The main file change in codex-rs/app-server-client/src/lib.rs expands must-deliver handling from terminal-only events to shared transcript-and-terminal notification classification, with comments calling out corrupted markdown and incomplete paragraphs as the failure mode.
  • codex-rs/app-server-client/src/remote.rs now delegates to the same shared server_notification_requires_delivery logic, which is evidence that both in-process and remote app-server transports were aligned around the new lossless transcript policy.
  • The commit set includes dedicated regression coverage for backpressure preservation plus follow-up docs and test adjustments, matching the PR's claim that transcript notifications now survive saturated queues.

Caveats

  • This is scoped to the app-server TUI path rather than the default legacy TUI.
  • The change preserves transcript integrity under backpressure, but it does not remove backpressure or address the root cause of a slow consumer.
  1. PR fix(tui_app_server): preserve transcript events under backpressure #15759
  2. Commit feat(tui_app_server): preserve transcript events under backpressure 86d0792
  3. Commit test(app-server-client): add backpressure regression coverage f45919b
  4. Commit docs(app-server-client): document backpressure forwarding internals e189c1c
  5. Commit test(core): relax remote backpressure event ordering assertion b66ae15
#14847
Capability Low impact Confirmed

App-server websocket mode now supports bearer-token auth

Merged PR #14847 adds websocket authentication for Codex app-server, so websocket clients can be challenged at upgrade time instead of being admitted first and checked later.

Why it matters

If you expose codex app-server over websockets beyond localhost, you now have a built-in way to require credentials at the transport boundary. That closes a meaningful security gap for remote deployments without forcing an immediate breaking default on existing clients.

Try path

Start a build that includes PR #14847 with codex app-server --listen ws://127.0.0.1:PORT --ws-auth capability-token --ws-token-file /absolute/path/token.txt, then attempt one websocket connection without Authorization: Bearer <token> and one with it.

Expected effect The unauthenticated websocket upgrade should be rejected, while the request carrying the configured bearer token should complete the handshake and proceed to normal app-server initialization.

Evidence 3 proof points
  • The PR body says websocket auth is enforced before JSON-RPC initialize, and that unauthenticated clients are rejected during the websocket handshake rather than after a connection is already open.
  • The README adds a new security note and user-facing auth options: --ws-auth capability-token --ws-token-file ... and --ws-auth signed-bearer-token --ws-shared-secret-file ..., with optional issuer, audience, and clock-skew checks, and it documents Authorization: Bearer <token> for clients.
  • The change adds a dedicated transport/auth.rs module and expands websocket transport tests, backing the feature with real transport-layer enforcement, constant-time capability-token checks, JWT verification via jsonwebtoken, and 403 rejection for Origin-bearing browser-style handshakes.

Caveats

  • Websocket transport is still described in the README as experimental and unsupported for production workloads.

Watch state During rollout, non-loopback websocket listeners still remain unauthenticated by default unless --ws-auth is explicitly configured.

  1. PR feat: add websocket auth for app-server #14847
  2. Commit feat: add websocket auth flags for app-server 22d51ec
  3. Commit refactor: rename transport auth module a19f46d
  4. Commit fix: harden websocket auth verification 35cff1b
  5. Commit fix: reject browser-origin websocket handshakes without auth c9e706f
  6. Commit fix: make websocket auth opt-in during rollout c1f1b6d
  7. Commit fix: use jwt for signed websocket auth 3b84329
  8. Commit refactor: remove insecure websocket rollout flag 61baaee
  9. Commit codex: address PR review feedback (#14847) 4e69aa8
  10. Commit refactor: use jsonwebtoken for websocket jwt auth 7b79230
  11. Commit Merge remote-tracking branch 'origin/main' into codex/viyatb/app-server-websocket-auth a91c332
#15259
Behavior change Low impact Confirmed

Manual /compact now queues follow-up prompts until the turn ends

PR #15259 changes both tui and tui_app_server so input submitted around a manual /compact is held and retried after that non-steerable turn finishes, instead of being treated like a normal same-turn steer.

Why it matters

This makes maintenance flows less brittle. Users can keep typing during a manual compact or review turn without losing the follow-up or having to re-enter it, and the UI now makes that deferred submission explicit.

Try path

Run a Codex build that includes PR #15259, start a manual /compact in the TUI, submit another prompt before compact finishes, and wait for the turn to complete. Optionally repeat in tui_app_server or while /review is running.

Expected effect The follow-up should appear under Messages to be submitted at end of turn while the current turn is active, then submit automatically once /compact or /review finishes.

Evidence 4 proof points
  • The PR body explicitly says the goal is to queue input after the user submits /compact until that manual compact turn ends, mirror the behavior in the app-server TUI, and add regressions for messages queued before and during compact.
  • codex-rs/protocol/src/protocol.rs adds NonSteerableTurnKind::{Review, Compact} plus an ActiveTurnNotSteerable error, showing /review and manual /compact now take a distinct retryable path instead of generic steering.
  • Both codex-rs/tui/src/chatwidget.rs and codex-rs/tui_app_server/src/chatwidget.rs add a rejected_steers_queue, and the pending-input preview snapshots add a new Messages to be submitted at end of turn section for those deferred prompts.
  • New and updated snapshots for compact_queues_user_messages and review_queues_user_messages, along with codex-rs/core/src/codex_tests.rs, verify the queued-retry behavior and visible messaging in both frontends.

Caveats

  • The user-facing retry flow is scoped to interactive tui and tui_app_server handling of non-steerable turns such as manual /compact and /review.
  1. PR tui: queue follow-ups during manual /compact #15259
  2. Commit steer: queue follow-ups for non-steerable turns ff28c3b
#15279
Behavior change Low impact Confirmed

Plugin-backed mentions now show as [Plugin] and hide duplicate app entries

Merged PR #15279 updates mention and picker UI in both tui and tui_app_server so plugin-backed connectors are labeled as [Plugin], duplicate app-style entries are suppressed, and filtered popup lists stop at eight rows.

Why it matters

Plugin-heavy pickers should be less confusing to scan. Users get more accurate labels, fewer duplicate entries for the same underlying plugin-backed connector, and a predictable first page of results instead of long filtered lists.

Try path

On a build that includes PR #15279, trigger mention completion in the TUI or tui_app_server for a plugin-backed connector, especially one that would previously also appear as an app-style entry, and inspect the filtered picker list.

Expected effect You should see a single plugin-labeled result instead of duplicate app/plugin entries, and the popup should show no more than eight filtered rows.

Evidence 3 proof points
  • The PR body explicitly says duplicate app mentions are suppressed for plugin-backed entries with the same display name, remaining connector mentions are labeled [Plugin] instead of [App] when plugin metadata exists, and mention result lists are capped to 8 rows in both tui and tui_app_server.
  • chat_composer.rs in both codex-rs/tui and codex-rs/tui_app_server now builds a set of plugin display names and checks connector.plugin_display_names, which is the concrete path for deduping and relabeling plugin-backed mention items.
  • file_search_popup.rs and skill_popup.rs in both frontends now truncate filtered results to MAX_POPUP_ROWS, and the added tests assert that only the first page of matches is kept after filtering.
  1. PR Label plugins as plugins, and hide skills/apps for given plugin #15279
  2. Commit Label plugins as plugins, and hide skills/apps for given plugin from 4ce939c
  3. Commit tui: keep plugin-backed app mentions visible in skill picker bb0beef
#15414
Behavior change Low impact Confirmed

tui_app_server drops legacy ChatGPT auth-refresh handling

Merged PR #15414 removes legacy app-server notification handling and the old local ChatGPT auth-refresh response path from tui_app_server, narrowing that compatibility layer as Codex moves toward the newer app-server stack.

Why it matters

This is a low-impact contract change for anyone still depending on the older tui_app_server path. Legacy clients should no longer expect this TUI-side adapter to service ChatGPT token-refresh requests, while current Codex development sheds outdated auth plumbing ahead of the broader migration.

Watch state

Watch only. No safe try path is published for this signal yet.

Evidence 3 proof points
  • The PR title and body explicitly say tui_app_server is removing legacy app-server notifications and dropping the local ChatGPT auth refresh request path, and frame it as cleanup split out from the larger app-server migration.
  • codex-rs/tui_app_server/src/app/app_server_adapter.rs removes imports for load_local_chatgpt_auth, ChatgptAuthTokensRefreshParams, and RequestId, and the patch excerpt shows the old AppServerEvent::ServerRequest handling branch being deleted.
  • codex-rs/tui_app_server/src/local_chatgpt_auth.rs removes ChatgptAuthTokensRefreshResponse plus the to_refresh_response helper, which is concrete evidence that this adapter no longer builds the legacy refresh response payload.

Caveats

  • This is scoped to the legacy tui_app_server compatibility path, not a broad auth change for standard Codex CLI or TUI usage.
  • The bundle excerpt clearly shows the legacy handler removal, but the exact runtime failure mode for stale clients is inferred because the deleted request branch is truncated in the patch excerpt.
  1. PR Remove legacy auth and notification handling from tui_app_server #15414
  2. Commit Remove legacy auth and notification handling from tui_app_server 263c63a
  3. Commit codex: fix CI failure on PR #15414 e65c137
#15390
Behavior change Low impact Confirmed

TUI app-server drops legacy warning and rollback notification support

Merged PR #15390 removes the TUI app-server's compatibility handling for older codex/event/* notifications, deleting the warning and rollback buffering paths that were kept only for legacy rollouts.

Why it matters

This is mostly a low-impact cleanup rather than a new feature. For current users, the main value is that the app-server TUI now stays closer to the newer client model with less obsolete compatibility code in the way; anyone still depending on very old rollout-era warning or rollback notifications should treat that path as removed.

Watch state

Watch the follow-up work referenced in the PR body for whether the remaining lower-level legacy event plumbing is removed too.

Evidence 4 proof points
  • The PR body explicitly says the removed handling was temporary, only needed for very old rollouts, and not supported by the IDE extension or app clients either.
  • codex-rs/tui_app_server/src/app/app_server_adapter.rs removes the legacy notification translation layer, including LegacyThreadNotification and the old JSONRPCNotification-based handling path.
  • codex-rs/tui_app_server/src/app.rs deletes LegacyWarning, LegacyRollback, the pending rollback queue, and related buffering/session-refresh logic, showing the TUI app-server no longer preserves or replays those events.
  • codex-rs/tui_app_server/src/chatwidget.rs removes the warning-message hook used by this path, completing the TUI-side cleanup.

Caveats

  • The PR body scopes this to very old rollouts, so direct user-visible impact for current Codex users should be limited.
  • The lower-level app-server and app-server-client legacy plumbing is intentionally left in place for follow-up work, so this PR removes only the TUI-facing compatibility layer.
  1. PR Remove legacy app-server notification handling from tui_app_server #15390
  2. Commit codex: remove tui_app_server legacy notification handling fcb4222
  3. Commit Merge remote-tracking branch 'origin/main' into codex/pr-15106-tui-legacy-notifications 05b63be
#15203
Capability Low impact Confirmed

Codex adds a cross-platform V8 integration proof of concept

Merged PR #15203 adds a v8-poc crate plus Bazel and CI wiring that proves Codex can link and run V8 across the main supported non-Windows target platforms.

Why it matters

This does not expose a new end-user feature yet, but it gives Codex a verified integration path for embedding V8 in future runtime or tooling work without treating cross-platform linking as an open risk.

Watch state

Watch for follow-up PRs that replace the dummy crate with a real V8-backed feature or re-enable the Windows Bazel path.

Evidence 3 proof points
  • The PR body explicitly says the new dummy v8-poc project demonstrates that Codex can successfully link and use V8 on the platforms it wants to target.
  • codex-rs/Cargo.toml adds a new v8-poc workspace member and pins v8 = =146.4.0, while codex-rs/v8-poc/src/lib.rs adds a proof-of-concept crate with tests that initialize V8 and evaluate an expression.
  • MODULE.bazel, third_party/v8/BUILD.bazel, and the Rust CI and release workflows add target-specific V8 artifact wiring, including musl overrides and Bazel-side source-built archives for shipped platforms.

Caveats

  • The PR describes this as a dummy proof-of-concept crate reserved for future V8 experiments, not a shipped user feature.
  • The PR body notes likely compatibility drift in the Windows Bazel builder and says Windows Bazel support still needs follow-up work.
  1. PR Add v8-poc consumer of our new built v8 #15203
  2. Commit Add v8-poc consumer of our new built v8 733e868
  3. Commit Build v8-poc as part of CI 20ce301
  4. Commit Working on all platforms 9ae2f06
  5. Commit Ignore codex-v8-poc 1fb916a
  6. Commit Prepull our artifacts for musl f8a239e
  7. Commit Path b6b58e1
  8. Commit Fix bazel build for v8-poc 7b80661
  9. Commit Repatch rusty_v8 393b560
  10. Commit Always link v8 6c0deb2
  11. Commit Build v8 for our bazel platforms ffbe942
  12. Commit Remove local=1 e43c0f6
  13. Commit darwin exception 9edd9a3
#15223
Behavior change Medium impact Confirmed

Resumed threads now restore generated image history

Merged PR #15223 restores image-generation items in resumed thread history and preserves the saved paths tied to those earlier outputs.

Why it matters

Image work no longer disappears when you come back to an older thread. That makes long-running image sessions easier to resume, audit, and copy from without losing the earlier generation context.

Try path

Resume a thread that previously generated images, then inspect the thread history and completed items for restored image entries and saved paths.

Expected effect Resumed threads should show earlier image-generation items and preserve saved image paths instead of dropping that part of the history.

Evidence 3 proof points
  • The PR body explicitly says image-generation items should be restored in resumed thread history.
  • The protocol schemas add a savedPath field to image-related notifications and thread responses so image history can carry the persisted file location.
  • The commit sequence includes Persist image generation end events for history replay and Add tests for resumed image history preservation, which confirms this is an intended behavior change.
  1. PR Feat/restore image generation history #15223
  2. Commit Restore image generation items in resumed thread history f065885
  3. Commit Persist image generation end events for history replay 005e6fc
  4. Commit Restore saved image paths in resumed history e870aae
  5. Commit Add copy guidance for generated images 85464fb
  6. Commit Fix tui app server image generation adapter f1a6367
  7. Commit Add tests for resumed image history preservation ace552c
  8. Commit Remove temporary image history proof tests b1ed4a7
  9. Commit Avoid duplicating saved image blobs in limited rollouts 050a478
  10. Commit Remove rollout image persistence test 66aa6d1
  11. Commit Revert rollout image blob clearing 6e7d372
  12. Commit Trim restore image history branch scope 0552a98
#15264
Behavior change Medium impact Confirmed

App server now syncs remote plugins once at startup

Merged PR #15264 adds a one-time startup remote plugin sync so app-server startup can reconcile curated plugin state automatically.

Why it matters

Plugin-enabled setups become closer to it just shows up. Early users do not have to rely on a later manual sync path before the plugin list reflects remote curated state.

Try path

Start an app-server session in a codex_home with plugins enabled and remote plugin sync configured, then open the plugin list on first startup.

Expected effect When the app server starts with plugin sync configured, remote curated plugin state should be reconciled automatically on first startup instead of waiting for a later explicit sync path.

Evidence 3 proof points
  • The PR body says early users with enabled apps should have plugins enabled as part of initial setup.
  • The core plugin manager now routes startup work through startup_sync.rs and renames the old curated-repo sync path into broader startup plugin tasks.
  • The integration test app_server_startup_remote_plugin_sync_runs_once verifies that the remote plugin sync happens once at startup.
  1. PR feat: Add One-Time Startup Remote Plugin Sync #15264
  2. Commit feat: Add One-Time Startup Remote Plugin Sync 56c33c2
#15252
Behavior change Low impact Confirmed

Hooks are disabled on Windows sessions in Codex Rust hook engine

The PR changes hook initialization so Windows sessions skip lifecycle hook discovery and return with no hooks plus a warning, reflecting that codex_hooks is not supported on Windows yet.

Why it matters

This prevents Windows users from hitting unsupported-hook execution paths by failing safely with a clear warning, which is a user-facing behavior change that keeps sessions usable while hook support is incomplete on that platform.

Watch state

Watch only. No safe try path is published for this signal yet.

Evidence 4 proof points
  • Primary PR metadata identifies the change as “Disable hooks on windows for now” and includes a temporary-status body (“We'll verify a bit later... and re-enable”).
  • The modified file codex-rs/hooks/src/engine/mod.rs adds a cfg!(windows) early return that initializes handlers as empty and sets a warnings message stating hooks are disabled because lifecycle hooks are not yet supported on Windows.
  • Bundle evidence shows exactly one commit (933ef3ccbdeb1877f2f9ba45d1379826f4c63088) with message “disable hooks on windows for now,” and that commit is tied to the merged PR 15252.
  • The patch shows no deletions and only additions around hook startup logic, indicating a targeted behavioral gate rather than broad refactoring.

Caveats

  • This is explicitly temporary behavior with explicit intent to re-enable later once Windows support is verified.
  1. PR Disable hooks on windows for now #15252
  2. Commit disable hooks on windows for now 933ef3c
#15215
Try now Medium impact Confirmed

A first /plugins browser lands in the TUI

Merged PR #15215 adds a first /plugins browser to both tui and tui_app_server, with listing, search, and read-only plugin detail views.

Why it matters

Plugin discovery moves into the terminal itself. Early users no longer need to hunt for plugin metadata outside Codex just to browse what is available and inspect what a plugin contains.

Try path

Launch Codex CLI with --enable plugins, run /plugins, search the curated marketplace, and open a plugin detail view. Optionally repeat with --enable tui_app_server.

Expected effect The TUI should expose a searchable /plugins flow with loading states, plugin detail views, and back navigation, and the same flow should work under tui_app_server.

Add to $CODEX_HOME/config.toml features.plugins = true features.tui_app_server = true
Evidence 3 proof points
  • The PR body explicitly describes a preliminary /plugins menu in both tui and tui_app_server, including loading, search, and detail-view behavior.
  • The testing section in the PR body documents the exact /plugins flow to verify, including disabled behavior when plugins are not enabled.
  • The patch adds plugin list and plugin read wiring in tui/src/app.rs and tui/src/app_event.rs, which is the concrete UI plumbing for the new menu.
  1. PR Initial plugins TUI menu - list and read only. tui + tui_app_server #15215
  2. Commit Initial plugins TUI - list and read only. tui + tui_app_server ff5efc8
  3. Commit Combine marketplace_path and plugin_name into PluginReadParams a101165
#15199
Behavior change Low impact Confirmed

Argument-comment lint now uses the released DotSlash artifact by default

PR #15199 retools the repository's standard argument-comment lint path to use a checked-in DotSlash package and introduces a separate source-build wrapper path, while fixing rustup/toolchain compatibility in the prebuilt runner.

Why it matters

This reduces lint turnaround in normal dev and CI workflows by avoiding repeated source builds and making the lint job more deterministic. It also lowers environment-fragility on CI, especially Windows, by standardizing toolchain context handling for the shipped prebuilt lint package.

Try path

Check out the PR version, run just argument-comment-lint (or CI argument_comment_lint_prebuilt path in rust-ci.yml), and confirm it executes via tools/argument-comment-lint/run-prebuilt-linter.sh with the DotSlash manifest.

Expected effect Linting uses the checked-in prebuilt package path, so normal local/CI runs avoid rebuilding the lint from source and no longer fail due to the Windows RUSTUP_HOME/toolchain naming assumptions the PR fixes.

Evidence 4 proof points
  • PR #15199 body explicitly states the lint path is moving to the released DotSlash artifact for normal CI and just workflows, while preserving source-build for active lint development.
  • The files changes include adding tools/argument-comment-lint/argument-comment-lint and run-prebuilt-linter.sh, plus wrapper behavior updates in tools/argument-comment-lint/run.sh and src/bin/argument-comment-lint.rs to normalize nightly toolchain naming and infer RUSTUP_HOME when needed.
  • CI and task wiring changed to enforce this path: .github/workflows/rust-ci.yml is split into dedicated lint jobs and justfile routes argument-comment-lint to the prebuilt wrapper instead of the source wrapper.
  • A follow-up evidence bundle commit (a1b8effb15edfc337ba58215adc4d70f60c548ac) adds compatibility fixes across Windows sandbox call sites to make the stricter lint clean on current code, supporting the PR’s stated goal of a green prebuilt lint run.

Caveats

  • Primarily affects contributor and CI lint infrastructure rather than end-user runtime behavior.
  • Behavioral value depends on developers consuming the updated just targets and CI workflows.
  1. PR Use released DotSlash package for argument-comment lint #15199
  2. Commit Use released DotSlash package for argument-comment lint a1b8eff
#15195
Try now Medium impact Confirmed

plugin/install now installs bundled MCP servers

Merged PR #15195 extends plugin/install so marketplace plugins can install their bundled MCP servers during the install flow instead of leaving that as a separate manual step.

Why it matters

Plugin setup becomes much closer to one step. Users and client builders get fewer post-install surprises when a plugin depends on MCP servers or requires OAuth to complete setup.

Try path

Enable plugins, call plugin/install for a plugin that ships an .mcp.json, then issue a follow-up plugin or MCP read in the same session.

Expected effect A plugin install that bundles MCP servers should make those servers available immediately after install, with auth surfaced as part of the install flow when needed.

Evidence 3 proof points
  • The app-server README now documents plugin/install as installing bundled MCPs in addition to returning auth policy information.
  • The new plugin_mcp_oauth.rs path wires OAuth login handling for MCP servers discovered during plugin installation.
  • The integration test plugin_install_makes_bundled_mcp_servers_available_to_followup_requests verifies that bundled MCP servers become usable right after install.
  1. PR [plugins] Install MCPs when calling plugin/install #15195
  2. Commit update 1a910fd
#15150
Capability Low impact Likely

Auth stack moved into dedicated codex-login crate

PR #15150 refactors auth ownership in openai/codex by relocating auth implementation details into codex-login and making codex-core re-export a compatibility surface for existing callers.

Why it matters

The split reduces cross-crate coupling around authentication and keeps legacy call sites working, which makes future auth changes and maintenance less risky while preserving current CLI/TUI/app-server behavior.

Watch state

Watch only. No safe try path is published for this signal yet.

Evidence 4 proof points
  • PR body explicitly states the intent: move auth implementation and token data into codex-login, while keeping codex-core re-exporting that surface.
  • New auth-focused files were added under codex-rs/login/src/auth (including error.rs and util.rs), and logic previously in core files (for example core/src/error.rs and core/src/util.rs) was moved to those modules.
  • codex-rs/core/src/lib.rs now re-exports codex_login auth/default-client modules so downstream crates can continue using core-facing auth APIs after the move.
  • Consumers were updated across app-server, exec, tui, and cli to import auth structures from codex_login compatibility paths, showing an intentional dependency re-alignment rather than a feature addition.

Caveats

  • Primary value is architectural; no clear new end-user feature is introduced directly in this PR.
  • The observable behavior should remain mostly stable because compatibility re-exports and updated matches were added for auth mode handling.
  1. PR Move auth code into login crate #15150
  2. Commit Move terminal module to its own crate df7a587
  3. Commit Rename terminal crate to terminal-detection 3661c08
  4. Commit codex: fix CI failure on PR #15216 9e6c404
  5. Commit Move auth code into login crate 4b9dde5
  6. Commit codex: clean up auth import style on PR #15150 a717396
  7. Commit codex: fix CI failure on PR #15150 905255d
  8. Commit codex: avoid default_client imports in login on PR #15150 59c056e
  9. Commit codex: restore login auth API surface on PR #15150 499c319
  10. Commit unify 112d231
#15021
Capability Low impact Confirmed

Add a dedicated Bazel pipeline for building and releasing rusty_v8 artifacts

PR #15021 adds a new Bazel-based workflow for building and packaging rusty_v8, including musl targets for x86_64/aarch64, while removing third_party/v8 from the default CI test path so V8 work is handled by dedicated canary/release flows.

Why it matters

This gives the project a reliable way to produce and publish prebuilt V8 artifacts for additional toolchains (notably musl), improving build reproducibility for dependents and reducing pressure on normal CI by isolating heavy V8 builds into explicit workflows.

Watch state

Watch only. No safe try path is published for this signal yet.

Evidence 5 proof points
  • The PR body explicitly says the approach is to use rusty_v8 everywhere possible and to build a musl V8 from source for x86/aarch64, with a release step for consumption.
  • Added .github/scripts/rusty_v8_bazel.py introduces the musl-oriented Bazel build orchestration and packaging metadata used by the new release path.
  • Added .github/workflows/v8-canary.yml and .github/workflows/rusty-v8-release.yml, creating a dedicated canary/release lane (including optional GitHub release publishing) for V8 artifacts instead of coupling them to standard CI.
  • Updated build metadata in MODULE.bazel, MODULE.bazel.lock, and new Bazel patches under patches/ to pin/use V8 14.6.202.9 plus required dependency/workspace overrides.
  • Adjusted .github/workflows/bazel.yml to exclude //third_party/v8:all from ordinary Bazel test runs, matching the PR’s “keep V8 out of ordinary CI” intent and evidence trail in commit history.

Caveats

  • No direct user-facing application behavior changes are shown; impact is primarily build/release infrastructure.
  1. PR V8 Bazel Build #15021
  2. Commit Setup a new v8-poc package d317180
  3. Commit Merge the v8 building for musl 6c2e61f
  4. Commit Update v8 version ca8204a
  5. Commit Link in the missing llvm runtime archives cef4b77
  6. Commit Version match f496726
  7. Commit Do not test this package by default d040eda
  8. Commit Add canary workflow for now dc98f8e
  9. Commit I swear no v8 4809cd1
  10. Commit Split v8-poc consumer to follow-up branch 1ab6566
  11. Commit rename to v8-canary 2d05604
  12. Commit Remove v8 from cargo.toml for now 93dbe48
  13. Commit Fix build 3b573d1
  14. Commit Hermetic python + cleanup e358585
  15. Commit skylib b9f2761
  16. Commit Build opt for release abc472b
  17. Commit Release fixes d0289aa
  18. Commit Stronger lean in to opt 14f4bd9
  19. Commit Address PR feedback f92d130
  20. Commit Drop patch to prebuilt v8 cef0a87
#15232
Capability Low impact Confirmed

Split ExecServer filesystem into local and remote backends

The PR refactors filesystem handling in codex-exec-server behind a shared trait with separate local and remote implementations, and routes execution environment selection through that abstraction.

Why it matters

This reduces coupling between local and remote execution paths, making remote file operations a first-class implementation path rather than ad-hoc logic and improving confidence the same filesystem behavior is available in both modes. It also sets up safer future changes by isolating responsibilities and extending test coverage to both backends.

Watch state

Watch only. No safe try path is published for this signal yet.

Evidence 7 proof points
  • PR narrative states the change pattern per feature: trait on environment, local implementation, remote implementation via network proxy, and handler integration for PRC requests.
  • codex-rs/exec-server/src/file_system.rs introduces the shared ExecutorFileSystem interface and supporting option/type definitions.
  • codex-rs/exec-server/src/environment.rs switches get_filesystem to return RemoteFileSystem when a remote client exists, otherwise LocalFileSystem.
  • codex-rs/exec-server/src/remote_file_system.rs adds a new remote implementation that fulfills the shared trait with protocol-level filesystem operations.
  • codex-rs/exec-server/tests/file_system.rs adds a large parameterized test module covering filesystem operations for both local and remote file systems.
  • codex-rs/exec-server/src/server/file_system_handler.rs and codex-rs/exec-server/src/server/handler.rs are updated to use the new module split and handler naming.
  • codex-rs/exec-server/src/server/transport.rs adds websocket URL output support used by the test harness (exec_server.rs).

Caveats

  • Most of the change is structural and test/implementation cleanup around existing exec-server behavior, not a large outward feature addition.
  • Remote behavior is now explicit in codepaths, which is an internal architecture change that may still need operational validation in real remote deployments.
  1. PR Refactor ExecServer filesystem split between local and remote #15232
  2. Commit Extract local and remote fs APIs 4b42ea8
  3. Commit Add parameterized file system tests ec76d77
  4. Commit Merge remote-tracking branch 'origin/main' into pakrym/compare-execserverfilesystem-and 7dc0759
  5. Commit Print exec server websocket URL 4a9479b
  6. Commit exec-server: remove expect usage in filesystem tests 4b303df
#15222
Behavior change Medium impact Confirmed

Generated images now save under codex_home instead of a temp directory

Merged PR #15222 moves generated-image artifacts out of transient temp paths and into a predictable location under codex_home.

Why it matters

This makes image outputs easier to find, persist, and script against. Users who rely on generated artifacts no longer have to guess where a temp file landed or whether it will disappear between runs.

Try path

Generate an image from a Codex build that includes PR #15222, then inspect the active codex_home directory for a generated_images/<thread_id>/ subtree.

Expected effect New image-generation outputs should land under codex_home/generated_images/<thread_id>/... instead of an OS temp directory.

Evidence 3 proof points
  • The PR body explicitly says the default image-generation save directory now points at codex_home with a per-thread path.
  • The Rust helper in stream_events_utils.rs now builds image artifact paths from codex_home and a dedicated generated_images directory instead of std::env::temp_dir().
  • Tests in codex_tests.rs and stream_events_utils_tests.rs were updated to expect the new codex-home path, which confirms this is a behavior change rather than a comment-only cleanup.
  1. PR changed save directory to codex_home #15222
  2. Commit changed save directory to codex_home 5d11650
  3. Commit Collapse generated image artifact helpers 6cd6f49
  4. Commit Avoid expect in image artifact path handling f8b8920
#15220
Try now Medium impact Confirmed

mcpServer/startupStatus/updated lands in API v2

Merged PR #15220 promotes MCP startup progress to a first-class API v2 notification instead of leaving it as a legacy internal event.

Why it matters

Clients can track MCP readiness without scraping legacy events. That makes plugin UIs, status surfaces, and startup diagnostics easier to build and less brittle.

Try path

Connect to the app-server v2 notification stream, trigger an MCP server startup or refresh, and listen for mcpServer/startupStatus/updated events.

Expected effect API v2 clients should receive starting, ready, failed, or cancelled MCP startup updates, including the server name and optional error details.

Evidence 3 proof points
  • The PR body explicitly says the legacy MCP startup update event is now exposed as an API v2 notification.
  • The protocol schemas add both McpServerStartupState and McpServerStatusUpdatedNotification, which defines the new event contract.
  • The server notification schema now registers mcpServer/startupStatus/updated as a first-class v2 notification method.
  1. PR feat(app-server): add mcpServer/startupStatus/updated notification #15220
  2. Commit feat(app-server): add mcpServer/status/updated notification 9c0fdb4
  3. Commit mcpServer/startupStatus/updated ba1d743
  4. Commit fix random bug c58e46d
#15217
Capability Low impact Confirmed

Expose needsAuth in plugin app summaries

PR #15217 extends Codex plugin summary payloads with a new required needsAuth boolean so plugin/read/plugin/list style responses can explicitly signal whether an app requires authorization.

Why it matters

Clients can now distinguish auth-gated plugins from directly usable ones before launching a plugin flow, which enables cleaner UI behavior (e.g., showing auth prompts or disabled actions) without guessing from installer metadata alone.

Watch state

Watch only. No safe try path is published for this signal yet.

Evidence 5 proof points
  • The PR narrative is explicitly feat: expose needs_auth for plugin/read and the merge record is openai/codex#15217.
  • Schema updates add needsAuth: boolean and require it in codex_app_server_protocol.schemas.json, codex_app_server_protocol.v2.schemas.json, v2/PluginInstallResponse.json, and v2/PluginReadResponse.json, indicating a contract-level API field addition.
  • Protocol type definitions were updated in v2/AppSummary.ts and protocol/v2.rs to carry a needs_auth/needsAuth field in AppSummary, with conversion paths updated to populate it.
  • plugin_app_helpers.rs now queries connector access/auth status before emitting plugin summaries, and returns early with plugin summaries when the auth-status service is unavailable, showing runtime handling for the new metadata.
  • Tests in plugin_install.rs were updated with needs_auth: true expectations for auth-required plugin cases, anchoring the new behavior in executable behavior checks.

Caveats

  • Only plugin schema objects and test-covered flows in this patch explicitly reflect the new field; other client surfaces may need follow-up updates to render or consume needsAuth.
  • When the auth-status lookup is not ready or fails, behavior follows existing fallback paths in helper logic.
  • The PR body is brief, so downstream UI behavior is an integration responsibility, not part of this patch alone.
  1. PR feat: expose needs_auth for plugin/read. #15217
  2. Commit feat: expose needs_auth for plugin/read. d9f6b7f
#15154
Behavior change Low impact Likely

TUI image history now shows generated files as file URIs

PR #15154 updates Codex TUI output so image-generation history entries render saved image locations as full file:// URIs (for example file:///tmp/...) instead of plain local paths, across both TUI binaries.

Why it matters

This makes generated images easier to open directly from the terminal history in environments that treat file:// links as clickable resources, improving discoverability right after generation.

Try path

Generate an image in the TUI workflow and inspect the resulting history row; verify the saved location is shown as a file://... path (e.g., file:///tmp/ig-1.png) in place of /tmp/..., then open it in VSCode Terminal.

Expected effect Generated-image entries now present Saved to values as URI links, enabling easier direct opening of files in supported terminals and reducing manual path-copy steps.

Evidence 5 proof points
  • Primary PR title/body says it adds full image paths so generated images are open-able in TUI, currently limited to VSCode Terminal.
  • In codex-rs/tui/src/chatwidget.rs and codex-rs/tui_app_server/src/chatwidget.rs, image generation end handling now maps saved paths through url::Url::from_file_path(...).to_string(), producing URI-formatted paths.
  • In both codex-rs/tui/src/history_cell.rs and codex-rs/tui_app_server/src/history_cell.rs, rendering changed from saved_to to saved_path and directly displays the formatted path string after Saved to:.
  • Snapshot and test updates in TUI history outputs/tests replace /tmp/ig-1.png with file:///tmp/ig-1.png, showing the visible output change.
  • Additional identical updates in both codex-rs/tui and codex-rs/tui_app_server indicate the behavior applies to both terminal UI variants.

Caveats

  • Behavior is explicitly scoped to VSCode Terminal per PR body; other terminals may not auto-handle file:// links the same way.
  • The change is primarily a UX/path-format improvement, not a new image generation capability.
  • A small unrelated filesystem initialization change (Environment::default().get_filesystem()) is present but not the user-facing headline.
  1. PR adding full imagepath to tui #15154
  2. Commit adding full imagepath to tui 51153be
  3. Commit added snapshots 8ca6ef3
  4. Commit flaky code f27a4e9
#15206
Capability Low impact Confirmed

Trace spans now include turn IDs for app-server turn APIs

This PR adds instrumentation to propagate turn.id into app-server request tracing for turn/start, turn/steer, and turn/interrupt, plus tests to verify the attribute is present.

Why it matters

It gives operators and maintainers a reliable way to correlate all spans for a single turn across the app-server lifecycle, making debugging and latency triage more precise without changing API payloads.

Watch state

Watch only. No safe try path is published for this signal yet.

Evidence 5 proof points
  • PR #15206 explicitly sets the goal to tag app-server turn spans with turn.id for turn/start, turn/steer, and turn/interrupt.
  • primary_pr.title and the two commits (7f9f93e057d7c73a84ea071aabcc88ddfe743150, 8e042a093cceac78a48d1d8cabd6f6247e51532f) are narrowly scoped to tracing and turn-id propagation.
  • app_server_tracing.rs adds a turn.id field into the server request span template.
  • codex_message_processor.rs records turn IDs into request context for both turn start and turn interrupt request flows.
  • outgoing_message.rs introduces a shared context method that stores turn IDs by request_id, and tracing tests assert turn.id equals the returned turn ID.

Caveats

  • This is an internal observability change; user-facing product behavior is unchanged for normal clients.
  • Signal mainly helps people consuming traces, not end users directly.
  1. PR feat(tracing): tag app-server turn spans with turn_id #15206
  2. Commit feat(tracing): tag app-server turn spans with turn_id 7f9f93e
  3. Commit also record turn id for turn/steer and turn/interrupt 8e042a0
#12334
Capability Low impact Confirmed

/title adds configurable terminal-title support in the TUI

PR #12334 introduces a new TUI /title command and config path so users can control which compact items appear in the terminal window/tab title, with a default spinner,project layout when unset.

Why it matters

This gives users a practical way to distinguish multiple active Codex sessions at the terminal level, improving session visibility and reducing “which tab is which” confusion without requiring app focus.

Watch state

Watch only. No safe try path is published for this signal yet.

Evidence 5 proof points
  • The PR description explicitly frames the change as solving multi-session identification and documents /title as a new, separate terminal-title surface.
  • codex-rs/core/src/config/types.rs and codex-rs/core/src/config/mod.rs add tui.terminal_title mapped into runtime config, with defaults in docs/schema (config.schema.json) to spinner and project when unset.
  • codex-rs/tui/src/slash_command.rs adds the /title command, and codex-rs/tui/src/bottom_pane/title_setup.rs introduces the in-TUI selection/reordering UI, wired through bottom_pane/mod.rs and app_event.rs.
  • codex-rs/tui/src/terminal_title.rs adds dedicated OSC terminal-title output and sanitization logic, while codex-rs/tui/src/chatwidget/status_surfaces.rs and chatwidget.rs integrate title refresh with the existing status pipeline.
  • The bundle includes added/updated tests and snapshots (title_setup snapshot + chatwidget/config tests), indicating behavior verification for the new user-facing flow rather than purely internal cleanup.

Caveats

  • Behavior depends on terminal/OS support for OSC title sequences; some terminals or environments may ignore title updates.
  • Feature changes terminal metadata only, so session distinction is improved in terminal tabs/windows but not in contexts that hide or override title rendering.
  1. PR feat(tui): add /title terminal title configuration #12334
  2. Commit feat(tui): add /title terminal title configuration db4b7fe
  3. Commit codex: fix CI failure on PR #12334 5d24272
#15090
Capability Low impact Confirmed

exec-server adds process and filesystem JSON-RPC capabilities

PR #15090 expands exec-server from a stub-oriented shape into a real process and filesystem RPC implementation, adding protocol methods, routing, client/server event plumbing, and tests. It also includes a CI cache guard for a specific macOS cross-target build issue.

Why it matters

This is a user-facing capability increase: clients can now drive process lifecycle and file operations through exec-server with structured RPCs and event notifications (output/exited), which is a prerequisite for richer automation and tool integration workflows. The CI tweak reduces environment-specific instability during release/integration builds.

Watch state

Watch only. No safe try path is published for this signal yet.

Evidence 8 proof points
  • The PR body explicitly states that it carries surviving exec-server process and filesystem RPC implementation on top of existing websocket-based scaffolding and calls out the macOS SCCACHE regression workaround.
  • Primary PR narrative + commits show a feature rollout: initial implementation (Add exec-server process and filesystem RPCs) plus follow-up lifecycle fix (exec-server: report false after retained exit).
  • codex-rs/exec-server/src/protocol.rs adds method constants for process (process/start, process/read, process/write, process/terminate, process/output, process/exited) and filesystem RPCs (fs/readFile, fs/writeFile, fs/createDirectory, etc.).
  • Server-side expansion is added in codex-rs/exec-server/src/server/filesystem.rs and codex-rs/exec-server/src/server/registry.rs, with substantial handler updates, indicating the new RPC surface is actually dispatched and handled.
  • Client-facing layers were updated (client.rs, client_api.rs, lib.rs, local_backend.rs) to expose/read new RPC/notification types, while transport/routing internals in rpc.rs/processor.rs were refactored to support the new request/notification paths.
  • Regression-hardening is included via .github/workflows/rust-ci.yml: SCCACHE is disabled for windows and macos-15-xlarge + x86_64-apple-darwin to avoid mixed-architecture ring/cc-rs cache failures.
  • New/updated tests in codex-rs/exec-server/src/server/handler/tests.rs and codex-rs/exec-server/tests/process.rs show validation of the new behavior path.
  • Build metadata changes (base64 and codex-utils-pty dependencies) and Cargo.lock updates support the newly added process and FS implementation paths.
  1. PR Add exec-server process and filesystem RPCs #15090
  2. Commit Add exec-server process and filesystem RPCs (#15090) dd1416a
  3. Commit exec-server: report false after retained exit ab89fdf
#15198
Capability Low impact Confirmed

argument-comment lint is now shipped as a runnable DotSlash package

The PR adds cross-platform release packaging for the argument-comment linter so teams can use a runnable artifact instead of building the linting tool from source.

Why it matters

This changes the developer workflow from rebuild-required to consume-ready, which reduces setup time and makes the lint more likely to be run earlier in day-to-day development and review loops.

Watch state

Watch only. No safe try path is published for this signal yet.

Evidence 5 proof points
  • Primary PR context states the previous linter flow required building from source and that PRs commonly failed later in CI because violations were not checked until later, motivating a prebuilt artifact distribution.
  • The new .github/dotslash-argument-comment-lint-config.json defines packaged outputs for macos-aarch64, linux-x86_64, linux-aarch64, and windows-x86_64, each pointing to argument-comment-lint executables under a packaged bin/ path.
  • A new .github/workflows/rust-release-argument-comment-lint.yml workflow is added to build host-specific release artifacts (archives/zips), and rust-release.yml is updated to invoke it and publish the new DotSlash manifest on releases.
  • tools/argument-comment-lint/src/bin/argument-comment-lint.rs adds a dedicated runner binary that resolves sibling packaged binaries/libraries and invokes cargo-dylint with the bundled library path, making the release artifact directly runnable.
  • Docs were updated (tools/argument-comment-lint/README.md) to describe the released argument-comment-lint DotSlash package layout and target coverage.

Caveats

  • The PR does not yet switch just clippy or other routine CI/dev hooks to use this package automatically, so behavior in existing daily commands is not fully transitioned yet.
  1. PR Publish runnable DotSlash package for argument-comment lint #15198
  2. Commit Publish runnable DotSlash package for argument-comment lint 5afbcf6
#15196
Capability Low impact Confirmed

Add experimental exec server URL override for Codex sessions

PR #15196 introduces an experimental experimental_exec_server_url configuration key and wires it into environment/session creation, allowing the remote exec server endpoint to be overridden from defaults.

Why it matters

It gives operators a configurable escape hatch for deployment-specific or proxied exec-server setups without requiring code changes, improving flexibility while keeping existing behavior unchanged by default.

Watch state

Watch only. No safe try path is published for this signal yet.

Evidence 5 proof points
  • The PR metadata identifies the change as "Add experimental exec server URL handling" and documents it as merged in openai/codex PR 15196, with commit 1f0ed50a125c758bb8d4d2f71e425e9eef3519f4.
  • codex-rs/core/src/config/mod.rs adds experimental_exec_server_url: Option<String> to both Config and ConfigToml, with doc text explicitly describing it as an override for the remote exec server URL.
  • codex-rs/core/src/config.schema.json adds experimental_exec_server_url as a schema field, exposing it as a configurable runtime input.
  • codex-rs/core/src/codex.rs now constructs environment via Environment::create(config.experimental_exec_server_url.clone()).await?, directly consuming the new config value during session setup.
  • codex-rs/exec-server/src/environment.rs replaces a unit Environment with a stateful struct that stores the optional override URL and a possible remote_exec_server_client, supporting the configurable connection path.

Caveats

  • The new setting is marked "Experimental / do not use," so behavior and stability are intentionally less guaranteed than stable config fields.
  1. PR Add experimental exec server URL handling #15196
  2. Commit Add experimental exec server config 1f0ed50
#15185
Behavior change Low impact Confirmed

Reverted MCP session/turn header forwarding

This PR rolls back PR #15011’s change that forwarded session and turn metadata as headers on MCP HTTP requests, restoring prior MCP request behavior.

Why it matters

It is a stabilization rollback: the revert removes a recently introduced request-header path that could alter MCP behavior for downstream MCP servers. Treating this as a behavior change is appropriate because it reverses a protocol-level transmission change that may have affected integrations, even though it does not add new capability.

Watch state

Watch only. No safe try path is published for this signal yet.

Evidence 6 proof points
  • Primary PR narrative is explicit: title is Revert "Forward session and turn headers to MCP HTTP requests" and body states it reverts openai/codex#15011.
  • The revert commit is bab2a28f26223da6a3a6f61bb9656d2f8d6cc4ee, whose message matches the PR title and confirms intent.
  • codex-rs/core/src/codex.rs removes sync_mcp_request_headers_for_turn, which was responsible for building/stashing turn- and session-derived request headers.
  • codex-rs/core/src/tasks/mod.rs removes both the per-turn header sync call and turn-state header-clear calls, indicating the rollback of that lifecycle behavior.
  • codex-rs/core/src/mcp_connection_manager.rs and codex-rs/core/src/mcp_connection_manager_tests.rs remove request-header storage/carrying state in AsyncManagedClient and related tests.
  • codex-rs/rmcp-client/src/rmcp_client.rs removes request-scoped-header handling for JSON-RPC client messages, including the message_uses_request_scoped_headers logic.

Caveats

  • No functional tests are shown in the bundle, so integration impact is inferred from the reverted diff and surrounding headers workflow.
  • This is explicitly a cleanup/revert; user-visible effects are likely subtle and environment-dependent.
  1. PR Revert "Forward session and turn headers to MCP HTTP requests" #15185
  2. Commit Revert "Forward session and turn headers to MCP HTTP requests (#15011)" bab2a28
#15175
Behavior change Low impact Confirmed

Disable memory generation during consolidation runs

The PR updates phase-2 memory consolidation so the internal sub-agent is configured with generate_memories disabled, and test coverage is adjusted to validate the configured consolidation thread path.

Why it matters

This prevents consolidation workers from writing memory entries while they are meant to consolidate context only, reducing the chance of recursive or noisy memory writes and helping keep stored memory cleaner and more stable across runs.

Watch state

Watch only. No safe try path is published for this signal yet.

Evidence 3 proof points
  • PR #15175 is explicitly framed as "morpheus does not generate memories" and is merged in openai/codex as a PR-first bundle (analysis_mode: pr_first).
  • codex-rs/core/src/memories/phase2.rs adds agent_config.memories.generate_memories = false when creating the consolidation sub-agent config, directly changing runtime behavior for that path.
  • codex-rs/core/src/memories/tests.rs now binds the consolidation thread id before fetching the thread and reads its config_snapshot, indicating test-level verification tied to the consolidation thread behavior.

Caveats

  • No direct user interface behavior is shown in the bundle; this is an internal control-flow change inferred from code/config updates.
  1. PR chore: morpheus does not generate memories #15175
  2. Commit chore: morpheus does not generate memories db01ae2
  3. Commit nit fix 9c1838e
#15180
Capability Low impact Confirmed

Added codex.profile.usage metric for active profile sessions

PR #15180 adds a new OpenTelemetry counter that increments when a session starts with an active profile, enabling explicit tracking of profile usage in telemetry pipelines.

Why it matters

This gives operators and maintainers a direct signal for how often active coding profiles are used in live sessions. It helps with visibility into feature adoption and debugging profile-related behavior without changing runtime user flows.

Watch state

Watch only. No safe try path is published for this signal yet.

Evidence 3 proof points
  • PR #15180 is titled chore: add metrics for profile and has a committed change set tied to a single merged commit (959dc2a4d88ebe8caad796b05e5a76096ba20f2e)
  • codex-rs/otel/src/metrics/names.rs now defines PROFILE_USAGE_METRIC as codex.profile.usage, establishing a new named metric in the shared telemetry namespace
  • codex-rs/otel/src/events/session_telemetry.rs imports PROFILE_USAGE_METRIC and increments it via self.counter(..., 1, &[]) whenever active_profile.is_some() is true

Caveats

  • No direct user-visible behavior changes; value appears only in exported telemetry/observability consumers
  1. PR chore: add metrics for profile #15180
  2. Commit chore: add metrics for profile 959dc2a
#15041
Behavior change Low impact Confirmed

Product-scoped plugins and skills via session source

PR 15041 makes session source a first-class input with --session-source and uses it to filter plugin installation and skill visibility by product, so different Codex surfaces can expose different plugin catalogs.

Why it matters

Users on one product surface are less likely to see or install incompatible plugins or skills. That reduces confusion and helps keep plugin availability aligned with the product context the session came from.

Try path

Start app-server with --session-source chatgpt or another custom source, then list or install marketplace plugins that declare policy.products restrictions.

Expected effect Plugins and skills whose product policy does not match the active session source should be filtered out or reported as unavailable, while unrestricted or matching items remain visible.

Evidence 5 proof points
  • The PR body explicitly frames the change around three behaviors: adding SessionSource::Custom(String) plus --session-source, enforcing plugin and skill products by session_source, and applying the same filtering to curated background refresh.
  • Protocol and schema changes add a custom session-source shape, which shows this is a supported runtime input rather than an internal one-off.
  • The runtime wiring passes the chosen session source through app-server setup instead of hardcoding a fixed source, making product-aware filtering active at execution time.
  • Plugin and skill loading paths now check product restrictions against the session-derived product, so mismatched items are hidden or treated as unavailable.
  • The test additions cover disallowed product plugins and product-scoped skill visibility, confirming this is a deliberate user-visible behavior change.

Caveats

  • The exact behavior depends on how session sources map to products; custom sources only help if that mapping resolves to the intended product restriction.
  1. PR feat: support product-scoped plugins. #15041
  2. Commit feat: support product-scoped plugins. d3b349c
  3. Commit Address comments. 06e9a1a
#14988
Capability Low impact Confirmed

App server adds thread/shellCommand support for TUI ! commands

Merged PR #14988 adds a new thread/shellCommand app-server request and wires app-server-backed TUI ! shell commands through that API, with command execution persisted into thread history.

Why it matters

This turns app-server-backed ! shell commands from a blocked path into a supported workflow. Users on the app-server TUI can run shell shortcuts again and have the command activity show up in the same thread history and execution-event flow as other command items.

Watch state

Watch only. No safe try path is published for this signal yet.

Evidence 5 proof points
  • The PR title and body frame the change around a new thread/shellCommand API plus TUI support for ! shell commands, making the PR itself a clear user-facing capability addition.
  • Protocol/schema files add a dedicated ThreadShellCommand request shape and ThreadShellCommandParams, while command items gain a CommandExecutionSource field, showing this is a first-class app-server surface rather than an internal workaround.
  • codex_message_processor.rs, app_server_session.rs, and tui_app_server/src/app.rs wire request handling and submission for thread/shellCommand, connecting the new API to the app-server-backed TUI path.
  • tui_app_server/src/chatwidget.rs removes the prior disabled-error behavior for ! commands and instead dispatches run_user_shell_command, while core/src/tasks/user_shell.rs adds rollout materialization for standalone shell-output persistence.
  • The new test suite app-server/tests/suite/v2/thread_shell_command.rs and updated chatwidget tests provide direct evidence that the request path and TUI behavior were intentionally added and verified.

Caveats

  • Merged protocol and README text describe thread/shellCommand as running unsandboxed with full access, which is stricter and more consequential than the PR body's earlier sandbox wording.
  1. PR Add thread/shellCommand to app server API surface #14988
  2. Commit Add thread shellCommand support to tui app server eb6a697
  3. Commit codex: address PR review feedback (#14988) e14a72a
  4. Commit codex: fix CI failure on PR #14988 aac5786
  5. Commit codex: revert broad rollout persistence change 3aadef3
  6. Commit codex: fix protocol clippy default derivation 6fa40a7
  7. Commit codex: fix CI formatting on PR #14988 03dd655
  8. Commit codex: clarify standalone shell turn docs on PR #14988 37d04c6
  9. Commit codex: revert thread command output delta raw-bytes followup (#14988) f4d42d0
#14970
Behavior change Low impact Confirmed

Codex now distinguishes directory mentions from file mentions

Merged PR #14970 adds basic directory-mention support by carrying directory vs. file match metadata through fuzzy file search results and related protocol schemas.

Why it matters

This makes path mentions less ambiguous in the TUI and gives clients enough information to treat folders differently from files. For users, that should reduce mistaken links for extensionless paths and make folder references clearer.

Try path

On a build that includes PR #14970, trigger fuzzy file search or mention completion for a known folder and a similarly named file, then inspect the returned mention/search result payloads or UI labels for directory-specific handling.

Expected effect Directory matches should be marked distinctly from file matches, with folder mentions rendered using a trailing slash and available for client-specific link behavior.

Evidence 3 proof points
  • The PR title and body explicitly frame the change as adding simple directory-mention support in the TUI, with trailing slashes used to distinguish directories from extensionless files.
  • The Rust search model in codex-rs/file-search adds a MatchType on search results, and the app-server mapping forwards that as FuzzyFileSearchMatchType with file and directory variants.
  • Generated JSON/TypeScript protocol schemas now require match_type on FuzzyFileSearchResult, and fuzzy-file-search tests were updated to expect the new field, confirming this is a real behavior-contract change rather than internal cleanup.

Caveats

  • The PR body says Codex App and VS Code need a minor follow-up change to recognize directory mentions and adjust link behavior, so downstream client UX may lag the protocol change.

Watch state Watch for follow-up client updates that consume match_type and fully differentiate folder links outside the TUI.

  1. PR Simple directory mentions #14970
  2. Commit Simple folder mentions a4277b0
  3. Commit Use trailing slash df3a8b4
  4. Commit Add match type 385be6b
  5. Commit Added match_type to indicate file/directory mentions c0617a5
  6. Commit Merge conflicts f9634cb
  7. Commit Fix test in windows envs 0dbfa40
#15118
Capability Low impact Confirmed

Stop and UserPromptSubmit hooks now receive the active turn_id

Merged PR #15118 adds a Codex-specific turn_id field to the Stop and UserPromptSubmit hook payloads so hook scripts can tie each invocation to a specific conversation turn.

Why it matters

This makes hook automation more precise. If you log, correlate, or enforce turn-scoped behavior in custom hooks, you can now distinguish one turn from the next instead of inferring that from prompt text or timestamps.

Try path

Enable Stop or UserPromptSubmit hooks in a build that includes PR #15118, print the incoming JSON payload in your hook script, and run two prompts in the same session.

Expected effect Each Stop and UserPromptSubmit invocation should include a turn_id string, and the value should differ between separate turns so your hook can correlate events within the same turn.

Evidence 3 proof points
  • The PR title and body explicitly frame the change as exposing turn_id to hook scripts so runs can be connected to particular turns.
  • The generated hook input schemas for stop.command.input and user-prompt-submit.command.input now require a string turn_id field.
  • The Rust hook event code now serializes request.turn_id into both Stop and UserPromptSubmit payloads, and the test suite was expanded to log hook inputs and verify turn-scoped behavior.

Caveats

  • The new field is a Codex-specific extension and only applies to the Stop and UserPromptSubmit hook payloads covered by this PR.
  1. PR [hooks] turn_id extension for Stop & UserPromptSubmit #15118
  2. Commit turn_id extension for stop/userpromptsubmit 9647be0
  3. Commit codex: fix CI failure on PR #15118 524f3aa
#15088
Capability Low impact Confirmed

Python SDK adds thread.run() convenience methods for one-shot turns

Merged PR #15088 adds thread.run(...) and async thread.run(...) to the Python SDK, giving users a simpler path for common prompt-response flows without manually creating and running a turn handle.

Why it matters

This lowers the amount of SDK code needed for basic request-response usage. Python users can now send a string or input bundle directly from a thread and get a compact result object back, while the lower-level turn API remains available for streaming and more advanced control.

Try path

In a Codex build that includes PR #15088, start a Python SDK thread with codex.thread_start(...) and call thread.run("Say hello in one sentence.") or await thread.run("Say hello in one sentence.") in the async API.

Expected effect The call should return a RunResult object with the collected thread items, optional token usage, and a final_response string when the turn produces a final-answer or phase-less assistant message.

Evidence 3 proof points
  • The PR title and body explicitly frame this as new Python SDK convenience methods: thread.run(...) and async thread.run(...) for the common case.
  • The code adds new _inputs.py and _run.py helpers, including RunInput and a RunResult dataclass with final_response, collected items, and optional usage.
  • The README, getting-started guide, quickstart examples, and runtime/signature tests were updated to use thread.run(...), which shows the new flow is intended for public use rather than internal refactoring.

Caveats

  • final_response is optional and may be null when the turn completes without a final-answer style assistant message.
  • The lower-level thread.turn(...) path still matters for streaming, steering, interrupting, and direct access to the raw Turn object.
  1. PR Add Python SDK thread.run convenience methods #15088
  2. Commit python-sdk: add thread.run convenience methods 3536149
  3. Commit python-sdk: update quickstart examples for thread.run 33289a1
  4. Commit python-sdk: fix thread.run final response semantics 5f141ad
  5. Commit python-sdk: use typed thread items for run results 62ff8ba
  6. Commit Merge remote-tracking branch 'origin/main' into dev/shaqayeq/python-sdk-thread-run 93f5ebe
  7. Commit python-sdk: prefer final-answer phase in run results 4c52a5d
  8. Commit python-sdk: split convenience helpers out of api 49ff282
  9. Commit python-sdk: inline turn handles into api facade a32b804
  10. Commit python-sdk: make run final_response optional 7f5e539
#15089
Capability Low impact Confirmed

Added a standalone exec-server binary with JSON-RPC protocol scaffolding

PR #15089 adds a new codex-exec-server crate and standalone binary with shared protocol types, Rust client APIs, and stdio/websocket transport support, while keeping exec and filesystem methods stubbed for later PRs.

Why it matters

This creates a separate execution-server boundary that future Codex integrations can build on without coupling everything to the main CLI process. It is a real new capability, but still an early one: the transport and handshake are in place before the full remote execution surface lands.

Watch state

Watch follow-up PRs for actual exec/filesystem method implementation and integration into the main Codex execution flow.

Evidence 5 proof points
  • The PR title and body explicitly frame this as an "initialize-only" exec-server stub slice with protocol docs, not a full execution feature.
  • codex-rs/Cargo.toml, codex-rs/exec-server/Cargo.toml, and codex-rs/Cargo.lock add a new codex-exec-server workspace crate and binary target.
  • codex-rs/exec-server/README.md documents a standalone server, shared JSON-RPC wire protocol, and two supported transports: ws://IP:PORT and stdio://.
  • codex-rs/exec-server/src/bin/codex-exec-server.rs, src/protocol.rs, src/rpc.rs, and src/server/transport.rs provide the new server entrypoint, initialize protocol types, RPC plumbing, and transport parsing/runtime support.
  • Smoke tests in codex-rs/exec-server/tests/stdio_smoke.rs and codex-rs/exec-server/tests/websocket_smoke.rs verify the initialize flow over both transport modes, which confirms the stub is functional at the protocol layer.

Caveats

  • The PR intentionally stops at transport, protocol, and initialize-handshake scaffolding; exec and filesystem RPC methods are still stubbed.
  • The new server is not yet wired into the main Codex CLI or unified execution path, so immediate end-user impact is limited.
  1. PR Add exec-server stub server and protocol docs #15089
  2. Commit Add codex-exec-server crate 144c359
  3. Commit docs(exec-server): add protocol README 949932c
  4. Commit Add Bazel package for exec-server 40cc199
  5. Commit Trim exec-server PR to stub server slice 2958067
  6. Commit Keep first exec-server PR initialize-only 7607197
  7. Commit Add generic RPC server glue to exec-server stub 16ff474
  8. Commit Add generic exec-server RPC foundation 0a846a2
  9. Commit Wire notification sender into exec-server RPC foundation c5dbe42
  10. Commit Remove outer handler mutex from exec-server RPC base 66f49ea
  11. Commit Test generic exec-server RPC response matching 43b112c
  12. Commit exec-server: simplify stub json-rpc transport shape 2661dc5
  13. Commit exec-server: address transport review feedback 3b4a522
  14. Commit exec-server: keep malformed-json connections alive 2ed509d
  15. Commit exec-server: trim unused stub dependencies 866743d
#15104
Behavior change Low impact Confirmed

Harden plugin listing/read behavior with resolved feature gating

PR #15104 updates plugin-related flows to use requirement-resolved config for the plugin feature gate, passes config-aware context through skill loading, and makes marketplace discovery tolerate malformed files instead of failing hard.

Why it matters

This change makes plugin commands more reliable for users by preventing a single broken marketplace file from breaking plugin list/read operations, while ensuring plugin enablement is consistently driven by resolved configuration.

Watch state

Watch only. No safe try path is published for this signal yet.

Evidence 4 proof points
  • The PR body states three user-visible objectives: use requirement-resolved config.features as the plugin gate, guard plugin list/read flows behind that gate, and skip bad marketplace.json files instead of failing the entire list.
  • codex-rs/core/src/plugins/marketplace.rs now wraps marketplace loading in a match that warns and continues on failure, and adds a test for skipping failing marketplaces.
  • codex-rs/app-server/src/codex_message_processor.rs changes plugin request handling to load latest config (load_latest_config) before continuing and treats plugin-disabled as a distinct case instead of treating marketplace/config issues as a hard plugin failure.
  • codex-rs/core/src/skills/manager.rs and call sites in codex-rs/core/src/codex.rs, codex-rs/core/src/codex_tests.rs, and codex-rs/core/src/tools/runtimes/shell/unix_escalation.rs now pass config into skills_for_cwd, making behavior follow the active config state.
  1. PR fix: harden plugin feature gating #15104
  2. Commit fix: read plugin feature flag from requirement-resolved config. 62b5fbc
  3. Commit guard plugin/*** with the feature flag. fdd9ab9
  4. Commit Fail open to marketplace.json fail. 2f834ba
  5. Commit Cleanup configured_plugin_states 801f834
#15103
Behavior change Low impact Confirmed

Code-mode update_plan now returns a structured result

This merged PR updates the plan tool path so code-mode calls to tools.update_plan now yield a parseable result payload, and adds a regression test for the nested call shape.

Why it matters

It makes scripted workflow updates in code mode more reliable by allowing the caller to inspect and act on update_plan output instead of treating the call as opaque.

Try path

In code mode, run an update_plan call like const result = await tools.update_plan({ plan: [{ step: 'Run update_plan', status: 'in_progress' }] }); text(JSON.stringify(result)); and check the response parses as JSON.

Expected effect If the behavior is present, code-mode workflows can consume update_plan return data programmatically instead of only relying on side effects.

Evidence 4 proof points
  • PR openai/codex#15103 is explicitly titled "Add update_plan code mode result" and the sole commit is message "Implement code-mode plan result," indicating a focused behavioral change.
  • codex-rs/core/src/tools/handlers/plan.rs changed imports and added PlanToolOutput, with new payload/output/model types (FunctionCallOutputPayload, ResponseInputItem, ToolOutput, serde_json::Value) tied to plan/update handling.
  • codex-rs/core/tests/suite/code_mode.rs adds code_mode_update_plan_nested_tool_result_is_empty_object, explicitly executing tools.update_plan(...) from code mode and asserting the nested tool call is successful plus parseable JSON handling.
  • The change is confined to plan-tool and code-mode test surfaces, matching the PR title and no unrelated files in the bundle.

Caveats

  • The bundle contains truncated patch excerpts, so implementation detail is summarized from available hunks and test intent rather than a full raw diff.
  • This is an incremental internal-API behavior fix with no user-facing UI changes, so operational impact is limited to code-mode automation.
  1. PR Add update_plan code mode result #15103
  2. Commit Implement code-mode plan result e1b3f11
#15077
Behavior change Low impact Confirmed

Realtime handoff output now labels the agent's final message

Merged PR #15077 changes realtime handoff payloads so the emitted assistant text is prefixed with an "Agent Final Message": label instead of sending the raw message body alone.

Why it matters

Clients that display or post-process realtime handoff output now get an explicit label marking the delegated agent's final response. This is a small but user-visible protocol change, and integrations that expect the old raw string format may need to adjust.

Try path

Run a Codex build that includes PR #15077, trigger a realtime conversation handoff, and inspect the emitted conversation.handoff.append payload in either the v1 or Realtime v2 websocket stream.

Expected effect The handoff text payload should begin with "Agent Final Message": followed by a blank line before the assistant's actual message content.

Evidence 3 proof points
  • The PR title and body explicitly say realtime handoff output should be prefixed with the agent final message label for both realtime v1 and v2.
  • methods_common.rs adds a shared AGENT_FINAL_MESSAGE_PREFIX constant and prepends it inside conversation_handoff_append_message, which is the code path that builds the outbound handoff message.
  • Realtime websocket and core conversation tests were updated to expect "Agent Final Message":\n\n... in both output_text and delegated output fields, confirming this is an intentional behavior change rather than a test-only refactor.
  1. PR Add final message prefix to realtime handoff output #15077
  2. Commit Add final message prefix to realtime handoff output 26e0227
#15102
Behavior change Low impact Confirmed

Custom app-server session sources were rolled back

Merged PR #15102 removes the newly introduced custom session_source path from Codex's app-server, protocol schemas, and plugin/skill filtering flow.

Why it matters

This closes off a just-landed integration path for tagging app-server threads as custom products and using that product identity to filter plugins or skills. Most users will see no change, but anyone testing custom app-server product sources loses that behavior for now.

Watch state

Watch for a replacement PR that reintroduces product-aware plugin or skill gating without the reverted custom session-source plumbing.

Evidence 4 proof points
  • The PR title and body explicitly mark this as a revert of PR #15020 because changes were merged before review was finished.
  • The protocol and generated schemas remove SessionSource::Custom(...), drop the custom thread source kind, and delete the --session-source app-server CLI argument.
  • App-server docs now say the default interactive sourceKinds set is only cli and vscode, no longer including custom product sources.
  • Core and app-server changes remove session-source-based skill and curated-plugin filtering helpers, and related plugin-list/plugin-install tests are deleted.

Caveats

  • Because this is a revert of an accidentally merged change, the same area may change again in a follow-up PR with a narrower design.
  1. PR Revert "fix: harden plugin feature gating" #15102
  2. Commit Revert "fix: harden plugin feature gating (#15020)" c5281d1
#15076
Behavior change Low impact Confirmed

Codex TUI now warns at startup when legacy custom prompts are present

Merged PR #15076 adds a startup deprecation notice in the Codex TUI when it finds custom prompts under $CODEX_HOME/prompts, with guidance to migrate them to skills.

Why it matters

Users still relying on legacy custom prompts now get an explicit migration warning before that path disappears. That reduces surprise from the deprecation and points them at the supported replacement instead of leaving the breakage to a later release.

Try path

Run a Codex build that includes PR #15076, place at least one custom prompt file under $CODEX_HOME/prompts, start the TUI, and confirm a deprecation notice appears at startup telling you to convert prompts into skills with $skill-creator.

Expected effect The TUI should show a startup warning only when one or more custom prompts are present, including the detected prompt count and migration guidance toward skills.

Evidence 3 proof points
  • The PR title and body explicitly frame the change as a startup deprecation warning for custom prompts, shown only when prompts are detected in $CODEX_HOME/prompts.
  • The main code change is in tui/src/app.rs, where startup now counts discovered custom prompts and inserts a deprecation notice that tells users to use the $skill-creator skill.
  • The bundle includes a new snapshot showing the rendered warning text, and the PR body says tests were added for present, missing, and empty prompts directories, which supports this as an intentional user-visible behavior change.

Caveats

  • This warning is scoped to the TUI startup path and only appears when Codex detects custom prompts in $CODEX_HOME/prompts.

Watch state Watch for the follow-up release that actually removes custom prompt support, since this PR is an advance warning rather than the removal itself.

  1. PR Add a startup deprecation warning for custom prompts #15076
  2. Commit Warn about deprecated custom prompts at startup 3c62fb0
#15072
Behavior change Low impact Confirmed

Code mode can now pass view_image results straight into image()

Merged PR #15072 makes Codex code mode treat view_image as a structured image producer, so scripts can hand its result directly to image() instead of manually extracting a URL string.

Why it matters

This removes glue code from image-handling scripts and makes local-image flows more predictable. Users can reuse a view_image result directly, with detail metadata preserved when available, instead of reformatting the tool output by hand.

Try path

Run a Codex build that includes PR #15072 in code mode, call const img = await tools.view_image({ path: "/absolute/path/to/local-image.png" }); image(img);, and confirm the script can attach the local image without manually pulling out img.image_url.

Expected effect view_image should return a structured payload that image() accepts directly, so the image is attached successfully and any returned detail hint can flow through with it.

Evidence 3 proof points
  • The PR title and body frame the change as a semantic cleanup: view_image now returns an object with image_url, and image() now accepts either a string or that structured object.
  • The changed tool docs and spec add a typed view_image output schema with image_url and detail, and update the code-mode helper signature from image(string) to image(string | { image_url, detail? }).
  • The bundle includes a dedicated test, code_mode_can_use_view_image_result_with_image_helper, which verifies the direct handoff path, and companion view_image test updates switch non-image inputs from placeholder output to an error, tightening the behavior around invalid files.

Caveats

  • This is scoped to code mode and the view_image tool path; it is not a broad change to every image-related API in Codex.
  1. PR Return image URL from view_image tool #15072
  2. Commit Handle view_image output b48f93d
  3. Commit Restore view image detail handling c0c2b71
  4. Commit Replace debug panic with assertion in code mode test b157203
  5. Commit codex: fix CI failure on PR #15072 1733c87
  6. Commit protocol: remove unused mime_guess dependency ce202b8
#15075
Behavior change Low impact Confirmed

Code mode now surfaces tool failures as exceptions

Merged PR #15075 changes Codex code mode so nested tool-call failures propagate as errors you can catch, instead of being folded into normal tool output.

Why it matters

Code-mode scripts can now distinguish real tool failures from successful results. That makes error handling more predictable and avoids silently treating a broken nested tool call as ordinary output.

Try path

Run a Codex build that includes PR #15075, execute a code-mode script that wraps an invalid nested tool call such as await tools.exec_command({}) in try/catch, and confirm the catch block receives the error.

Expected effect The failing nested tool call should throw into the script's catch path with the tool error message, rather than returning a normal result payload.

Evidence 3 proof points
  • PR #15075 explicitly says it pushes FunctionCallError up to the dispatcher so code mode can surface failures as exceptions.
  • The code-mode protocol adds an error_text field, and runner.cjs rejects the pending call when that field is present, which turns backend tool failures into script exceptions instead of resolved values.
  • The router and parallel tool runtime switch to a code-mode-aware dispatch path, and the added test code_mode_exec_surfaces_handler_errors_as_exceptions verifies a failing tools.exec_command({}) call is caught by try/catch.
  1. PR Propagate tool errors to code mode #15075
  2. Commit Handle code-mode tool errors b2f2dc2
  3. Commit Update tool call error handling e62bd04
  4. Commit Merge remote-tracking branch 'origin/main' into pakrym/add-tests-for-respondtomodel-errors a07b1c7
  5. Commit Fix post-merge code mode worker and custom output shape 68f228c
#15092
Behavior change Low impact Confirmed

Codex CI now stages npm packages from a newer retained release artifact

Merged PR #15092 updates the PR CI workflow so the "Stage npm package" step pulls artifacts from Codex 0.115.0 instead of the older 0.74.0 release whose workflow history appears to have aged out.

Why it matters

This is mainly a contributor-facing reliability fix: PRs should be less likely to fail in the npm-package staging check just because the workflow was pinned to an older release artifact that GitHub no longer retains.

Watch state

Watch for follow-up PRs that remove or automate this pinned release-artifact dependency in the npm-package staging job.

Evidence 3 proof points
  • The PR body explicitly says the failing CI step is fixed by switching from release 0.74.0 to 0.115.0 because the older workflow history was likely reaped.
  • The only changed file is .github/workflows/ci.yml, where CODEX_VERSION for the "Stage npm package" step is bumped from 0.74.0 to 0.115.0.
  • The bundle contains a single merged commit and no product-code changes, which supports reading this as a scoped CI behavior fix rather than a broader feature update.

Caveats

  • This is a CI-only maintenance change, not a new CLI or runtime capability for Codex users.
  • The workflow still depends on a hardcoded retained release artifact, so a similar refresh may be needed again later if that source ages out.
  1. PR fix: try to fix "Stage npm package" step in ci.yml #15092
  2. Commit fix: try to fix "Stage npm package" step in ci.yml ee651d1
#14945
Behavior change Low impact Confirmed

App-server TUI now restores composer history

Merged PR #14945 brings prompt-history recall and persistence to the app-server TUI, so Up/Down navigation and cross-session history now work like the legacy TUI.

Why it matters

Users on the app-server TUI can recover previous prompts instead of hitting a stubbed "not available" path, and new submissions now persist to the shared history file for later sessions.

Try path

Run a Codex build that includes PR #14945 in app-server TUI mode, submit a prompt, then press Up in the composer or restart the session and press Up again to recall earlier entries.

Expected effect Previously entered prompts should be available through composer history in the app-server TUI, including entries persisted in $CODEX_HOME/history.jsonl from earlier sessions.

Evidence 3 proof points
  • The PR description says the app-server TUI previously showed a stub for Up/Down history recall and dropped new submissions from the shared history file, and that this change restores both behaviors locally.
  • codex-rs/tui_app_server/src/app.rs and related TUI files add local handling for GetHistoryEntryRequest and AddToHistory, routing history lookups and writes through codex_core::message_history instead of the unsupported RPC path.
  • Tests were updated to verify async history navigation, per-thread routing of history responses, and bootstrap population of history_log_id / history_entry_count, confirming the restored behavior is exercised end to end.

Caveats

  • The change is scoped to the app-server TUI; the legacy TUI already used this history path.
  • History I/O failures are still logged and swallowed rather than surfaced directly in the UI.
  1. PR feat(tui): restore composer history in app-server tui #14945
  2. Commit feat(tui): restore composer history in app-server tui 4d02185