Commit Graph

5561 Commits

  • Avoid false shell snapshot cleanup warnings (#18441)
    ## Why
    Fresh app-server thread startup can create a shell snapshot through a
    temp file and then promote it to the final snapshot path. The previous
    implementation briefly wrapped the temp path in `ShellSnapshot`, so
    after a successful rename its `Drop` attempted to delete the old temp
    path and could log a false `ENOENT` warning.
    
    Fixes #17549.
    
    ## What changed
    - Validate the temp snapshot path directly before promotion.
    - Rename the temp path directly to the final snapshot path.
    - Keep explicit cleanup of the temp path on validation or finalization
    failures.
  • [codex] Use background agent task auth for backend calls (#18094)
    ## Summary
    
    Introduces a single background/control-plane agent task for ChatGPT
    backend requests that do not have a thread-scoped task, with
    `AuthManager` owning the default ChatGPT backend authorization decision.
    
    Callers now ask `AuthManager` for the default ChatGPT backend
    authorization header. `AuthManager` decides whether that is bearer or
    background AgentAssertion based on config/internal state, while
    low-level bootstrap paths can explicitly request bearer-only auth.
    
    This PR is stacked on PR4 and focuses on the shared background task auth
    plumbing plus the first tranche of backend/control-plane consumers. The
    remaining callsite wiring is split into PR4.2 to keep review size down.
    
    ## Stack
    
    - PR1: https://github.com/openai/codex/pull/17385 - add
    `features.use_agent_identity`
    - PR2: https://github.com/openai/codex/pull/17386 - register agent
    identities when enabled
    - PR3: https://github.com/openai/codex/pull/17387 - register agent tasks
    when enabled
    - PR3.1: https://github.com/openai/codex/pull/17978 - persist and
    prewarm registered tasks per thread
    - PR4: https://github.com/openai/codex/pull/17980 - use task-scoped
    `AgentAssertion` for downstream calls
    - PR4.1: this PR - introduce AuthManager-owned background/control-plane
    `AgentAssertion` auth
    - PR4.2: https://github.com/openai/codex/pull/18260 - use background
    task auth for additional backend/control-plane calls
    
    ## What Changed
    
    - add background task registration and assertion minting inside
    `codex-login`
    - persist `agent_identity.background_task_id` separately from
    per-session task state
    - make `BackgroundAgentTaskManager` private to `codex-login`; call sites
    do not instantiate or pass it around
    - teach `AuthManager` the ChatGPT backend base URL and feature-derived
    background auth mode from resolved config
    - expose bearer-only helpers for bootstrap/registration/refresh-style
    paths that must not use AgentAssertion
    - wire `AuthManager` default ChatGPT authorization through app listing,
    connector directory listing, remote plugins, MCP status/listing,
    analytics, and core-skills remote calls
    - preserve bearer fallback when the feature is disabled, the backend
    host is unsupported, or background task registration is not available
    
    ## Validation
    
    - `just fmt`
    - `cargo check -p codex-core -p codex-login -p codex-analytics -p
    codex-app-server -p codex-cloud-requirements -p codex-cloud-tasks -p
    codex-models-manager -p codex-chatgpt -p codex-model-provider -p
    codex-mcp -p codex-core-skills`
    - `cargo test -p codex-login agent_identity`
    - `cargo test -p codex-model-provider bearer_auth_provider`
    - `cargo test -p codex-core agent_assertion`
    - `cargo test -p codex-app-server remote_control`
    - `cargo test -p codex-cloud-requirements fetch_cloud_requirements`
    - `cargo test -p codex-models-manager manager::tests`
    - `cargo test -p codex-chatgpt`
    - `cargo test -p codex-cloud-tasks`
    - `just fix -p codex-core -p codex-login -p codex-analytics -p
    codex-app-server -p codex-cloud-requirements -p codex-cloud-tasks -p
    codex-models-manager -p codex-chatgpt -p codex-model-provider -p
    codex-mcp -p codex-core-skills`
    - `just fix -p codex-app-server`
    - `git diff --check`
  • feat: log client use min log level (#18661)
    In the log client, use the log level filter as a minimum severity
    instead of exact match
    
    ---------
    
    Co-authored-by: Codex <noreply@openai.com>
  • chore: drop review prompt from TUI UX (#18659)
    Due to the app-server rebase of the TUI, the review prompt was leaked
    into the transcript on the TUI
    This is not a security issue but it was bad UX. This PR fixes this
  • feat: add metric to track the number of turns with memory usage (#18662)
    Add a metric `codex.turn.memory` to know if a turn used memories or not.
    This is not part of the other turn metrics as a label to limit
    cardinality
  • feat: chronicle alias (#18651)
    Rename Telepathy to Chronicle and add an alias for backward
    compatibility
  • feat: add --ignore-user-config and --ignore-rules (#18646)
    Add those 2 flags to be able to fully isolate a run of `codex exec` from
    any rules or tools.
    This will be used by Chronicle
  • fix: FS watcher when file does not exist yet (#18492)
    The initial goal of this PR was to stabilise the test
    `fs_watch_allows_missing_file_targets`. After further investigation, it
    turns out that this test was always failing and the unstability was
    coming from a race between timeouts mostly
    
    The goal of the test was to test what happens if a notifier gets
    subscribed while a file does not exist yet. But actually the main code
    was broken and in case of a file not existing yet, the notifier used to
    never notify anything (even if the file ended up being created)
    
    This PR fixes the main code (and the test). For this, we basically watch
    the sup-directory when a file does not exist and refresh on it when the
    files gets created
  • Stabilize marketplace/remove installedRoot test (#17721)
    ## Why
    
    This addresses the review comment from #17751 about `marketplace/remove`
    app-server test portability:
    https://github.com/openai/codex/pull/17751#discussion_r3104378613
    
    The API returns the removed installed root using the app-server's
    effective `CODEX_HOME`. On macOS, temporary directory paths can appear
    as either `/var/...` or `/private/var/...`, so comparing one raw path
    against another can fail even when `marketplace/remove` behaves
    correctly.
    
    ## What changed
    
    - Removed the direct whole-response equality assertion for the installed
    root path.
    - Asserted the stable response field, `marketplace_name`, directly.
    - Compared the expected and returned installed-root paths after
    canonicalizing their existing parent directories, which avoids requiring
    the removed leaf directory to still exist.
    
    ## Verification
    
    - `cargo test -p codex-app-server
    marketplace_remove_deletes_config_and_installed_root`
    - `cargo test -p codex-app-server marketplace_remove`
  • chore: morpheus to path (#18353)
    Make the morpheus agent (which is the phase 2 memories agent) follow the
    agent-v2 path system by naming it `/morpheus`. To maintain the path
    primitive this means moving it to a dedicated `AgentControl`
    
    Co-authored-by: Codex <noreply@openai.com>
  • feat: add mem 2 agent header (#18644)
    Add a header to memory phase 2 agent for analytics
  • [codex] Add marketplace/remove app-server RPC (#17751)
    ## Summary
    
    Add a new app-server `marketplace/remove` RPC on top of the shared
    marketplace-remove implementation.
    
    This change:
    - adds `MarketplaceRemoveParams` / `MarketplaceRemoveResponse` to the
    app-server protocol
    - wires the new request through `codex_message_processor`
    - reuses the shared core marketplace-remove flow from the stacked
    refactor PR
    - updates generated schema files and adds focused app-server coverage
    
    ## Validation
    
    - `just write-app-server-schema`
    - `just fmt`
    - heavy compile/test coverage deferred to GitHub CI per request
  • [codex] Use AgentAssertion downstream behind use_agent_identity (#17980)
    ## Summary
    
    This is the AgentAssertion downstream slice for feature-gated agent
    identity support, replacing the oversized AgentAssertion slice from PR
    #17807.
    
    It isolates task-scoped downstream AgentAssertion wiring on top of the
    merged PR3.1 work without re-carrying the earlier agent registration,
    task registration, or task-state history.
    
    This PR includes the task-scoped bug-fix call sites from the review:
    generic file upload auth, MCP OpenAI file upload auth, and ARC monitor
    auth. Broader user/control-plane calls move to PR4.1 and PR4.2.
    
    ## Stack
    
    - PR1: https://github.com/openai/codex/pull/17385 - add
    `features.use_agent_identity`
    - PR2: https://github.com/openai/codex/pull/17386 - register agent
    identities when enabled
    - PR3: https://github.com/openai/codex/pull/17387 - register agent tasks
    when enabled
    - PR3.1: https://github.com/openai/codex/pull/17978 - persist and
    prewarm registered tasks per thread
    - PR4: this PR - use task-scoped `AgentAssertion` downstream when
    enabled
    - PR4.1: https://github.com/openai/codex/pull/18094 - introduce
    AuthManager-owned background/control-plane `AgentAssertion` auth
    - PR4.2: https://github.com/openai/codex/pull/18260 - use background
    task auth for additional backend/control-plane calls
    
    ## What Changed
    
    - add AgentAssertion envelope generation in `codex-core`
    - route downstream HTTP and websocket auth through AgentAssertion when
    an agent task is present
    - extend the model-provider auth provider so non-bearer authorization
    schemes can be passed through cleanly
    - make generic file uploads attach the full authorization header value
    - make MCP OpenAI file uploads use the cached thread agent task
    assertion when present
    - make ARC monitor calls use the cached thread agent task assertion when
    present
    
    ## Why
    
    The original PR had drifted ancestry and showed a much larger diff than
    the semantic change actually required. Restacking it onto PR3.1 keeps
    the reviewable surface down to the downstream assertion slice.
    
    ## Validation
    
    - `just fmt`
    - `cargo check -p codex-core -p codex-login -p codex-analytics -p
    codex-app-server -p codex-cloud-requirements -p codex-cloud-tasks -p
    codex-models-manager -p codex-chatgpt -p codex-model-provider -p
    codex-mcp -p codex-core-skills`
    - `cargo test -p codex-model-provider bearer_auth_provider`
    - `cargo test -p codex-core agent_assertion`
    - `cargo test -p codex-app-server remote_control`
    - `cargo test -p codex-cloud-requirements fetch_cloud_requirements`
    - `cargo test -p codex-models-manager manager::tests`
    - `cargo test -p codex-chatgpt`
    - `cargo test -p codex-cloud-tasks`
    - `cargo test -p codex-login agent_identity`
    - `just fix -p codex-core -p codex-login -p codex-analytics -p
    codex-app-server -p codex-cloud-requirements -p codex-cloud-tasks -p
    codex-models-manager -p codex-chatgpt -p codex-model-provider -p
    codex-mcp -p codex-core-skills`
    - `just fix -p codex-app-server`
    - `git diff --check`
  • [codex] Add workspace owner usage nudge UI (#18221)
    ## Summary
    
    Third PR in the split from #17956. Stacked on #18220.
    
    - shows workspace-owner/member-specific rate-limit messages behind
    `workspace_owner_usage_nudge`
    - prompts workspace members to notify the owner or request a usage-limit
    increase
    - sends the confirmed nudge through the app-server API and renders
    completion feedback
    - adds focused TUI snapshot coverage for prompts and completion states
    - feature gate
    
    ## Validation
    
    - `cargo test -p codex-backend-client`
    - `cargo test -p codex-app-server-protocol`
    - `cargo test -p codex-app-server rate_limits`
    - `cargo test -p codex-tui workspace_`
    - `cargo test -p codex-tui status_`
    - `just fmt`
    - `just fix -p codex-backend-client`
    - `just fix -p codex-app-server-protocol`
    - `just fix -p codex-app-server`
    - `just fix -p codex-tui`
  • TUI: remove simple legacy_core re-exports (#18605)
    ## Summary
    
    The TUI still imported several symbols through the transitional
    app-server-client `legacy_core` facade even though those symbols are
    already owned by smaller crates. This PR narrows that facade by rewiring
    those imports directly to their owner crates.
    
    ## Changes
    
    No functional changes, just import rewiring. This is part of our ongoing
    effort to whittle away at the `legacy_core` namespace, which represents
    all of the remaining symbols that the TUI imports from the core.
  • Use thread IDs in TUI resume hints (#18440)
    ## Summary
    
    Fixes #18313.
    
    Recent TUI resume breadcrumbs could print a thread title instead of the
    stable thread UUID. For sessions whose title was auto-derived from the
    first prompt, that made the suggested codex resume command look like it
    should resume a long prompt rather than the session ID.
    
    This updates the TUI and CLI post-exit resume hints, plus the in-session
    summary shown when switching/forking threads, to always use the stable
    thread ID for these recovery breadcrumbs. Explicit name-based resume
    support remains available elsewhere.
  • fix(guardian) disable skills message in guardian thread (#18599)
    ## Summary
    Remove the skills message from the guardian dev message
    
    ## Test Plan
    - [x] Ran locally
    - [x] Added unit test
    
    ---------
    
    Co-authored-by: Codex <noreply@openai.com>
  • chore(multiagent) skills instructions toggle (#18596)
    ## Summary
    Support toggling the skills message off.
    
    ## Test Plan
    - [x] Updated unit tests
  • Soften Fast mode plan usage copy (#18601)
    Fast mode TUI copy currently names a specific plan-usage multiplier in
    two lightweight promo/help surfaces. This swaps that exact multiplier
    language for the broader increased plan usage wording we use elsewhere.
    
    There are no behavior changes here; the slash command and startup tip
    still point users at the same Fast mode flow.
  • Persist and prewarm agent tasks per thread (#17978)
    ## Summary
    - persist registered agent tasks in the session state update stream so
    the thread can reuse them
    - prewarm task registration once identity registration succeeds, while
    keeping startup failures best-effort
    - isolate the session-side task lifecycle into a dedicated module so
    AgentIdentityManager and RegisteredAgentTask do not leak across as many
    core layers
    
    ## Testing
    - cargo test -p codex-core startup_agent_task_prewarm
    - cargo test -p codex-core
    cached_agent_task_for_current_identity_clears_stale_task
    - cargo test -p codex-core record_initial_history_
  • Filter Windows sandbox roots from SSH config dependencies (#18493)
    ## Stack
    
    1. Base PR: #18443 stops granting ACLs on `USERPROFILE`.
    2. This PR: filters additional SSH-owned profile roots discovered from
    SSH config.
    
    ## Bug
    
    The base PR removes the broadest bad grant: `USERPROFILE` itself.
    
    That still leaves one important case. A user profile child can be
    SSH-owned even when its name is not one of our fixed exclusions.
    
    For example:
    
    ```sshconfig
    Host devbox
      IdentityFile ~/.keys/devbox
      CertificateFile ~/.certs/devbox-cert.pub
      UserKnownHostsFile ~/.known_hosts_custom
      Include ~/.ssh/conf.d/*.conf
    ```
    
    After profile expansion, the sandbox might see these as normal profile
    children:
    
    ```text
    C:\Users\me\.keys
    C:\Users\me\.certs
    C:\Users\me\.known_hosts_custom
    C:\Users\me\.ssh
    ```
    
    Those paths have another owner: OpenSSH and the tools that manage SSH
    identity and host-key state. Codex should not add sandbox ACLs to them.
    
    OpenSSH describes this dependency tree in
    [`ssh_config(5)`](https://man.openbsd.org/ssh_config.5), and the client
    parser follows the same shape in `readconf.c`:
    
    - `Include` recursively reads more config files and expands globs
    - `IdentityFile` and `CertificateFile` name authentication files
    - `UserKnownHostsFile`, `GlobalKnownHostsFile`, and `RevokedHostKeys`
    name host-key files
    - `ControlPath` and `IdentityAgent` can name profile-owned sockets or
    control files
    - these path directives can use forms such as `~`, `%d`, and `${HOME}`
    
    ## Change
    
    This PR adds a small SSH config dependency scanner.
    
    It starts at:
    
    ```text
    ~/.ssh/config
    ```
    
    Then it returns concrete paths named by `Include` and by path-valued SSH
    config directives:
    
    ```text
    IdentityFile
    CertificateFile
    UserKnownHostsFile
    GlobalKnownHostsFile
    RevokedHostKeys
    ControlPath
    IdentityAgent
    ```
    
    For example:
    
    ```sshconfig
    IdentityFile ~/.keys/devbox
    CertificateFile ~/.certs/devbox-cert.pub
    Include ~/.ssh/conf.d/*.conf
    ```
    
    returns paths like:
    
    ```text
    C:\Users\me\.keys\devbox
    C:\Users\me\.certs\devbox-cert.pub
    C:\Users\me\.ssh\conf.d\devbox.conf
    ```
    
    The setup code then maps those paths back to their top-level
    `USERPROFILE` child and filters matching sandbox roots out of both the
    writable and readable root lists.
    
    ## Why this shape
    
    The parser reports what SSH config references. The sandbox setup code
    decides which `USERPROFILE` roots are unsafe to grant.
    
    That keeps the policy simple:
    
    1. expand broad profile grants
    2. remove the profile root
    3. remove fixed sensitive profile folders
    4. remove profile folders referenced by SSH config dependencies
    
    If a path has two possible owners, the sandbox steps back. SSH keeps
    control of SSH config, keys, certificates, known-hosts files, sockets,
    and included config files.
    
    ## Tests
    
    - `cargo test -p codex-windows-sandbox --lib`
    - `just bazel-lock-check`
    - `just fix -p codex-windows-sandbox`
    - `git diff --check`
  • Do not grant Windows sandbox ACLs on USERPROFILE (#18443)
    ## Stack
    
    1. This PR: expand and filter `USERPROFILE` roots.
    2. Follow-up: #18493 filters SSH config dependency roots on top of this
    base.
    
    ## Bug
    
    On Windows, Codex can grant the sandbox ACL access to the whole user
    profile directory.
    
    That means the sandbox ACL can be applied under paths like:
    
    ```text
    C:\Users\me\.ssh
    C:\Users\me\.tsh
    ```
    
    This breaks SSH. Windows OpenSSH checks permissions on SSH config and
    key material. If Codex adds a sandbox group ACL to those files, OpenSSH
    can reject the config or keys.
    
    The bad interaction is:
    
    1. Codex asks the Windows sandbox to grant access to `USERPROFILE`.
    2. The sandbox applies ACLs under that root.
    3. SSH-owned files get an extra ACL entry.
    4. OpenSSH rejects those files because their permissions are no longer
    strict enough.
    
    ## Why this happens more now
    
    Codex now has more flows that naturally start in the user profile:
    
    - a new chat can start in the user directory
    - a project can be rooted in the user directory
    - a user can start the Codex CLI from the user directory
    
    Those are valid user actions. The bug is that `USERPROFILE` is too broad
    a sandbox root.
    
    ## Change
    
    This PR keeps the useful behavior of starting from the user profile
    without granting the profile root itself.
    
    The new flow is:
    
    1. collect the normal read and write roots
    2. if a root is exactly `USERPROFILE`, replace it with the direct
    children of `USERPROFILE`
    3. remove `USERPROFILE` itself from the final root list
    4. apply the existing user-profile read exclusions to both read and
    write roots
    5. add `.tsh` and `.brev` to that exclusion list
    
    So this input:
    
    ```text
    C:\Users\me
    ```
    
    becomes roots like:
    
    ```text
    C:\Users\me\Desktop
    C:\Users\me\Documents
    C:\Users\me\Downloads
    ```
    
    and does not include:
    
    ```text
    C:\Users\me
    C:\Users\me\.ssh
    C:\Users\me\.tsh
    C:\Users\me\.brev
    ```
    
    If `USERPROFILE` cannot be listed, expansion falls back to the profile
    root and the later filter removes it. That keeps the failure mode closed
    for this bug.
    
    ## Why this shape
    
    The sandbox still gets access to ordinary profile folders when the user
    starts from home.
    
    The sandbox no longer grants access to the profile root itself.
    
    All filtering happens after expansion, for both read and write roots.
    That gives us one simple rule: expand broad profile grants first, then
    remove roots the sandbox must not own.
    
    ## Tests
    
    - `just fmt`
    - `cargo test -p codex-windows-sandbox`
    - `just fix -p codex-windows-sandbox`
    - `git diff --check`
  • Avoid redundant memory enable notice (#18580)
    ## Summary
    
    Fixes #18554.
    
    The `/experimental` menu can submit the full experimental feature state
    even when the user presses Enter without toggling anything. Previously,
    Codex showed `Memories will be enabled in the next session.` whenever
    the submitted updates included `Feature::MemoryTool = true`, so sessions
    where Memories were already enabled could show a redundant warning on a
    no-op save.
    
    This change records whether `Feature::MemoryTool` was enabled before
    applying feature updates and only emits the next-session notice when
    Memories actually transitions from disabled to enabled.
  • Add /side conversations (#18190)
    The TUI supports long-running turns and agent threads, but quick side
    questions have required interrupting the main flow or manually
    forking/navigating threads. This PR adds a guarded `/side` flow so users
    can ask brief side-conversation questions in an ephemeral fork while
    keeping the primary thread focused. This also helps address the feature
    request in #18125.
    
    The implementation creates one side conversation at a time, lets `/side`
    open either an empty side thread or immediately submit `/side
    <question>`, and returns to the parent with Esc or Ctrl+C. Side
    conversations get hidden developer guardrails that treat inherited
    history as reference-only and steer the model away from workspace
    mutations unless explicitly requested in the side conversation.
    
    The TUI hides most slash commands while side mode is active, leaving
    only `/copy`, `/diff`, `/mention`, and `/status` available there.
  • Remove unused models.json (#18585)
    - Remove the stale core models catalog.
    - Update the release workflow to refresh the active models-manager
    catalog.
  • Log realtime session id (#18571)
    - Log the actual realtime session id when the session.updated event
    arrives.
  • Queue slash and shell prompts in the TUI (#18542)
    ## Why
    
    Users have asked to queue follow-up slash commands while a task is
    running, including in #14081, #14588, #14286, and #13779. The previous
    TUI behavior validated slash commands immediately, so commands that are
    only meaningful once the current turn is idle could not be queued
    consistently.
    
    The queue should preserve what the user typed and defer command parsing
    until the item is actually dispatched. This also gives `/fast`, `/review
    ...`, `/rename ...`, `/model`, `/permissions`, and similar slash
    workflows the same FIFO behavior as plain queued prompts.
    
    ## What Changed
    
    - Added a queued-input action enum so queued items can be dispatched as
    plain prompts, slash commands, or user shell commands.
    - Changed `Tab` queueing to accept slash-led prompts without validating
    them up front, then parse and dispatch them when dequeued.
    - Added `!` shell-command queueing for `Tab` while a task is running,
    while preserving existing `Enter` behavior for immediate shell
    execution.
    - Moved queued slash dispatch through shared slash-command parsing so
    inline commands, unavailable commands, unknown commands, and local
    config commands report at dequeue time.
    - Continued queue draining after local-only actions and after slash menu
    cancellation or selection when no task is running.
    - Preserved slash-popup completion behavior so `/mo<Tab>` completes to
    `/model ` instead of queueing the prefix.
    - Updated pending-input preview snapshots to show queued follow-up
    inputs.
    
    ## Verification
    
    I did a bunch of manual validation (and found and fixed a few bugs along
    the way).
  • Support codex app on macOS (Intel) and Windows (#18500)
    ## Summary
    
    `codex app` should be a platform-aware entry point for opening Codex
    Desktop or helping users install it. Before this change, the command
    only existed on macOS and its default installer URL always pointed at
    the Apple Silicon DMG, which sent Intel Mac users to the wrong build.
    
    This updates the macOS path to choose the Apple Silicon or Intel DMG
    based on the detected processor, while keeping `--download-url` as an
    advanced override. It also enables `codex app` on Windows, where the CLI
    opens an installed Codex Desktop app when available and otherwise opens
    the Windows installer URL.
    
    ---------
    
    Co-authored-by: Felipe Coury <felipe.coury@openai.com>
  • feat(tui): show context used in plan implementation prompt (#18573)
    # Summary
    
    When a user finishes planning, the TUI asks whether to implement in the
    current conversation or start fresh with the approved plan. The
    clear-context choice is easier to evaluate when the prompt shows how
    much context has already been used, because the user can see when
    carrying the full prior conversation is likely to be less useful than
    preserving only the plan.
    
    <img width="1612" height="1312" alt="image"
    src="https://github.com/user-attachments/assets/694bcf87-8be5-4e88-a412-e562af62d5f7"
    />
        
    This PR adds that context signal directly to the clear-context option
    while keeping the copy compact enough for the Plan-mode selection popup.
    
    # What Changed
    
    - Compute an optional context-usage label when opening the plan
    implementation prompt.
    - Show the label only on `Yes, clear context and implement`, where it
    informs the cleanup decision.
    - Prefer a percentage-used label when context-window information is
    available, with a compact token-used fallback when only token totals are
    known.
    - Preserve the original option description when usage is unknown or
    effectively zero.
    - Add rustdoc comments around the prompt-copy boundary so future changes
    keep the context label formatting and selection rendering
    responsibilities clear.
    
    # Testing
    
    - `cargo test -p codex-tui plan_implementation`
    
    # Notes
    
    The footer continues to show context remaining as ambient status. The
    implementation prompt intentionally shows context used because the user
    is choosing whether to clean up the current thread before
    implementation.
  • [5/6] Wire executor-backed MCP stdio (#18212)
    ## Summary
    - Add the executor-backed RMCP stdio transport.
    - Wire MCP stdio placement through the executor environment config.
    - Cover local and executor-backed stdio paths with the existing MCP test
    helpers.
    
    ## Stack
    ```text
    o  #18027 [6/6] Fail exec client operations after disconnect
    │
    @  #18212 [5/6] Wire executor-backed MCP stdio
    │
    o  #18087 [4/6] Abstract MCP stdio server launching
    │
    o  #18020 [3/6] Add pushed exec process events
    │
    o  #18086 [2/6] Support piped stdin in exec process API
    │
    o  #18085 [1/6] Add MCP server environment config
    │
    o  main
    ```
    
    ---------
    
    Co-authored-by: Codex <noreply@openai.com>
  • Fix plugin cache panic when cwd is unavailable (#18499)
    ## Summary
    
    Fixes #16637. (I hit this bug after 11h of work on a long-running task.)
    
    Plugin cache initialization could panic when an already-absolute cache
    path was normalized through `AbsolutePathBuf::from_absolute_path`,
    because that path still consulted `current_dir()`.
    
    This changes absolute-path normalization so already-absolute paths do
    not depend on cwd, and makes plugin cache root construction available as
    a fallible path through `PluginStore::try_new()`. Plugin cache subpaths
    now use `AbsolutePathBuf::join()` instead of re-absolutizing derived
    absolute paths.
  • Update image outputs to default to high detail (#18386)
    Do not assume the default `detail`.
  • Revert "[codex] drain mailbox only at request boundaries" (#18325)
    ## Summary
    - Reverts PR #17749 so queued inter-agent mail can again preempt after
    reasoning/commentary output item boundaries.
    - Applies the revert to the current `codex/turn.rs` module layout and
    restores the prior pending-input test expectations/snapshots.
    
    ## Testing
    - `just fmt`
    - `cargo test -p codex-core --test all pending_input`
    - `cargo test -p codex-core` failed in unrelated
    `tools::js_repl::tests::js_repl_imported_local_files_can_access_repl_globals`:
    dotslash download hit `mktemp: mkdtemp failed ... Operation not
    permitted` in the sandbox temp dir.
    
    Co-authored-by: Codex <noreply@openai.com>
  • Add max context window model metadata (#18382)
    Adds max_context_window to model metadata and routes core context-window
    reads through resolved model info. Config model_context_window overrides
    are clamped to max_context_window when present; without an override, the
    model context_window is used.
  • [codex] Add marketplace remove command and shared logic (#17752)
    ## Summary
    
    Move the marketplace remove implementation into shared core logic so
    both the CLI command and follow-up app-server RPC can reuse the same
    behavior.
    
    This change:
    - adds a shared `codex_core::plugins::remove_marketplace(...)` flow
    - moves validation, config removal, and installed-root deletion out of
    the CLI
    - keeps the CLI as a thin wrapper over the shared implementation
    - adds focused core coverage for the shared remove path
    
    ## Validation
    
    - `just fmt`
    - focused local coverage for the shared remove path
    - heavier follow-up validation deferred to stacked PR CI
  • [codex] Add owner nudge app-server API (#18220)
    ## Summary
    
    Second PR in the split from #17956. Stacked on #18227.
    
    - adds app-server v2 protocol/schema support for
    `account/sendAddCreditsNudgeEmail`
    - adds the backend-client `send_add_credits_nudge_email` request and
    request body mapping
    - handles the app-server request with auth checks, backend call, and
    cooldown mapping
    - adds the disabled `workspace_owner_usage_nudge` feature flag and
    focused app-server/backend tests
    
    ## Validation
    
    - `cargo test -p codex-backend-client`
    - `cargo test -p codex-app-server-protocol`
    - `cargo test -p codex-app-server rate_limits`
    - `cargo test -p codex-tui workspace_`
    - `cargo test -p codex-tui status_`
    - `just fmt`
    - `just fix -p codex-backend-client`
    - `just fix -p codex-app-server-protocol`
    - `just fix -p codex-app-server`
    - `just fix -p codex-tui`
  • [codex] Describe uninstalled cross-repo plugin reads (#18449)
    ## Summary
    - Populate `PluginDetail.description` in core for uninstalled cross-repo
    plugins when detailed fields are unavailable until install.
    - Include the source Git URL plus optional path/ref/sha details in that
    fallback description.
    - Keep `details_unavailable_reason` as the structured signal while
    app-server forwards the description normally.
    - Add plugin-read coverage proving the response does not clone the
    remote source just to show the message.
    
    ## Why
    Uninstalled cross-repo plugins intentionally return sparse detail data
    so listing/reading does not clone the plugin source. Without a
    description, Desktop and TUI detail pages look like an ordinary empty
    plugin. This gives users a concrete explanation and source pointer while
    keeping the existing structured reason available for callers.
    
    ## Validation
    - `just fmt`
    - `cargo test -p codex-core
    read_plugin_for_config_uninstalled_git_source_requires_install_without_cloning`
    - `cargo test -p codex-app-server plugin_read --test all`
    - `just fix -p codex-core`
    - `just fix -p codex-app-server`
    
    Note: `cargo test -p codex-app-server` was also attempted before the
    latest refactor and failed broadly in unrelated v2
    thread/realtime/review/skills suites; the new plugin-read test passed in
    that run as well.
  • feat: Budget skill metadata and surface trimming as a warning (#18298)
    Cap the model-visible skills section to a small share of the context
    window, with a fallback character budget, and keep only as many implicit
    skills as fit within that budget.
    
    Emit a non-fatal warning when enabled skills are omitted, and add a new
    app-server warning notification
    
    Record thread-start skill metrics for total enabled skills, kept skills,
    and whether truncation happened
    
    ---------
    
    Co-authored-by: Matthew Zeng <mzeng@openai.com>
    Co-authored-by: Codex <noreply@openai.com>
  • Feat/auto review dev message marker (#18369)
    supporting guardian's rebrand to auto-review!
  • [TUI] add external config migration prompt when start TUI (#17891)
    - add a TUI startup migration prompt for external agent config
    - support migrating external configs including config, skills, AGENTS.md
    and plugins
    - gate the prompt behind features.external_migrate (default false)
    
    <img width="1037" height="480" alt="Screenshot 2026-04-14 at 9 29 14 PM"
    src="https://github.com/user-attachments/assets/6060849b-03cb-429a-9c13-c7bb46ad2e65"
    />
    <img width="713" height="183" alt="Screenshot 2026-04-14 at 9 29 26 PM"
    src="https://github.com/user-attachments/assets/d13f177e-d4c4-479c-8736-ef29636081e1"
    />
    
    ---------
    
    Co-authored-by: Eric Traut <etraut@openai.com>
  • fix: trust-gate project hooks and exec policies (#14718)
    ## Summary
    - trust-gate project `.codex` layers consistently, including repos that
    have `.codex/hooks.json` or `.codex/execpolicy/*.rules` but no
    `.codex/config.toml`
    - keep disabled project layers in the config stack so nested trusted
    project layers still resolve correctly, while preventing hooks and exec
    policies from loading until the project is trusted
    - update app-server/TUI onboarding copy to make the trust boundary
    explicit and add regressions for loader, hooks, exec-policy, and
    onboarding coverage
    
    ## Security
    Before this change, an untrusted repo could auto-load project hooks or
    exec policies from `.codex/` as long as `config.toml` was absent. This
    makes trust the single gate for project-local config, hooks, and exec
    policies.
    
    ## Stack
    - Parent of #15936
    
    ## Test
    - cargo test -p codex-core without_config_toml
    
    ---------
    
    Co-authored-by: Codex <noreply@openai.com>
  • /plugins: Add inline enablement toggles (#18395)
    This PR adds inline enable/disable controls to the new /plugins browse
    menu. Installed plugins can now be toggled directly from the list with
    keyboard interaction, and the associated config-write plumbing is
    included so the UI and persisted plugin state stay in sync. This also
    includes the queued-write handling needed to avoid stale toggle
    completions overwriting newer intent.
    
    - Add toggleable plugin rows for installed plugins in /plugins
    - Support Space to enable or disable without leaving the list
    - Persist plugin enablement through the existing app/config write path
    - Preserve the current selection while the list refreshes after a toggle
    - Add tests and snapshot updates for toggling behavior
    
    ---------
    
    Co-authored-by: Codex <noreply@openai.com>
  • feat: Add remote plugin fields to plugin API (#17277)
    ## Summary
    Update the plugin API for the new remote plugin model.
    
    The mental model is no longer “keep local plugin state in sync with
    remote.” Instead, local and remote plugins are becoming separate
    sources. Remote catalog entries can be shown directly from the remote
    API before installation; after installation they are still downloaded
    into the local cache for execution, but remote installed state will come
    from the API and be held in memory rather than being read from config.
    
    • ## API changes
    - Remove `forceRemoteSync` from `plugin/list`, `plugin/install`, and
    `plugin/uninstall`.
      - Remove `remoteSyncError` from `plugin/list`.
      - Add remote-capable metadata to `plugin/list` / `plugin/read`:
        - nullable `marketplaces[].path`
        - `source: { type: "remote", downloadUrl }`
        - URL asset fields alongside local path fields:
      `composerIconUrl`, `logoUrl`, `screenshotUrls`
      - Make `plugin/read` and `plugin/install` source-compatible:
        - `marketplacePath?: AbsolutePathBuf | null`
        - `remoteMarketplaceName?: string | null`
        - exactly one source is required at runtime