Commit Graph

11 Commits

Author SHA1 Message Date
jif-oai
0b04d1b3cc 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`
2026-05-01 17:46:02 +02:00
Eric Traut
a93c89f497 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"
/>
2026-04-30 22:42:48 -07:00
Tom
fe05acad23 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).
2026-04-30 21:24:59 -07:00
Felipe Coury
b6f81257f8 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.
2026-04-30 17:20:51 -07:00
pakrym-oai
b52083146c Stop emitting item/fileChange/outputDelta output delta notifications (#20471)
## Why

`item/fileChange/outputDelta` text output was only the tool's summary or
error text and not used by client surfaces.

We keep `item/fileChange/outputDelta` in the app-server protocol as a
deprecated compatibility entry, but the server no longer emits it.

## What changed

- stop the `apply_patch` runtime from emitting `ExecCommandOutputDelta`
events
- simplify `item_event_to_server_notification` so command output deltas
always map to `item/commandExecution/outputDelta`
- remove the app-server bookkeeping that tried to detect whether an
output delta belonged to a file change
- mark `item/fileChange/outputDelta` as a deprecated legacy protocol
entry in the v2 types, schema, and README
- simplify the file-change approval tests so they only wait for
completion instead of expecting output-delta notifications

## Testing

- `cargo test -p codex-app-server-protocol`
- `cargo test -p codex-thread-manager-sample`
- `cargo test -p codex-app-server-protocol
protocol::event_mapping::tests::exec_command_output_delta_maps_to_command_execution_output_delta
-- --exact`
- `cargo test -p codex-app-server
turn_start_file_change_approval_accept_for_session_persists_v2 --
--exact` *(failed before the test assertions because the wiremock
`/responses` mock received 0 requests in setup)*
2026-04-30 11:42:07 -07:00
pakrym-oai
5cc5f12efc Move item event mapping into app-server-protocol (#20299)
## Why

Follow-up to #20291.

The v2 item-event-to-notification translation had been embedded in
`app-server/src/bespoke_event_handling.rs`, which made it hard to reuse
anywhere else. This PR moves that stateless mapping into shared protocol
code so other entry points can produce the same `ServerNotification`
payloads without copying app-server logic.

That also lets `thread-manager-sample` demonstrate the same notification
surface that the app server exposes, instead of only printing the final
assistant message.

## What changed

- move `item_event_to_server_notification` into
`codex-app-server-protocol::protocol::event_mapping`
- keep the mapper tests next to the shared implementation in
`codex-app-server-protocol`
- re-export the mapper from `codex-core-api` so lightweight consumers
can use it without reaching into `app-server-protocol` directly
- simplify `app-server/src/bespoke_event_handling.rs` so it delegates
the stateless event-to-notification projection to the shared helper
- update `thread-manager-sample` to:
  - print mapped notifications as newline-delimited JSON
  - use the shared mapper through `codex-core-api`
- enable the default feature set so the sample exposes the normal tool
surface
- use a `read_only` permission profile so shell commands can run in the
sample without widening permissions

## Testing

- `cargo test -p codex-app-server-protocol`
- `cargo test -p codex-core-api`
- `cargo test -p codex-app-server bespoke_event_handling::tests`
- `cargo test -p codex-thread-manager-sample`
- `cargo run -p codex-thread-manager-sample -- "briefly explore the repo
with pwd and ls, then summarize it"`
2026-04-30 11:02:13 -07:00
Michael Bolin
ac4332c05b permissions: expose active profile metadata (#20095) 2026-04-29 20:54:59 -07:00
pakrym-oai
fedcefe9da Reduce the surface of collaboration modes (#20149)
Collaboration modes were slightly invasive both into ThreadManager
construction and ModelProvider
2026-04-29 17:22:41 -07:00
pakrym-oai
8de2a7a16d Add codex-core public API listing (#20243)
Summary:
- Add a checked-in codex-core public API listing generated by
cargo-public-api.
- Add scripts/regen-public-api.sh with an embedded crate list,
auto-install for cargo-public-api 0.51.0, pinned nightly, and --check
mode.
- Add Rust CI jobs on the codex Linux x64 runner pool to verify the
listing stays up to date.

Testing:
- bash -n scripts/regen-public-api.sh
- just regen-public-api --check
- yq '.' .github/workflows/rust-ci.yml
.github/workflows/rust-ci-full.yml
- git diff --check
2026-04-29 22:58:08 +00:00
Alex Daley
f63b19bedd [apps] Add apps MCP path override (#20231)
Summary

- Add `[features.apps_mcp_path_override]` config with a `path` field for
overriding only the built-in apps MCP path.
- Keep existing host/base URL derivation unchanged and append the
configured path after that base.
- Regenerate the config schema with the custom feature-config case.

Test Plan

- Not run for latest revision; only `just fmt` and `just
write-config-schema` were run.
- Earlier revision: `cargo test -p codex-features`
- Earlier revision: `cargo test -p codex-mcp`
2026-04-29 18:08:06 -04:00
pakrym-oai
8356806fc9 Add ThreadManager sample crate (#20141)
Summary:
- Add codex-thread-manager-sample, a one-shot binary that starts a
ThreadManager thread, submits a prompt, and prints the final assistant
output.
- Pass ThreadStore into ThreadManager::new and expose
thread_store_from_config for existing callsites.
- Build the sample Config directly with only --model and prompt inputs.

Verification:
- just fmt
- cargo check -p codex-thread-manager-sample -p codex-app-server -p
codex-mcp-server
- git diff --check

Tests: Not run per request.
2026-04-29 11:21:06 -07:00