Conversation
Adds `--branch` to `codex cloud exec` to set base branch.
- Inline response recording during streaming: `run_turn` now records items as they arrive instead of building a `ProcessedResponseItem` list and post‑processing via `process_items`. - Simplify turn handling: `handle_output_item_done` returns the follow‑up signal + optional tool future; `needs_follow_up` is set only there, and in‑flight tool futures are drained once at the end (errors logged, no extra state writes). - Flattened stream loop: removed `process_items` indirection and the extra output queue - - Tests: relaxed `tool_parallelism::tool_results_grouped` to allow any completion order while still requiring matching call/output IDs.
- Use the codex-api crate to introduce models endpoint. - Add `models` to codex core tests helpers - Add `ModelsInfo` for the endpoint return type
Seems like a nice field to have, and also VSCE does render this one.
VSCE renders `codex/event/stream_error` (automatically retried, e.g. `"Reconnecting... 1/n"`) and `codex/event/error` (terminal errors) differently, so add `will_retry` on ErrorNotification to indicate this.
**Summary**
- Shortcut toggle using `?` in `handle_shortcut_overlay_key` fails to
trigger on some platforms (notably Windows). Current match requires
`KeyCode::Char('?')` with `KeyModifiers::NONE`. Some terminals set
`SHIFT` when producing `?` (since it is typically `Shift + /`), so the
strict `NONE` check prevents toggling.
**Impact**
- On Windows consoles/terminals, pressing `?` with an empty composer
often does nothing, leading to inconsistent UX compared to macOS/Linux.
**Root Cause**
- Crossterm/terminal backends report modifiers inconsistently across
platforms. Generating `?` may include `SHIFT`. The code enforces
`modifiers == NONE`, so valid `?` presses with `SHIFT` are ignored.
AltGr keyboards may also surface as `ALT`.
**Repro Steps**
- Open the TUI, ensure the composer is empty.
- Press `?`.
- Expected: Shortcut overlay toggles.
- Actual (Windows frequently): No toggle occurs.
**Fix Options**
- Option 1 (preferred): Accept `?` regardless of `SHIFT`, but reject
`CONTROL` and `ALT`.
- Rationale: Keeps behavior consistent across platforms with minimal
code change.
- Example change:
- Before: matching `KeyModifiers::NONE` only.
- After: allow `SHIFT`, disallow `CONTROL | ALT`.
- Suggested condition:
```rust
let toggles = matches!(key_event.code, KeyCode::Char('?'))
&& !key_event.modifiers.intersects(KeyModifiers::CONTROL |
KeyModifiers::ALT)
&& self.is_empty();
```
- Option 2: Platform-specific handling (Windows vs non-Windows).
- Implement two variants or conditional branches using `#[cfg(target_os
= "windows")]`.
- On Windows, accept `?` with `SHIFT`; on other platforms, retain
current behavior.
- Trade-off: Higher maintenance burden and code divergence for limited
benefit.
---
close #5495
…#7615) The caller should decide whether wrapping the policy in `Arc<RwLock>` is necessary. This should make openai/codex#7609 a bit smoother. - `exec_policy_for()` -> `load_exec_policy_for_features()` - introduce `load_exec_policy()` that does not take `Features` as an arg - both return `Result<Policy, ExecPolicyError>` instead of Result<Arc<RwLock<Policy>>, ExecPolicyError>` This simplifies the tests as they have no need for `Arc<RwLock>`.
## Summary This PR introduces an End to End test suite for apply-patch, so we can easily validate behavior against other implementations as well. ## Testing - [x] These are tests
- Introduce `with_remote_overrides` and update `refresh_available_models` - Put `auth_manager` instead of `auth_mode` on `models_manager` - Remove `ShellType` and `ReasoningLevel` to use already existing structs
adding execpolicy support into the `posix` mcp Co-authored-by: Michael Bolin <mbolin@openai.com>
…(#7610) pull plan type from the usage endpoint, persist it in session state / tui state, and propagate through rate limit snapshots
- This PR wires `with_remote_overrides` and make the `construct_model_families` an async function - Moves getting model family a level above to keep the function `sync` - Updates the tests to local, offline, and `sync` helper for model families
## Summary Adds the `login` parameter to the `shell_command` tool - optional, defaults to true. ## Testing - [x] Tested locally
Fix unified_exec on windows Requires removal of PSUEDOCONSOLE_INHERIT_CURSOR flag so child processed don't attempt to wait for cursor position response (and timeout). https://github.com/wezterm/wezterm/compare/main...pakrym:wezterm:PSUEDOCONSOLE_INHERIT_CURSOR?expand=1 --------- Co-authored-by: pakrym-oai <pakrym@openai.com>
Adds cli commands for getting the status of cloud tasks, and for getting/applying the diffs from same.
## Summary - move the workspace justfile to the repository root for easier discovery - set the just working directory to codex-rs so existing recipes still run in the Rust workspace ## Testing - not run (not requested) ------ [Codex Task](https://chatgpt.com/codex/tasks/task_i_69334db473108329b0cc253b7fd8218e)
## Summary This PR is heavily based on #4017, which contains the core logic for the fix. To reduce the risk, we are first introducing it only on windows. We can then expand to wsl / other environments as needed, and then tackle net new files. ## Testing - [x] added unit tests in apply-patch - [x] add integration tests to apply_patch_cli.rs --------- Co-authored-by: Chase Naples <Cnaples79@gmail.com>
Also load skills from /REPO_ROOT/codex/skills.
This fixes two issues with the OTEL HTTP exporter: 1. **Runtime panic with async reqwest client** The `opentelemetry_sdk` `BatchLogProcessor` spawns a dedicated OS thread that uses `futures_executor::block_on()` rather than tokio's runtime. When the async reqwest client's timeout mechanism calls `tokio::time::sleep()`, it panics with "there is no reactor running, must be called from the context of a Tokio 1.x runtime". The fix is to use `reqwest::blocking::Client` instead, which doesn't depend on tokio for timeouts. However, the blocking client creates its own internal tokio runtime during construction, which would panic if built from within an async context. We wrap the construction in `tokio::task::block_in_place()` to handle this. 2. **mTLS certificate handling** The HTTP client wasn't properly configured for mTLS, matching the fixes previously done for the model provider client: - Added `.tls_built_in_root_certs(false)` when using a custom CA certificate to ensure only our CA is trusted - Added `.https_only(true)` when using client identity - Added `rustls-tls` feature to ensure rustls is used (required for `Identity::from_pem()` to work correctly)
Previous to this change, large `EscalateRequest` payloads exceeded the kernel send buffer, causing our single `sendmsg(2)` call (with attached FDs) to be split and retried without proper control handling; this led to `EINVAL`/broken pipe in the `handle_escalate_session_respects_run_in_sandbox_decision()` test when using an `env` with large contents. **Before:** `AsyncSocket::send_with_fds()` called `send_json_message()`, which called `send_message_bytes()`, which made one `socket.sendmsg()` call followed by additional `socket.send()` calls, as necessary: https://github.com/openai/codex/blob/2e4a40252157751765dff176b35c692df8a9fb4e/codex-rs/exec-server/src/posix/socket.rs#L198-L209 **After:** `AsyncSocket::send_with_fds()` now calls `send_stream_frame()`, which calls `send_stream_chunk()` one or more times. Each call to `send_stream_chunk()` calls `socket.sendmsg()`. In the previous implementation, the subsequent `socket.send()` writes had no control information associated with them, whereas in the new `send_stream_chunk()` implementation, a fresh `MsgHdr` (using `with_control()`, as appropriate) is created for `socket.sendmsg()` each time. Additionally, with this PR, stream sending attaches `SCM_RIGHTS` only on the first chunk, and omits control data when there are no FDs, allowing oversized payloads to deliver correctly while preserving FD limits and error checks.
## Summary - Updated the rmcp client flag's documentation in config.md file - changed it from `experimental_use_rmcp_client` to `rmcp_client`
Removed experimental Rust MCP client option from config.
Update install and contributing guides to use the root justfile helpers (`just fmt`, `just fix -p <crate>`, and targeted tests) instead of the older cargo fmt/clippy/test instructions that have been in place since 459363e. This matches the justfile relocation to the repo root in 952d6c9 and the current lint/test workflow for CI (see `.github/workflows/rust-ci.yml`).
When I put up openai/codex#7617 for review, initially I started seeing failures on the `ubuntu-24.04` runner used for Rust test runs for the `x86_64-unknown-linux-gnu` architecture. Chat suggested a number of things that could be removed to save space, which seems to help.
…ixes (#7680) As noted in the code comment, we introduced a key fix for `brew` in Homebrew/brew#21157 that Codex needs, but it has not hit stable yet, so we update our CI job to use latest `brew` from `origin/main`. This is necessary for the new integration tests introduced in openai/codex#7617.
…(#7617) This PR introduces integration tests that run [codex-shell-tool-mcp](https://www.npmjs.com/package/@openai/codex-shell-tool-mcp) as a user would. Note that this requires running our fork of Bash, so we introduce a [DotSlash](https://dotslash-cli.com/) file for `bash` so that we can run the integration tests on multiple platforms without having to check the binaries into the repository. (As noted in the DotSlash file, it is slightly more heavyweight than necessary, which may be worth addressing as disk space in CI is limited: openai/codex#7678.) To start, this PR adds two tests: - `list_tools()` makes the `list_tools` request to the MCP server and verifies we get the expected response - `accept_elicitation_for_prompt_rule()` defines a `prefix_rule()` with `decision="prompt"` and verifies the elicitation flow works as expected Though the `accept_elicitation_for_prompt_rule()` test **only works on Linux**, as this PR reveals that there are currently issues when running the Bash fork in a read-only sandbox on Linux. This will have to be fixed in a follow-up PR. Incidentally, getting this test run to correctly on macOS also requires a recent fix we made to `brew` that hasn't hit a mainline release yet, so getting CI green in this PR required openai/codex#7680.
We should not have any `PathBuf` fields in `ConfigToml` or any of the transitive structs we include, as we should use `AbsolutePathBuf` instead so that we do not have to keep track of the file from which `ConfigToml` was loaded such that we need it to resolve relative paths later when the values of `ConfigToml` are used. I only found two instances of this: `experimental_instructions_file` and `experimental_compact_prompt_file`. Incidentally, when these were specified as relative paths, they were resolved against `cwd` rather than `config.toml`'s parent, which seems wrong to me. I changed the behavior so they are resolved against the parent folder of the `config.toml` being parsed, which we get "for free" due to the introduction of `AbsolutePathBufGuard ` in openai/codex#7796. While it is not great to change the behavior of a released feature, these fields are prefixed with `experimental_`, which I interpret to mean we have the liberty to change the contract. For reference: - `experimental_instructions_file` was introduced in openai/codex#1803 - `experimental_compact_prompt_file` was introduced in openai/codex#5959
### Summary * Make `app_server.list_models` to be non-blocking and consumers (i.e. extension) can manage the flow themselves. * Force config to use remote models and therefore fetch codex-auto model list.
- Load models from static file as a fallback - Make API users use this file directly - Add tests to make sure updates to the file always serialize
- Batch read ACL creation for online/offline sandbox user - creates a new ACL helper process that is long-lived and runs in the background - uses a mutex so that only one helper process is running at a time.
# External (non-OpenAI) Pull Request Requirements Before opening this Pull Request, please read the dedicated "Contributing" markdown file or your PR may be closed: https://github.com/openai/codex/blob/main/docs/contributing.md If your PR conforms to our contribution guidelines, replace this text with a detailed and high quality description of your changes. Include a link to a bug report or enhancement request.
This PR does various types of cleanup before I can proceed with more ambitious changes to config loading. First, I noticed duplicated code across these two methods: https://github.com/openai/codex/blob/774bd9e432fa2e0f4e059e97648cf92216912e19/codex-rs/core/src/config/mod.rs#L314-L324 https://github.com/openai/codex/blob/774bd9e432fa2e0f4e059e97648cf92216912e19/codex-rs/core/src/config/mod.rs#L334-L344 This has now been consolidated in `load_config_as_toml_with_cli_overrides()`. Further, I noticed that `Config::load_with_cli_overrides()` took two similar arguments: https://github.com/openai/codex/blob/774bd9e432fa2e0f4e059e97648cf92216912e19/codex-rs/core/src/config/mod.rs#L308-L311 The difference between `cli_overrides` and `overrides` was not immediately obvious to me. At first glance, it appears that one should be able to be expressed in terms of the other, but it turns out that some fields of `ConfigOverrides` (such as `cwd` and `codex_linux_sandbox_exe`) are, by design, not configurable via a `.toml` file or a command-line `--config` flag. That said, I discovered that many callers of `Config::load_with_cli_overrides()` were passing `ConfigOverrides::default()` for `overrides`, so I created two separate methods: - `Config::load_with_cli_overrides(cli_overrides: Vec<(String, TomlValue)>)` - `Config::load_with_cli_overrides_and_harness_overrides(cli_overrides: Vec<(String, TomlValue)>, harness_overrides: ConfigOverrides)` The latter has a long name, as it is _not_ what should be used in the common case, so the extra typing is designed to draw attention to this fact. I tried to update the existing callsites to use the shorter name, where possible. Further, in the cases where `ConfigOverrides` is used, usually only a limited subset of fields are actually set, so I updated the declarations to leverage `..Default::default()` where possible.
# External (non-OpenAI) Pull Request Requirements Before opening this Pull Request, please read the dedicated "Contributing" markdown file or your PR may be closed: https://github.com/openai/codex/blob/main/docs/contributing.md If your PR conforms to our contribution guidelines, replace this text with a detailed and high quality description of your changes. Include a link to a bug report or enhancement request.
1. Remove PUBLIC skills and introduce SYSTEM skills embedded in the binary and installed into $CODEX_HOME/skills/.system at startup. 2. Skills are now always enabled (feature flag removed). 3. Update skills/list to accept forceReload and plumb it through (not used by clients yet).
Instead of failing to start Codex, clearly call out that N skills did not load and provide warnings so that the user may fix them. <img width="3548" height="874" alt="image" src="https://github.com/user-attachments/assets/6ce041b2-1373-4007-a6dd-0194e58fafe4" />
Introduce `ConfigBuilder` as an alternative to our existing `Config` constructors. I noticed that the existing constructors, `Config::load_with_cli_overrides()` and `Config::load_with_cli_overrides_and_harness_overrides()`, did not take `codex_home` as a parameter, which can be a problem. Historically, when Codex was purely a CLI, we wanted to be extra sure that the creation of `codex_home` was always done via `find_codex_home()`, so we did not expose `codex_home` as a parameter when creating `Config` in business logic. But in integration tests, `codex_home` nearly always needs to be configured (as a temp directory), which is why callers would have to go through `Config::load_from_base_config_with_overrides()` instead. Now that the Codex harness also functions as an app server, which could conceivably load multiple threads where `codex_home` is parameterized differently in each one, I think it makes sense to make this configurable. Going to a builder pattern makes it more flexible to ensure an arbitrary permutation of options can be set when constructing a `Config` while using the appropriate defaults for the options that aren't set explicitly. Ultimately, I think this should make it possible for us to make `Config::load_from_base_config_with_overrides()` private because all integration tests should be able to leverage `ConfigBuilder` instead. Though there could be edge cases, so I'll pursue that migration after we get through the current config overhaul. --- [//]: # (BEGIN SAPLING FOOTER) Stack created with [Sapling](https://sapling-scm.com). Best reviewed with [ReviewStack](https://reviewstack.dev/openai/codex/pull/8235). * #8237 * __->__ #8235
This pull request updates the ChatGPT login description in the onboarding authentication widgets to clarify which plans include usage. The description now lists "Business" rather than "Team" and adds "Education" plans in addition to the previously mentioned plans. I have read the CLA Document and I hereby sign the CLAs. --------- Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
1. Reintroduce feature flags for skills; 2. UI tweaks (truncate descriptions, better validation error display).
Over in `config_loader/macos.rs`, we were doing this complicated `mod` thing to expose one version of `load_managed_admin_config_layer()` for Mac: https://github.com/openai/codex/blob/580c59aa9af61cb4bffb5b204bd16a5dcc4bc911/codex-rs/core/src/config_loader/macos.rs#L4-L5 While exposing a trivial implementation for non-Mac: https://github.com/openai/codex/blob/580c59aa9af61cb4bffb5b204bd16a5dcc4bc911/codex-rs/core/src/config_loader/macos.rs#L110-L117 That was being used like this: https://github.com/openai/codex/blob/580c59aa9af61cb4bffb5b204bd16a5dcc4bc911/codex-rs/core/src/config_loader/layer_io.rs#L47-L48 This PR simplifies that callsite in `layer_io.rs` to just be: ```rust #[cfg(not(target_os = "macos"))] let managed_preferences = None; ``` And updates `config_loader/mod.rs` so we only pull in `macos.rs` on Mac: ```rust #[cfg(target_os = "macos")] mod macos; ``` This simplifies `macos.rs` considerably, though it looks like a big change because everything gets unindented and reformatted because we can drop the whole `mod native` thing now. --- [//]: # (BEGIN SAPLING FOOTER) Stack created with [Sapling](https://sapling-scm.com). Best reviewed with [ReviewStack](https://reviewstack.dev/openai/codex/pull/8248). * #8251 * #8249 * __->__ #8248
# External (non-OpenAI) Pull Request Requirements Before opening this Pull Request, please read the dedicated "Contributing" markdown file or your PR may be closed: https://github.com/openai/codex/blob/main/docs/contributing.md If your PR conforms to our contribution guidelines, replace this text with a detailed and high quality description of your changes. Include a link to a bug report or enhancement request.
This is some minor API cleanup that will make it easier to use `AbsolutePathBuf` in more places in a subsequent PR.
This pull request makes a small update to the session picker documentation for `codex resume`. The main change clarifies how to view the original working directory (CWD) for sessions and when the Git branch is shown. - The session picker now displays the recorded Git branch when available, and instructions are added for showing the original working directory by using the `--all` flag, which also disables CWD filtering and adds a `CWD` column.
Welcome caribou <img width="1536" height="1024" alt="image" src="https://github.com/user-attachments/assets/2a67b21f-40cf-4518-aee4-691af331ab50" />
Add a name to Beta features <img width="906" height="153" alt="Screenshot 2025-12-18 at 16 42 49" src="https://github.com/user-attachments/assets/d56f3519-0613-4d9a-ad4d-38b1a7eb125a" />
## Summary - add a shared git-ref resolver and use it for `codex cloud exec` and TUI task submission - expose a new `--branch` flag to override the git ref passed to cloud tasks - cover the git-ref resolution behavior with new async unit tests and supporting dev dependencies ## Testing - cargo test -p codex-cloud-tasks ------ [Codex Task](https://chatgpt.com/codex/tasks/task_i_692decc6cbec8332953470ef063e11ab) --------- Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> Co-authored-by: Jeremy Rose <172423086+nornagon-openai@users.noreply.github.com> Co-authored-by: Jeremy Rose <nornagon@openai.com>
This is a significant change to how layers of configuration are applied. In particular, the `ConfigLayerStack` now has two important fields: - `layers: Vec<ConfigLayerEntry>` - `requirements: ConfigRequirements` We merge `TomlValue`s across the layers, but they are subject to `ConfigRequirements` before creating a `Config`. How I would review this PR: - start with `codex-rs/app-server-protocol/src/protocol/v2.rs` and note the new variants added to the `ConfigLayerSource` enum: `LegacyManagedConfigTomlFromFile` and `LegacyManagedConfigTomlFromMdm` - note that `ConfigLayerSource` now has a `precedence()` method and implements `PartialOrd` - `codex-rs/core/src/config_loader/layer_io.rs` is responsible for loading "admin" preferences from `/etc/codex/managed_config.toml` and MDM. Because `/etc/codex/managed_config.toml` is now deprecated in favor of `/etc/codex/requirements.toml` and `/etc/codex/config.toml`, we now include some extra information on the `LoadedConfigLayers` returned in `layer_io.rs`. - `codex-rs/core/src/config_loader/mod.rs` has major changes to `load_config_layers_state()`, which is what produces `ConfigLayerStack`. The docstring has the new specification and describes the various layers that will be loaded and the precedence order. - It uses the information from `LoaderOverrides` "twice," both in the spirit of legacy support: - We use one instances to derive an instance of `ConfigRequirements`. Currently, the only field in `managed_config.toml` that contributes to `ConfigRequirements` is `approval_policy`. This PR introduces `Constrained::allow_only()` to support this. - We use a clone of `LoaderOverrides` to derive `ConfigLayerSource::LegacyManagedConfigTomlFromFile` and `ConfigLayerSource::LegacyManagedConfigTomlFromMdm` layers, as appropriate. As before, this ends up being a "best effort" at enterprise controls, but is enforcement is not guaranteed like it is for `ConfigRequirements`. - Now we only create a "user" layer if `$CODEX_HOME/config.toml` exists. (Previously, a user layer was always created for `ConfigLayerStack`.) - Similarly, we only add a "session flags" layer if there are CLI overrides. - `config_loader/state.rs` contains the updated implementation for `ConfigLayerStack`. Note the public API is largely the same as before, but the implementation is quite different. We leverage the fact that `ConfigLayerSource` is now `PartialOrd` to ensure layers are in the correct order. - A `Config` constructed via `ConfigBuilder.build()` will use `load_config_layers_state()` to create the `ConfigLayerStack` and use the associated `ConfigRequirements` when constructing the `Config` object. - That said, a `Config` constructed via `Config::load_from_base_config_with_overrides()` does _not_ yet use `ConfigBuilder`, so it creates a `ConfigRequirements::default()` instead of loading a proper `ConfigRequirements`. I will fix this in a subsequent PR. Then the following files are mostly test changes: ``` codex-rs/app-server/tests/suite/v2/config_rpc.rs codex-rs/core/src/config/service.rs codex-rs/core/src/config_loader/tests.rs ``` Again, because we do not always include "user" and "session flags" layers when the contents are empty, `ConfigLayerStack` sometimes has fewer layers than before (and the precedence order changed slightly), which is the main reason integration tests changed.
# External (non-OpenAI) Pull Request Requirements Before opening this Pull Request, please read the dedicated "Contributing" markdown file or your PR may be closed: https://github.com/openai/codex/blob/main/docs/contributing.md If your PR conforms to our contribution guidelines, replace this text with a detailed and high quality description of your changes. Include a link to a bug report or enhancement request.
Upstream Release Summary: rust-v0.75.0This sync brings in 4 commits from upstream (501 commits when counting the full history merge). Release NotesSource: openai/codex rust-v0.75.0 Changes Summary1. Configuration Loading Strategy Migration (#8251) 🔧Most significant architectural change in this release
2. Cloud Execution Branch Handling (#7460) ☁️
3. Splash Screen Enhancement (#8270) 🎨
Vital Work Items for NoriBased on the upstream changes, here are recommended action items for the nori project:
Recommendation: Prioritize items #1 and #2 as they represent the most significant architectural changes that could impact core functionality. |
Upstream Sync
This PR syncs changes from upstream release
rust-v0.75.0.Summary
rust-v0.75.0Workflow Sanitization
The following upstream workflows had their triggers replaced with `workflow_dispatch`:
cargo-deny.ymlci.ymlcla.ymlclose-stale-contributor-prs.ymlcodespell.ymlissue-deduplicator.ymlissue-labeler.ymlrust-release-prepare.ymlrust-release.ymlsdk.ymlshell-tool-mcp-ci.ymlshell-tool-mcp.ymlMerge Instructions
git checkout dev git merge sync/upstream-v0.75.0 --no-ff # Resolve conflicts if anycd codex-rs && cargo testcargo insta reviewAfter Merge
sync/upstream-v0.75.0branch