Codex may run many per-thread proxy instances, so hardcoded proxy ports
are brittle and conflict-prone. The previous "ephemeral" approach still
had a race: `build()` read `local_addr()` from temporary listeners and
dropped them before `run()` rebound the ports. That left a
[TOCTOU](https://en.wikipedia.org/wiki/Time-of-check_to_time-of-use)
window where the OS (or another process) could reuse the same port,
causing intermittent `EADDRINUSE` and partial proxy startup.
Change the managed proxy path to reserve real listener sockets up front
and keep them alive until startup:
- add `ReservedListeners` on `NetworkProxy` to hold HTTP/SOCKS/admin std
listeners allocated during `build()`
- in managed mode, bind `127.0.0.1:0` for each listener and carry those
bound sockets into `run()` instead of rebinding by address later
- add `run_*_with_std_listener` entry points for HTTP, SOCKS5, and admin
servers so `run()` can start services from already-reserved sockets
- keep static/configured ports only when `managed_by_codex(false)`,
including explicit `socks_addr` override support
- remove fallback synthetic port allocation and add tests for managed
ephemeral loopback binding and unmanaged configured-port behavior
This makes managed startup deterministic, avoids port collisions, and
preserves the intended distinction between Codex-managed ephemeral ports
and externally managed fixed ports.
The dynamic model refresh feature (`https://api.openai.com/v1/models`
endpoint) is currently gated on a runtime check for an auth method other
than API Key. It should be gated on a check specifically for ChatGPT
Auth because some custom model providers (e.g. for local models) use no
auth mechanism. A call to `self.auth_manager.auth_mode()` will return
`None` in this case.
Addresses #11213
Bumps [regex](https://github.com/rust-lang/regex) from 1.12.2 to 1.12.3.
<details>
<summary>Changelog</summary>
<p><em>Sourced from <a
href="https://github.com/rust-lang/regex/blob/master/CHANGELOG.md">regex's
changelog</a>.</em></p>
<blockquote>
<h1>1.12.3 (2025-02-03)</h1>
<p>This release excludes some unnecessary things from the archive
published to
crates.io. Specifically, fuzzing data and various shell scripts are now
excluded. If you run into problems, please file an issue.</p>
<p>Improvements:</p>
<ul>
<li><a
href="https://redirect.github.com/rust-lang/regex/pull/1319">#1319</a>:
Switch from a Cargo <code>exclude</code> list to an <code>include</code>
list, and exclude some
unnecessary stuff.</li>
</ul>
</blockquote>
</details>
<details>
<summary>Commits</summary>
<ul>
<li><a
href="b028e4f40e"><code>b028e4f</code></a>
1.12.3</li>
<li><a
href="5e195de266"><code>5e195de</code></a>
regex-automata-0.4.14</li>
<li><a
href="a3433f6918"><code>a3433f6</code></a>
regex-syntax-0.8.9</li>
<li><a
href="0c07fae444"><code>0c07fae</code></a>
regex-lite-0.1.9</li>
<li><a
href="6a810068f0"><code>6a81006</code></a>
cargo: exclude development scripts and fuzzing data</li>
<li><a
href="4733e28ba4"><code>4733e28</code></a>
automata: fix <code>onepass::DFA::try_search_slots</code> panic when too
many slots are ...</li>
<li>See full diff in <a
href="https://github.com/rust-lang/regex/compare/1.12.2...1.12.3">compare
view</a></li>
</ul>
</details>
<br />
[](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores)
Dependabot will resolve any conflicts with this PR as long as you don't
alter it yourself. You can also trigger a rebase manually by commenting
`@dependabot rebase`.
[//]: # (dependabot-automerge-start)
[//]: # (dependabot-automerge-end)
---
<details>
<summary>Dependabot commands and options</summary>
<br />
You can trigger Dependabot actions by commenting on this PR:
- `@dependabot rebase` will rebase this PR
- `@dependabot recreate` will recreate this PR, overwriting any edits
that have been made to it
- `@dependabot show <dependency name> ignore conditions` will show all
of the ignore conditions of the specified dependency
- `@dependabot ignore this major version` will close this PR and stop
Dependabot creating any more for this major version (unless you reopen
the PR or upgrade to it yourself)
- `@dependabot ignore this minor version` will close this PR and stop
Dependabot creating any more for this minor version (unless you reopen
the PR or upgrade to it yourself)
- `@dependabot ignore this dependency` will close this PR and stop
Dependabot creating any more for this dependency (unless you reopen the
PR or upgrade to it yourself)
</details>
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Bumps [anyhow](https://github.com/dtolnay/anyhow) from 1.0.100 to
1.0.101.
<details>
<summary>Release notes</summary>
<p><em>Sourced from <a
href="https://github.com/dtolnay/anyhow/releases">anyhow's
releases</a>.</em></p>
<blockquote>
<h2>1.0.101</h2>
<ul>
<li>Add #[inline] to anyhow::Ok helper (<a
href="https://redirect.github.com/dtolnay/anyhow/issues/437">#437</a>,
thanks <a
href="https://github.com/Ibitier"><code>@Ibitier</code></a>)</li>
</ul>
</blockquote>
</details>
<details>
<summary>Commits</summary>
<ul>
<li><a
href="80bfe291b1"><code>80bfe29</code></a>
Release 1.0.101</li>
<li><a
href="dff8c432f9"><code>dff8c43</code></a>
Merge pull request <a
href="https://redirect.github.com/dtolnay/anyhow/issues/437">#437</a>
from Ibitier/inline-ok-helper</li>
<li><a
href="85d9ea9a1c"><code>85d9ea9</code></a>
Add #[inline] to anyhow::Ok helper</li>
<li><a
href="54036cc289"><code>54036cc</code></a>
Update ui test suite to nightly-2026-01-21</li>
<li><a
href="cce0579d85"><code>cce0579</code></a>
Update actions/upload-artifact@v5 -> v6</li>
<li><a
href="f2c598ca0e"><code>f2c598c</code></a>
Update actions/upload-artifact@v4 -> v5</li>
<li><a
href="2c0bda4ce9"><code>2c0bda4</code></a>
Update to 2021 edition</li>
<li><a
href="0d82268129"><code>0d82268</code></a>
Remove rustc version requirement from readme</li>
<li><a
href="67df01216d"><code>67df012</code></a>
Merge pull request <a
href="https://redirect.github.com/dtolnay/anyhow/issues/436">#436</a>
from dtolnay/up</li>
<li><a
href="c8984880a8"><code>c898488</code></a>
Raise required compiler to Rust 1.68</li>
<li>Additional commits viewable in <a
href="https://github.com/dtolnay/anyhow/compare/1.0.100...1.0.101">compare
view</a></li>
</ul>
</details>
<br />
[](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores)
Dependabot will resolve any conflicts with this PR as long as you don't
alter it yourself. You can also trigger a rebase manually by commenting
`@dependabot rebase`.
[//]: # (dependabot-automerge-start)
[//]: # (dependabot-automerge-end)
---
<details>
<summary>Dependabot commands and options</summary>
<br />
You can trigger Dependabot actions by commenting on this PR:
- `@dependabot rebase` will rebase this PR
- `@dependabot recreate` will recreate this PR, overwriting any edits
that have been made to it
- `@dependabot show <dependency name> ignore conditions` will show all
of the ignore conditions of the specified dependency
- `@dependabot ignore this major version` will close this PR and stop
Dependabot creating any more for this major version (unless you reopen
the PR or upgrade to it yourself)
- `@dependabot ignore this minor version` will close this PR and stop
Dependabot creating any more for this minor version (unless you reopen
the PR or upgrade to it yourself)
- `@dependabot ignore this dependency` will close this PR and stop
Dependabot creating any more for this dependency (unless you reopen the
PR or upgrade to it yourself)
</details>
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
…ount_id and chatgpt_plan_type
### Summary
Following up on external auth mode which was introduced here:
https://github.com/openai/codex/pull/10012
Turns out some clients have a differently shaped ID token and don't have
a chosen workspace (aka chatgpt_account_id) encoded in their ID token.
So, let's replace `id_token` param with `chatgpt_account_id` and
`chatgpt_plan_type` (optional) when initializing the external ChatGPT
auth mode (`account/login/start` with `chatgptAuthTokens`).
The client was able to test end-to-end with a Codex build from this
branch and verified it worked!
Summary
- add platform-aware defaults for shell command timeouts so Windows
tests get longer waits
- keep medium timeout longer on Windows to ensure flakiness is reduced
Testing
- Not run (not requested)
## Summary
- add deterministic child-process cleanup to both test `McpProcess`
helpers
- keep Tokio `kill_on_drop(true)` but also reap via bounded `try_wait()`
polling in `Drop`
- document the failure mode and why this avoids nondeterministic `LEAK`
flakes
## Why
`cargo nextest` leak detection can intermittently report `LEAK` when a
spawned server outlives test teardown, making CI flaky.
## Testing
- `just fmt`
- `cargo test -p codex-app-server`
- `cargo test -p codex-mcp-server`
## Failing CI Reference
- Original failing job:
https://github.com/openai/codex/actions/runs/21845226299/job/63039443593?pr=11245
Automated update of models.json.
---------
Co-authored-by: aibrahim-oai <219906144+aibrahim-oai@users.noreply.github.com>
Co-authored-by: Ahmed Ibrahim <aibrahim@openai.com>
# 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.
When steer mode is enabled, Tab used to only queue while a task was
running and otherwise did nothing. Treat Tab as an immediate submit when
no task is running so input isn't dropped when the inflight turn ends
mid-typing.
Adds a regression test and updates docs/tooltips.
Fixes#11020
I do think think `nix build` should run in CI, I had multiple issues
trying to build the flake in the past, as it's continuously out of sync
with the rest of the repo. (like a few days ago I didn't need the
updated outputHashes, just the missing packages).
Co-authored-by: Eric Traut <etraut@openai.com>
Match model metadata by longest matching remote slug prefix before local
fallback.
- Update `get_model_info` to prefer the most specific remote slug prefix
for the requested model.
- Add an integration test to assert `gpt-5.3-codex-test` resolves to
`gpt-5.3-codex` over `gpt-5.3`.
## Problem
When unified-exec background sessions appear while the status indicator
is visible, the bottom pane can grow by one row to show a dedicated
footer line. That row insertion/removal makes the composer jump
vertically and produces visible jitter/flicker during streaming turns.
## Mental model
The bottom pane should expose one canonical background-exec summary
string, but it should surface that string in only one place at a time:
- if the status indicator row is visible, show the summary inline on
that row;
- if the status indicator row is hidden, show the summary as the
standalone unified-exec footer row.
This keeps status information visible while preserving a stable pane
height.
## Non-goals
This change does not alter unified-exec lifecycle, process tracking, or
`/ps` behavior. It does not redesign status text copy, spinner timing,
or interrupt handling semantics.
## Tradeoffs
Inlining the summary preserves layout stability and keeps interrupt
affordances in a fixed location, but it reduces horizontal space for
long status/detail text in narrow terminals. We accept that truncation
risk in exchange for removing vertical jitter and keeping the composer
anchored.
## Architecture
`UnifiedExecFooter` remains the source of truth for background-process
summary copy via `summary_text()`. `BottomPane` mirrors that text into
`StatusIndicatorWidget::update_inline_message()` whenever process state
changes or a status widget is created. Rendering enforces single-surface
output: the standalone footer row is skipped while status is present,
and the status row appends the summary after the elapsed/interrupt
segment.
## Documentation pass
Added non-functional docs/comments that make the new invariant explicit:
- status row owns inline summary when present;
- unified-exec footer row renders only when status row is absent;
- summary ordering keeps elapsed/interrupt affordance in a stable
position.
## Observability
No new telemetry or logs are introduced. The behavior is traceable
through:
- `BottomPane::set_unified_exec_processes()` for state updates,
- `BottomPane::sync_status_inline_message()` for status-row
synchronization,
- `StatusIndicatorWidget::render()` for final inline ordering.
## Tests
- Added
`bottom_pane::tests::unified_exec_summary_does_not_increase_height_when_status_visible`
to lock the no-height-growth invariant.
- Updated the unified-exec status restoration snapshot to match inline
rendering order.
- Validated with:
- `just fmt`
- `cargo test -p codex-tui --lib`
---------
Co-authored-by: Sayan Sisodiya <sayan@openai.com>
**Why We Did This**
- The goal is to reduce MCP tool context pollution by not exposing the
full MCP tool list up front
- It forces an explicit discovery step (`search_tool_bm25`) so the model
narrows tool scope before making MCP calls, which helps relevance and
lowers prompt/tool clutter.
**What It Changed**
- Added a new experimental feature flag `search_tool` in
`core/src/features.rs:90` and `core/src/features.rs:430`.
- Added config/schema support for that flag in
`core/config.schema.json:214` and `core/config.schema.json:1235`.
- Added BM25 dependency (`bm25`) in `Cargo.toml:129` and
`core/Cargo.toml:23`.
- Added new tool handler `search_tool_bm25` in
`core/src/tools/handlers/search_tool_bm25.rs:18`.
- Registered the handler and tool spec in
`core/src/tools/handlers/mod.rs:11` and `core/src/tools/spec.rs:780` and
`core/src/tools/spec.rs:1344`.
- Extended `ToolsConfig` to carry `search_tool` enablement in
`core/src/tools/spec.rs:32` and `core/src/tools/spec.rs:56`.
- Injected dedicated developer instructions for tool-discovery workflow
in `core/src/codex.rs:483` and `core/src/codex.rs:1976`, using
`core/templates/search_tool/developer_instructions.md:1`.
- Added session state to store one-shot selected MCP tools in
`core/src/state/session.rs:27` and `core/src/state/session.rs:131`.
- Added filtering so when feature is enabled, only selected MCP tools
are exposed on the next request (then consumed) in
`core/src/codex.rs:3800` and `core/src/codex.rs:3843`.
- Added E2E suite coverage for
enablement/instructions/hide-until-search/one-turn-selection in
`core/tests/suite/search_tool.rs:72`,
`core/tests/suite/search_tool.rs:109`,
`core/tests/suite/search_tool.rs:147`, and
`core/tests/suite/search_tool.rs:218`.
- Refactored test helper utilities to support config-driven tool
collection in `core/tests/suite/tools.rs:281`.
**Net Behavioral Effect**
- With `search_tool` **off**: existing MCP behavior (tools exposed
normally).
- With `search_tool` **on**: MCP tools start hidden, model must call
`search_tool_bm25`, and only returned `selected_tools` are available for
the next model call.
## Summary
- add targeted remote-compaction failure diagnostics in compact_remote
logging
- log the specific values needed to explain overflow timing:
- last_api_response_total_tokens
- estimated_tokens_of_items_added_since_last_successful_api_response
- estimated_bytes_of_items_added_since_last_successful_api_response
- failing_compaction_request_body_bytes
- simplify breakdown naming and remove
last_api_response_total_bytes_estimate (it was an approximation and not
useful for debugging)
## Why
When compaction fails with context_length_exceeded, we need concrete,
low-ambiguity numbers that map directly to:
1) what the API most recently reported, and
2) what local history added since then.
This keeps the failure logs actionable without adding broad, noisy
metrics.
## Testing
- just fmt
- cargo test -p codex-core
## Summary
This PR fixes long-text rendering in the `request_user_input` TUI
overlay while preserving a clear two-column option layout. (Issue
https://github.com/openai/codex/issues/11093)
Before:
- very long option labels could push description text into a narrow
right-edge strip
- option labels were effectively single-line when descriptions were
present, causing truncation/poor readability
- label and description wrapping interacted in one combined wrapped line
<img width="504" height="409" alt="Screenshot 2026-02-08 at 2 27 25 PM"
src="https://github.com/user-attachments/assets/a9afd108-d792-4522-bce1-e43b3cce882b"
/>
After:
- option labels wrap inside the left column
- descriptions wrap independently inside the right column
- row measurement and row rendering use the same wrapping path, so
layout stays stable
<img width="582" height="211" alt="Screenshot 2026-02-09 at 10 28 02 AM"
src="https://github.com/user-attachments/assets/47885a1c-07e5-4b0f-b992-032b149f1b0d"
/>
## Problem
`request_user_input` needs to handle verbose prompts/options. With
oversized labels:
- descriptions could collapse into a thin, hard-to-read column
- important label context was lost
## Root Cause
In shared row rendering (`selection_popup_common`):
- rows were wrapped as a single combined line
- auto column sizing could still place `desc_col` too far right for long
labels
- `request_user_input` rows did not provide wrap metadata to align
continuation lines after the option prefix
## What Changed
### 1) `request_user_input` rows opt into wrapped labels
File: `codex-rs/tui/src/bottom_pane/request_user_input/mod.rs`
- In `option_rows()`, compute the rendered option prefix (`› 1. ` / ` 2.
`) and set `wrap_indent` from its display width.
- Apply the same behavior to the synthetic “None of the above” row.
- Add long-text snapshot test coverage
(`question_with_very_long_option_text` +
`request_user_input_long_option_text_snapshot`).
### 2) Shared renderer now has an opt-in two-column wrapping path
File: `codex-rs/tui/src/bottom_pane/selection_popup_common.rs`
- Add focused helpers:
- `should_wrap_name_in_column`
- `wrap_two_column_row`
- `wrap_standard_row`
- `wrap_row_lines`
- `apply_row_state_style`
- For opted-in rows (plain option rows with `wrap_indent` +
description), wrap label and description independently in their own
columns.
- Keep the legacy standard wrapping path for non-opted rows.
- Use the same `wrap_row_lines` function in both rendering and height
measurement to keep them in sync.
### 3) Keep column sizing simple and derived from existing fixed split
constants
File: `codex-rs/tui/src/bottom_pane/selection_popup_common.rs`
- Keep fixed mode at `3/10` left column (`30/70` split).
- In auto modes, cap label width using those same fixed constants (max
70% label, min 30% description), instead of extra special-case
constants/branches.
- Add/keep narrow-width safety guard in `wrap_two_column_row` so
extremely small widths do not panic.
### 4) Snapshot coverage
File: `codex-rs/tui/src/bottom_pane/request_user_input/snapshots/
codex_tui__bottom_pane__request_user_input__tests__request_user_input_long_option_text.snap`
- Add snapshot for long-label/long-description two-column rendering
behavior.
## Summary
- remove `network-proxy-cli` from the Rust workspace members
- delete the dedicated `codex-network-proxy-cli` crate files
- remove the stale `codex-network-proxy-cli` package entry from
`Cargo.lock`
## Testing
- just fmt
- cargo test -p codex-network-proxy
Instead of storing a special connection on the client level make the
regular task responsible for establishing a normal client session and
open a connection on it.
Then when the turn is started we pass in a pre-established session.
Instead of storing a special connection on the client level make the
regular task responsible for establishing a normal client session and
open a connection on it.
Then when the turn is started we pass in a pre-established session.
On some platforms, the "notify" file watcher library emits events for
file opens and reads, not just file modifications or deletes. The
previous implementation didn't take this into account.
Furthermore, the `tracing.info!` call that I previously added was
emitting a lot of logs. I had assumed incorrectly that `info` level
logging was disabled by default, but it's apparently enabled for this
crate. This is resulting in large logs (hundreds of MB) for some users.
## Summary
- change compaction pre-check accounting to include all items added
after the last model-generated item, not only trailing codex-generated
outputs
- use that boundary consistently in get_total_token_usage() and
get_total_token_usage_breakdown()
- update history tests to cover user/tool-output items after the last
model item
## Why
last_token_usage.total_tokens is API-reported for the last successful
model response. After that point, local history may gain additional
items (user messages, injected context, tool outputs). Compaction
triggering must account for all of those items to avoid late compaction
attempts that can overflow context.
## Testing
- just fmt
- cargo test -p codex-core
We support requirements on Unix, loading from
`/etc/codex/requirements.toml`. On MacOS, we also support MDM.
Now, on Windows, we'll load requirements from
`%ProgramData%\OpenAI\Codex\requirements.toml`
```
FAIL [ 1.903s] (1926/3311) codex-core::all suite::tool_parallelism::mixed_parallel_tools_run_in_parallel
stdout ───
running 1 test
test suite::tool_parallelism::mixed_parallel_tools_run_in_parallel ... FAILED
failures:
failures:
suite::tool_parallelism::mixed_parallel_tools_run_in_parallel
test result: FAILED. 0 passed; 1 failed; 0 ignored; 0 measured; 684 filtered out; finished in 1.86s
stderr ───
thread 'suite::tool_parallelism::mixed_parallel_tools_run_in_parallel' (205083) panicked at core/tests/suite/tool_parallelism.rs:74:5:
expected parallel execution to finish quickly, got 1.406255993s
stack backtrace:
0: __rustc::rust_begin_unwind
at /rustc/254b59607d4417e9dffbc307138ae5c86280fe4c/library/std/src/panicking.rs:689:5
1: core::panicking::panic_fmt
at /rustc/254b59607d4417e9dffbc307138ae5c86280fe4c/library/core/src/panicking.rs:80:14
2: all::suite::tool_parallelism::assert_parallel_duration
at ./tests/suite/tool_parallelism.rs:74:5
3: all::suite::tool_parallelism::mixed_parallel_tools_run_in_parallel::{{closure}}
at ./tests/suite/tool_parallelism.rs:206:5
4: <core::pin::Pin<P> as core::future::future::Future>::poll
at /home/runner/.rustup/toolchains/1.93.0-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/future/future.rs:133:9
5: tokio::runtime::park::CachedParkThread::block_on::{{closure}}
at /home/runner/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/tokio-1.49.0/src/runtime/park.rs:284:71
6: tokio::task::coop::with_budget
at /home/runner/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/tokio-1.49.0/src/task/coop/mod.rs:167:5
7: tokio::task::coop::budget
at /home/runner/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/tokio-1.49.0/src/task/coop/mod.rs:133:5
8: tokio::runtime::park::CachedParkThread::block_on
at /home/runner/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/tokio-1.49.0/src/runtime/park.rs:284:31
9: tokio::runtime::context::blocking::BlockingRegionGuard::block_on
at /home/runner/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/tokio-1.49.0/src/runtime/context/blocking.rs:66:14
10: tokio::runtime::scheduler::multi_thread::MultiThread::block_on::{{closure}}
at /home/runner/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/tokio-1.49.0/src/runtime/scheduler/multi_thread/mod.rs:89:22
11: tokio::runtime::context::runtime::enter_runtime
at /home/runner/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/tokio-1.49.0/src/runtime/context/runtime.rs:65:16
12: tokio::runtime::scheduler::multi_thread::MultiThread::block_on
at /home/runner/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/tokio-1.49.0/src/runtime/scheduler/multi_thread/mod.rs:88:9
13: tokio::runtime::runtime::Runtime::block_on_inner
at /home/runner/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/tokio-1.49.0/src/runtime/runtime.rs:370:50
14: tokio::runtime::runtime::Runtime::block_on
at /home/runner/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/tokio-1.49.0/src/runtime/runtime.rs:342:18
15: all::suite::tool_parallelism::mixed_parallel_tools_run_in_parallel
at ./tests/suite/tool_parallelism.rs:208:7
16: all::suite::tool_parallelism::mixed_parallel_tools_run_in_parallel::{{closure}}
at ./tests/suite/tool_parallelism.rs:178:52
17: core::ops::function::FnOnce::call_once
at /home/runner/.rustup/toolchains/1.93.0-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/ops/function.rs:250:5
18: core::ops::function::FnOnce::call_once
at /rustc/254b59607d4417e9dffbc307138ae5c86280fe4c/library/core/src/ops/function.rs:250:5
note: Some details are omitted, run with `RUST_BACKTRACE=full` for a verbose backtrace.
```
With this PR we do not close the unified exec processes (i.e. background
terminals) at the end of a turn unless:
* The user interrupt the turn
* The user decide to clean the processes through `app-server` or
`/clean`
I made sure that `codex exec` correctly kill all the processes