Commit Graph

136 Commits

  • Reduce js_repl Node version requirement to 22.22.0 (#12857)
    ## Summary
    
    Lower the `js_repl` minimum Node version from `24.13.1` to `22.22.0`.
    
    This updates the enforced minimum in `codex-rs/node-version.txt` and the
    corresponding user-facing `/experimental` description for the JavaScript
    REPL feature.
    
    ## Rationale
    
    The previous `24.13.1` floor was stricter than necessary for `js_repl`.
    I validated the REPL kernel behavior under Node `22.22.0` still works.
    
    ## Why `22.22.0`
    
    `22.22.0` is a current, widely packaged Node 22 release across common
    developer environments and distros, including Homebrew `node@22`, Fedora
    `nodejs22`, Arch `nodejs-lts-jod`, and Debian testing. That makes it a
    better exact floor than guessing at an older `22.x` patch we have not
    validated.
    
    `22.x` is also a maintenance branch that will be supported through April
    2027, where the previous maintenance branch of `20.x` is only supported
    through April of this year.
    
    ## Changes
    
    - Update `codex-rs/node-version.txt` from `24.13.1` to `22.22.0`
    - Update the `/experimental` JavaScript REPL description to say
    `Requires Node >= v22.22.0 installed.`
  • Revert "Add skill approval event/response (#12633)" (#12811)
    This reverts commit https://github.com/openai/codex/pull/12633. We no
    longer need this PR, because we favor sending normal exec command
    approval server request with `additional_permissions` of skill
    permissions instead
  • Remove steer feature flag (#12026)
    All code should go in the direction that steer is enabled
    
    ---------
    
    Co-authored-by: Codex <noreply@openai.com>
  • Enable request_user_input in Default mode (#12735)
    ## Summary
    - allow `request_user_input` in Default collaboration mode as well as
    Plan
    - update the Default-mode instructions to prefer assumptions first and
    use `request_user_input` only when a question is unavoidable
    - update request_user_input and app-server tests to match the new
    Default-mode behavior
    - refactor collaboration-mode availability plumbing into
    `CollaborationModesConfig` for future mode-related flags
    
    ## Codex author
    `codex resume 019c9124-ed28-7c13-96c6-b916b1c97d49`
  • Promote js_repl to experimental with Node requirement (#12712)
    ## Summary
    
    - Promote `js_repl` to an experimental feature that users can enable
    from `/experimental`.
    - Add `js_repl` experimental metadata, including the Node prerequisite
    and activation guidance.
    - Add regression coverage for the feature metadata and the
    `/experimental` popup.
    
    ## What Changed
    
    - Changed `Feature::JsRepl` from `Stage::UnderDevelopment` to
    `Stage::Experimental`.
    - Added experimental metadata for `js_repl` in `core/src/features.rs`:
      - name: `JavaScript REPL`
    - description: calls out interactive website debugging, inline
    JavaScript execution, and the required Node version (`>= v24.13.1`)
    - announcement: tells users to enable it, then start a new chat or
    restart Codex
    - Added a core unit test that verifies:
      - `js_repl` is experimental
      - `js_repl` is disabled by default
    - the hardcoded Node version in the description matches
    `node-version.txt`
    - Added a TUI test that opens the `/experimental` popup and verifies the
    rendered `js_repl` entry includes the Node requirement text.
    
    ## Testing
    
    - `just fmt`
    - `cargo test -p codex-tui`
    - `cargo test -p codex-core` (unit-test phase passed; stopped during the
    long `tests/all.rs` integration suite)
  • Add TUI realtime conversation mode (#12687)
    - Add a hidden `realtime_conversation` feature flag and `/realtime`
    slash command for start/stop live voice sessions.
    - Reuse transcription composer/footer UI for live metering, stream mic
    audio, play assistant audio, render realtime user text events, and
    force-close on feature disable.
    
    ---------
    
    Co-authored-by: Codex <noreply@openai.com>
  • feat(sleep-inhibitor): add Linux and Windows idle-sleep prevention (#11766)
    ## Background
    - follow-up to previous macOS-only PR:
    https://github.com/openai/codex/pull/11711
    - follow-up macOS refactor PR (current structural approach used here):
    https://github.com/openai/codex/pull/12340
    
    ## Summary
    - extend `codex-utils-sleep-inhibitor` with Linux and Windows backends
    while preserving existing macOS behavior
    - Linux backend:
      - use `systemd-inhibit` (`--what=idle --mode=block`) when available
    - fall back to `gnome-session-inhibit` (`--inhibit idle`) when available
      - keep no-op behavior if neither backend exists on host
    - Windows backend:
    - use Win32 power request handles (`PowerCreateRequest` +
    `PowerSetRequest` / `PowerClearRequest`) with
    `PowerRequestSystemRequired`
    - make `prevent_idle_sleep` Experimental on macOS/Linux/Windows; keep
    under development on other targets
    
    ## Testing
    - `just fmt`
    - `cargo test -p codex-utils-sleep-inhibitor`
    - `cargo test -p codex-core features::tests::`
    - `cargo test -p codex-tui chatwidget::tests::`
    - `just fix -p codex-utils-sleep-inhibitor`
    - `just fix -p codex-core`
    
    ## Semantics and API references
    - Goal remains: prevent idle system sleep while a turn is running.
    - Linux:
      - `systemd-inhibit` / login1 inhibitor model:
    -
    https://www.freedesktop.org/software/systemd/man/latest/systemd-inhibit.html
    -
    https://www.freedesktop.org/software/systemd/man/org.freedesktop.login1.html
        - https://systemd.io/INHIBITOR_LOCKS/
      - xdg-desktop-portal Inhibit (relevant for sandboxed apps):
    -
    https://flatpak.github.io/xdg-desktop-portal/docs/doc-org.freedesktop.portal.Inhibit.html
    - Windows:
      - `PowerCreateRequest`:
    -
    https://learn.microsoft.com/en-us/windows/win32/api/winbase/nf-winbase-powercreaterequest
      - `PowerSetRequest`:
    -
    https://learn.microsoft.com/en-us/windows/win32/api/winbase/nf-winbase-powersetrequest
      - `PowerClearRequest`:
    -
    https://learn.microsoft.com/en-us/windows/win32/api/winbase/nf-winbase-powerclearrequest
      - `SetThreadExecutionState` (alternative baseline API):
    -
    https://learn.microsoft.com/en-us/windows/win32/api/winbase/nf-winbase-setthreadexecutionstate
    
    ## Chromium vs this PR
    - Chromium Linux backend:
    -
    https://github.com/chromium/chromium/blob/main/services/device/wake_lock/power_save_blocker/power_save_blocker_linux.cc
    - Chromium Windows backend:
    -
    https://github.com/chromium/chromium/blob/main/services/device/wake_lock/power_save_blocker/power_save_blocker_win.cc
    - Electron powerSaveBlocker entry point:
    -
    https://github.com/electron/electron/blob/main/shell/browser/api/electron_api_power_save_blocker.cc
    
    ## Why we differ from Chromium
    - Linux implementation mechanism:
    - Chromium uses in-process D-Bus APIs plus UI-integrated screen-saver
    suspension.
    - This PR uses command-based inhibitor backends (`systemd-inhibit`,
    `gnome-session-inhibit`) instead of linking a Linux D-Bus client in this
    crate.
    - Reason: keep `codex-utils-sleep-inhibitor` dependency-light and avoid
    Linux CI/toolchain fragility from new native D-Bus linkage, while
    preserving the same runtime intent (hold an inhibitor while a turn
    runs).
    - Linux UI integration scope:
    - Chromium also uses `display::Screen::SuspendScreenSaver()` in its UI
    stack.
    - Codex `codex-rs` does not have that display abstraction in this crate,
    so this PR scopes Linux behavior to process-level sleep inhibition only.
    - Windows wake-lock type breadth:
    - Chromium supports both display/system wake-lock types and extra
    display-specific handling for some pre-Win11 scenarios.
    - Codex’s feature is scoped to turn execution continuity (not forcing
    display on), so this PR uses `PowerRequestSystemRequired` only.
  • feat(core) Introduce Feature::RequestPermissions (#11871)
    ## Summary
    Introduces the initial implementation of Feature::RequestPermissions.
    RequestPermissions allows the model to request that a command be run
    inside the sandbox, with additional permissions, like writing to a
    specific folder. Eventually this will include other rules as well, and
    the ability to persist these permissions, but this PR is already quite
    large - let's get the core flow working and go from there!
    
    <img width="1279" height="541" alt="Screenshot 2026-02-15 at 2 26 22 PM"
    src="https://github.com/user-attachments/assets/0ee3ec0f-02ec-4509-91a2-809ac80be368"
    />
    
    ## Testing
    - [x] Added tests
    - [x] Tested locally
    - [x] Feature
  • Add skill approval event/response (#12633)
    Set the stage for skill-level permission approval in addition to
    command-level.
    
    Behind a feature flag.
  • voice transcription (#3381)
    Adds voice transcription on press-and-hold of spacebar.
    
    
    https://github.com/user-attachments/assets/85039314-26f3-46d1-a83b-8c4a4a1ecc21
    
    ---------
    
    Co-authored-by: Codex <199175422+chatgpt-codex-connector[bot]@users.noreply.github.com>
    Co-authored-by: David Zbarsky <zbarsky@openai.com>
  • remove feature flag collaboration modes (#12028)
    All code should go in the direction that steer is enabled
    
    ---------
    
    Co-authored-by: Codex <noreply@openai.com>
  • chore: rename memory feature flag (#12580)
    `memory_tool` -> `memories`
  • chore: move config diagnostics out of codex-core (#12427)
    ## Why
    
    Compiling `codex-rs/core` is a bottleneck for local iteration, so this
    change continues the ongoing extraction of config-related functionality
    out of `codex-core` and into `codex-config`.
    
    The goal is not just to move code, but to reduce `codex-core` ownership
    and indirection so more code depends on `codex-config` directly.
    
    ## What Changed
    
    - Moved config diagnostics logic from
    `core/src/config_loader/diagnostics.rs` into
    `config/src/diagnostics.rs`.
    - Updated `codex-core` to use `codex-config` diagnostics types/functions
    directly where possible.
    - Removed the `core/src/config_loader/diagnostics.rs` shim module
    entirely; the remaining `ConfigToml`-specific calls are in
    `core/src/config_loader/mod.rs`.
    - Moved `CONFIG_TOML_FILE` into `codex-config` and updated existing
    references to use `codex_config::CONFIG_TOML_FILE` directly.
    - Added a direct `codex-config` dependency to `codex-cli` for its
    `CONFIG_TOML_FILE` use.
  • Skip removed features during metrics emission (#12253)
    Summary
    - avoid emitting metrics for features marked as `Stage::Removed`
    - keep feature metrics aligned with active and planned states only
    
    Testing
    - Not run (not requested)
  • Update docs links for feature flag notice (#12164)
    Summary
    - replace the stale `docs/config.md#feature-flags` reference in the
    legacy feature notice with the canonical published URL
    - align the deprecation notice test to expect the new link
    
    This addresses #12123
  • feat(core): zsh exec bridge (#12052)
    zsh fork PR stack:
    - https://github.com/openai/codex/pull/12051 
    - https://github.com/openai/codex/pull/12052 👈 
    
    ### Summary
    This PR introduces a feature-gated native shell runtime path that routes
    shell execution through a patched zsh exec bridge, removing MCP-specific
    behavior from the shell hot path while preserving existing
    CommandExecution lifecycle semantics.
    
    When shell_zsh_fork is enabled, shell commands run via patched zsh with
    per-`execve` interception through EXEC_WRAPPER. Core receives wrapper
    IPC requests over a Unix socket, applies existing approval policy, and
    returns allow/deny before the subcommand executes.
    
    ### What’s included
    **1) New zsh exec bridge runtime in core**
    - Wrapper-mode entrypoint (maybe_run_zsh_exec_wrapper_mode) for
    EXEC_WRAPPER invocations.
    - Per-execution Unix-socket IPC handling for wrapper requests/responses.
    - Approval callback integration using existing core approval
    orchestration.
    - Streaming stdout/stderr deltas to existing command output event
    pipeline.
    - Error handling for malformed IPC, denial/abort, and execution
    failures.
    
    **2) Session lifecycle integration**
    SessionServices now owns a `ZshExecBridge`.
    Session startup initializes bridge state; shutdown tears it down
    cleanly.
    
    **3) Shell runtime routing (feature-gated)**
    When `shell_zsh_fork` is enabled:
    - Build execution env/spec as usual.
    - Add wrapper socket env wiring.
    - Execute via `zsh_exec_bridge.execute_shell_request(...)` instead of
    the regular shell path.
    - Non-zsh-fork behavior remains unchanged.
    
    **4) Config + feature wiring**
    - Added `Feature::ShellZshFork` (under development).
    - Added config support for `zsh_path` (optional absolute path to patched
    zsh):
    - `Config`, `ConfigToml`, `ConfigProfile`, overrides, and schema.
    - Session startup validates that `zsh_path` exists/usable when zsh-fork
    is enabled.
    - Added startup test for missing `zsh_path` failure mode.
    
    **5) Seatbelt/sandbox updates for wrapper IPC**
    - Extended seatbelt policy generation to optionally allow outbound
    connection to explicitly permitted Unix sockets.
    - Wired sandboxing path to pass wrapper socket path through to seatbelt
    policy generation.
    - Added/updated seatbelt tests for explicit socket allow rule and
    argument emission.
    
    **6) Runtime entrypoint hooks**
    - This allows the same binary to act as the zsh wrapper subprocess when
    invoked via `EXEC_WRAPPER`.
    
    **7) Tool selection behavior**
    - ToolsConfig now prefers ShellCommand type when shell_zsh_fork is
    enabled.
    - Added test coverage for precedence with unified-exec enabled.
  • chore: rm remote models fflag (#11699)
    rm `remote_models` feature flag.
    
    We see issues like #11527 when a user has `remote_models` disabled, as
    we always use the default fallback `ModelInfo`. This causes issues with
    model performance.
    
    Builds on #11690, which helps by warning the user when they are using
    the default fallback. This PR will make that happen much less frequently
    as an accidental consequence of disabling `remote_models`.
  • chore: clarify web_search deprecation notices and consolidate tests (#11224)
    follow up to #10406, clarify default-enablement of web_search.
    
    also consolidate pseudo-redundant tests
    
    Tests pass
  • chore(core) rm Feature::RequestRule (#11866)
    ## Summary
    This feature is now reasonably stable, let's remove it so we can
    simplify our upcoming iterations here.
    
    ## Testing 
    - [x] Existing tests pass
  • chore: rename collab feature flag key to multi_agent (#11918)
    Summary
    - rename the collab feature key to multi_agent while keeping the Feature
    enum unchanged
    - add legacy alias support so both "multi_agent" and "collab" map to the
    same feature
    - cover the alias behavior with a new unit test
  • feat(tui): prevent macOS idle sleep while turns run (#11711)
    ## Summary
    - add a shared `codex-core` sleep inhibitor that uses native macOS IOKit
    assertions (`IOPMAssertionCreateWithName` / `IOPMAssertionRelease`)
    instead of spawning `caffeinate`
    - wire sleep inhibition to turn lifecycle in `tui` (`TurnStarted`
    enables; `TurnComplete` and abort/error finalization disable)
    - gate this behavior behind a `/experimental` feature toggle
    (`[features].prevent_idle_sleep`) instead of a dedicated `[tui]` config
    flag
    - expose the toggle in `/experimental` on macOS; keep it under
    development on other platforms
    - keep behavior no-op on non-macOS targets
    
    <img width="1326" height="577" alt="image"
    src="https://github.com/user-attachments/assets/73fac06b-97ae-46a2-800a-30f9516cf8a3"
    />
    
    ## Testing
    - `cargo check -p codex-core -p codex-tui`
    - `cargo test -p codex-core sleep_inhibitor::tests -- --nocapture`
    - `cargo test -p codex-core
    tui_config_missing_notifications_field_defaults_to_enabled --
    --nocapture`
    - `cargo test -p codex-core prevent_idle_sleep_is_ -- --nocapture`
    
    ## Semantics and API references
    - This PR targets `caffeinate -i` semantics: prevent *idle system sleep*
    while allowing display idle sleep.
    - `caffeinate -i` mapping in Apple open source (`assertionMap`):
      - `kIdleAssertionFlag -> kIOPMAssertionTypePreventUserIdleSystemSleep`
    - Source:
    https://github.com/apple-oss-distributions/PowerManagement/blob/PowerManagement-1846.60.12/caffeinate/caffeinate.c#L52-L54
    - Apple IOKit docs for assertion types and API:
    -
    https://developer.apple.com/documentation/iokit/iopmlib_h/iopmassertiontypes
    -
    https://developer.apple.com/documentation/iokit/1557092-iopmassertioncreatewithname
      - https://developer.apple.com/library/archive/qa/qa1340/_index.html
    
    ## Codex Electron vs this PR (full stack path)
    - Codex Electron app requests sleep blocking with
    `powerSaveBlocker.start("prevent-app-suspension")`:
    -
    https://github.com/openai/codex/blob/main/codex/codex-vscode/electron/src/electron-message-handler.ts
    - Electron maps that string to Chromium wake lock type
    `kPreventAppSuspension`:
    -
    https://github.com/electron/electron/blob/main/shell/browser/api/electron_api_power_save_blocker.cc
    - Chromium macOS backend maps wake lock types to IOKit assertion
    constants and calls IOKit:
      - `kPreventAppSuspension -> kIOPMAssertionTypeNoIdleSleep`
    - `kPreventDisplaySleep / kPreventDisplaySleepAllowDimming ->
    kIOPMAssertionTypeNoDisplaySleep`
    -
    https://github.com/chromium/chromium/blob/main/services/device/wake_lock/power_save_blocker/power_save_blocker_mac.cc
    
    ## Why this PR uses a different macOS constant name
    - This PR uses `"PreventUserIdleSystemSleep"` directly, via
    `IOPMAssertionCreateWithName`, in
    `codex-rs/core/src/sleep_inhibitor.rs`.
    - Apple’s IOKit header documents `kIOPMAssertionTypeNoIdleSleep` as
    deprecated and recommends `kIOPMAssertPreventUserIdleSystemSleep` /
    `kIOPMAssertionTypePreventUserIdleSystemSleep`:
    -
    https://github.com/apple-oss-distributions/IOKitUser/blob/IOKitUser-100222.60.2/pwr_mgt.subproj/IOPMLib.h#L1000-L1030
    - So Chromium and this PR are using different constant names, but
    semantically equivalent idle-system-sleep prevention behavior.
    
    ## Future platform support
    The architecture is intentionally set up for multi-platform extensions:
    - UI code (`tui`) only calls `SleepInhibitor::set_turn_running(...)` on
    turn lifecycle boundaries.
    - Platform-specific behavior is isolated in
    `codex-rs/core/src/sleep_inhibitor.rs` behind `cfg(...)` blocks.
    - Feature exposure is centralized in `core/src/features.rs` and surfaced
    via `/experimental`.
    - Adding new OS backends should not require additional TUI wiring; only
    the backend internals and feature stage metadata need to change.
    
    Potential follow-up implementations:
    - Windows:
    - Add a backend using Win32 power APIs
    (`SetThreadExecutionState(ES_CONTINUOUS | ES_SYSTEM_REQUIRED)` as
    baseline).
    - Optionally move to `PowerCreateRequest` / `PowerSetRequest` /
    `PowerClearRequest` for richer assertion semantics.
    - Linux:
    - Add a backend using logind inhibitors over D-Bus
    (`org.freedesktop.login1.Manager.Inhibit` with `what="sleep"`).
      - Keep a no-op fallback where logind/D-Bus is unavailable.
    
    This PR keeps the cross-platform API surface minimal so future PRs can
    add Windows/Linux support incrementally with low churn.
    
    ---------
    
    Co-authored-by: jif-oai <jif@openai.com>
  • Added a test to verify that feature flags that are enabled by default are stable (#11275)
    We've had a few cases recently where someone enabled a feature flag for
    a feature that's still under development or experimental. This test
    should prevent this.
  • Add new apps_mcp_gateway (#11630)
    Adds a new apps_mcp_gateway flag to route Apps MCP calls through
    https://api.openai.com/v1/connectors/mcp/ when enabled, while keeping
    legacy MCP routing as default.
  • Add js_repl_tools_only model and routing restrictions (#10671)
    # External (non-OpenAI) Pull Request Requirements
    
    Before opening this Pull Request, please read the dedicated
    "Contributing" markdown file or your PR may be closed:
    https://github.com/openai/codex/blob/main/docs/contributing.md
    
    If your PR conforms to our contribution guidelines, replace this text
    with a detailed and high quality description of your changes.
    
    Include a link to a bug report or enhancement request.
    
    
    #### [git stack](https://github.com/magus/git-stack-cli)
    -  `1` https://github.com/openai/codex/pull/10674
    -  `2` https://github.com/openai/codex/pull/10672
    - 👉 `3` https://github.com/openai/codex/pull/10671
    -  `4` https://github.com/openai/codex/pull/10673
    -  `5` https://github.com/openai/codex/pull/10670
  • Consolidate search_tool feature into apps (#11509)
    ## Summary
    - Remove `Feature::SearchTool` and the `search_tool` config key from the
    feature registry/schema.
    - Gate `search_tool_bm25` exposure via `Feature::Apps` in
    `core/src/tools/spec.rs`.
    - Update MCP selection logic in `core/src/codex.rs` to use
    `Feature::Apps` for search-tool behavior.
    - Update `core/tests/suite/search_tool.rs` to enable `Feature::Apps`.
    - Regenerate `core/config.schema.json` via `just write-config-schema`.
    
    ## Testing
    - `just fmt`
    - `cargo test -p codex-core --test all suite::search_tool::`
    
    ## Tickets
    - None
  • Add feature-gated freeform js_repl core runtime (#10674)
    ## Summary
    
    This PR adds an **experimental, feature-gated `js_repl` core runtime**
    so models can execute JavaScript in a persistent REPL context across
    tool calls.
    
    The implementation integrates with existing feature gating, tool
    registration, prompt composition, config/schema docs, and tests.
    
    ## What changed
    
    - Added new experimental feature flag: `features.js_repl`.
    - Added freeform `js_repl` tool and companion `js_repl_reset` tool.
    - Gated tool availability behind `Feature::JsRepl`.
    - Added conditional prompt-section injection for JS REPL instructions
    via marker-based prompt processing.
    - Implemented JS REPL handlers, including freeform parsing and pragma
    support (timeout/reset controls).
    - Added runtime resolution order for Node:
      1. `CODEX_JS_REPL_NODE_PATH`
      2. `js_repl_node_path` in config
      3. `PATH`
    - Added JS runtime assets/version files and updated docs/schema.
    
    ## Why
    
    This enables richer agent workflows that require incremental JavaScript
    execution with preserved state, while keeping rollout safe behind an
    explicit feature flag.
    
    ## Testing
    
    Coverage includes:
    
    - Feature-flag gating behavior for tool exposure.
    - Freeform parser/pragma handling edge cases.
    - Runtime behavior (state persistence across calls and top-level `await`
    support).
    
    ## Usage
    
    ```toml
    [features]
    js_repl = true
    ```
    
    Optional runtime override:
    
    - `CODEX_JS_REPL_NODE_PATH`, or
    - `js_repl_node_path` in config.
    
    #### [git stack](https://github.com/magus/git-stack-cli)
    - 👉 `1` https://github.com/openai/codex/pull/10674
    -  `2` https://github.com/openai/codex/pull/10672
    -  `3` https://github.com/openai/codex/pull/10671
    -  `4` https://github.com/openai/codex/pull/10673
    -  `5` https://github.com/openai/codex/pull/10670
  • Promote Windows Sandbox (#11341)
    1. Move Windows Sandbox NUX to right after trust directory screen
    2. Don't offer read-only as an option in Sandbox NUX.
    Elevated/Legacy/Quit
    3. Don't allow new untrusted directories. It's trust or quit
    4. move experimental sandbox features to `[windows]
    sandbox="elevated|unelevatd"`
    5. Copy tweaks = elevated -> default, non-elevated -> non-admin
  • feat(core): promote Linux bubblewrap sandbox to Experimental (#11381)
    ## Summary
    - Promote `use_linux_sandbox_bwrap` to `Stage::Experimental` on Linux so
    users see it in `/experimental` and get a startup nudge.
  • memories: add extraction and prompt module foundation (#11200)
    ## Summary
    - add the new `core/src/memories` module (phase-one parsing, rollout
    filtering, storage, selection, prompts)
    - add Askama-backed memory templates for stage-one input/system and
    consolidation prompts
    - add module tests for parsing, filtering, path bucketing, and summary
    maintenance
    
    ## Testing
    - just fmt
    - cargo test -p codex-core --lib memories::
  • fix(feature) UnderDevelopment feature must be off (#11242)
    ## Summary
    1. Bump RemoteModels to Stable
    2. Assert that all UnderDevelopment features are off by default
    
    ## Testing
    - [x] Added unit test
  • feat: search_tool (#10657)
    **Why We Did This**
    - The goal is to reduce MCP tool context pollution by not exposing the
    full MCP tool list up front
    - It forces an explicit discovery step (`search_tool_bm25`) so the model
    narrows tool scope before making MCP calls, which helps relevance and
    lowers prompt/tool clutter.
    
    **What It Changed**
    - Added a new experimental feature flag `search_tool` in
    `core/src/features.rs:90` and `core/src/features.rs:430`.
    - Added config/schema support for that flag in
    `core/config.schema.json:214` and `core/config.schema.json:1235`.
    - Added BM25 dependency (`bm25`) in `Cargo.toml:129` and
    `core/Cargo.toml:23`.
    - Added new tool handler `search_tool_bm25` in
    `core/src/tools/handlers/search_tool_bm25.rs:18`.
    - Registered the handler and tool spec in
    `core/src/tools/handlers/mod.rs:11` and `core/src/tools/spec.rs:780` and
    `core/src/tools/spec.rs:1344`.
    - Extended `ToolsConfig` to carry `search_tool` enablement in
    `core/src/tools/spec.rs:32` and `core/src/tools/spec.rs:56`.
    - Injected dedicated developer instructions for tool-discovery workflow
    in `core/src/codex.rs:483` and `core/src/codex.rs:1976`, using
    `core/templates/search_tool/developer_instructions.md:1`.
    - Added session state to store one-shot selected MCP tools in
    `core/src/state/session.rs:27` and `core/src/state/session.rs:131`.
    - Added filtering so when feature is enabled, only selected MCP tools
    are exposed on the next request (then consumed) in
    `core/src/codex.rs:3800` and `core/src/codex.rs:3843`.
    - Added E2E suite coverage for
    enablement/instructions/hide-until-search/one-turn-selection in
    `core/tests/suite/search_tool.rs:72`,
    `core/tests/suite/search_tool.rs:109`,
    `core/tests/suite/search_tool.rs:147`, and
    `core/tests/suite/search_tool.rs:218`.
    - Refactored test helper utilities to support config-driven tool
    collection in `core/tests/suite/tools.rs:281`.
    
    **Net Behavioral Effect**
    - With `search_tool` **off**: existing MCP behavior (tools exposed
    normally).
    - With `search_tool` **on**: MCP tools start hidden, model must call
    `search_tool_bm25`, and only returned `selected_tools` are available for
    the next model call.
  • Support alternative websocket API (#10861)
    **Test plan**
    
    ```
    cargo build -p codex-cli && RUST_LOG='codex_api::endpoint::responses_websocket=trace,codex_core::client=debug,codex_core::codex=debug' \
      ./target/debug/codex \
        --enable responses_websockets_v2 \
        --profile byok \
        --full-auto
    ```
  • Removed "exec_policy" feature flag (#10851)
    This is no longer needed because it's on by default
  • feat: add memory tool (#10637)
    Add a tool for memory to retrieve a full memory based on the memory ID
  • Make steer stable by default (#10690)
    Promotes the Steer feature from Experimental to Stable and enables it by
    default.
    
    ## What is Steer mode?
    
    Steer mode changes how message submission works in the TUI:
    
    - **With Steer enabled (new default)**: 
      - `Enter` submits messages immediately, even when a task is running
    - `Tab` queues messages when a task is running (allows building up a
    queue)
      
    - **With Steer disabled (old behavior)**:
      - `Enter` queues messages when a task is running
      - This preserves the previous "queue while a task is running" behavior
    
    ## How Steer vs Queue work
    
    The key difference is in the submission behavior:
    
    1. **Steer mode** (`steer_enabled = true`):
    - Enter → `InputResult::Submitted` → sends immediately via
    `submit_user_message()`
    - Tab → `InputResult::Queued` → queues via `queue_user_message()` if a
    task is running
    - This gives users direct control: Enter for immediate submission, Tab
    for queuing
    
    2. **Queue mode** (`steer_enabled = false`, previous default):
    - Enter → `InputResult::Queued` → always queues when a task is running
       - Tab → `InputResult::Queued` → queues when a task is running
    - This preserves the original behavior where Enter respects the running
    task queue
    
    ## Implementation details
    
    The behavior is controlled in
    `ChatComposer::handle_key_event_without_popup()`:
    - When `steer_enabled` is true, Enter calls `handle_submission(false)`
    (submit immediately)
    - When `steer_enabled` is false, Enter calls `handle_submission(true)`
    (queue)
    
    See `codex-rs/tui/src/bottom_pane/chat_composer.rs` for the
    implementation.
    
    ## Documentation
    
    For more details on the chat composer behavior, see:
    - [TUI Chat Composer documentation](docs/tui-chat-composer.md)
    - Feature flag definition: `codex-rs/core/src/features.rs`
  • feat(linux-sandbox): add bwrap support (#9938)
    ## Summary
    This PR introduces a gated Bubblewrap (bwrap) Linux sandbox path. The
    curent Linux sandbox path relies on in-process restrictions (including
    Landlock). Bubblewrap gives us a more uniform filesystem isolation
    model, especially explicit writable roots with the option to make some
    directories read-only and granular network controls.
    
    This is behind a feature flag so we can validate behavior safely before
    making it the default.
    
    - Added temporary rollout flag:
      - `features.use_linux_sandbox_bwrap`
    - Preserved existing default path when the flag is off.
    - In Bubblewrap mode:
    - Added internal retry without /proc when /proc mount is not permitted
    by the host/container.
  • feat: land unified_exec (#10641)
    Land `unified_exec` for all non-windows OS
  • Cleanup collaboration mode variants (#10404)
    ## Summary
    
    This PR simplifies collaboration modes to the visible set `default |
    plan`, while preserving backward compatibility for older partners that
    may still send legacy mode
    names.
    
    Specifically:
    - Renames the old Code behavior to **Default**.
    - Keeps **Plan** as-is.
    - Removes **Custom** mode behavior (fallbacks now resolve to Default).
    - Keeps `PairProgramming` and `Execute` internally for compatibility
    plumbing, while removing them from schema/API and UI visibility.
    - Adds legacy input aliasing so older clients can still send old mode
    names.
    
    ## What Changed
    
    1. Mode enum and compatibility
    - `ModeKind` now uses `Plan` + `Default` as active/public modes.
    - `ModeKind::Default` deserialization accepts legacy values:
      - `code`
      - `pair_programming`
      - `execute`
      - `custom`
    - `PairProgramming` and `Execute` variants remain in code but are hidden
    from protocol/schema generation.
    - `Custom` variant is removed; previous custom fallbacks now map to
    `Default`.
    
    2. Collaboration presets and templates
    - Built-in presets now return only:
      - `Plan`
      - `Default`
    - Template rename:
      - `core/templates/collaboration_mode/code.md` -> `default.md`
    - `execute.md` and `pair_programming.md` remain on disk but are not
    surfaced in visible preset lists.
    
    3. TUI updates
    - Updated user-facing naming and prompts from “Code” to “Default”.
    - Updated mode-cycle and indicator behavior to reflect only visible
    `Plan` and `Default`.
    - Updated corresponding tests and snapshots.
    
    4. request_user_input behavior
    - `request_user_input` remains allowed only in `Plan` mode.
    - Rejection messaging now consistently treats non-plan modes as
    `Default`.
    
    5. Schemas
    - Regenerated config and app-server schemas.
    - Public schema types now advertise mode values as:
      - `plan`
      - `default`
    
    ## Backward Compatibility Notes
    
    - Incoming legacy mode names (`code`, `pair_programming`, `execute`,
    `custom`) are accepted and coerced to `default`.
    - Outgoing/public schema surfaces intentionally expose only `plan |
    default`.
    - This allows tolerant ingestion of older partner payloads while
    standardizing new integrations on the reduced mode set.
    
    ## Codex author
    `codex fork 019c1fae-693b-7840-b16e-9ad38ea0bd00`
  • fix: clarify deprecation message for features.web_search (#10406)
    clarify that the new `web_search` is not a feature flag under
    `[features]` in the deprecation CTA
  • chore(features) Personality => Stable (#10310)
    ## Summary
    Bump `/personality` to stable
    
    ## Testing
     - [x] unit tests pass
  • enable plan mode (#10313)
    # External (non-OpenAI) Pull Request Requirements
    
    Before opening this Pull Request, please read the dedicated
    "Contributing" markdown file or your PR may be closed:
    https://github.com/openai/codex/blob/main/docs/contributing.md
    
    If your PR conforms to our contribution guidelines, replace this text
    with a detailed and high quality description of your changes.
    
    Include a link to a bug report or enhancement request.
  • chore(features) remove Experimental tag from UTF8 (#10296)
    ## Summary
    This has been default on for some time, it should now be the default.
    
    ## Testing
    - [x] Existing tests pass