This PR introduces introduces a new
`OutgoingMessage::AppServerNotification` variant that is designed to
wrap a `ServerNotification`, which makes the serialization more
straightforward compared to
`OutgoingMessage::Notification(OutgoingNotification)`. We still use the
latter for serializing an `Event` as a `JSONRPCMessage::Notification`,
but I will try to get away from that in the near future.
With this change, now the generated TypeScript type for
`ServerNotification` is:
```typescript
export type ServerNotification =
| { "method": "authStatusChange", "params": AuthStatusChangeNotification }
| { "method": "loginChatGptComplete", "params": LoginChatGptCompleteNotification };
```
whereas before it was:
```typescript
export type ServerNotification =
| { type: "auth_status_change"; data: AuthStatusChangeNotification }
| { type: "login_chat_gpt_complete"; data: LoginChatGptCompleteNotification };
```
Once the `Event`s are migrated to the `ServerNotification` enum in Rust,
it should be considerably easier to work with notifications on the
TypeScript side, as it will be possible to `switch (message.method)` and
check for exhaustiveness.
Though we will probably need to introduce:
```typescript
export type ServerMessage = ServerRequest | ServerNotification;
```
and then we still need to group all of the `ServerResponse` types
together, as well.
#### Summary
- Emit a “Proposed Command” history cell when an ExecApprovalRequest
arrives (parity with proposed patches).
- Simplify the approval dialog: show only the reason/instructions; move
the command preview into history.
- Make approval/abort decision history concise:
- Single line snippet; if multiline, show first line + " ...".
- Truncate to 80 graphemes with ellipsis for very long commands.
#### Details
- History
- Add `new_proposed_command` to render a header and indented command
preview.
- Use shared `prefix_lines` helper for first/subsequent line prefixes.
- Approval UI
- `UserApprovalWidget` no longer renders the command in the modal; shows
optional `reason` text only.
- Decision history renders an inline, dimmed snippet per rules above.
- Tests (snapshot-based)
- Proposed/decision flow for short command.
- Proposed multi-line + aborted decision snippet with “ ...”.
- Very long one-line command -> truncated snippet with “…”.
- Updated existing exec approval snapshots and test reasons.
<img width="1053" height="704" alt="Screenshot 2025-09-03 at 11 57
35 AM"
src="https://github.com/user-attachments/assets/9ed4c316-9daf-4ac1-80ff-7ae1f481dd10"
/>
after approving:
<img width="1053" height="704" alt="Screenshot 2025-09-03 at 11 58
18 AM"
src="https://github.com/user-attachments/assets/a44e243f-eb9d-42ea-87f4-171b3fb481e7"
/>
rejection:
<img width="1053" height="207" alt="Screenshot 2025-09-03 at 11 58
45 AM"
src="https://github.com/user-attachments/assets/a022664b-ae0e-4b70-a388-509208707934"
/>
big command:
https://github.com/user-attachments/assets/2dd976e5-799f-4af7-9682-a046e66cc494
# 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.
We had multiple issues with context size calculation:
1. `initial_prompt_tokens` calculation based on cache size is not
reliable, cache misses might set it to much higher value. For now
hardcoded to a safer constant.
2. Input context size for GPT-5 is 272k (that's where 33% came from).
Fixes.
Bumps [uuid](https://github.com/uuid-rs/uuid) from 1.17.0 to 1.18.0.
<details>
<summary>Release notes</summary>
<p><em>Sourced from <a
href="https://github.com/uuid-rs/uuid/releases">uuid's
releases</a>.</em></p>
<blockquote>
<h2>v1.18.0</h2>
<h2>What's Changed</h2>
<ul>
<li>Fix up mismatched_lifetime_syntaxes lint by <a
href="https://github.com/KodrAus"><code>@KodrAus</code></a> in <a
href="https://redirect.github.com/uuid-rs/uuid/pull/837">uuid-rs/uuid#837</a></li>
<li>Conversions between <code>Timestamp</code> and
<code>std::time::SystemTime</code> by <a
href="https://github.com/dcormier"><code>@dcormier</code></a> in <a
href="https://redirect.github.com/uuid-rs/uuid/pull/835">uuid-rs/uuid#835</a></li>
<li>Wrap the error type used in time conversions by <a
href="https://github.com/KodrAus"><code>@KodrAus</code></a> in <a
href="https://redirect.github.com/uuid-rs/uuid/pull/838">uuid-rs/uuid#838</a></li>
<li>Prepare for 1.18.0 release by <a
href="https://github.com/KodrAus"><code>@KodrAus</code></a> in <a
href="https://redirect.github.com/uuid-rs/uuid/pull/839">uuid-rs/uuid#839</a></li>
</ul>
<h2>New Contributors</h2>
<ul>
<li><a href="https://github.com/dcormier"><code>@dcormier</code></a>
made their first contribution in <a
href="https://redirect.github.com/uuid-rs/uuid/pull/835">uuid-rs/uuid#835</a></li>
</ul>
<p><strong>Full Changelog</strong>: <a
href="https://github.com/uuid-rs/uuid/compare/v1.17.0...v1.18.0">https://github.com/uuid-rs/uuid/compare/v1.17.0...v1.18.0</a></p>
</blockquote>
</details>
<details>
<summary>Commits</summary>
<ul>
<li><a
href="60a49eb94f"><code>60a49eb</code></a>
Merge pull request <a
href="https://redirect.github.com/uuid-rs/uuid/issues/839">#839</a> from
uuid-rs/cargo/v1.18.0</li>
<li><a
href="eb8c697083"><code>eb8c697</code></a>
prepare for 1.18.0 release</li>
<li><a
href="281f26fcd9"><code>281f26f</code></a>
Merge pull request <a
href="https://redirect.github.com/uuid-rs/uuid/issues/838">#838</a> from
uuid-rs/chore/time-conversion</li>
<li><a
href="2d67ab2b5e"><code>2d67ab2</code></a>
don't use allocated values in errors</li>
<li><a
href="c284ed562f"><code>c284ed5</code></a>
wrap the error type used in time conversions</li>
<li><a
href="87a4359f25"><code>87a4359</code></a>
Merge pull request <a
href="https://redirect.github.com/uuid-rs/uuid/issues/835">#835</a> from
dcormier/main</li>
<li><a
href="8927396625"><code>8927396</code></a>
Merge pull request <a
href="https://redirect.github.com/uuid-rs/uuid/issues/837">#837</a> from
uuid-rs/fix/lifetime-syntaxes</li>
<li><a
href="6dfb4b135c"><code>6dfb4b1</code></a>
Conversions between <code>Timestamp</code> and
<code>std::time::SystemTime</code></li>
<li><a
href="b508383aff"><code>b508383</code></a>
fix up mismatched_lifetime_syntaxes lint</li>
<li>See full diff in <a
href="https://github.com/uuid-rs/uuid/compare/v1.17.0...v1.18.0">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 merge` will merge this PR after your CI passes on it
- `@dependabot squash and merge` will squash and merge this PR after
your CI passes on it
- `@dependabot cancel merge` will cancel a previously requested merge
and block automerging
- `@dependabot reopen` will reopen this PR if it is closed
- `@dependabot close` will close this PR and stop Dependabot recreating
it. You can achieve the same result by closing it manually
- `@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>
## Summary
Follow-up to #3056
This PR updates the mcp-server interface for reading the config settings
saved by the user. At risk of introducing _another_ Config struct, I
think it makes sense to avoid tying our protocol to ConfigToml, as its
become a bit unwieldy. GetConfigTomlResponse was a de-facto struct for
this already - better to make it explicit, in my opinion.
This is technically a breaking change of the mcp-server protocol, but
given the previous interface was introduced so recently in #2725, and we
have not yet even started to call it, I propose proceeding with the
breaking change - but am open to preserving the old endpoint.
## Testing
- [x] Added additional integration test coverage
Summary:
- pause the status timer while waiting on approval modals
- expose deterministic pause/resume helpers to avoid sleep-based tests
- simplify bottom pane timer handling now that the widget owns the clock
when the pager is scrolled to the bottom of the buffer, keep it there.
this should make transcript mode feel a bit more "alive". i've also seen
some confusion about what transcript mode does/doesn't show that i think
has been related to it not pinning scroll.
#### Summary
- render the edit queued message shortcut with the ⌥ modifier on macOS
builds
- add a helper for status indicator snapshot suffixes
- record macOS-specific snapshots for the status indicator widget
#### Summary
Avoid a potential panic when rendering the active execution cell when
the allocated area has zero height.
#### Changes
- Guard rendering with `active_cell_area.height > 0` and presence of
`active_exec_cell`.
- Use `saturating_add(1)` for the Y offset to avoid overflow.
- Render via `active_exec_cell.as_ref().unwrap().render_ref(...)` after
the explicit `is_some` check.
When serializing to JSON, the existing solution created an enormous
array of ints, which is far more bytes on the wire than a base64-encoded
string would be.
Last week, I thought I found the smoking gun in our flaky integration
tests where holding these locks could have led to potential deadlock:
- https://github.com/openai/codex/pull/2876
- https://github.com/openai/codex/pull/2878
Yet even after those PRs went in, we continued to see flakinees in our
integration tests! Though with the additional logging added as part of
debugging those tests, I now saw things like:
```
read message from stdout: Notification(JSONRPCNotification { jsonrpc: "2.0", method: "codex/event/exec_approval_request", params: Some(Object {"id": String("0"), "msg": Object {"type": String("exec_approval_request"), "call_id": String("call1"), "command": Array [String("python3"), String("-c"), String("print(42)")], "cwd": String("/tmp/.tmpFj2zwi/workdir")}, "conversationId": String("c67b32c5-9475-41bf-8680-f4b4834ebcc6")}) })
notification: Notification(JSONRPCNotification { jsonrpc: "2.0", method: "codex/event/exec_approval_request", params: Some(Object {"id": String("0"), "msg": Object {"type": String("exec_approval_request"), "call_id": String("call1"), "command": Array [String("python3"), String("-c"), String("print(42)")], "cwd": String("/tmp/.tmpFj2zwi/workdir")}, "conversationId": String("c67b32c5-9475-41bf-8680-f4b4834ebcc6")}) })
read message from stdout: Request(JSONRPCRequest { id: Integer(0), jsonrpc: "2.0", method: "execCommandApproval", params: Some(Object {"conversation_id": String("c67b32c5-9475-41bf-8680-f4b4834ebcc6"), "call_id": String("call1"), "command": Array [String("python3"), String("-c"), String("print(42)")], "cwd": String("/tmp/.tmpFj2zwi/workdir")}) })
writing message to stdin: Response(JSONRPCResponse { id: Integer(0), jsonrpc: "2.0", result: Object {"decision": String("approved")} })
in read_stream_until_notification_message(codex/event/task_complete)
[mcp stderr] 2025-09-04T00:00:59.738585Z INFO codex_mcp_server::message_processor: <- response: JSONRPCResponse { id: Integer(0), jsonrpc: "2.0", result: Object {"decision": String("approved")} }
[mcp stderr] 2025-09-04T00:00:59.738740Z DEBUG codex_core::codex: Submission sub=Submission { id: "1", op: ExecApproval { id: "0", decision: Approved } }
[mcp stderr] 2025-09-04T00:00:59.738832Z WARN codex_core::codex: No pending approval found for sub_id: 0
```
That is, a response was sent for a request, but no callback was in place
to handle the response!
This time, I think I may have found the underlying issue (though the
fixes for holding locks for too long may have also been part of it),
which is I found cases where we were sending the request:
234c0a0469/codex-rs/core/src/codex.rs (L597)
before inserting the `Sender` into the `pending_approvals` map (which
has to wait on acquiring a mutex):
234c0a0469/codex-rs/core/src/codex.rs (L598-L601)
so it is possible the request could go out and the client could respond
before `pending_approvals` was updated!
Note this was happening in both `request_command_approval()` and
`request_patch_approval()`, which maps to the sorts of errors we have
been seeing when these integration tests have been flaking on us.
While here, I am also adding some extra logging that prints if inserting
into `pending_approvals` overwrites an entry as opposed to purely
inserting one. Today, a conversation can have only one pending request
at a time, but as we are planning to support parallel tool calls, this
invariant may not continue to hold, in which case we need to revisit
this abstraction.
Adds a TUI resume flow with an interactive picker and quick resume.
- CLI:
- --resume / -r: open picker to resume a prior session
- --continue / -l: resume the most recent session (no picker)
- Behavior on resume: initial history is replayed, welcome banner
hidden, and the first redraw is suppressed to avoid flicker.
- Implementation:
- New tui/src/resume_picker.rs (paginated listing via
RolloutRecorder::list_conversations)
- App::run accepts ResumeSelection; resumes from disk when requested
- ChatWidget refactor with ChatWidgetInit and new_from_existing; replays
initial messages
- Tests: cover picker sorting/preview extraction and resumed-history
rendering.
- Docs: getting-started updated with flags and picker usage.
https://github.com/user-attachments/assets/1bb6469b-e5d1-42f6-bec6-b1ae6debda3b
Bumps [wiremock](https://github.com/LukeMathWalker/wiremock-rs) from
0.6.4 to 0.6.5.
<details>
<summary>Commits</summary>
<ul>
<li><a
href="6b193047bf"><code>6b19304</code></a>
chore: Release wiremock version 0.6.5</li>
<li><a
href="ebaa70b024"><code>ebaa70b</code></a>
feat: Make method and MethodExactMatcher case in-sensitive (<a
href="https://redirect.github.com/LukeMathWalker/wiremock-rs/issues/165">#165</a>)</li>
<li><a
href="613b4f9135"><code>613b4f9</code></a>
Make <code>BodyPrintLimit</code> public (<a
href="https://redirect.github.com/LukeMathWalker/wiremock-rs/issues/167">#167</a>)</li>
<li><a
href="abfafd2227"><code>abfafd2</code></a>
chore: Upgrade all deps to their latest version (<a
href="https://redirect.github.com/LukeMathWalker/wiremock-rs/issues/170">#170</a>)</li>
<li><a
href="60688cfdde"><code>60688cf</code></a>
ci: Upgrade actions. Upgrade dependencies. (<a
href="https://redirect.github.com/LukeMathWalker/wiremock-rs/issues/169">#169</a>)</li>
<li>See full diff in <a
href="https://github.com/LukeMathWalker/wiremock-rs/compare/v0.6.4...v0.6.5">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 merge` will merge this PR after your CI passes on it
- `@dependabot squash and merge` will squash and merge this PR after
your CI passes on it
- `@dependabot cancel merge` will cancel a previously requested merge
and block automerging
- `@dependabot reopen` will reopen this PR if it is closed
- `@dependabot close` will close this PR and stop Dependabot recreating
it. You can achieve the same result by closing it manually
- `@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>
This PR does the following:
- divides user msgs into 3 categories: plain, user instructions, and
environment context
- Centralizes adding user instructions and environment context to a
degree
- Improve the integration testing
Building on top of #3123
Specifically this
[comment](https://github.com/openai/codex/pull/3123#discussion_r2319885089).
We need to send the user message while ignoring the User Instructions
and Environment Context we attach.
### Overview
This PR introduces the following changes:
1. Adds a unified mechanism to convert ResponseItem into EventMsg.
2. Ensures that when a session is initialized with initial history, a
vector of EventMsg is sent along with the session configuration. This
allows clients to re-render the UI accordingly.
3. Added integration testing
### Caveats
This implementation does not send every EventMsg that was previously
dispatched to clients. The excluded events fall into two categories:
• “Arguably” rolled-out events
Examples include tool calls and apply-patch calls. While these events
are conceptually rolled out, we currently only roll out ResponseItems.
These events are already being handled elsewhere and transformed into
EventMsg before being sent.
• Non-rolled-out events
Certain events such as TurnDiff, Error, and TokenCount are not rolled
out at all.
### Future Directions
At present, resuming a session involves maintaining two states:
• UI State
Clients can replay most of the important UI from the provided EventMsg
history.
• Model State
The model receives the complete session history to reconstruct its
internal state.
This design provides a solid foundation. If, in the future, more precise
UI reconstruction is needed, we have two potential paths:
1. Introduce a third data structure that allows us to derive both
ResponseItems and EventMsgs.
2. Clearly divide responsibilities: the core system ensures the
integrity of the model state, while clients are responsible for
reconstructing the UI.
In this test, the ChatGPT token path is used, and the auth layer tries
to refresh the token if it thinks the token is “old.” Your helper writes
a fixed last_refresh timestamp that has now aged past the 28‑day
threshold, so the code attempts a real refresh against auth.openai.com,
never reaches the mock, and you end up with
received_requests().await.unwrap() being empty.
## Summary
It appears that #2108 hit a merge conflict with #2355 - I failed to
notice the path difference when re-reviewing the former. This PR
rectifies that, and consolidates it into the protocol package, in line
with our philosophy of specifying types in one place.
## Testing
- [x] Adds config test for model_verbosity
**What?**
Auto-approve patches when `SandboxPolicy::DangerFullAccess` is enabled
on platforms without sandbox support.
Changes in `codex-rs/core/src/safety.rs`: return
`SafetyCheck::AutoApprove { sandbox_type: SandboxType::None }` when no
sandbox is available and DangerFullAccess is set.
**Why?**
On platforms lacking sandbox support, requiring explicit user approval
despite `DangerFullAccess` being explicitly enabled adds friction
without additional safety. This aligns behavior with the stated policy
intent.
**How?**
Extend `assess_patch_safety` match:
* If `get_platform_sandbox()` returns `Some`, keep `AutoApprove {
sandbox_type }`.
* If `None` **and** `SandboxPolicy::DangerFullAccess`, return
`AutoApprove { SandboxType::None }`.
* Otherwise, fall back to `AskUser`.
**Tests**
* Local checks:
```bash
cargo test && cargo clippy --tests && cargo fmt -- --config
imports_granularity=Item
```
(Additionally: `just fmt`, `just fix -p codex-core`, `cargo check -p
codex-core`.)
**Docs**
No user-facing CLI changes. No README/help updates needed.
**Risk/Impact**
Reduces prompts on non-sandboxed platforms when DangerFullAccess is
explicitly chosen; consistent with policy semantics.
---------
Co-authored-by: Michael Bolin <bolinfest@gmail.com>
# Improve @ file search: include specific hidden dirs
This should close#2980
## What
- Extend `@` fuzzy file search to include select top-level hidden
directories:
`.github`, `.gitlab`, `.circleci`, `.devcontainer`, `.azuredevops`,
`.vscode`, `.cursor`.
- Keep all other hidden directories excluded to avoid noise and heavy
traversals.
## Why
- Common project config lives under these dot-dirs (CI, editor,
devcontainer); users expect `@.github/...` and similar paths to resolve.
- Prior behavior hid all dot-dirs, making these files undiscoverable.
## How
- In `codex-file-search` walker:
- Enable hidden entries via `WalkBuilder.hidden(false)`.
- Add `filter_entry` to only allow those specific root dot-directories;
other hidden paths remain filtered out.
- Preserve `.gitignore` semantics and existing exclude handling.
## Local checks
- Ran formatting: `just fmt`
- Ran lint (scoped): `just fix -p codex-file-search`
- Ran tests:
- `cargo test -p codex-file-search`
- `cargo test -p codex-tui`
## Readiness
- Branch is up-to-date locally; tests pass; lint/format applied.
- No merge conflicts expected.
- Marking Ready for review.
---------
Signed-off-by: lionelchg <lionel.cheng@hotmail.fr>
Correct the `shell` tool description for sandboxed runs and add targeted
tests.
- Fix the WorkspaceWrite description to clearly state that writes
outside the writable roots require escalated permissions; reads are not
restricted. The previous wording/formatting could be read as restricting
reads outside the workspace.
- Render the writable roots list on its own lines under a newline after
"writable roots:" for clarity.
- Show the "Commands that require network access" note only in
WorkspaceWrite when network is disabled.
- Add focused tests that call `create_shell_tool_for_sandbox` directly
and assert the exact description text for WorkspaceWrite, ReadOnly, and
DangerFullAccess.
- Update AGENTS.md to note that `just fmt` can be run automatically
without asking.
- Move rollout persistence and listing into a dedicated module:
rollout/{recorder,list}.
- Expose lightweight conversation listing that returns file paths plus
the first 5 JSONL records for preview.
Bumps [thiserror](https://github.com/dtolnay/thiserror) from 2.0.12 to
2.0.16.
<details>
<summary>Release notes</summary>
<p><em>Sourced from <a
href="https://github.com/dtolnay/thiserror/releases">thiserror's
releases</a>.</em></p>
<blockquote>
<h2>2.0.16</h2>
<ul>
<li>Add to "no-std" crates.io category (<a
href="https://redirect.github.com/dtolnay/thiserror/issues/429">#429</a>)</li>
</ul>
<h2>2.0.15</h2>
<ul>
<li>Prevent <code>Error::provide</code> API becoming unavailable from a
future new compiler lint (<a
href="https://redirect.github.com/dtolnay/thiserror/issues/427">#427</a>)</li>
</ul>
<h2>2.0.14</h2>
<ul>
<li>Allow build-script cleanup failure with NFSv3 output directory to be
non-fatal (<a
href="https://redirect.github.com/dtolnay/thiserror/issues/426">#426</a>)</li>
</ul>
<h2>2.0.13</h2>
<ul>
<li>Documentation improvements</li>
</ul>
</blockquote>
</details>
<details>
<summary>Commits</summary>
<ul>
<li><a
href="40b58536cc"><code>40b5853</code></a>
Release 2.0.16</li>
<li><a
href="83dfb5f99b"><code>83dfb5f</code></a>
Merge pull request <a
href="https://redirect.github.com/dtolnay/thiserror/issues/429">#429</a>
from dtolnay/nostd</li>
<li><a
href="9b4a99fb90"><code>9b4a99f</code></a>
Add to "no-std" crates.io category</li>
<li><a
href="f6145ebe84"><code>f6145eb</code></a>
Release 2.0.15</li>
<li><a
href="2717177976"><code>2717177</code></a>
Merge pull request <a
href="https://redirect.github.com/dtolnay/thiserror/issues/427">#427</a>
from dtolnay/caplints</li>
<li><a
href="2cd13e6767"><code>2cd13e6</code></a>
Make error_generic_member_access compatible with -Dwarnings</li>
<li><a
href="eea6799e2d"><code>eea6799</code></a>
Release 2.0.14</li>
<li><a
href="a2aa6d7a57"><code>a2aa6d7</code></a>
Merge pull request <a
href="https://redirect.github.com/dtolnay/thiserror/issues/426">#426</a>
from dtolnay/enotempty</li>
<li><a
href="f00ebc57be"><code>f00ebc5</code></a>
Allow build-script cleanup failure with NFSv3 output directory to be
non-fatal</li>
<li><a
href="61f28da3df"><code>61f28da</code></a>
Release 2.0.13</li>
<li>Additional commits viewable in <a
href="https://github.com/dtolnay/thiserror/compare/2.0.12...2.0.16">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 merge` will merge this PR after your CI passes on it
- `@dependabot squash and merge` will squash and merge this PR after
your CI passes on it
- `@dependabot cancel merge` will cancel a previously requested merge
and block automerging
- `@dependabot reopen` will reopen this PR if it is closed
- `@dependabot close` will close this PR and stop Dependabot recreating
it. You can achieve the same result by closing it manually
- `@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>
## Summary
This PR implements advisory file locking for the message history using
Rust 1.89+ stabilized std::fs::File locking APIs, eliminating the need
for external dependencies.
## Key Changes
- **Stable API Usage**: Uses std::fs::File::try_lock() and
try_lock_shared() APIs stabilized in Rust 1.89
- **Cross-Platform Compatibility**:
- Unix systems use try_lock_shared() for advisory read locks
- Windows systems use try_lock() due to different lock semantics
- **Retry Logic**: Maintains existing retry behavior for concurrent
access scenarios
- **No External Dependencies**: Removes need for external file locking
crates
## Technical Details
The implementation provides advisory file locking to prevent corruption
when multiple Codex processes attempt to write to the message history
file simultaneously. The locking is platform-aware to handle differences
in Windows vs Unix file locking behavior.
## Testing
- ✅ Builds successfully on all platforms
- ✅ Existing message history tests pass
- ✅ File locking retry logic verified
Related to discussion in #2773 about using stabilized Rust APIs instead
of external dependencies.
---------
Co-authored-by: Michael Bolin <bolinfest@gmail.com>
## Summary
This PR enables Codex to build and run on Android/Termux environments by
conditionally gating the arboard clipboard dependency for Android
targets.
## Key Changes
- **Android Compatibility**: Gate arboard dependency for Android targets
where clipboard access may be restricted
- **Build Fixes**: Add missing tempfile::Builder import for image
clipboard operations
- **Code Cleanup**: Remove unnecessary parentheses to resolve formatting
warnings
## Technical Details
### Clipboard Dependency Gating
- Uses conditional compilation to exclude arboard on Android targets
- Maintains full clipboard functionality on other platforms
- Prevents build failures on Android/Termux where system clipboard
access is limited
### Import Fixes
- Adds missing tempfile::Builder import that was causing compilation
errors
- Ensures image clipboard operations work correctly when clipboard is
available
## Platform Support
- ✅ **Linux/macOS/Windows**: Full clipboard functionality maintained
- ✅ **Android/Termux**: Builds successfully without clipboard dependency
- ✅ **Other Unix platforms**: Unchanged behavior
## Testing
- ✅ Builds successfully on Android/Termux
- ✅ Maintains clipboard functionality on supported platforms
- ✅ No regression in existing functionality
This addresses the Android/Termux compatibility issues while keeping
clipboard functionality intact for platforms that support it.
- Summary:
- Updated the hardcoded hyperlink shown when no MCP servers are
configured to point at the canonical docs section:
- From: codex-rs/config.md#mcp_servers (moved/obsolete)
- To: docs/config.md#mcp_servers (correct GitHub path)
- Rationale:
- The TUI link was pointing to a file that only redirects; this makes
the link accurate and reduces user confusion.
- Validation:
- Verified that the target anchor exists at:
https://github.com/openai/codex/blob/main/docs/config.md#mcp_servers
- UI behavior unchanged otherwise (rendering of link text remains “MCP
docs”).
- Impact:
- One-line change in TUI display logic; no functional behavior change.
Co-authored-by: Michael Bolin <mbolin@openai.com>
The gpt-oss models require reasoning with subsequent Chat Completions
requests because otherwise the model forgets why the tools were called.
This change fixes that and also adds some additional missing
documentation around how to handle context windows in Ollama and how to
show the CoT if you desire to.
## Summary
Fixes an issue with the lark grammar definition for the apply_patch
freeform tool. This does NOT change the defaults, merely patches the
root cause of the issue we were seeing with empty lines, and an issue
with config flowing through correctly.
Specifically, the following requires that a line is non-empty:
```
add_line: "+" /(.+)/ LF -> line
```
but many changes _should_ involve creating/updating empty lines. The new
definition is:
```
add_line: "+" /(.*)/ LF -> line
```
## Testing
- [x] Tested locally, reproduced the issue without the update and
confirmed that the model will produce empty lines wiht the new lark
grammar
## Summary
- allow selection popups to specify their empty state message
- show a "loading..." placeholder in the file search popup while matches
are pending
- update other popup call sites to continue using a "no matches" message
## Testing
- just fmt
- just fix -p codex-tui
- cargo test -p codex-tui
------
https://chatgpt.com/codex/tasks/task_i_68b73e956e90832caf4d04a75fcc9c46
We have two ways of loading conversation with a previous history. Fork
conversation and the experimental resume that we had before. In this PR,
I am unifying their code path. The path is getting the history items and
recording them in a brand new conversation. This PR also constraint the
rollout recorder responsibilities to be only recording to the disk and
loading from the disk.
The PR also fixes a current bug when we have two forking in a row:
History 1:
<Environment Context>
UserMessage_1
UserMessage_2
UserMessage_3
**Fork with n = 1 (only remove one element)**
History 2:
<Environment Context>
UserMessage_1
UserMessage_2
<Environment Context>
**Fork with n = 1 (only remove one element)**
History 2:
<Environment Context>
UserMessage_1
UserMessage_2
**<Environment Context>**
This shouldn't happen but because we were appending the `<Environment
Context>` after each spawning and it's considered as _user message_.
Now, we don't add this message if restoring and old conversation.
Fixes excessive blank lines appearing during agent message streaming.
- Only insert a separator blank line for new, non-streaming history
cells.
- Streaming continuations now append without adding a spacer,
eliminating extra gaps between chunks.
Affected area: TUI display of agent messages (tui/src/app.rs).
Hide the “/init” suggestion in the new-session banner when an
`AGENTS.md` exists anywhere from the repo root down to the current
working directory.
Changes
- Conditional suggestion: use `discover_project_doc_paths(config)` to
suppress `/init` when agents docs are present.
- TUI style cleanup: switch banner construction to `Stylize` helpers
(`.bold()`, `.dim()`, `.into()`), avoiding `Span::styled`/`Span::raw`.
- Fixture update: remove `/init` line in
`tui/tests/fixtures/ideal-binary-response.txt` to match the new banner.
Validation
- Ran formatting and scoped lint fixes: `just fmt` and `just fix -p
codex-tui`.
- Tests: `cargo test -p codex-tui` passed (`176 passed, 0 failed`).
Notes
- No change to the `/init` command itself; only the welcome banner now
adapts based on presence of `AGENTS.md`.