## Why
Image-view results should be represented as a core-produced turn item
instead of being reconstructed by app-server. At the same time, existing
rollout/history paths still understand the legacy `ViewImageToolCall`
event, so this keeps that event as compatibility output generated from
the new item lifecycle.
## What changed
- Added `TurnItem::ImageView` to `codex-protocol`.
- Emitted image-view item start/completion directly from the core
`view_image` handler.
- Kept `ViewImageToolCall` as a legacy event and generate it from
completed `TurnItem::ImageView` items.
- Kept `thread_history.rs` on the legacy `ViewImageToolCall` replay
path, with `ImageView` item lifecycle events ignored there.
- Updated app-server protocol conversion, rollout persistence, and
affected exhaustive event matches for the new item plus legacy fan-out
shape.
## Verification
- `cargo test -p codex-protocol -p codex-app-server-protocol -p
codex-rollout -p codex-rollout-trace -p codex-mcp-server -p
codex-app-server --lib`
- `cargo test -p codex-core --test all
view_image_tool_attaches_local_image`
- `just fix -p codex-protocol -p codex-core -p codex-app-server-protocol
-p codex-app-server -p codex-rollout -p codex-rollout-trace -p
codex-mcp-server`
- `git diff --check`
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.
## Why
`ConfigBuilder::build` performs a large amount of async config loading.
Leaving that entire future on the caller stack makes config startup more
fragile on small runtime worker stacks.
## What changed
- keep `ConfigBuilder::build` as a thin wrapper that boxes the
config-loading future before awaiting it
- move the existing implementation into a private `build_inner` method
so the large async state machine lives on the heap instead of the
runtime thread stack
## Testing
- Not run locally
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`
## Summary
- make selected turn environments the source of truth for session
runtime cwd and MCP runtime environment selection
- keep local/no-selection fallback behavior intact
- add coverage for duplicate selected environments, cwd resolution, and
MCP runtime environment selection
## Validation
- git diff --check
- rustfmt was run on touched Rust files during the implementation
workflow
CI should provide the full Bazel/test signal.
---------
Co-authored-by: Codex <noreply@openai.com>
## Summary
- Route loaded `thread/read` + `includeTurns` through
`CodexThread::load_history` / ThreadStore history instead of direct
rollout JSONL reads.
- Add an in-memory ThreadStore regression test covering loaded
`thread/read includeTurns` without a local rollout path.
# Why
`notify` is the remaining compatibility surface from the legacy hook
implementation. The newer lifecycle hook engine now owns the active hook
system, so we should start steering users away from adding new `notify`
configs before removing the old path entirely. This also adds a
lightweight watchpoint for the deprecation so we can see how much legacy
usage remains before the clean drop.
# What
- emit a startup deprecation notice when a non-empty `notify` command is
configured
- emit `codex.notify.configured` when a session starts with legacy
`notify` configured
- emit `codex.notify.run` when the legacy notify path fires after a
completed turn
- mark `notify` as deprecated in the config schema and repo docs
- remove the orphaned `codex-rs/hooks/src/user_notification.rs` file
that is no longer compiled
- add regression coverage for the new deprecation notice
# Next steps
A follow-up PR can remove the legacy notify path entirely once we are
ready for the clean drop. Before then, we can watch
`codex.notify.configured` and `codex.notify.run` to understand the
deprecation impact and remaining active usage. The cleanup PR should
then delete the `notify` config field, the `legacy_notify`
implementation, the old compatibility dispatch types and callsites that
only exist for the legacy path, and the remaining compatibility
docs/tests.
# Testing
- `cargo test -p codex-hooks`
- `cargo test -p codex-config`
- `cargo test -p codex-core emits_deprecation_notice_for_notify`