Commit Graph

72 Commits

  • 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>
  • feat: add memory tool (#10637)
    Add a tool for memory to retrieve a full memory based on the memory ID
  • feat(core): add configurable log_dir (#10678)
    Adds a top-level `log_dir` config key (defaults to `$CODEX_HOME/log`) so
    one-off runs can redirect `codex-tui.log` via `-c`, e.g.:
    
      codex -c log_dir=./.codex-log
    
    Also resolves relative paths in CLI `-c/--config` overrides for
    `AbsolutePathBuf` values against the effective cwd (when available).
    
    Tests:
    - cargo test -p codex-core
  • add none personality option (#10688)
    - add none personality enum value and empty placeholder behavior\n- add
    docs/schema updates and e2e coverage
  • 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.
  • 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(config) config schema newline (#10323)
    ## Summary
    Looks like we may have introduced a formatting issue in recent PRs.
    
    ## Testing
    - [x] ran `just write-config-schema`
  • chore(config) Rename config setting to personality (#10314)
    ## Summary
    Let's make the setting name consistent with the SlashCommand!
    
    ## Testing
    - [x] Updated tests
  • feat: show runtime metrics in console (#10278)
    Summary of changes:
    
    - Adds a new feature flag: runtime_metrics
      - Declared in core/src/features.rs
      - Added to core/config.schema.json
      - Wired into OTEL init in core/src/otel_init.rs
    
    - Enables on-demand runtime metric snapshots in OTEL
      - Adds runtime_metrics: bool to otel/src/config.rs
      - Enables experimental custom reader features in otel/Cargo.toml
      - Adds snapshot/reset/summary APIs in:
        - otel/src/lib.rs
        - otel/src/metrics/client.rs
        - otel/src/metrics/config.rs
        - otel/src/metrics/error.rs
    
    - Defines metric names and a runtime summary builder
      - New files:
        - otel/src/metrics/names.rs
        - otel/src/metrics/runtime_metrics.rs
      - Summarizes totals for:
        - Tool calls
        - API requests
        - SSE/streaming events
    
    - Instruments metrics collection in OTEL manager
      - otel/src/traces/otel_manager.rs now records:
        - API call counts + durations
        - SSE event counts + durations (success/failure)
        - Tool call metrics now use shared constants
    
    - Surfaces runtime metrics in the TUI
      - Resets runtime metrics at turn start in tui/src/chatwidget.rs
    - Displays metrics in the final separator line in
    tui/src/history_cell.rs
    
    - Adds tests
      - New OTEL tests:
        - otel/tests/suite/snapshot.rs
        - otel/tests/suite/runtime_summary.rs
      - New TUI test:
    - final_message_separator_includes_runtime_metrics in
    tui/src/history_cell.rs
    
    Scope:
    - 19 files changed
    - ~652 insertions, 38 deletions
    
    
    <img width="922" height="169" alt="Screenshot 2026-01-30 at 4 11 34 PM"
    src="https://github.com/user-attachments/assets/1efd754d-a16d-4564-83a5-f4442fd2f998"
    />
  • feat(app-server): support external auth mode (#10012)
    This enables a new use case where `codex app-server` is embedded into a
    parent application that will directly own the user's ChatGPT auth
    lifecycle, which means it owns the user’s auth tokens and refreshes it
    when necessary. The parent application would just want a way to pass in
    the auth tokens for codex to use directly.
    
    The idea is that we are introducing a new "auth mode" currently only
    exposed via app server: **`chatgptAuthTokens`** which consist of the
    `id_token` (stores account metadata) and `access_token` (the bearer
    token used directly for backend API calls). These auth tokens are only
    stored in-memory. This new mode is in addition to the existing `apiKey`
    and `chatgpt` auth modes.
    
    This PR reuses the shape of our existing app-server account APIs as much
    as possible:
    - Update `account/login/start` with a new `chatgptAuthTokens` variant,
    which will allow the client to pass in the tokens and have codex
    app-server use them directly. Upon success, the server emits
    `account/login/completed` and `account/updated` notifications.
    - A new server->client request called
    `account/chatgptAuthTokens/refresh` which the server can use whenever
    the access token previously passed in has expired and it needs a new one
    from the parent application.
    
    I leveraged the core 401 retry loop which typically triggers auth token
    refreshes automatically, but made it pluggable:
    - **chatgpt** mode refreshes internally, as usual.
    - **chatgptAuthTokens** mode calls the client via
    `account/chatgptAuthTokens/refresh`, the client responds with updated
    tokens, codex updates its in-memory auth, then retries. This RPC has a
    10s timeout and handles JSON-RPC errors from the client.
    
    Also some additional things:
    - chatgpt logins are blocked while external auth is active (have to log
    out first. typically clients will pick one OR the other, not support
    both)
    - `account/logout` clears external auth in memory
    - Ensures that if `forced_chatgpt_workspace_id` is set via the user's
    config, we respect it in both:
    - `account/login/start` with `chatgptAuthTokens` (returns a JSON-RPC
    error back to the client)
    - `account/chatgptAuthTokens/refresh` (fails the turn, and on next
    request app-server will send another `account/chatgptAuthTokens/refresh`
    request to the client).
  • Remove WebSocket wire format (#10179)
    I'd like WireApi to go away (when chat is removed) and WebSockets is
    still responses API just over a different transport.
  • Better handling skill depdenencies on ENV VAR. (#9017)
    An experimental flow for env var skill dependencies. Skills can now
    declare required env vars in SKILL.md; if missing, the CLI prompts the
    user to get the value, and Core will store it in memory (eventually to a
    local persistent store)
    <img width="790" height="169" alt="image"
    src="https://github.com/user-attachments/assets/cd928918-9403-43cb-a7e7-b8d59bcccd9a"
    />
  • [connectors] Support connectors part 2 - slash command and tui (#9728)
    - [x] Support `/apps` slash command to browse the apps in tui.
    - [x] Support inserting apps to prompt using `$`.
    - [x] Lots of simplification/renaming from connectors to apps.