Commit Graph

85 Commits

  • 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
  • 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`
  • Agent jobs (spawn_agents_on_csv) + progress UI (#10935)
    ## Summary
    - Add agent job support: spawn a batch of sub-agents from CSV, auto-run,
    auto-export, and store results in SQLite.
    - Simplify workflow: remove run/resume/get-status/export tools; spawn is
    deterministic and completes in one call.
    - Improve exec UX: stable, single-line progress bar with ETA; suppress
    sub-agent chatter in exec.
    
    ## Why
    Enables map-reduce style workflows over arbitrarily large repos using
    the existing Codex orchestrator. This addresses review feedback about
    overly complex job controls and non-deterministic monitoring.
    
    ## Demo (progress bar)
    ```
    ./codex-rs/target/debug/codex exec \
      --enable collab \
      --enable sqlite \
      --full-auto \
      --progress-cursor \
      -c agents.max_threads=16 \
      -C /Users/daveaitel/code/codex \
      - <<'PROMPT'
    Create /tmp/agent_job_progress_demo.csv with columns: path,area and 30 rows:
    path = item-01..item-30, area = test.
    
    Then call spawn_agents_on_csv with:
    - csv_path: /tmp/agent_job_progress_demo.csv
    - instruction: "Run `python - <<'PY'` to sleep a random 0.3–1.2s, then output JSON with keys: path, score (int). Set score = 1."
    - output_csv_path: /tmp/agent_job_progress_demo_out.csv
    PROMPT
    ```
    
    ## Review feedback addressed
    - Auto-start jobs on spawn; removed run/resume/status/export tools.
    - Auto-export on success.
    - More descriptive tool spec + clearer prompts.
    - Avoid deadlocks on spawn failure; pending/running handled safely.
    - Progress bar no longer scrolls; stable single-line redraw.
    
    ## Tests
    - `cd codex-rs && cargo test -p codex-exec`
    - `cd codex-rs && cargo build -p codex-cli`
  • 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(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>
  • chore: rename memory feature flag (#12580)
    `memory_tool` -> `memories`
  • feat(tui): syntax highlighting via syntect with theme picker (#11447)
    ## Summary
    
    Adds syntax highlighting to the TUI for fenced code blocks in markdown
    responses and file diffs, plus a `/theme` command with live preview and
    persistent theme selection. Uses syntect (~250 grammars, 32 bundled
    themes, ~1 MB binary cost) — the same engine behind `bat`, `delta`, and
    `xi-editor`. Includes guardrails for large inputs, graceful fallback to
    plain text, and SSH-aware clipboard integration for the `/copy` command.
    
    <img width="1554" height="1014" alt="image"
    src="https://github.com/user-attachments/assets/38737a79-8717-4715-b857-94cf1ba59b85"
    />
    
    <img width="2354" height="1374" alt="image"
    src="https://github.com/user-attachments/assets/25d30a00-c487-4af8-9cb6-63b0695a4be7"
    />
    
    ## Problem
    
    Code blocks in the TUI (markdown responses and file diffs) render
    without syntax highlighting, making it hard to scan code at a glance.
    Users also have no way to pick a color theme that matches their terminal
    aesthetic.
    
    ## Mental model
    
    The highlighting system has three layers:
    
    1. **Syntax engine** (`render::highlight`) -- a thin wrapper around
    syntect + two-face. It owns a process-global `SyntaxSet` (~250 grammars)
    and a `RwLock<Theme>` that can be swapped at runtime. All public entry
    points accept `(code, lang)` and return ratatui `Span`/`Line` vectors or
    `None` when the language is unrecognized or the input exceeds safety
    guardrails.
    
    2. **Rendering consumers** -- `markdown_render` feeds fenced code blocks
    through the engine; `diff_render` highlights Add/Delete content as a
    whole file and Update hunks per-hunk (preserving parser state across
    hunk lines). Both callers fall back to plain unstyled text when the
    engine returns `None`.
    
    3. **Theme lifecycle** -- at startup the config's `tui.theme` is
    resolved to a syntect `Theme` via `set_theme_override`. At runtime the
    `/theme` picker calls `set_syntax_theme` to swap themes live; on cancel
    it restores the snapshot taken at open. On confirm it persists `[tui]
    theme = "..."` to config.toml.
    
    ## Non-goals
    
    - Inline diff highlighting (word-level change detection within a line).
    - Semantic / LSP-backed highlighting.
    - Theme authoring tooling; users supply standard `.tmTheme` files.
    
    ## Tradeoffs
    
    | Decision | Upside | Downside |
    | ------------------------------------------------ |
    ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
    |
    -----------------------------------------------------------------------------------------------------------------------
    |
    | syntect over tree-sitter / arborium | ~1 MB binary increase for ~250
    grammars + 32 themes; battle-tested crate powering widely-used tools
    (`bat`, `delta`, `xi-editor`). tree-sitter would add ~12 MB for 20-30
    languages or ~35 MB for full coverage. | Regex-based; less structurally
    accurate than tree-sitter for some languages (e.g. language injections
    like JS-in-HTML). |
    | Global `RwLock<Theme>` | Enables live `/theme` preview without
    threading Theme through every call site | Lock contention risk
    (mitigated: reads vastly outnumber writes, single UI thread) |
    | Skip background / italic / underline from themes | Terminal BG
    preserved, avoids ugly rendering on some themes | Themes that rely on
    these properties lose fidelity |
    | Guardrails: 512 KB / 10k lines | Prevents pathological stalls on huge
    diffs or pastes | Very large files render without color |
    
    ## Architecture
    
    ```
    config.toml  ─[tui.theme]─>  set_theme_override()  ─>  THEME (RwLock)
                                                                  │
                      ┌───────────────────────────────────────────┘
                      │
      markdown_render ─── highlight_code_to_lines(code, lang) ─> Vec<Line>
      diff_render     ─── highlight_code_to_styled_spans(code, lang) ─> Option<Vec<Vec<Span>>>
                      │
                      │   (None ⇒ plain text fallback)
                      │
      /theme picker   ─── set_syntax_theme(theme)    // live preview swap
                      ─── current_syntax_theme()      // snapshot for cancel
                      ─── resolve_theme_by_name(name) // lookup by kebab-case
    ```
    
    Key files:
    
    - `tui/src/render/highlight.rs` -- engine, theme management, guardrails
    - `tui/src/diff_render.rs` -- syntax-aware diff line wrapping
    - `tui/src/theme_picker.rs` -- `/theme` command builder
    - `tui/src/bottom_pane/list_selection_view.rs` -- side content panel,
    callbacks
    - `core/src/config/types.rs` -- `Tui::theme` field
    - `core/src/config/edit.rs` -- `syntax_theme_edit()` helper
    
    ## Observability
    
    - `tracing::warn` when a configured theme name cannot be resolved.
    - `Config::startup_warnings` surfaces the same message as a TUI banner.
    - `tracing::error` when persisting theme selection fails.
    
    ## Tests
    
    - Unit tests in `highlight.rs`: language coverage, fallback behavior,
    CRLF stripping, style conversion, guardrail enforcement, theme name
    mapping exhaustiveness.
    - Unit tests in `diff_render.rs`: snapshot gallery at multiple terminal
    sizes (80x24, 94x35, 120x40), syntax-highlighted wrapping, large-diff
    guardrail, rename-to-different-extension highlighting, parser state
    preservation across hunk lines.
    - Unit tests in `theme_picker.rs`: preview rendering (wide + narrow),
    dim overlay on deletions, subtitle truncation, cancel-restore, fallback
    for unavailable configured theme.
    - Unit tests in `list_selection_view.rs`: side layout geometry, stacked
    fallback, buffer clearing, cancel/selection-changed callbacks.
    - Integration test in `lib.rs`: theme warning uses the final
    (post-resume) config.
    
    ## Cargo Deny: Unmaintained Dependency Exceptions
    
    This PR adds two `cargo deny` advisory exceptions for transitive
    dependencies pulled in by `syntect v5.3.0`:
    
    | Advisory | Crate | Status |
    |----------|-------|--------|
    | RUSTSEC-2024-0320 | `yaml-rust` | Unmaintained (maintainer
    unreachable) |
    | RUSTSEC-2025-0141 | `bincode` | Unmaintained (development ceased;
    v1.3.3 considered complete) |
    
    **Why this is safe in our usage:**
    
    - Neither advisory describes a known security vulnerability. Both are
    "unmaintained" notices only.
    - `bincode` is used by syntect to deserialize pre-compiled syntax sets.
    Again, these are **static vendored artifacts** baked into the binary at
    build time. No user-supplied bincode data is ever deserialized. - Attack
    surface is zero for both crates; exploitation would require a
    supply-chain compromise of our own build artifacts.
    - These exceptions can be removed when syntect migrates to `yaml-rust2`
    and drops `bincode`, or when alternative crates are available upstream.
  • profile-level model_catalog_json overrie (#12410)
    enable `model-catalog_json` config value on `ConfigProfile` as well
  • Add experimental realtime websocket backend prompt override (#12418)
    - add top-level `experimental_realtime_ws_backend_prompt` config key
    (experimental / do not use) and include it in config schema
    - apply the override only to `Op::RealtimeConversation` websocket
    `backend_prompt`, with config + realtime tests
  • Improve Plan mode reasoning selection flow (#12303)
    Addresses https://github.com/openai/codex/issues/11013
    
    ## Summary
    - add a Plan implementation path in the TUI that lets users choose
    reasoning before switching to Default mode and implementing
    - add Plan-mode reasoning scope handling (Plan-only override vs
    all-modes default), including config/schema/docs plumbing for
    `plan_mode_reasoning_effort`
    - remove the hardcoded Plan preset medium default and make the reasoning
    popup reflect the active Plan override as `(current)`
    - split the collaboration-mode switch notification UI hint into #12307
    to keep this diff focused
    
    If I have `plan_mode_reasoning_effort = "medium"` set in my
    `config.toml`:
    <img width="699" height="127" alt="Screenshot 2026-02-20 at 6 59 37 PM"
    src="https://github.com/user-attachments/assets/b33abf04-6b7a-49ed-b2e9-d24b99795369"
    />
    
    If I don't have `plan_mode_reasoning_effort` set in my `config.toml`:
    <img width="704" height="129" alt="Screenshot 2026-02-20 at 7 01 51 PM"
    src="https://github.com/user-attachments/assets/88a086d4-d2f1-49c7-8be4-f6f0c0fa1b8d"
    />
    
    ## Codex author
    `codex resume 019c78a2-726b-7fe3-adac-3fa4523dcc2a`
  • Add experimental realtime websocket URL override (#12416)
    - add top-level `experimental_realtime_ws_base_url` config key
    (experimental / do not use) and include it in config schema
    - apply the override only to `Op::RealtimeConversation` websocket
    transport, with config + realtime tests
  • clarify model_catalog_json only applied on startup (#12379)
    # 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.
  • [apps] Implement apps configs. (#12086)
    - [x] Implement apps configs.
  • fix(network-proxy): add unix socket allow-all and update seatbelt rules (#11368)
    ## Summary
    Adds support for a Unix socket escape hatch so we can bypass socket
    allowlisting when explicitly enabled.
    
    ## Description
    * added a new flag, `network.dangerously_allow_all_unix_sockets` as an
    explicit escape hatch
    * In codex-network-proxy, enabling that flag now allows any absolute
    Unix socket path from x-unix-socket instead of requiring each path to be
    explicitly allowlisted. Relative paths are still rejected.
    * updated the macOS seatbelt path in core so it enforces the same Unix
    socket behavior:
      * allowlisted sockets generate explicit network* subpath rules
      * allow-all generates a broad network* (subpath "/") rule
    
    ---------
    
    Co-authored-by: Codex <199175422+chatgpt-codex-connector[bot]@users.noreply.github.com>
  • feat(config): add permissions.network proxy config wiring (#12054)
    ## Summary
    
    Implements the `ConfigToml.permissions.network` and uses it to populate
    `NetworkProxyConfig`. We now parse a new nested permissions/network
    config shape which is converted into the proxy’s runtime config.
    
    When managed requirements exist, we still apply those constraints on top
    of user settings (so managed policy still wins).
    
    * Cleaned up the old constructor path so it now accepts both user config
    + managed constraints directly.
    * Updated the reload path so live proxy config reloads respect
    [permissions.network] too, while still supporting the existing top-level
    [network] format.
    
    ### Behavior
    - User-defined `[permissions.network]` values are now honored.
    - Managed constraints still take effect and are validated against the
    resulting policy.
  • Add configurable MCP OAuth callback URL for MCP login (#11382)
    ## Summary
    
    Implements a configurable MCP OAuth callback URL override for `codex mcp
    login` and app-server OAuth login flows, including support for non-local
    callback endpoints (for example, devbox ingress URLs).
    
    ## What changed
    
    - Added new config key: `mcp_oauth_callback_url` in
    `~/.codex/config.toml`.
    - OAuth authorization now uses `mcp_oauth_callback_url` as
    `redirect_uri` when set.
    - Callback handling validates the callback path against the configured
    redirect URI path.
    - Listener bind behavior is now host-aware:
    - local callback URL hosts (`localhost`, `127.0.0.1`, `::1`) bind to
    `127.0.0.1`
      - non-local callback URL hosts bind to `0.0.0.0`
    - `mcp_oauth_callback_port` remains supported and is used for the
    listener port.
    - Wired through:
      - CLI MCP login flow
      - App-server MCP OAuth login flow
      - Skill dependency OAuth login flow
    - Updated config schema and config tests.
    
    ## Why
    
    Some environments need OAuth callbacks to land on a specific reachable
    URL (for example ingress in remote devboxes), not loopback. This change
    allows that while preserving local defaults for existing users.
    
    ## Backward compatibility
    
    - No behavior change when `mcp_oauth_callback_url` is unset.
    - Existing `mcp_oauth_callback_port` behavior remains intact.
    - Local callback flows continue binding to loopback by default.
    
    ## Testing
    
    - `cargo test -p codex-rmcp-client callback -- --nocapture`
    - `cargo test -p codex-core --lib mcp_oauth_callback -- --nocapture`
    - `cargo check -p codex-cli -p codex-app-server -p codex-rmcp-client`
    
    ## Example config
    
    ```toml
    mcp_oauth_callback_port = 5555
    mcp_oauth_callback_url = "https://<devbox>-<namespace>.gateway.<cluster>.internal.api.openai.org/callback"
  • feat: add Reject approval policy with granular prompt rejection controls (#12087)
    ## Why
    
    We need a way to auto-reject specific approval prompt categories without
    switching all approvals off.
    
    The goal is to let users independently control:
    - sandbox escalation approvals,
    - execpolicy `prompt` rule approvals,
    - MCP elicitation prompts.
    
    ## What changed
    
    - Added a new primary approval mode in `protocol/src/protocol.rs`:
    
    ```rust
    pub enum AskForApproval {
        // ...
        Reject(RejectConfig),
        // ...
    }
    
    pub struct RejectConfig {
        pub sandbox_approval: bool,
        pub rules: bool,
        pub mcp_elicitations: bool,
    }
    ```
    
    - Wired `RejectConfig` semantics through approval paths in `core`:
      - `core/src/exec_policy.rs`
        - rejects rule-driven prompts when `rules = true`
        - rejects sandbox/escalation prompts when `sandbox_approval = true`
    - preserves rule priority when both rule and sandbox prompt conditions
    are present
      - `core/src/tools/sandboxing.rs`
    - applies `sandbox_approval` to default exec approval decisions and
    sandbox-failure retry gating
      - `core/src/safety.rs`
    - keeps `Reject { all false }` behavior aligned with `OnRequest` for
    patch safety
        - rejects out-of-root patch approvals when `sandbox_approval = true`
      - `core/src/mcp_connection_manager.rs`
        - auto-declines MCP elicitations when `mcp_elicitations = true`
    
    - Ensured approval policy used by MCP elicitation flow stays in sync
    with constrained session policy updates.
    
    - Updated app-server v2 conversions and generated schema/TypeScript
    artifacts for the new `Reject` shape.
    
    ## Verification
    
    Added focused unit coverage for the new behavior in:
    - `core/src/exec_policy.rs`
    - `core/src/tools/sandboxing.rs`
    - `core/src/mcp_connection_manager.rs`
    - `core/src/safety.rs`
    - `core/src/tools/runtimes/apply_patch.rs`
    
    Key cases covered include rule-vs-sandbox prompt precedence, MCP
    auto-decline behavior, and patch/sandbox retry behavior under
    `RejectConfig`.
  • Add configurable agent spawn depth (#12251)
    Summary
    - expose `agents.max_depth` in config schema and toml parsing, with
    defaults and validation
    - thread-spawn depth guards and multi-agent handler now respect the
    configured limit instead of a hardcoded value
    - ensure documentation and helpers account for agent depth limits
  • client side modelinfo overrides (#12101)
    TL;DR
    Add top-level `model_catalog_json` config support so users can supply a
    local model catalog override from a JSON file path (including adding new
    models) without backend changes.
    
    ### Problem
    Codex previously had no clean client-side way to replace/overlay model
    catalog data for local testing of model metadata and new model entries.
    
    ### Fix
    - Add top-level `model_catalog_json` config field (JSON file path).
    - Apply catalog entries when resolving `ModelInfo`:
      1. Base resolved model metadata (remote/fallback)
      2. Catalog overlay from `model_catalog_json`
    3. Existing global top-level overrides (`model_context_window`,
    `model_supports_reasoning_summaries`, etc.)
    
    ### Note
    Will revisit per-field overrides in a follow-up
    
    ### Tests
    Added tests
  • feat: add configurable write_stdin timeout (#12228)
    Add max timeout as config for `write_stdin`. This is only used for empty
    `write_stdin`.
    
    Also increased the default value from 30s to 5mins.
  • Enable default status line indicators in TUI config (#12015)
    Default statusline to something
    <img width="307" height="83" alt="Screenshot 2026-02-17 at 18 16 12"
    src="https://github.com/user-attachments/assets/44e16153-0aa2-4c1a-9b4a-02e2feb8b7f6"
    />
  • [js_repl] paths for node module resolution can be specified for js_repl (#11944)
    # External (non-OpenAI) Pull Request Requirements
    
    In `js_repl` mode, module resolution currently starts from
    `js_repl_kernel.js`, which is written to a per-kernel temp dir. This
    effectively means that bare imports will not resolve.
    
    This PR adds a new config option, `js_repl_node_module_dirs`, which is a
    list of dirs that are used (in order) to resolve a bare import. If none
    of those work, the current working directory of the thread is used.
    
    For example:
    ```toml
    js_repl_node_module_dirs = [
        "/path/to/node_modules/",
        "/other/path/to/node_modules/",
    ]
    ```
  • 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: 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>
  • 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
  • chore(core) Deprecate approval_policy: on-failure (#11631)
    ## Summary
    In an effort to start simplifying our sandbox setup, we're announcing
    this approval_policy as deprecated. In general, it performs worse than
    `on-request`, and we're focusing on making fewer sandbox configurations
    perform much better.
    
    ## Testing
    - [x] Tested locally
    - [x] Existing tests pass
  • 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: 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
    ```
  • Add app configs to config.toml (#10822)
    Adds app configs to config.toml + tests
  • Removed "exec_policy" feature flag (#10851)
    This is no longer needed because it's on by default
  • Handle required MCP startup failures across components (#10902)
    Summary
    - add a `required` flag for MCP servers everywhere config/CLI data is
    touched so mandatory helpers can be round-tripped
    - have `codex exec` and `codex app-server` thread start/resume fail fast
    when required MCPs fail to initialize
  • feat(tui): add /statusline command for interactive status line configuration (#10546)
    ## Summary
    - Adds a new `/statusline` command to configure TUI footer status line
    - Introduces reusable `MultiSelectPicker` component with keyboard
    navigation, optional ordering and toggle support
    - Implement status line setup modal that persist configuration to
    config.toml
    
      ## Status Line Items
      The following items can be displayed in the status line:
      - **Model**: Current model name (with optional reasoning level)
      - **Context**: Remaining/used context window percentage
      - **Rate Limits**: 5-day and weekly usage limits
      - **Git**: Current branch (with optimized lookups)
      - **Tokens**: Used tokens, input/output token counts
      - **Session**: Session ID (full or shortened prefix)
      - **Paths**: Current directory, project root
      - **Version**: Codex version
    
      ## Features
      - Live preview while configuring status line items
      - Fuzzy search filtering in the picker
      - Intelligent truncation when items don't fit
      - Items gracefully omit when data is unavailable
      - Configuration persists to `config.toml`
      - Validates and warns about invalid status line items
    
      ## Test plan
      - [x] Run `/statusline` and verify picker UI appears
      - [x] Toggle items on/off and verify live preview updates
      - [x] Confirm selection persists after restart
      - [x] Verify truncation behavior with many items selected
      - [x] Test git branch detection in and out of git repos
    
    ---------
    
    Co-authored-by: Josh McKinney <joshka@openai.com>