mirror of
https://github.com/pchuan98/codex.git
synced 2026-07-01 00:31:56 +08:00
dev
2053 Commits
-
feat(tui): add PR summary statusline items (#20892)
## Why? The Codex App already exposes branch and PR context in its branch-details UI. This brings the same context into the CLI footer as opt-in statusline items, so users can choose the extra signal without making the default footer busier. ## What? Add optional `pull-request-number` and `branch-changes` items to the configurable TUI status line. - `pull-request-number` shows the open PR for the current checkout and renders as a clickable terminal hyperlink when OSC 8 links are supported. - `branch-changes` shows committed additions/deletions against the repository default branch, or `No changes` when the branch has no committed diff. <img width="1257" height="261" alt="CleanShot 2026-05-03 at 20 44 15" src="https://github.com/user-attachments/assets/10b4380b-c3e9-4729-9ee1-3f742068fa47" /> ## Architecture This follows the same client/app-server split as the Codex App: the TUI owns presentation, caching, and optional rendering, while workspace-sensitive `git` and `gh` discovery runs through app-server. The new TUI-local `workspace_command` layer sends bounded, non-interactive `command/exec` requests to the active app-server. That makes the implementation remote-friendly: the TUI does not decide whether commands run in an embedded local workspace or a remote workspace, and it does not bypass app-server sandbox or permission policy. The branch summary logic stays internal to `codex-tui` because this PR only needs TUI statusline behavior. The command boundary is still isolated behind `WorkspaceCommandExecutor`, so the lookup code can be lifted or reused later without changing statusline rendering. ## How? - Add a TUI `WorkspaceCommandExecutor` abstraction backed by app-server `command/exec`. - Add branch summary probes for: - current branch name, - open PR metadata, - committed branch diff stats against the default branch. - Prefer remote-tracking default branch refs for diff stats, avoiding stale or absent local `main` branches. - Resolve PRs with `gh pr view` first, then fall back to commit-associated PR lookup across parent/fork repos. - Add `/statusline` picker entries, preview values, rendering, and OSC 8 clickable PR links. - Keep all probes best-effort so missing `git`, missing `gh`, auth failures, or non-git directories hide optional items instead of surfacing footer errors. ## Validation - `cargo test -p codex-tui branch_summary -- --nocapture` - Snapshot coverage for the `/statusline` preview/setup rendering paths - Hyperlink rendering coverage for clickable PR statusline cells
Felipe Coury ·
2026-05-04 16:11:15 -03:00 -
state: pass state db handles through consumers (#20561)
## Why SQLite state was still being opened from consumer paths, including lazy `OnceCell`-backed thread-store call sites. That let one process construct multiple state DB connections for the same Codex home, which makes SQLite lock contention and `database is locked` failures much easier to hit. State DB lifetime should be chosen by main-like entrypoints and tests, then passed through explicitly. Consumers should use the supplied `Option<StateDbHandle>` or `StateDbHandle` and keep their existing filesystem fallback or error behavior when no handle is available. The startup path also needs to keep the rollout crate in charge of SQLite state initialization. Opening `codex_state::StateRuntime` directly bypasses rollout metadata backfill, so entrypoints should initialize through `codex_rollout::state_db` and receive a handle only after required rollout backfills have completed. ## What Changed - Initialize the state DB in main-like entrypoints for CLI, TUI, app-server, exec, MCP server, and the thread-manager sample. - Pass `Option<StateDbHandle>` through `ThreadManager`, `LocalThreadStore`, app-server processors, TUI app wiring, rollout listing/recording, personality migration, shell snapshot cleanup, session-name lookup, and memory/device-key consumers. - Remove the lazy local state DB wrapper from the thread store so non-test consumers use only the supplied handle or their existing fallback path. - Make `codex_rollout::state_db::init` the local state startup path: it opens/migrates SQLite, runs rollout metadata backfill when needed, waits for concurrent backfill workers up to a bounded timeout, verifies completion, and then returns the initialized handle. - Keep optional/non-owning SQLite helpers, such as remote TUI local reads, as open-only paths that do not run startup backfill. - Switch app-server startup from direct `codex_state::StateRuntime::init` to the rollout state initializer so app-server cannot skip rollout backfill. - Collapse split rollout lookup/list APIs so callers use the normal methods with an optional state handle instead of `_with_state_db` variants. - Restore `getConversationSummary(ThreadId)` to delegate through `ThreadStore::read_thread` instead of a LocalThreadStore-specific rollout path special case. - Keep DB-backed rollout path lookup keyed on the DB row and file existence, without imposing the filesystem filename convention on existing DB rows. - Verify readable DB-backed rollout paths against `session_meta.id` before returning them, so a stale SQLite row that points at another thread's JSONL falls back to filesystem search and read-repairs the DB row. - Keep `debug prompt-input` filesystem-only so a one-off debug command does not initialize or backfill SQLite state just to print prompt input. - Keep goal-session test Codex homes alive only in the goal-specific helper, rather than leaking tempdirs from the shared session test helper. - Update tests and call sites to pass explicit state handles where DB behavior is expected and explicit `None` where filesystem-only behavior is intended. ## Validation - `CARGO_TARGET_DIR=/tmp/codex-target-state-db cargo check -p codex-rollout -p codex-thread-store -p codex-app-server -p codex-core -p codex-tui -p codex-exec -p codex-cli --tests` - `CARGO_TARGET_DIR=/tmp/codex-target-state-db cargo test -p codex-rollout state_db_` - `CARGO_TARGET_DIR=/tmp/codex-target-state-db cargo test -p codex-rollout find_thread_path` - `CARGO_TARGET_DIR=/tmp/codex-target-state-db cargo test -p codex-rollout find_thread_path -- --nocapture` - `CARGO_TARGET_DIR=/tmp/codex-target-state-db cargo test -p codex-rollout try_init_ -- --nocapture` - `CARGO_TARGET_DIR=/tmp/codex-target-state-db cargo test -p codex-rollout` - `CARGO_TARGET_DIR=/tmp/codex-target-state-db cargo clippy -p codex-rollout --lib -- -D warnings` - `CARGO_TARGET_DIR=/tmp/codex-target-state-db cargo test -p codex-thread-store read_thread_falls_back_when_sqlite_path_points_to_another_thread -- --nocapture` - `CARGO_TARGET_DIR=/tmp/codex-target-state-db cargo test -p codex-thread-store` - `CARGO_TARGET_DIR=/tmp/codex-target-state-db cargo test -p codex-core shell_snapshot` - `CARGO_TARGET_DIR=/tmp/codex-target-state-db cargo test -p codex-core --test all personality_migration` - `CARGO_TARGET_DIR=/tmp/codex-target-state-db cargo test -p codex-core --test all rollout_list_find` - `RUST_MIN_STACK=8388608 CODEX_SKIP_VENDORED_BWRAP=1 CARGO_TARGET_DIR=/tmp/codex-target-state-db cargo test -p codex-core --test all rollout_list_find::find_prefers_sqlite_path_by_id -- --nocapture` - `RUST_MIN_STACK=8388608 CODEX_SKIP_VENDORED_BWRAP=1 CARGO_TARGET_DIR=/tmp/codex-target-state-db cargo test -p codex-core --test all rollout_list_find -- --nocapture` - `CARGO_TARGET_DIR=/tmp/codex-target-state-db cargo test -p codex-core interrupt_accounts_active_goal_before_pausing` - `CARGO_TARGET_DIR=/tmp/codex-target-state-db cargo test -p codex-app-server get_auth_status -- --test-threads=1` - `CODEX_SKIP_VENDORED_BWRAP=1 CARGO_TARGET_DIR=/tmp/codex-target-state-db cargo test -p codex-app-server --lib` - `CODEX_SKIP_VENDORED_BWRAP=1 CARGO_TARGET_DIR=/tmp/codex-target-state-db cargo check -p codex-rollout -p codex-app-server --tests` - `CARGO_TARGET_DIR=/tmp/codex-target-state-db just fix -p codex-rollout -p codex-thread-store -p codex-core -p codex-app-server -p codex-tui -p codex-exec -p codex-cli` - `CODEX_SKIP_VENDORED_BWRAP=1 CARGO_TARGET_DIR=/tmp/codex-target-state-db just fix -p codex-rollout -p codex-app-server` - `CARGO_TARGET_DIR=/tmp/codex-target-state-db just fix -p codex-rollout` - `CODEX_SKIP_VENDORED_BWRAP=1 CARGO_TARGET_DIR=/tmp/codex-target-state-db just fix -p codex-core` - `just argument-comment-lint -p codex-core` - `just argument-comment-lint -p codex-rollout` Focused coverage added in `codex-rollout`: - `recorder::tests::state_db_init_backfills_before_returning` verifies the rollout metadata row exists before startup init returns. - `state_db::tests::try_init_waits_for_concurrent_startup_backfill` verifies startup waits for another worker to finish backfill instead of disabling the handle for the process. - `state_db::tests::try_init_times_out_waiting_for_stuck_startup_backfill` verifies startup does not hang indefinitely on a stuck backfill lease. - `tests::find_thread_path_accepts_existing_state_db_path_without_canonical_filename` verifies DB-backed lookup accepts valid existing rollout paths even when the filename does not include the thread UUID. - `tests::find_thread_path_falls_back_when_db_path_points_to_another_thread` verifies DB-backed lookup ignores a stale row whose existing path belongs to another thread and read-repairs the row after filesystem fallback. Focused coverage updated in `codex-core`: - `rollout_list_find::find_prefers_sqlite_path_by_id` now uses a DB-preferred rollout file with matching `session_meta.id`, so it still verifies that valid SQLite paths win without depending on stale/empty rollout contents. `cargo test -p codex-app-server thread_list_respects_search_term_filter -- --test-threads=1 --nocapture` was attempted locally but timed out waiting for the app-server test harness `initialize` response before reaching the changed thread-list code path. `bazel test //codex-rs/thread-store:thread-store-unit-tests --test_output=errors` was attempted locally after the thread-store fix, but this container failed before target analysis while fetching `v8+` through BuildBuddy/direct GitHub. The equivalent local crate coverage, including `cargo test -p codex-thread-store`, passes. A plain local `cargo check -p codex-rollout -p codex-app-server --tests` also requires system `libcap.pc` for `codex-linux-sandbox`; the follow-up app-server check above used `CODEX_SKIP_VENDORED_BWRAP=1` in this container.
Ruslan Nigmatullin ·
2026-05-04 11:46:03 -07:00 -
tui: retire /approvals and rename /autoreview to /approve (#21034)
## Why The TUI currently exposes overlapping command names for the same permissions flow: `/permissions` and the older `/approvals` alias. It also uses `/autoreview` for the manual retry flow, even though the action users take there is approving one denied auto-review request. This change makes the command surface consistent with the hard rebrand: - `/permissions` is the only command for permission settings. - `/approve` is the command for approving a recent auto-review denial. ## What changed - Removed the legacy `/approvals` slash command and its dispatch path. - Kept `/permissions` as the single permissions command shown and accepted by the TUI. - Renamed the auto-review denial command from `/autoreview` to `/approve`. - Updated nearby comments so they refer to `/permissions` rather than the retired `/approvals` name. ## Verification - Updated the slash-command unit test to assert that `AutoReview` now renders and parses as `approve`.
Won Park ·
2026-05-04 17:50:34 +00:00 -
feat(tui): add keymap debug inspector (#20794)
## Why We constantly get bug reports about keys not being recognized by Codex when the terminal is not handling the key press. Running `/keymap debug` or `/keymap` and going to the Debug tab, we can allow the user to either understand that the key being pressed is not being recognized or to check what it's being recognized as and report or reassign that key. | Menu | Inspector | Hint | |---|---|---| | <img width="1369" height="796" alt="CleanShot 2026-05-02 at 12 57 12" src="https://github.com/user-attachments/assets/512b6faa-344e-4aee-9c00-b4bdc633a662" /> | <img width="1261" height="754" alt="CleanShot 2026-05-02 at 12 56 36" src="https://github.com/user-attachments/assets/a6ddae7d-e174-4ee4-893f-e6bec4fff4ab" /> | <img width="1369" height="796" alt="CleanShot 2026-05-02 at 12 57 30" src="https://github.com/user-attachments/assets/db507784-f40a-4cff-ac23-a61d9703769b" /> | ## Summary - add a Debug tab to `/keymap` and support `/keymap debug` for direct access - show what key Codex receives, the config key representation, raw event details, and matching actions - add a progressive missing-key hint that escalates after a few seconds with no detected keypress ## Validation - `just fmt` - `cargo test -p codex-tui keymap_setup::tests::debug_view` - `cargo test -p codex-tui keymap_setup::tests` - `cargo test -p codex-tui slash_keymap` - `cargo test -p codex-tui` (unit tests passed; integration test `suite::model_availability_nux::resume_startup_does_not_consume_model_availability_nux_count` failed locally by itself with `codex resume` exiting 1 and terminal probe escape output) - `just fix -p codex-tui` - `just argument-comment-lint` - `cargo insta pending-snapshots` - `git diff --check`
Felipe Coury ·
2026-05-04 14:40:50 -03:00 -
Speed up /side parent restore replay (#20815)
## Why Returning from a `/side` conversation restores the parent thread by replaying its snapshot into the TUI. For very long parent threads, replaying every transcript row can take noticeable time even though most rows immediately scroll out of terminal history. ## What Changed - Buffer thread-switch replay for parent restores when terminal resize reflow is enabled. - Reuse the existing resize-reflow tail renderer so only the retained transcript tail is written back to scrollback when a row cap is configured.
Eric Traut ·
2026-05-04 09:00:30 -07:00 -
Keep paused goals paused on thread resume (#20790)
## Summary Early adopters of the `/goal` feature have provided feedback that they expect a goal they explicitly paused to remain paused when they resume a thread. Previously, resuming a thread would reactivate a paused goal. This PR keeps persisted goal status unchanged during thread resume. This honors the user feedback while also simplifying the core goal logic. Rather than have the core logic automatically resume a paused goal, that responsibility is transferred to the client. The TUI now detects a resumed thread with a paused goal and asks the user whether to `Resume goal` or `Leave paused`. The prompt appears only for quiet resume flows, so users who resume with an immediate prompt are not interrupted. <img width="544" height="111" alt="image" src="https://github.com/user-attachments/assets/0ac9de1c-6ee6-47ba-b223-c03c8eb4c192" />
Eric Traut ·
2026-05-04 08:58:07 -07:00 -
fix(tui): bound startup terminal probes (#20654)
## Summary Bound TUI startup terminal response probes so unsupported terminals cannot stall startup for multiple seconds. This replaces the Unix startup uses of crossterm's blocking response probes with short `/dev/tty` probes that use nonblocking reads and `poll` with a 100ms timeout. It covers the initial cursor-position query, keyboard enhancement support detection, and OSC 10/11 default-color detection. The default-color probe uses one shared deadline for foreground and background instead of allowing two independent full waits. The diagnostic mode/trace env vars from the investigation branch are intentionally not included. The shipped behavior is simply bounded probing by default, while non-Unix keeps the existing crossterm fallback path. ## Details - Add a private `terminal_probe` module for bounded Unix terminal probes and response parsers. - Let `custom_terminal::Terminal` accept a caller-provided initial cursor position so startup can compute it before constructing the terminal. - Use bounded cursor, keyboard enhancement, and default-color probes on Unix startup. - Preserve default-color cache behavior so a failed attempted query does not retry forever. ## Validation - `cd codex-rs && just fmt` - `cd codex-rs && cargo test -p codex-tui terminal_probe` - `cd codex-rs && just fix -p codex-tui` - `cd codex-rs && just argument-comment-lint` - `git diff --check` - `git diff --cached --check` `cd codex-rs && cargo test -p codex-tui` still aborts on the pre-existing local stack overflow in `app::tests::discard_side_thread_keeps_local_state_when_server_close_fails`; I reproduced that same focused failure on `main` before this PR work, so it is not introduced by this change. Manual validation in the VM showed the original crossterm path taking about 2s per unanswered probe, while bounded probing returned in about 100ms per probe.
Felipe Coury ·
2026-05-02 01:20:57 +00:00 -
Clear live hook rows when turns finalize (#20674)
# Why When a user interrupts a turn while a hook is still running, the normal turn status is cleared but the separate live hook row can remain visible as `Running` because the TUI may never receive a matching `HookCompleted` event before cancellation. Once the turn itself is finalized, that turn-scoped live state should not remain on screen. # What - clear any still-live `active_hook_cell` during turn finalization - add a regression snapshot covering an interrupted turn with a visible `PreToolUse` hook row # Testing - `cargo test -p codex-tui interrupted_turn_clears_visible_running_hook` - attempted `cargo test -p codex-tui` (currently aborts on unrelated existing stack overflow in `app::tests::discard_side_thread_removes_agent_navigation_entry`)
Abhinav ·
2026-05-01 14:48:22 -07:00 -
/plugins: add marketplace upgrade flow (#20478)
This PR adds marketplace upgrade to the `/plugins` menu so users can update configured marketplaces. It adds a `Ctrl+U` shortcut on eligible marketplace tabs, a loading state, and the app-server request flow needed to perform `marketplace/upgrade`. After a successful upgrade, the TUI refreshes plugin data, plugin mentions, and user config so updated marketplace contents show up across the menu and other plugin surfaces. It also preserves the current marketplace tab on no-op and failure paths and surfaces backend error details directly in the TUI. - Add a `Ctrl+U` upgrade option for user-configured marketplace tabs in `/plugins` - Show the upgrade footer hint only on upgradeable marketplace tabs - Show a loading state during `marketplace/upgrade` - Surface already-up-to-date and per-marketplace failure results from the backend - Refresh plugin data, plugin mentions, and user config after successful upgrades - Add tests and snapshot updates for the shortcut flow, loading state, and failure messaging Steps to test: 1. Add a `/plugin` marketplace to Codex TUI. 2. Open `/plugins`, move to that marketplace tab, and confirm the footer shows `Ctrl+U` to upgrade. 3. Press `Ctrl+U` and confirm the popup switches into an upgrade loading state. 4. When the request finishes, confirm you see the expected result: updated marketplace contents on success, an already-up-to-date message on no-op, or backend error details on failure. On no-op or failure, confirm the popup stays on the same marketplace tab.
canvrno-oai ·
2026-05-01 11:26:29 -07:00 -
fix(tui): restore alt-enter newline alias (#20535)
Fixes https://github.com/openai/codex/issues/20501 ## Summary - add Alt+Enter to the built-in editor newline aliases - update keymap tests that used Alt+Enter as a custom submit binding now that it conflicts with newline - refresh the keymap action-menu snapshot fixture ## Test Plan - `just fmt` - `cargo test -p codex-tui keymap::tests` - `cargo test -p codex-tui bottom_pane::textarea::tests` - `cargo test -p codex-tui keymap_setup::tests` - `cargo test -p codex-tui` - `cargo insta pending-snapshots` - `git diff --check` - `just argument-comment-lint`
Felipe Coury ·
2026-05-01 15:22:02 -03:00 -
Add /ide context support to the TUI (#20294)
## Why Users have asked for a `/ide` command in the TUI so Codex can use the active IDE session for live context such as the current file, open tabs, and selected ranges. We already support a similar feature in the Codex desktop app, so bringing it to the TUI makes sense. One subtle compatibility constraint is that the injected prompt wrapper and transcript stripping should match the desktop app and IDE extension. By using the same `## My request for Codex:` delimiter and hiding the injected context from transcript rendering the same way, threads created in the TUI render correctly in desktop and IDE surfaces, and threads created there replay correctly in the TUI, even when IDE context was included. Addresses https://github.com/openai/codex/issues/13834. ## What changed ### Summary This PR consists of four four pieces: 1. An IPC client that uses a socket (Mac/Linux) or named pipe (Windows) to talk to the IDE Extension 2. Logic that establishes the IPC connection and requests IDE context (open files, selection) on demand 3. Logic that injects this context into the user prompt (using the same technique as the desktop app) and hides the added context when rendering the prompt in the TUI transcript 4. A new slash command for enabling/disabling this mode and text within the footer to indicate when it's enabled ### Details - Added `/ide [on|off|status]` to the TUI, with bare `/ide` toggling IDE context on or off. - Added a Rust IDE context client that connects to the local Codex IDE IPC route as a client and requests context from the IDE extension flow. - Injected IDE context using the same prompt delimiter and transcript-stripping convention as the desktop app and IDE extension so shared threads render consistently across surfaces. - Added an `IDE context` status-line indicator while the feature is active and cleared it when enabling or fetching context fails. - Added handling for multiple selection ranges, oversized selections, interleaved IPC messages, and transient reconnect timing after quick toggles. ## Verification Did extensive manual testing in addition to running automated unit and regression tests. To test: - Launch VS Code (or Cursor) with the IDE extension. - Open one or more files in the IDE and select a range of text within one of them. - Start the TUI. - Ask the agent which files you have open in your IDE, and it should say that it does not know. - Enable `/ide` mode; note that `IDE context` appears in the lower right. - Ask the agent what files you have open in your IDE and what text is selected.
Eric Traut ·
2026-05-01 09:39:48 -07:00 -
Enforce
animations = falsefor screen readers (#20564)## Why Issue #20489 calls out that animated TUI affordances can be noisy for screen-reader users. Codex already has `tui.animations = false` as a reduced-motion setting, but some live activity rows render spinner-style prefixes in that mode. These were relatively recent regressions. We have also regressed this pattern more than once by adding new spinner/shimmer callsites that do not think through the reduced-motion path, so this PR adds a small guardrail while fixing the current surfaces. ## What changed - Omit the live status-row spinner when animations are disabled, so the row starts with stable text like `Working (...)`. - Render running hook headers without the spinner prefix when animations are disabled, while preserving shimmer/spinner behavior when animations are enabled. - Centralize TUI activity indicators in `tui/src/motion.rs`, with explicit reduced-motion choices for hidden prefixes, static bullets, and plain shimmer-text fallbacks. - Route existing spinner/shimmer callsites through the central motion helper, including exec rows, MCP/web-search/loading rows, hook rows, plugin loading, and onboarding loading text. - Add a source-scan regression test that rejects direct `spinner(...)` or `shimmer_spans(...)` usage outside the central module and primitive definition. - Add focused coverage that reduced-motion active exec rows are stable, status rows start without a spinner, running hooks omit the spinner, and MCP inventory loading stays stable. - Update the one affected status-indicator snapshot; the existing detail tree prefix remains unchanged. ## Verification - `cargo test -p codex-tui`
Eric Traut ·
2026-05-01 09:07:56 -07:00 -
feat: export and replay effective config locks (#20405)
## Why For reproducibility. A hand-written `config.toml` is not enough to recreate what a Codex session actually ran with because layered config, CLI overrides, defaults, feature aliases, resolved feature config, prompt setup, and model-catalog/session values can all affect the final runtime behavior. This PR adds an effective config lockfile path: one run can export the resolved session config, and a later run can replay that lockfile and fail early if the regenerated effective config drifts. ## What Changed - Add a dedicated `ConfigLockfileToml` wrapper with top-level lockfile metadata plus the replayable config: ```toml version = 1 codex_version = "..." [config] # effective ConfigToml fields ``` - Keep lockfile metadata out of regular `ConfigToml`; replay loads `ConfigLockfileToml` and then uses its nested `config` as the authoritative config layer. - Add `debug.config_lockfile.export_dir` to write `<thread_id>.config.lock.toml` when a root session starts. - Add `debug.config_lockfile.load_path` to replay a saved lockfile and validate the regenerated session lockfile against it. - Add `debug.config_lockfile.allow_codex_version_mismatch` to optionally tolerate Codex binary version drift while still comparing the rest of the lockfile. - Add `debug.config_lockfile.save_fields_resolved_from_model_catalog` so lock creation can either save model-catalog/session-resolved fields or intentionally leave those fields dynamic. - Build lockfiles from the effective config plus resolved runtime values such as model selection, reasoning settings, prompts, service tier, web search mode, feature states/config, memories config, skill instructions, and agent limits. - Materialize feature aliases and custom feature config into the lockfile so replay compares canonical resolved behavior instead of user-authored alias shape. - Strip profile/debug/file-include/environment-specific inputs from generated lockfiles so they contain replayable values rather than the inputs that produced those values. - Surface JSON-RPC server error code/data in app-server client and TUI bootstrap errors so config-lock replay failures include the actual TOML diff. - Regenerate the config schema for the new debug config keys. ## Review Notes The main flow is split across these files: - `config/src/config_toml.rs`: lockfile/debug TOML shapes. - `core/src/config/mod.rs`: loading `debug.config_lockfile.*`, replaying a lockfile as a config layer, and preserving the expected lockfile for validation. - `core/src/session/config_lock.rs`: exporting the current session lockfile and materializing resolved session/config values. - `core/src/config_lock.rs`: lockfile parsing, metadata/version checks, replay comparison, and diff formatting. ## Usage Export a lockfile from a normal session: ```sh codex -c 'debug.config_lockfile.export_dir="/tmp/codex-locks"' ``` Export a lockfile without saving model-catalog/session-resolved fields: ```sh codex -c 'debug.config_lockfile.export_dir="/tmp/codex-locks"' \ -c 'debug.config_lockfile.save_fields_resolved_from_model_catalog=false' ``` Replay a saved lockfile in a later session: ```sh codex -c 'debug.config_lockfile.load_path="/tmp/codex-locks/<thread_id>.config.lock.toml"' ``` If replay resolves to a different effective config, startup fails with a TOML diff. To tolerate Codex binary version drift during replay: ```sh codex -c 'debug.config_lockfile.load_path="/tmp/codex-locks/<thread_id>.config.lock.toml"' \ -c 'debug.config_lockfile.allow_codex_version_mismatch=true' ``` ## Limitations This does not support custom rules/network policies. ## Verification - `cargo test -p codex-core config_lock` - `cargo test -p codex-config` - `cargo test -p codex-thread-manager-sample`
jif-oai ·
2026-05-01 17:46:02 +02:00 -
Color TUI statusline from active theme (#19631)
## Why Users have shared that the TUI can feel too visually flat because themes mostly show up in code syntax highlighting. The configurable statusline is a natural place to make the active theme more visible, while still letting users keep the existing monotone statusline if they prefer it. ## What Changed - Added a statusline styling helper that builds the rendered statusline from `(StatusLineItem, text)` segments, preserving item identity while keeping the plain text output unchanged. - Derived foreground accent colors from the active syntax theme by looking up TextMate scopes through the existing syntax highlighter, with conservative ANSI fallbacks when a scope does not provide a foreground. - Tuned theme-derived colors to keep the accents visible without making the statusline feel overly bright. - Added `[tui].status_line_use_colors`, defaulting to `true`, plus a separated `/statusline` toggle so users can enable or disable theme-derived statusline colors from the setup UI. - Updated the live statusline and `/statusline` preview to use the same styled builder, while keeping terminal-title preview text plain. - Kept statusline separators and active-agent add-ons subdued while removing blanket dimming from the whole passive statusline. ## Verification - `cargo test -p codex-tui status_line` - `cargo test -p codex-tui theme_picker` - `cargo test -p codex-tui foreground_style_for_scopes` - `cargo test -p codex-tui` - `cargo test -p codex-config` - `cargo test -p codex-core status_line_use_colors` - `cargo insta pending-snapshots --manifest-path tui/Cargo.toml` ## Visual <img width="369" height="23" alt="Screenshot 2026-04-30 at 6 16 08 PM" src="https://github.com/user-attachments/assets/11d03efb-8e4f-4450-8f4d-00a9659ef4cd" /> <img width="385" height="23" alt="Screenshot 2026-04-30 at 6 16 02 PM" src="https://github.com/user-attachments/assets/a3d89f36-bdc1-42e8-8e84-61350e3999e2" />
Eric Traut ·
2026-04-30 22:42:48 -07:00 -
Format multi-day goal durations in the TUI (#20558)
## Why Goal mode shows elapsed time in compact hour/minute form. That is easy to scan for shorter runs, but once a goal runs past 24 hours, large hour counts become harder to read at a glance. ## What changed Updated `codex-rs/tui/src/goal_display.rs` so unbudgeted goal elapsed time keeps the existing compact format below one day, then switches to a day-aware format once the elapsed time reaches 24 hours: - `23h 59m` - `1d 0h 0m` - `2d 23h 42m` The formatter now covers the 24-hour boundary in unit tests, and the TUI status-line snapshot for a completed elapsed goal now exercises the multi-day display. ## Verification - `cargo test -p codex-tui` Here's my longest-running test task: <img width="186" height="23" alt="image" src="https://github.com/user-attachments/assets/cedfcdab-7f6e-44e6-8495-8a39f63973fb" />
Eric Traut ·
2026-04-30 22:42:07 -07:00 -
Make thread store process-scoped (#19474)
- Build one app-server process ThreadStore from startup config and share it with ThreadManager and CodexMessageProcessor. - Remove per-thread/fork store reconstruction so effective thread config cannot switch the persistence backend. - Add params to ThreadStore create/resume for specifying thread metadata, since otherwise the metadata from store creation would be used (incorrectly).
Tom ·
2026-04-30 21:24:59 -07:00 -
[codex] Remove unused event messages (#20511)
## Why Several legacy `EventMsg` variants were still emitted or mapped even though clients either ignored them or had moved to item/lifecycle events. `Op::Undo` had also degraded to an unavailable shim, so this removes that dead task path instead of preserving a command that cannot do useful work. `McpStartupComplete`, `WebSearchBegin`, and `ImageGenerationBegin` are intentionally kept because useful consumers still depend on them: MCP startup completion drives readiness behavior, and the begin events let app-server/core consumers surface in-progress web-search and image-generation items before the final payload arrives. ## What Changed - Removed weak legacy event variants and payloads from `codex-protocol`, including legacy agent deltas, background events, and undo lifecycle events. - Kept/restored `EventMsg::McpStartupComplete`, `EventMsg::WebSearchBegin`, and `EventMsg::ImageGenerationBegin` with serializer and emission coverage. - Updated core, rollout, MCP server, app-server thread history, review/delegate filtering, and tests to rely on the useful replacement events that remain. - Removed `Op::Undo`, `UndoTask`, the undo test module, and stale TUI slash-command comments. - Stopped agent job/background progress and compaction retry notices from emitting `BackgroundEvent` payloads. ## Verification - `cargo check -p codex-protocol -p codex-app-server-protocol -p codex-core -p codex-rollout -p codex-rollout-trace -p codex-mcp-server` - `cargo test -p codex-protocol -p codex-app-server-protocol -p codex-rollout -p codex-rollout-trace -p codex-mcp-server` - `cargo test -p codex-core --test all suite::items` - `just fix -p codex-protocol -p codex-app-server-protocol -p codex-core -p codex-rollout -p codex-rollout-trace -p codex-mcp-server` - Earlier coverage on this PR also included `codex-mcp`, `codex-tui`, core library tests, MCP/plugin/delegate/review/agent job tests, and MCP startup TUI tests.
pakrym-oai ·
2026-04-30 20:03:26 -07:00 -
Surface admin-disabled remote plugin status (#20298)
## Summary Remote plugin-service returns plugin availability separately from a user's installed/enabled state. This adds `PluginAvailabilityStatus` to the app-server protocol, propagates remote catalog `status` into `PluginSummary`, and rejects install attempts for remote plugins marked `DISABLED_BY_ADMIN` before downloading or caching the bundle. This is the `openai/codex` half of the change. The companion `openai/openai` webview PR is https://github.com/openai/openai/pull/873269. ## Validation - `cargo run -p codex-app-server-protocol --bin write_schema_fixtures` - `cargo test -p codex-app-server --test all plugin_list_marks_remote_plugin_disabled_by_admin` - `cargo test -p codex-app-server --test all plugin_list_includes_remote_marketplaces_when_remote_plugin_enabled` - `cargo test -p codex-app-server --test all plugin_install_rejects_remote_plugin_disabled_by_admin_before_download` - `cargo test -p codex-app-server-protocol schema_fixtures`
xli-oai ·
2026-04-30 20:00:07 -07:00 -
feat(tui): add vim composer mode (#18595)
## Why Codex now has configurable TUI keymaps, but the composer still behaves like a plain text field. Users who prefer modal editing need a way to keep Vim muscle memory while drafting prompts, and the keymap picker needs to expose Vim-specific actions if those bindings are configurable instead of hardcoded. ## What Changed - Adds composer Vim mode with insert/normal state, common normal-mode movement and editing commands, `d`/`y` operator-pending flows, and mode-aware footer and cursor indicators. - Adds `/vim`, an optional global `toggle_vim_mode` binding, and `tui.vim_mode_default` so Vim mode can be toggled per session or enabled as the default composer state. - Extends runtime and config keymaps with `vim_normal` and `vim_operator` contexts, exposes those contexts in `/keymap`, refreshes the config schema, and validates Vim bindings separately. - Integrates Vim normal mode with existing composer behavior: `/` opens slash command entry, `!` enters shell mode, `j`/`k` navigate history at history boundaries, successful submissions reset back to normal mode, and paste burst handling remains insert-mode only. - Teaches the TUI render path to apply and restore cursor style so Vim insert mode can use a bar cursor without leaving the terminal in that state after exit. ## Validation - `cargo test -p codex-tui keymap -- --nocapture` on the keymap/Vim coverage - `cargo insta pending-snapshots` ## Docs This introduces user-facing `/vim`, `tui.vim_mode_default`, and Vim keymap contexts under `tui.keymap`, so the public CLI configuration and slash-command docs should be updated before the feature ships.
Felipe Coury ·
2026-04-30 17:20:51 -07:00 -
fix(tui): set persist_extended_history: false (#20502)
Large rollouts are no good. This updates the TUI to behave the same as the Codex App, which is also turning it off.
Owen Lin ·
2026-04-30 23:31:31 +00:00 -
xl-openai ·
2026-04-30 14:26:14 -07:00 -
fix: show correct Bedrock runtime endpoint in /status (#20275)
## Why `/status` was showing the configured `ModelProviderInfo.base_url` for Amazon Bedrock, which can be stale or misleading because the actual Bedrock Mantle endpoint is derived at runtime from the resolved AWS region. This made sessions report the wrong provider endpoint even though requests used the correct runtime URL. ## What changed - Added `ModelProvider::runtime_base_url()` so provider implementations can expose the request-time base URL through the shared runtime provider abstraction. - Moved Bedrock region-to-Mantle URL resolution into `amazon_bedrock::mantle::runtime_base_url()`, keeping region resolution private to the Mantle module. - Overrode `runtime_base_url()` for Amazon Bedrock so it returns the resolved Mantle endpoint instead of the configured default. - Resolved and cached the runtime provider base URL during TUI startup, then used that cached value when rendering `/status`. - Added status coverage that verifies Bedrock displays the runtime URL and ignores the configured Bedrock `base_url` when they differ. ## Verification model provider is resolved correctly in local build: <img width="696" height="245" alt="Screenshot 2026-04-29 at 5 01 36 PM" src="https://github.com/user-attachments/assets/a13c10a5-3720-41ab-8ace-3c4bc573f971" />
Celia Chen ·
2026-04-30 19:02:34 +00:00 -
Add /hooks browser for lifecycle hooks (#19882)
## Why `hooks/list` and `hooks/config/write` give us read/write access to hooks and their state. This hooks up the TUI as a client so users can inspect and manage that state directly. ## What - add a two-page `/hooks` browser in the TUI: an event overview with installed/active counts, followed by a per-event handler page with toggle controls and detail rendering - thread managed-state metadata through hook discovery and `hooks/list` so the UI can label admin-managed hooks and suppress toggles for them - persist hook toggles through the existing config-write path and add snapshot coverage for the event list, handler list, managed-hook, and empty states ## Stack 1. openai/codex#19705 2. openai/codex#19778 3. openai/codex#19840 4. This PR - openai/codex#19882 ## Reviewer Notes - Main UI logic is in `codex-rs/tui/src/bottom_pane/hooks_browser_view.rs`; most of the diff is the new view plus its snapshot coverage - Request / write plumbing for opening the browser and persisting toggles is in `codex-rs/tui/src/app/background_requests.rs` and `codex-rs/tui/src/chatwidget/hooks.rs` - Outside the TUI, the only behavioral change in this PR is threading `is_managed` through hook discovery and `hooks/list` so managed hooks render as non-toggleable - The `codex-rs/tui/src/status/snapshots/` churn is unrelated merge fallout from the stacked base branch's newer permission-label rendering --------- Co-authored-by: Codex <noreply@openai.com>
Abhinav ·
2026-04-30 11:58:27 -07:00 -
Remove core protocol dependency [2/2] (#20325)
## Why With the local model layer and app-server routing in place from PR1, this PR moves the active TUI runtime onto app-server notifications. The affected pieces share the same event flow, so the command surface, session state, bottom-pane prompts, chat rendering, history/status views, and tests move together to keep the stacked branch buildable. This PR also removes the obsolete compatibility surface that is no longer used after the migration. The proposed protocol-boundary verifier layer was dropped from the stack; enforcing that final boundary will be simpler once `codex-tui` no longer needs any `codex_protocol` references. This PR is part 2 of a 2-PR stack: 1. Add TUI-owned replacement models and extract app-server event routing. 2. Move the active TUI flow to app-server notifications and delete obsolete adapter code. ## What changed - Rewired app command and session handling to use app-server request and notification shapes. - Moved approval overlays, request-user-input flows, MCP elicitation, realtime events, and review commands onto the app-server-facing model surface. - Updated chat rendering, history cells, status views, multi-agent UI, replay state, and TUI tests to use app-server notifications plus the local models introduced in PR1. - Deleted `codex-rs/tui/src/app/app_server_adapter.rs` and the superseded `chatwidget/tests/background_events.rs` fixture path. ## Verification - `cargo check -p codex-tui --tests` - Top of stack: `cargo test -p codex-tui`
Eric Traut ·
2026-04-30 11:34:34 -07:00 -
Remove core protocol dependency [1/2] (#20324)
## Why This stack moves `codex-tui` away from the core protocol event surface and toward app-server API shapes plus TUI-owned local models. This first PR sets up the lower-risk foundation: it introduces the local model surface and extracts app-server event routing into focused TUI modules while preserving the existing behavior for the larger migration in PR2. This PR is part 1 of a 2-PR stack: 1. Add TUI-owned replacement models and extract app-server event routing. 2. Move the active TUI flow to app-server notifications and delete obsolete adapter code. ## What changed - Added TUI-owned approval, diff, session state, session resume, token usage, and user-message models. - Added `app/app_server_event_targets.rs` and `app/app_server_events.rs` to hold app-server event targeting and dispatch logic outside `app.rs`. - Updated app/status tests to use the local model layer and added focused routing coverage. - Boxed a few large async TUI test futures so this base layer remains checkable without overflowing the default test stack. ## Verification - `cargo check -p codex-tui --tests`
Eric Traut ·
2026-04-30 10:52:19 -07:00 -
/plugins: remove marketplace (#19843)
This PR adds marketplace removal to the /plugins menu, giving users a way to remove user-configured plugin marketplaces. It adds a `Ctrl+R` shortcut to remove selected marketplace tabs, a confirmation prompt, loading and error states, and the app-server request flow needed to perform marketplace/remove. After a successful removal, the TUI refreshes config, plugin mentions, user config, and plugin data so the removed marketplace disappears from the menu and other surfaces in the TUI. - Add `Ctrl+R` removal option for user-configured marketplace tabs - Show marketplace removal confirmation, loading, and error states - Route `marketplace/remove` through the TUI background request flow - Refresh config, plugin mentions, and plugin data after successful removal - Adds reusable per-tab footer hints so removal guidance only appears on applicable tabs - Add test coverage for `Ctrl+R` behavior while plugin search is active Steps to test: - Add a marketplace using the TUI /plugins menu - Use Ctrl+R to remove the marketplace - Accept the confirmation prompt - Confirm the marketplace is removed when the process completes.
canvrno-oai ·
2026-04-30 10:25:07 -07:00 -
realtime: rename provider session ids (#20361)
## Summary Codex is repurposing `session` to mean a thread group, so the realtime provider session id should no longer use `session_id` / `sessionId` in Codex-facing protocol payloads. This PR renames that provider-specific field to `realtime_session_id` / `realtimeSessionId` and intentionally breaks clients that still send the old field names. ## What Changed - Renamed realtime provider session fields in `ConversationStartParams`, `RealtimeConversationStartedEvent`, and `RealtimeEvent::SessionUpdated`. - Renamed app-server v2 realtime request and notification fields to `realtimeSessionId`. - Removed legacy serde aliases for `session_id` / `sessionId`; clients must send the new names. - Propagated the rename through core realtime startup, app-server adapters, codex-api websocket handling, and TUI realtime state. - Regenerated app-server protocol schema/TypeScript outputs and updated app-server README examples. - Kept upstream Realtime API concepts unchanged: provider `session.id` parsing and `x-session-id` headers still use the upstream wire names. ## Testing - CI is running on the latest pushed commit. - Earlier local verification on this PR: - `cargo test -p codex-protocol` - `CODEX_SKIP_VENDORED_BWRAP=1 cargo test -p codex-core realtime_conversation` - `cargo test -p codex-app-server-protocol` - `CODEX_SKIP_VENDORED_BWRAP=1 cargo test -p codex-app-server realtime_conversation` - attempted `CODEX_SKIP_VENDORED_BWRAP=1 cargo test -p codex-tui` (local linker bus error while linking the test binary) --------- Co-authored-by: Codex <noreply@openai.com>
Ahmed Ibrahim ·
2026-04-30 13:39:48 +03:00 -
Michael Bolin ·
2026-04-29 20:54:59 -07:00 -
tui: return from side chat on Ctrl-D (#20282)
## Why Fixes #20264. Side conversations are an ephemeral layer on top of the main chat. Pressing `Ctrl+D` from an empty side-chat composer should unwind back to the parent thread, matching the existing side-return behavior, instead of falling through to the global quit shortcut and exiting Codex. ## What changed The side-return shortcut matcher now treats `Ctrl+D` the same way it already treats `Esc` and `Ctrl+C`. Because app-level side-return handling runs before the chat widget's global quit handling, this returns from `/side` while preserving normal `Ctrl+D` quit behavior outside side conversations. The existing shortcut coverage was updated to include lowercase and uppercase `Ctrl+D` key events. ## Verification - `cargo test -p codex-tui side_return_shortcuts_match_esc_ctrl_c_and_ctrl_d` - `cargo test -p codex-tui` starts successfully and the new shortcut test passes, but the broader suite later aborts in the unrelated existing test `app::tests::attach_live_thread_for_selection_rejects_unmaterialized_fallback_threads` with a stack overflow.
Eric Traut ·
2026-04-29 17:26:11 -07:00 -
Reduce the surface of collaboration modes (#20149)
Collaboration modes were slightly invasive both into ThreadManager construction and ModelProvider
pakrym-oai ·
2026-04-29 17:22:41 -07:00 -
Update Codex login success page UX (#20136)
## Summary update the local login success page to match the Codex desktop auth UX use theme-aware colors and an inline 20px Codex mark keep the actual localhost success page aligned with the browser auth UX PR ## Tests <img width="1728" height="1117" alt="Screenshot 2026-04-29 at 12 00 34 PM" src="https://github.com/user-attachments/assets/76a40c3f-07c3-452c-97da-e7c43717cd2c" />
rafael-jac ·
2026-04-29 19:14:53 -04:00 -
[mcp] Fix plugin MCP approval policy. (#19537)
Plugin MCP servers are loaded from plugin manifests rather than top-level `[mcp_servers]`, so their tool approval preferences need to be stored and applied through the owning plugin config. Without this, choosing "Always allow" for a plugin MCP tool could write a preference that was not reliably used on later tool calls. ## Summary - Add plugin-scoped MCP policy config under `plugins.<plugin>.mcp_servers`, including server enablement, tool allow/deny lists, server defaults, and per-tool approval modes. - Overlay plugin MCP policy onto manifest-provided server configs when plugins are loaded. - Route persistent "Always allow" writes for plugin MCP tools back to the owning `plugins.<plugin>.mcp_servers.<server>.tools.<tool>` config entry. - Reload user config after persisting an approval and make the plugin load cache config-aware so stale plugin MCP policy is not reused after `config.toml` changes. - Regenerate the config schema and add coverage for plugin MCP policy loading, approval lookup, persistence, and stale-cache prevention. ## Testing - `cargo test -p codex-config` - `cargo test -p codex-core-plugins` - `cargo test -p codex-core --lib plugin_mcp`
Matthew Zeng ·
2026-04-29 15:40:03 -07:00 -
Include auto-review rollout in feedback uploads (#20064)
## Summary - include the live auto-review trunk rollout when `/feedback` uploads logs - upload that attachment as `auto-review-rollout-<parent-thread-id>.jsonl` so it is distinguishable from the parent rollout - show the same auto-review attachment name in the TUI consent popup ## Scope - this only covers the live cached auto-review trunk for the current parent thread - it does not add durable historical parent->auto-review lookup - it does not add persisted rollout support for ephemeral parallel review forks ## UI <img width="599" height="185" alt="Screenshot 2026-04-28 at 1 17 18 PM" src="https://github.com/user-attachments/assets/6a0e79c2-5d21-4702-8a89-f765778bc9e9" /> ## Validation - `cargo test -p codex-core cached_guardian_subagent_exposes_its_rollout_path` - `cargo test -p codex-feedback` - `cargo test -p codex-app-server` - `cargo test -p codex-tui feedback_upload_consent_popup_snapshot` - `cargo test -p codex-tui feedback_good_result_consent_popup_includes_connectivity_diagnostics_filename` ## Known unrelated local failures - `cargo test -p codex-core` currently fails in the pre-existing proxy env snapshot test `tools::runtimes::tests::maybe_wrap_shell_lc_with_snapshot_keeps_user_proxy_env_when_proxy_inactive` - `cargo test -p codex-tui` currently hits pre-existing `status::*` snapshot drift unrelated to this change ## Follow-Up - persist parallel auto-review fork sessions so /feedback can include their rollout history too - attach each persisted fork as its own clearly named file, for example auto-review-rollout-<parent-thread-id>-fork <n>.jsonl, instead of merging multiple Guardian sessions into one attachment - keep the same live-session-only scope initially; durable historical parent -> auto-review lookup can remain a separate decision if we later need feedback from resumed sessions
Won Park ·
2026-04-29 11:44:55 -07:00 -
TUI: Remove core protocol dependency [3/7] (#20174)
## Why This is part 3 of a 7-PR stack to remove direct `codex_protocol::protocol` usage from `codex-tui` while keeping each layer reviewable and shippable. With `AppCommand` now explicit, the internal app event bus can carry TUI commands directly instead of bouncing through core `Op` values. ## What changed - Changed `AppEvent::CodexOp` and `AppEvent::SubmitThreadOp` to carry `AppCommand`. - Updated app-event senders and direct emitters to submit `AppCommand` values. - Adjusted tests to match `AppCommand` or convert back through `into_core()` where they intentionally assert legacy payload equality. ## Verification - `cargo test -p codex-tui --no-run`
Eric Traut ·
2026-04-29 10:52:10 -07:00 -
TUI: Remove core protocol dependency [2/7] (#20173)
## Why This is part 2 of a 7-PR stack to remove direct `codex_protocol::protocol` usage from `codex-tui` while keeping each layer reviewable and shippable. Before the TUI event bus can stop carrying core `Op` values, `AppCommand` needs to be an owned TUI command shape rather than a thin wrapper around `Op`. ## What changed - Replaced the opaque `AppCommand(Op)` wrapper with explicit owned variants for the commands the TUI submits. - Preserved `into_core()` so this layer does not yet change the app/thread submission boundary. - Kept existing core leaf types for now so this remains a mechanical command-shape refactor. ## Verification - `cargo check -p codex-tui`
Eric Traut ·
2026-04-29 10:28:04 -07:00 -
TUI: Remove core protocol dependency [1/7] (#20172)
## Why This is part 1 of a 7-PR stack to remove direct `codex_protocol::protocol` usage from `codex-tui` while keeping each layer reviewable and shippable. This first layer reduces the size of the later `chatwidget` diff by mechanically moving MCP startup bookkeeping out of the central widget file without changing the event shapes or behavior. ## What changed - Extracted MCP startup status handling into `tui/src/chatwidget/mcp_startup.rs`. - Kept the existing core event types in place for this purely mechanical move. - Updated the MCP startup tests to import the moved test-only event types directly. ## Verification - `cargo test -p codex-tui chatwidget::tests::mcp_startup`
Eric Traut ·
2026-04-29 09:10:22 -07:00 -
Use /goal resume for paused goals (#20082)
## Why The paused goal statusline currently points users at `/goal` to unpause a goal, but bare `/goal` is the summary command and does not change the goal state. Instead of making `/goal` mutate state only when a goal is paused, this gives the action an explicit command that reads naturally in the UI. ## What Changed - Replace `/goal unpause` with `/goal resume` for reactivating a paused goal. - Update the paused goal statusline and `/goal` summary copy to point at `/goal resume`.
Eric Traut ·
2026-04-29 08:56:02 -07:00 -
chore(cli) deprecate --full-auto (#20133)
## Summary Starts the process of getting rid of `--full-auto`, with some concessions: 1. Fully removes the command from the tui, since it just resolves to the default permissions there, and encourages users to use the one-time trust flow if they're not in a trusted repo. 2. Marks the command as deprecated in `codex exec`, in case users are actively relying on this. We'll remove in an upcoming n+X release. 3. Cleans up some of the `codex sandbox` cli logic, to keep supporting legacy sandbox policies for now. This isn't the cleanest setup, but I think it is worthwhile to warn users for one release before hard-removing it. ## Testing - [x] Updated unit tests
Dylan Hurd ·
2026-04-29 04:41:30 +00:00 -
Add environment provider snapshot (#20058)
## Summary - Change `EnvironmentProvider` to return concrete `Environment` instances instead of `EnvironmentConfigurations`. - Make `DefaultEnvironmentProvider` provide the provider-visible `local` environment plus optional `remote` environment from `CODEX_EXEC_SERVER_URL`. - Keep `EnvironmentManager` as the concrete cache while exposing its own explicit local environment for `local_environment()` fallback paths. ## Validation - `just fmt` - `git diff --check` --------- Co-authored-by: Codex <noreply@openai.com>
starr-openai ·
2026-04-28 20:05:18 -07:00 -
Soften skill description budget warnings (#20112)
Updates skill description budget messaging to be less alarming
xl-openai ·
2026-04-28 19:56:25 -07:00 -
Restore TUI working status after steer message is set (#19939)
Fix for #19925 Restore the `Working` indicator after a streamed final answer finishes when a user steer message is sent. Add regression coverage for long output plus a mid-stream steer: `cargo test -p codex-tui final_answer_completion_restores_status_indicator_for_pending_steer` Duplication/testing steps: 1. Start a new thread and ask for a long response. 2. While the response is streaming, submit a steer message. 3. When the first response finishes, observe whether `Working...` is shown while waiting for the steer message response.
canvrno-oai ·
2026-04-28 18:10:40 -07:00 -
Support detect and import MCP, Subagents, hooks, commands from external (#19949)
## Why This PR expands the migration path so Codex can detect and import MCP server config, hooks, commands, and subagents configs in a Codex-native shape. ## What changed - Added a `codex-external-agent-migration` crate that owns conversion logic for external-agent MCP servers, hooks, commands, and subagents. - Extended the app-server external-agent config detection/import API with migration item types for MCP server config, hooks, commands, and subagents. ## Migration strategy The migration is intentionally conservative: Codex only imports external-agent config that can be represented safely in Codex today. Unsupported or ambiguous config is skipped instead of being partially translated into behavior that may not match the source system. - **MCP servers**: import supported stdio and HTTP MCP server definitions into `mcp_servers`. Disabled servers and servers filtered out by source `enabledMcpjsonServers` / `disabledMcpjsonServers` are skipped. Project-scoped MCP entries from `.claude.json` are included when they match the repo path. - **Hooks**: import only supported command hooks into `.codex/hooks.json`. Unsupported hook features such as conditional groups, async handlers, prompt/http hooks, or unknown fields are skipped. Referenced hook scripts are copied into `.codex/hooks/`, preserving any existing target scripts. - **Commands**: import supported external commands as Codex skills under `.agents/skills/source-command-*`. Commands that rely on source runtime expansion such as `$ARGUMENTS`, `$1`, `@file` references, shell interpolation, or colliding generated names are skipped. - **Subagents**: import valid subagent Markdown files into `.codex/agents/*.toml` when they have the minimum Codex agent fields. Source model names are not migrated, so imported agents keep the user’s Codex default model; compatible reasoning effort and sandbox mode are migrated when present. - **Skills and project guidance**: copy missing skill directories into `.agents/skills` and migrate `CLAUDE.md` guidance into `AGENTS.md`, rewriting source-agent terminology to Codex terminology where appropriate. - **Detection details**: detected migration items include lightweight details for UI preview, such as MCP server names, hook event names, generated command skill names, and subagent names. Import still recomputes from disk instead of trusting details as the source of truth. - Adds focused coverage for the new migration behavior and app-server import flow. ## Verification - `cargo test -p codex-external-agent-migration` - `cargo test -p codex-hooks` - `cargo test -p codex-app-server external_agent_config` - `just bazel-lock-check`
alexsong-oai ·
2026-04-29 00:45:24 +00:00 -
app-server: notify clients of remote-control status changes (#19919)
## Why Remote-control app-server enrollments have both an internal server id and the environment id exposed to remote-control clients. App-server clients need one current status snapshot that says whether remote control is usable and which environment id, if any, is exposed. A temporary websocket disconnect is not itself an identity change. Account changes, stale enrollment invalidation, successful re-enrollment, and missing ChatGPT auth are meaningful status changes. Disabled remote control remains `disabled` regardless of auth or SQLite state. SQLite startup failure disablement and enrollment persistence failures are handled in #20068; this PR reports the resulting effective status to clients. ## What changed - Adds v2 `remoteControl/status/changed` carrying `state` and `environmentId`. - Adds `RemoteControlConnectionState` values: `disabled`, `connecting`, `connected`, and `errored`. - Exposes remote-control status updates through `RemoteControlHandle` using a Tokio watch channel. - Always sends the current remote-control status snapshot to newly initialized app-server clients. - Broadcasts status changes to initialized app-server clients when state or environment id changes. - Treats missing ChatGPT auth as an `errored` status while leaving it retryable because auth can change at runtime. - Clears `environmentId` when enrollment is cleared for account changes, auth loss, stale backend invalidation, or disabled remote control. - Updates app-server protocol schema fixtures, generated TypeScript, app-server README, remote-control tests, and TUI exhaustive notification matches. ## Stack - Builds on #20068. ## Verification - `just write-app-server-schema` - `cargo test -p codex-app-server-protocol` - `cargo test -p codex-app-server transport::remote_control --lib` - `cargo check -p codex-tui` - `just fix -p codex-app-server-protocol` - `just fix -p codex-app-server` - `just fix -p codex-tui`
Ruslan Nigmatullin ·
2026-04-28 23:52:14 +00:00 -
core tests: submit turns with permission profiles (#20010)
## Summary - Add `PermissionProfile`-based turn submission helpers to `core_test_support`, while keeping the legacy `SandboxPolicy` helper for tests that intentionally exercise legacy fallback behavior. - Switch the default `TestCodex::submit_turn()` path to send a real `PermissionProfile` plus the required legacy compatibility projection in `Op::UserTurn`. - Migrate straightforward app/search/shell/truncation tests from `SandboxPolicy::{DangerFullAccess, ReadOnly}` to `PermissionProfile::{Disabled, read_only}`. - Add a TUI compatibility projection helper for legacy app-server fields so non-legacy writable roots are preserved instead of being downgraded to read-only. - Fix remote start/resume/fork sandbox-mode projection to classify any managed profile with writable roots as workspace-write, not only profiles that can write `cwd`. - Reduce `SandboxPolicy` references in `codex-rs/core/tests` from 47 files to 41 files without changing production behavior. ## Testing - `cargo check -p codex-core --tests` - `cargo test -p codex-tui compatibility_profile_preserves_unbridgeable_write_roots` - `cargo test -p codex-tui sandbox_mode_preserves_non_cwd_write_roots_for_remote_sessions` - `just fmt` - `just fix -p core_test_support` - `just fix -p codex-core`Michael Bolin ·
2026-04-28 23:01:40 +00:00 -
/plugins: add marketplace install flow (#18704)
This PR adds a new feature to the `/plugins` menu that gives users the ability to add new plugin marketplaces. It introduces an Add Marketplace tab to the right of installed marketplaces, a source prompt, loading and error states, and the app-server request flow needed to perform the install. After a successful `marketplace/add`, the popup refreshes back into the newly added marketplace tab so the new plugins are immediately visible. - Add an Add Marketplace tab to the `/plugins` menu - Prompt for marketplace source input from git repo, URL, or local path - Show loading and error states during `marketplace/add` - Refresh plugin data after success and switch into the newly added marketplace tab - Add tests and snapshot updates
canvrno-oai ·
2026-04-28 14:22:39 -07:00 -
tui: use permission profiles for sandbox state (#20008)
## Summary - Move TUI permission state from legacy `SandboxPolicy` values to canonical `PermissionProfile` values across presets, app events, chat widget state, app commands, thread routing, and cached thread session state. - Keep app-server compatibility boundaries explicit: embedded sessions send `permissionProfile`, while remote sessions send only a legacy `sandbox` projection and fall back to read-only when a custom profile cannot be projected. - Update status/add-dir UI summaries and snapshots to render the active permission profile, including workspace profiles selected by the new built-in defaults. ## Verification - `rg '\bSandboxPolicy\b' codex-rs/tui -n` returns no matches. - `cargo test -p codex-tui` - `cargo check -p codex-tui --tests` - `cargo test -p codex-tui additional_dirs` - `just fmt` - `just fix -p codex-tui` --- [//]: # (BEGIN SAPLING FOOTER) Stack created with [Sapling](https://sapling-scm.com). Best reviewed with [ReviewStack](https://reviewstack.dev/openai/codex/pull/20008). * #20041 * #20040 * #20037 * #20035 * #20034 * #20033 * #20032 * #20030 * #20028 * #20027 * #20026 * #20024 * #20021 * #20018 * #20016 * #20015 * #20013 * #20011 * #20010 * __->__ #20008
Michael Bolin ·
2026-04-28 20:36:48 +00:00 -
Fix plan mode nudge test after task completion signature change (#20045)
Updates the plan mode nudge test to pass the new `duration_ms` argument to task completion. Co-authored-by: Codex <noreply@openai.com>
canvrno-oai ·
2026-04-28 11:24:22 -07:00 -
External agent session support (#19895)
## Summary This extends external agent detection/import beyond config artifacts so Codex can detect recent sessions files from the external agent home and import them into Codex rollout history. ## What changed - Added a focused `external_agent_sessions` module for: - session discovery - source-record parsing - rollout construction - import ledger tracking - Wired session detection/import into the app-server external agent config API. - Added compaction handling so large imported sessions can be resumed safely before the first follow-up turn. ## Testing Added coverage for: - recent-session detection - custom-title handling - recency filtering - dedupe and re-detect-after-source-change behavior - visible imported turn construction - backward-compatible import payload deserialization - end-to-end RPC import flow - rejection of undetected session paths - repeat-import behavior - large-session compaction before first follow-up Ran: - `cargo test -p codex-app-server external_agent_config_import_ --test all`
stefanstokic-oai ·
2026-04-28 17:42:36 +00:00 -
fix(tui): let esc exit empty shell mode (#19986)
## Summary - exit shell mode when `Esc` is pressed while the absorbed `!` is the only input - add direct regression coverage plus a composer snapshot for the restored normal prompt state ## Root cause Shell mode stores the leading `!` outside the editable textarea. After typing only `!`, the textarea is empty but the composer is still in bash mode, so the existing empty-composer `Esc` handling never runs. ## Validation - `just fmt` - `cargo test -p codex-tui bottom_pane::chat_composer::tests::esc_exits_empty_shell_mode` - `cargo test -p codex-tui bottom_pane::chat_composer::tests::footer_mode_snapshots` - `cargo insta pending-snapshots` `cargo test -p codex-tui` still reports unrelated existing `/status` snapshot drift in this local environment because the rendered permissions text is `workspace-write with network access` instead of the older `read-only` fixture text.
Felipe Coury ·
2026-04-28 14:35:24 -03:00 -
Move local /resume cwd filtering into thread/list (#19931)
Move local resume and fork cwd filtering to `thread/list` instead of filtering in the TUI. This makes the `/resume` menu feel slightly faster to load when working in repos with many historical threads, and centralizes the cwd filtering in app-server. **Affected:** - /resume from inside the TUI. - codex resume with no session ID and without --last - codex resume --all - codex fork with no session ID and without --last - codex fork --all **Not affected:** - codex resume <id> - codex fork <id> - codex resume --last - codex fork --last Steps to test performance improvement in a real Codex environment: - Launch `codex resume` using compiled binary in a directory that has seen many threads. - Launch `codex resume` using release binary in same directory. - Observe difference in time-to-full-page as threads load.
canvrno-oai ·
2026-04-28 10:35:10 -07:00