Commit Graph

1026 Commits

Author SHA1 Message Date
Matthew Zeng
b9cd089d1f [connectors] Support connectors part 2 - slash command and tui (#9728)
- [x] Support `/apps` slash command to browse the apps in tui.
- [x] Support inserting apps to prompt using `$`.
- [x] Lots of simplification/renaming from connectors to apps.
2026-01-28 19:51:58 -08:00
natea-oai
ecc66f4f52 removing quit from dropdown menu, but not autocomplete [cli] (#10128)
Currently we have both `\quit` and `\exit` which do the same thing. This
removes `\quit` from the slash command menu but allows it to still be an
autocomplete option & working for those used to that command.

`/quit` autocomplete:
<img width="232" height="108" alt="Screenshot 2026-01-28 at 4 32 53 PM"
src="https://github.com/user-attachments/assets/d71e079f-77f6-4edc-9590-44a01e2a4ff5"
/>

slash command menu:
<img width="425" height="191" alt="Screenshot 2026-01-28 at 4 32 36 PM"
src="https://github.com/user-attachments/assets/a9458cff-1784-4ce0-927d-43ad13d2a97c"
/>
2026-01-28 17:52:27 -08:00
Dylan Hurd
ce3d764ae1 chore(config) personality as a feature (#10116)
## Summary
Sets up an explicit Feature flag for `/personality`, so users can now
opt in to it via `/experimental`. #10114 also updates the config

## Testing
- [x] Tested locally
2026-01-28 17:58:28 -07:00
Eric Traut
147e7118e0 Added tui.notifications_method config option (#10043)
This PR adds a new `tui.notifications_method` config option that accepts
values of "auto", "osc9" and "bel". It defaults to "auto", which
attempts to auto-detect whether the terminal supports OSC 9 escape
sequences and falls back to BEL if not.

The PR also removes the inconsistent handling of notifications on
Windows when WSL was used.
2026-01-28 12:00:32 -08:00
iceweasel-oai
66de985e4e allow elevated sandbox to be enabled without base experimental flag (#10028)
elevated flag = elevated sandbox
experimental flag = non-elevated sandbox
both = elevated
2026-01-28 11:38:29 -08:00
Jeremy Rose
b8156706e6 file-search: improve file query perf (#9939)
switch nucleo-matcher for nucleo and use a "file search session" w/ live
updating query instead of a single hermetic run per query.
2026-01-28 10:54:43 -08:00
Charley Cunningham
96386755b6 Refine request_user_input TUI interactions and option UX (#10025)
## Summary
Overhaul the ask‑user‑questions TUI to support “Other/None” answers,
better notes handling, improved option selection
UX, and a safer submission flow with confirmation for unanswered
questions.

Multiple choice (number keys for quick selection, up/down or jk for
cycling through options):
<img width="856" height="169" alt="Screenshot 2026-01-27 at 7 22 29 PM"
src="https://github.com/user-attachments/assets/cabd1b0e-25e0-4859-bd8f-9941192ca274"
/>

Tab to add notes:
<img width="856" height="197" alt="Screenshot 2026-01-27 at 7 22 45 PM"
src="https://github.com/user-attachments/assets/a807db5e-e966-412c-af91-6edc60062f35"
/>

Freeform (also note enter tooltip is highlighted on last question to
indicate questions UI will be exited upon submission):
<img width="854" height="112" alt="Screenshot 2026-01-27 at 7 23 13 PM"
src="https://github.com/user-attachments/assets/2e7b88bf-062b-4b9f-a9da-c9d8c8a59643"
/>

Confirmation dialogue (submitting with unanswered questions):
<img width="854" height="126" alt="Screenshot 2026-01-27 at 7 23 29 PM"
src="https://github.com/user-attachments/assets/93965c8f-54ac-45bc-a660-9625bcd101f8"
/>

## Key Changes
- **Options UI refresh**
- Render options as numbered entries; allow number keys to select &
submit.
- Remove “Option X/Y” header and allow the question UI height to expand
naturally.
- Keep spacing between question, options, and notes even when notes are
visible.
- Hide the title line and render the question prompt in cyan **only when
uncommitted**.

- **“Other / None of the above” support**
  - Wire `isOther` to add “None of the above”.
  - Add guidance text: “Optionally, add details in notes (tab).”

- **Notes composer UX**
- Remove “Notes” heading; place composer directly under the selected
option.
- Preserve pending paste placeholders across question navigation and
after submission.
  - Ctrl+C clears notes **only when the notes composer has focus**.
  - Ctrl+C now triggers an immediate redraw so the clear is visible.

- **Committed vs uncommitted state**
  - Introduce a unified `answer_committed` flag per question.
- Editing notes (including adding text or pastes) marks the answer
uncommitted.
- Changing the option highlight (j/k, up/down) marks the answer
uncommitted.
  - Clearing options (Backspace/Delete) also clears pending notes.
  - Question prompt turns cyan only when the answer is uncommitted.

- **Submission safety & confirmation**
  - Only submit notes/freeform text once explicitly committed.
- Last-question submit with unanswered questions shows a confirmation
dialog.
  - Confirmation options:
    1. **Proceed** (default)
    2. **Go back**
  - Description reflects count: “Submit with N unanswered question(s).”
  - Esc/Backspace in confirmation returns to first unanswered question.
  - Ctrl+C in confirmation interrupts and exits the overlay.

- **Footer hints**
- Cyan highlight restored for “enter to submit answer” / “enter to
submit all”.

## Codex author
`codex fork 019c00ed-323a-7000-bdb5-9f9c5a635bd9`
2026-01-28 09:41:59 -08:00
iceweasel-oai
9f79365691 error code/msg details for failed elevated setup (#9941) 2026-01-27 23:06:10 -08:00
Matthew Zeng
3bb8e69dd3 [skills] Auto install MCP dependencies when running skils with dependency specs. (#9982)
Auto install MCP dependencies when running skils with dependency specs.
2026-01-27 19:02:45 -08:00
Charley Cunningham
add648df82 Restore image attachments/text elements when recalling input history (Up/Down) (#9628)
**Summary**
- Up/Down input history now restores image attachments and text elements
for local entries.
- Composer history stores rich local entries (text + text elements +
local image paths) while persistent history remains text-only.
- Added tests to verify history recall rehydrates image placeholders and
attachments in both `tui` and `tui2`.

**Changes**
- `tui/src/bottom_pane/chat_composer_history.rs`: store `HistoryEntry`
(text + elements + image paths) for local history; adapt navigation +
tests.
- `tui2/src/bottom_pane/chat_composer_history.rs`: same as above.
- `tui/src/bottom_pane/chat_composer.rs`: record rich history entries
and restore them on Up/Down; update Ctrl+C history and tests.
- `tui2/src/bottom_pane/chat_composer.rs`: same as above.
2026-01-27 18:39:59 -08:00
SlKzᵍᵐ
3f3916e595 tui: stabilize shortcut overlay snapshots on WSL (#9359)
Fixes #9361

## Context
Split out from #9059 per review:
https://github.com/openai/codex/pull/9059#issuecomment-3757859033

## Summary
The shortcut overlay renders different paste-image bindings on WSL
(Ctrl+Alt+V) vs non-WSL (Ctrl+V), which makes snapshot tests
non-deterministic when run under WSL.

## Changes
- Gate WSL detection behind `cfg(not(test))` so snapshot tests are
deterministic across environments.
- Add a focused unit test that still asserts the WSL-specific
paste-image binding.

## Testing
- `just fmt`
- `just fix -p codex-tui`
- `just fix -p codex-tui2`
- `cargo test -p codex-tui`
- `cargo test -p codex-tui2`
2026-01-28 01:10:16 +00:00
Charley Cunningham
19d8f71a98 Ask user question UI footer improvements (#9949)
## Summary

Polishes the `request_user_input` TUI overlay

Question 1 (unanswered)
<img width="853" height="167" alt="Screenshot 2026-01-27 at 1 30 09 PM"
src="https://github.com/user-attachments/assets/3c305644-449e-4e8d-a47b-d689ebd8702c"
/>

Tab to add notes
<img width="856" height="198" alt="Screenshot 2026-01-27 at 1 30 25 PM"
src="https://github.com/user-attachments/assets/0d2801b0-df0c-49ae-85af-e6d56fc2c67c"
/>

Question 2 (unanswered)
<img width="854" height="168" alt="Screenshot 2026-01-27 at 1 30 55 PM"
src="https://github.com/user-attachments/assets/b3723062-51f9-49c9-a9ab-bb1b32964542"
/>

Ctrl+p or h to go back to q1 (answered)
<img width="853" height="195" alt="Screenshot 2026-01-27 at 1 31 27 PM"
src="https://github.com/user-attachments/assets/c602f183-1c25-4c51-8f9f-e565cb6bd637"
/>

Unanswered freeform
<img width="856" height="126" alt="Screenshot 2026-01-27 at 1 31 42 PM"
src="https://github.com/user-attachments/assets/7e3d9d8b-820b-4b9a-9ef2-4699eed484c5"
/>

## Key changes

- Footer tips wrap at tip boundaries (no truncation mid‑tip); footer
height scales to wrapped tips.
- Keep tooltip text as Esc: interrupt in all states.
- Make the full Tab: add notes tip cyan/bold when applicable; hide notes
UI by default.
- Notes toggling/backspace:
- Tab opens notes when an option is selected; Tab again clears notes and
hides the notes UI.
    - Backspace in options clears the current selection.
    - Backspace in empty notes closes notes and returns to options.
- Selection/answering behavior:
- Option questions highlight a default option but are not answered until
Enter.
- Enter no longer auto‑selects when there’s no selection (prevents
accidental answers).
    - Notes submission can commit the selected option when present.
- Freeform questions require Enter with non‑empty text to mark answered;
drafts are not submitted unless committed.
- Unanswered cues:
    - Skipped option questions count as unanswered.
    - Unanswered question titles are highlighted for visibility.
- Typing/navigation in options:
    - Typing no longer opens notes; notes are Tab‑only.
- j/k move option selection; h/l switch questions (Ctrl+n/Ctrl+p still
work).

## Tests

- Added unit coverage for:
    - tip‑level wrapping
    - focus reset when switching questions with existing drafts
    - backspace clearing selection
    - backspace closing empty notes
    - typing in options does not open notes
    - freeform draft submission gating
    - h/l question navigation in options
- Updated snapshots, including narrow footer wrap.

## Why

These changes make the ask‑user‑question overlay:

- safer (no silent auto‑selection or accidental freeform submission),
- clearer (tips wrap cleanly and unanswered states stand out),
- more ergonomic (Tab explicitly controls notes; backspace acts like
undo/close).

## Codex author
`codex fork 019bfc3c-2c42-7982-9119-fee8b9315c2f`

---------

Co-authored-by: Ahmed Ibrahim <aibrahim@openai.com>
2026-01-27 14:57:07 -08:00
Josh McKinney
3ae966edd8 Clarify external editor env var message (#10030)
### Motivation
- Improve UX by making it explicit that `VISUAL`/`EDITOR` must be set
before launching Codex, not during a running session.

### Description
- Update the external editor error text in `codex-rs/tui/src/app.rs` to:
`"Cannot open external editor: set $VISUAL or $EDITOR before starting
Codex."` and run `just fmt` to apply formatting.

### Testing
- Ran `just fmt` successfully; attempted `cargo test -p codex-tui` but
it failed due to network errors when fetching git dependencies (tests
did not complete).

------
[Codex
Task](https://chatgpt.com/codex/tasks/task_i_6972c2c984948329b1a37d5c5839aff3)
2026-01-27 13:29:55 -08:00
K Bediako
337643b00a Fix: Render MCP image outputs regardless of ordering (#9815)
## What?
- Render an MCP image output cell whenever a decodable image block
exists in `CallToolResult.content` (including text-before-image or
malformed image before valid image).

## Why?
- Tool results that include caption text before the image currently drop
the image output cell.
- A malformed image block can also suppress later valid image output.

## How?
- Iterate `content` and return the first successfully decoded image
instead of only checking the first block.
- Add unit tests that cover text-before-image ordering and
invalid-image-before-valid.

## Before
```rust
let image = match result {
    Ok(mcp_types::CallToolResult { content, .. }) => {
        if let Some(mcp_types::ContentBlock::ImageContent(image)) = content.first() {
            // decode image (fails -> None)
        } else {
            None
        }
    }
    _ => None,
}?;
```
## After
```rust
let image = result
    .as_ref()
    .ok()?
    .content
    .iter()
    .find_map(decode_mcp_image)?;
```

## Risk / Impact
- Low: only affects image cell creation for MCP tool results; no change
for non-image outputs.

## Tests
- [x] `just fmt`
- [x] `cargo test -p codex-tui`
- [x] Rerun after branch update (2026-01-27): `just fmt`, `cargo test -p
codex-tui`

Manual testing

# Manual testing: MCP image tool result rendering (Codex TUI)

# Build the rmcp stdio test server binary:
cd codex-rs
cargo build -p codex-rmcp-client --bin test_stdio_server

# Register the server as an MCP server (absolute path to the built binary):
codex mcp add mcpimg -- /Users/joshka/code/codex-pr-review/codex-rs/target/debug/test_stdio_server

# Then in Codex TUI, ask it to call:
- mcpimg.image_scenario({"scenario":"image_only"})
- mcpimg.image_scenario({"scenario":"text_then_image","caption":"Here is the image:"})
- mcpimg.image_scenario({"scenario":"invalid_base64_then_image"})
- mcpimg.image_scenario({"scenario":"invalid_image_bytes_then_image"})
- mcpimg.image_scenario({"scenario":"multiple_valid_images"})
- mcpimg.image_scenario({"scenario":"image_then_text","caption":"Here is the image:"})
- mcpimg.image_scenario({"scenario":"text_only","caption":"Here is the image:"})

# Expected:
# - You should see an extra history cell: "tool result (image output)" when the
#   tool result contains at least one decodable image block (even if earlier
#   blocks are text or invalid images).


Fixes #9814

---------

Co-authored-by: Josh McKinney <joshka@openai.com>
2026-01-27 21:14:08 +00:00
iceweasel-oai
c40ad65bd8 remove sandbox globals. (#9797)
Threads sandbox updates through OverrideTurnContext for active turn
Passes computed sandbox type into safety/exec
2026-01-27 11:04:23 -08:00
Charley Cunningham
538e1059a3 TUI footer: right-align context and degrade shortcut summary + mode cleanly (#9944)
## Summary
Refines the bottom footer layout to keep `% context left` right-aligned
while making the left side degrade cleanly

## Behavior with empty textarea
Full width:
<img width="607" height="62" alt="Screenshot 2026-01-26 at 2 59 59 PM"
src="https://github.com/user-attachments/assets/854f33b7-d714-40be-8840-a52eb3bda442"
/>
Less:
<img width="412" height="66" alt="Screenshot 2026-01-26 at 2 59 48 PM"
src="https://github.com/user-attachments/assets/9c501788-c3a2-4b34-8f0b-8ec4395b44fe"
/>
Min width:
<img width="218" height="77" alt="Screenshot 2026-01-26 at 2 59 33 PM"
src="https://github.com/user-attachments/assets/0bed2385-bdbf-4254-8ae4-ab3452243628"
/>

## Behavior with message in textarea and agent running (steer enabled)
Full width:
<img width="753" height="63" alt="Screenshot 2026-01-26 at 4 33 54 PM"
src="https://github.com/user-attachments/assets/1856b352-914a-44cf-813d-1cb50c7f183b"
/>

Less:
<img width="353" height="61" alt="Screenshot 2026-01-26 at 4 30 12 PM"
src="https://github.com/user-attachments/assets/d951c4d5-f3e7-4116-8fe1-6a6c712b3d48"
/>

Less:
<img width="304" height="64" alt="Screenshot 2026-01-26 at 4 30 51 PM"
src="https://github.com/user-attachments/assets/1433e994-5cbc-4e20-a98a-79eee13c8699"
/>

Less:
<img width="235" height="61" alt="Screenshot 2026-01-26 at 4 30 56 PM"
src="https://github.com/user-attachments/assets/e216c3c6-84cd-40fc-ae4d-83bf28947f0e"
/>

Less:
<img width="165" height="59" alt="Screenshot 2026-01-26 at 4 31 08 PM"
src="https://github.com/user-attachments/assets/027de5de-7185-47ce-b1cc-5363ea33d9b1"
/>

## Notes / Edge Cases
- In steer mode while typing, the queue hint no longer replaces the mode
label; it renders as `tab to queue message · {Mode}`.
- Collapse priorities differ by state:
- With the queue hint active, `% context left` is hidden before
shortening or dropping the queue hint.
- In the empty + non-running state, `? for shortcuts` is dropped first,
and `% context left` is only shown if `(shift+tab to
cycle)` can also fit.
- Transient instructional states (`?` overlay, Esc hint, Ctrl+C/D
reminders, and flash/override hints) intentionally suppress the
mode label (and context) to focus the next action.

## Implementation Notes
- Renamed the base footer modes to make the state explicit:
`ComposerEmpty` and `ComposerHasDraft`, and compute the base mode
directly from emptiness.
- Unified collapse behavior in `single_line_footer_layout` for both base
modes, with:
- Queue-hint behavior that prefers keeping the queue hint over context.
- A cycle-hint guard that prevents context from reappearing after
`(shift+tab to cycle)` is dropped.
- Kept rendering responsibilities explicit:
  - `single_line_footer_layout` decides what fits.
  - `render_footer_line` renders a chosen line.
- `render_footer_from_props` renders the canonical mode-to-text mapping.
- Expanded snapshot coverage:
- Added `footer_collapse_snapshots` in `chat_composer.rs` to lock the
distinct collapse states across widths.
- Consolidated the width-aware snapshot helper usage (e.g.,
`snapshot_composer_state_with_width`,
`snapshot_footer_with_mode_indicator`).
2026-01-27 17:43:09 +00:00
Ahmed Ibrahim
509ff1c643 Fixing main and make plan mode reasoning effort medium (#9980)
It's overthinking so much on high and going over the context window.
2026-01-26 22:30:24 -08:00
Ahmed Ibrahim
4db6da32a3 tui: wrapping user input questions (#9971) 2026-01-26 21:30:09 -08:00
sayan-oai
86adf53235 fix: handle all web_search actions and in progress invocations (#9960)
### Summary
- Parse all `web_search` tool actions (`search`, `find_in_page`,
`open_page`).
- Previously we only parsed + displayed `search`, which made the TUI
appear to pause when the other actions were being used.
- Show in progress `web_search` calls as `Searching the web`
  - Previously we only showed completed tool calls

<img width="308" height="149" alt="image"
src="https://github.com/user-attachments/assets/90a4e8ff-b06a-48ff-a282-b57b31121845"
/>

### Tests
Added + updated tests, tested locally

### Follow ups
Update VSCode extension to display these as well
2026-01-27 03:33:48 +00:00
jif-oai
5d13427ef4 NIT larger buffer (#9957) 2026-01-27 01:26:55 +00:00
Ahmed Ibrahim
394b967432 Reuse ChatComposer in request_user_input overlay (#9892)
Reuse the shared chat composer for notes and freeform answers in
request_user_input.

- Build the overlay composer with ChatComposerConfig::plain_text.
- Wire paste-burst flushing + menu surface sizing through the bottom
pane.
2026-01-26 17:21:41 -08:00
jif-oai
73bd84dee0 fix: try to fix freezes 2 (#9951)
Fixes a TUI freeze caused by awaiting `mpsc::Sender::send()` that blocks
the tokio thread, stopping the consumption runtime and creating a
deadlock. This could happen if the server was producing enough chunks to
fill the `mpsc` fast enough. To solve this we try on insert using a
`try_send()` (not requiring an `await`) and delegate to a tokio task if
this does not work

This is a temporary solution as it can contain races for delta elements
and a stronger design should come here
2026-01-27 01:02:22 +00:00
JBallin
32b062d0e1 fix: use brew upgrade --cask codex to avoid warnings and ambiguity (#9823)
Fixes #9822 

### Summary

Make the Homebrew upgrade command explicit by using `brew upgrade --cask
codex`.

### Motivation

During the Codex self-update, Homebrew can emit an avoidable warning
because the
name `codex` resolves to a cask:

```
Warning: Formula codex was renamed to homebrew/cask/codex.
````

While the upgrade succeeds, this relies on implicit name resolution and
produces
unnecessary output during the update flow.

### Why `--cask`

* Eliminates warning/noise for users
* Explicitly matches how Codex is distributed via Homebrew
* Avoids reliance on name resolution behavior
* Makes the command more robust if a `codex` formula is ever introduced

### Context

This restores the `--cask` flag that was removed in #6238 after being
considered
“not necessary” during review:
[https://github.com/openai/codex/pull/6238#discussion_r2505947880](https://github.com/openai/codex/pull/6238#discussion_r2505947880).

Co-authored-by: Eric Traut <etraut@openai.com>
2026-01-26 16:21:09 -08:00
Ahmed Ibrahim
a8f195828b Add composer config and shared menu surface helpers (#9891)
Centralize built-in slash-command gating and extract shared menu-surface
helpers.

- Add bottom_pane::slash_commands and reuse it from composer + command
popup.
- Introduce ChatComposerConfig + shared menu surface rendering without
changing default behavior.
2026-01-26 23:16:29 +00:00
blevy-oai
bdc4742bfc Add MCP server scopes config and use it as fallback for OAuth login (#9647)
### Motivation
- Allow MCP OAuth flows to request scopes defined in `config.toml`
instead of requiring users to always pass `--scopes` on the CLI.
CLI/remote parameters should still override config values.

### Description
- Add optional `scopes: Option<Vec<String>>` to `McpServerConfig` and
`RawMcpServerConfig`, and propagate it through deserialization and the
built config types.
- Serialize `scopes` into the MCP server TOML via
`serialize_mcp_server_table` in `core/src/config/edit.rs` and include
`scopes` in the generated config schema (`core/config.schema.json`).
- CLI: update `codex-rs/cli/src/mcp_cmd.rs` `run_login` to fall back to
`server.scopes` when the `--scopes` flag is empty, with explicit CLI
scopes still taking precedence.
- App server: update
`codex-rs/app-server/src/codex_message_processor.rs`
`mcp_server_oauth_login` to use `params.scopes.or_else(||
server.scopes.clone())` so the RPC path also respects configured scopes.
- Update many test fixtures to initialize the new `scopes` field (set to
`None`) so test code builds with the new struct field.

### Testing
- Ran config tooling and formatters: `just write-config-schema`
(succeeded), `just fmt` (succeeded), and `just fix -p codex-core`, `just
fix -p codex-cli`, `just fix -p codex-app-server` (succeeded where
applicable).
- Ran unit tests for the CLI: `cargo test -p codex-cli` (passed).
- Ran unit tests for core: `cargo test -p codex-core` (ran; many tests
passed but several failed, including model refresh/403-related tests,
shell snapshot/timeouts, and several `unified_exec` expectations).
- Ran app-server tests: `cargo test -p codex-app-server` (ran; many
integration-suite tests failed due to mocked/remote HTTP 401/403
responses and wiremock expectations).

If you want, I can split the tests into smaller focused runs or help
debug the failing integration tests (they appear to be unrelated to the
config change and stem from external HTTP/mocking behaviors encountered
during the test runs).

------
[Codex
Task](https://chatgpt.com/codex/tasks/task_i_69718f505914832ea1f334b3ba064553)
2026-01-26 14:13:04 -08:00
Eric Traut
b77bf4d36d Aligned feature stage names with public feature maturity stages (#9929)
We've recently standardized a [feature maturity
model](https://developers.openai.com/codex/feature-maturity) that we're
using in our docs and support forums to communicate expectations to
users. This PR updates the internal stage names and descriptions to
match.

This change involves a simple internal rename and updates to a few
user-visible strings. No functional change.
2026-01-26 11:43:36 -08:00
Shijie Rao
3ba702c5b6 Feat: add isOther to question returned by request user input tool (#9890)
### Summary
Add `isOther` to question object from request_user_input tool input and
remove `other` option from the tool prompt to better handle tool input.
2026-01-26 09:52:38 -08:00
gt-oai
6316e57497 Fix up config disabled err msg (#9916)
**Before:**
<img width="745" height="375" alt="image"
src="https://github.com/user-attachments/assets/d6c23562-b87f-4af9-8642-329aab8e594d"
/>

**After:**
<img width="1042" height="354" alt="image"
src="https://github.com/user-attachments/assets/c9a2413c-c945-4c34-8b7e-c6c9b8fbf762"
/>

Two changes:
1. only display if there is a `config.toml` that is skipped (i.e. if
there is just `.codex/skills` but no `.codex/config.toml` we do not
display the error)
2. clarify the implications and the fix in the error message.
2026-01-26 17:49:31 +00:00
jif-oai
c66662c61b feat: rebase multi-agent tui on config_snapshot (#9818) 2026-01-26 10:18:47 +00:00
jif-oai
d594693d1a feat: dynamic tools injection (#9539)
## Summary
Add dynamic tool injection to thread startup in API v2, wire dynamic
tool calls through the app server to clients, and plumb responses back
into the model tool pipeline.

### Flow (high level)
- Thread start injects `dynamic_tools` into the model tool list for that
thread (validation is done here).
- When the model emits a tool call for one of those names, core raises a
`DynamicToolCallRequest` event.
- The app server forwards it to the client as `item/tool/call`, waits
for the client’s response, then submits a `DynamicToolResponse` back to
core.
- Core turns that into a `function_call_output` in the next model
request so the model can continue.

### What changed
- Added dynamic tool specs to v2 thread start params and protocol types;
introduced `item/tool/call` (request/response) for dynamic tool
execution.
- Core now registers dynamic tool specs at request time and routes those
calls via a new dynamic tool handler.
- App server validates tool names/schemas, forwards dynamic tool call
requests to clients, and publishes tool outputs back into the session.
- Integration tests
2026-01-26 10:06:44 +00:00
Dylan Hurd
031bafd1fb feat(tui) /personality (#9718)
## Summary
Adds /personality selector in the TUI, which leverages the new core
interface in #9644

Notes:
- We are doing some of our own state management for model_info loading
here, but not sure if that's ideal. open to opinions on simpler
approach, but would like to avoid blocking on a larger refactor
- Right now, the `/personality` selector just hides when the model
doesn't support it. we can update this behavior down the line

## Testing
- [x] Tested locally
- [x] Added snapshot tests
2026-01-25 21:59:42 -08:00
Ahmed Ibrahim
cb2bbe5cba Adjust modes masks (#9868) 2026-01-25 12:44:17 -08:00
Ahmed Ibrahim
58450ba2a1 Use collaboration mode masks without mutating base settings (#9806)
Keep an unmasked base collaboration mode and apply the active mask on
demand. Simplify the TUI mask helpers and update tests/docs to match the
mask contract.
2026-01-25 07:35:31 +00:00
Charley Cunningham
18acec09df Ask for cwd choice when resuming session from different cwd (#9731)
# Summary
- Fix resume/fork config rebuild so cwd changes inside the TUI produce a
fully rebuilt Config (trust/approval/sandbox) instead of mutating only
the cwd.
- Preserve `--add-dir` behavior across resume/fork by normalizing
relative roots to absolute paths once (based on the original cwd).
- Prefer latest `TurnContext.cwd` for resume/fork prompts but fall back
to `SessionMeta.cwd` if the latest cwd no longer exists.
- Align resume/fork selection handling and ensure UI config matches the
resumed thread config.
- Fix Windows test TOML path escaping in trust-level test.

# Details
- Rebuild Config via `ConfigBuilder` when resuming into a different cwd;
carry forward runtime approval/sandbox overrides.
- Add `normalize_harness_overrides_for_cwd` to resolve relative
`additional_writable_roots` against the initial cwd before reuse.
- Guard `read_session_cwd` with filesystem existence check for the
latest `TurnContext.cwd`.
- Update naming/flow around cwd comparison and prompt selection.

<img width="603" height="150" alt="Screenshot 2026-01-23 at 5 42 13 PM"
src="https://github.com/user-attachments/assets/d1897386-bb28-4e8a-98cf-187fdebbecb0"
/>

And proof the model understands the new cwd:

<img width="828" height="353" alt="Screenshot 2026-01-22 at 5 36 45 PM"
src="https://github.com/user-attachments/assets/12aed8ca-dec3-4b64-8dae-c6b8cff78387"
/>
2026-01-24 21:57:19 -08:00
Matthew Zeng
182000999c Raise welcome animation breakpoint to 37 rows (#9778)
### Motivation
- The large ASCII welcome animation can push onboarding content below
the fold on default-height terminals, making the CLI appear
unresponsive; raising the breakpoint prevents that.
- The existing test measured an arbitrary row count rather than
asserting the welcome line position relative to the animation frame,
which made the intent unclear.

### Description
- Increase `MIN_ANIMATION_HEIGHT` from `20` to `37` in
`codex-rs/tui/src/onboarding/welcome.rs` so the animation is skipped
unless there is enough vertical space.
- Replace the brittle measurement logic in the welcome render test with
a `row_containing` helper and assert the welcome row equals the frame
height plus the spacer line (`frame_lines + 1`).
- Add a regression test
`welcome_skips_animation_below_height_breakpoint` that verifies the
animation is not rendered when the viewport height is one row below the
breakpoint.

### Testing
- Ran formatting with `~/.cargo/bin/just fmt` which completed
successfully.
- Ran unit tests for the crate with `cargo test -p codex-tui --lib` and
they passed (unit test suite succeeded).
- Ran `cargo test -p codex-tui` which reported a failing integration
test in this environment because the test cannot locate the `codex`
binary, so full crate tests are blocked here (environment limitation).

------
[Codex
Task](https://chatgpt.com/codex/tasks/task_i_6973b0a710d4832c9ff36fac26eb1519)
2026-01-24 21:50:35 -08:00
Charley Cunningham
279c9534a1 Prevent backspace from removing a text element when the cursor is at the element’s left edge (#9630)
**Summary**
- Prevent backspace from removing a text element when the cursor is at
the element’s left edge.
- Instead just delete the char before the placeholder (moving it to the
left).
2026-01-24 10:41:39 -08:00
jif-oai
83775f4df1 feat: ephemeral threads (#9765)
Add ephemeral threads capabilities. Only exposed through the
`app-server` v2

The idea is to disable the rollout recorder for those threads.
2026-01-24 14:57:40 +00:00
Eric Traut
713ae22c04 Another round of improvements for config error messages (#9746)
In a [recent PR](https://github.com/openai/codex/pull/9182), I made some
improvements to config error messages so errors didn't leave app server
clients in a dead state. This is a follow-on PR to make these error
messages more readable and actionable for both TUI and GUI users. For
example, see #9668 where the user was understandably confused about the
source of the problem and how to fix it.

The improved error message:
1. Clearly identifies the config file where the error was found (which
is more important now that we support layered configs)
2. Provides a line and column number of the error
3. Displays the line where the error occurred and underlines it

For example, if my `config.toml` includes the following:
```toml
[features]
collaboration_modes = "true"
```

Here's the current CLI error message:
```
Error loading config.toml: invalid type: string "true", expected a boolean in `features`
```

And here's the improved message:
```
Error loading config.toml:
/Users/etraut/.codex/config.toml:43:23: invalid type: string "true", expected a boolean
   |
43 | collaboration_modes = "true"
   |                       ^^^^^^
```

The bulk of the new logic is contained within a new module
`config_loader/diagnostics.rs` that is responsible for calculating the
text range for a given toml path (which is more involved than I would
have expected).

In addition, this PR adds the file name and text range to the
`ConfigWarningNotification` app server struct. This allows GUI clients
to present the user with a better error message and an optional link to
open the errant config file. This was a suggestion from @.bolinfest when
he reviewed my previous PR.
2026-01-23 20:11:09 -08:00
Ahmed Ibrahim
b3127e2eeb Have a coding mode and only show coding and plan (#9802) 2026-01-23 19:28:49 -08:00
Ahmed Ibrahim
69cfc73dc6 change collaboration mode to struct (#9793)
Shouldn't cause behavioral change
2026-01-23 17:00:23 -08:00
Ahmed Ibrahim
1167465bf6 Chore: remove mode from header (#9792) 2026-01-23 22:38:17 +00:00
gt-oai
7938c170d9 Print warning if we skip config loading (#9611)
https://github.com/openai/codex/pull/9533 silently ignored config if
untrusted. Instead, we still load it but disable it. Maybe we shouldn't
try to parse it either...

<img width="939" height="515" alt="Screenshot 2026-01-21 at 14 56 38"
src="https://github.com/user-attachments/assets/e753cc22-dd99-4242-8ffe-7589e85bef66"
/>
2026-01-23 20:06:37 +00:00
charley-oai
935d88b455 Persist text element ranges and attached images across history/resume (#9116)
**Summary**
- Backtrack selection now rehydrates `text_elements` and
`local_image_paths` from the chosen user history cell so Esc‑Esc history
edits preserve image placeholders and attachments.
- Composer prefill uses the preserved elements/attachments in both `tui`
and `tui2`.
- Extended backtrack selection tests to cover image placeholder elements
and local image paths.

**Changes**
- `tui/src/app_backtrack.rs`: Backtrack selection now carries text
elements + local image paths; composer prefill uses them (removes TODO).
- `tui2/src/app_backtrack.rs`: Same as above.
- `tui/src/app.rs`: Updated backtrack test to assert restored
elements/paths.
- `tui2/src/app.rs`: Same test updates.

### The original scope of this PR (threading text elements and image
attachments through the codex harness thoroughly/persistently) was
broken into the following PRs other than this one:

The diff of this PR was reduced by changing types in a starter PR:
https://github.com/openai/codex/pull/9235

Then text element metadata was added to protocol, app server, and core
in this PR: https://github.com/openai/codex/pull/9331

Then the end-to-end flow was completed by wiring TUI/TUI2 input,
history, and restore behavior in
https://github.com/openai/codex/pull/9393

Prompt expansion was supported in this PR:
https://github.com/openai/codex/pull/9518

TextElement optional placeholder field was protected in
https://github.com/openai/codex/pull/9545
2026-01-23 10:18:19 -08:00
jif-oai
f30f39b28b feat: tui beta for collab (#9690)
https://github.com/user-attachments/assets/1ca07e7a-3d82-40da-a5b0-8ab2eef0bb69
2026-01-23 13:57:59 +01:00
charley-oai
02fced28a4 Hide mode cycle hint while a task is running (#9730)
## Summary
- hide the “(shift+tab to cycle)” suffix on the collaboration mode label
while a task is running
- keep the cycle hint visible when idle
- add a snapshot to cover the running-task label state
2026-01-22 18:32:06 -08:00
charley-oai
0e79d239ed TUI: prompt to implement plan and switch to Execute (#9712)
## Summary
- Replace the plan‑implementation prompt with a standard selection
popup.
- “Yes” submits a user turn in Execute via a dedicated app event to
preserve normal transcript behavior.
- “No” simply dismisses the popup.

<img width="977" height="433" alt="Screenshot 2026-01-22 at 2 00 54 PM"
src="https://github.com/user-attachments/assets/91fad06f-7b7a-4cd8-9051-f28a19b750b2"
/>

## Changes
- Add a plan‑implementation popup using `SelectionViewParams`.
- Add `SubmitUserMessageWithMode` so “Yes” routes through
`submit_user_message` (ensures user history + separator state).
- Track `saw_plan_update_this_turn` so the prompt appears even when only
`update_plan` is emitted.
- Suppress the plan popup on replayed turns, when messages are queued,
or when a rate‑limit prompt is pending.
- Add `execute_mode` helper for collaboration modes.
- Add tests for replay/queued/rate‑limit guards and plan update without
final message.
- Add snapshots for both the default and “No”‑selected popup states.
2026-01-23 00:25:50 +00:00
Dylan Hurd
8b3521ee77 feat(core) update Personality on turn (#9644)
## Summary
Support updating Personality mid-Thread via UserTurn/OverwriteTurn. This
is explicitly unused by the clients so far, to simplify PRs - app-server
and tui implementations will be follow-ups.

## Testing
- [x] added integration tests
2026-01-22 12:04:23 -08:00
charley-oai
4210fb9e6c Modes label below textarea (#9645)
# Summary
- Add a collaboration mode indicator rendered at the bottom-right of the
TUI composer footer.
- Style modes per design (Plan in #D72EE1, Execute matching dim context
style, Pair Programming using the same cyan as text elements).
- Add shared “(shift+tab to cycle)” hint text for all mode labels and
align the indicator with the left footer margin.

NOTE: currently this is hidden if the Collaboration Modes feature flag
is disabled, or in Custom mode. Maybe we should show it in Custom mode
too? I'll leave that out of this PR though

# UI
- Mode indicator appears below the textarea, bottom-right of the footer
line.
- Includes “(shift+tab to cycle)” and keeps right padding aligned to the
left footer indent.

<img width="983" height="200" alt="Screenshot 2026-01-21 at 7 17 54 PM"
src="https://github.com/user-attachments/assets/d1c5e4ed-7d7b-4f6c-9e71-bc3cf6400e0e"
/>

<img width="980" height="200" alt="Screenshot 2026-01-21 at 7 18 53 PM"
src="https://github.com/user-attachments/assets/d22ff0da-a406-4930-85c5-affb2234e84b"
/>

<img width="979" height="201" alt="Screenshot 2026-01-21 at 7 19 12 PM"
src="https://github.com/user-attachments/assets/862cb17f-0495-46fa-9b01-a4a9f29b52d5"
/>
2026-01-22 17:31:11 +00:00
Dylan Hurd
038b78c915 feat(tui) /permissions flow (#9561)
## Summary
Adds the `/permissions` command, with a (usually) shorter set of
permissions. `/approvals` still exists, for backwards compatibility.

<img width="863" height="309" alt="Screenshot 2026-01-20 at 4 12 51 PM"
src="https://github.com/user-attachments/assets/c49b5ba5-bc47-46dd-9067-e1a5670328fe"
/>


## Testing
- [x] updated unit tests
- [x] Tested locally
2026-01-21 21:38:46 -08:00
pakrym-oai
836f0343a3 Add tui.experimental_mode setting (#9656)
To simplify testing
2026-01-22 05:27:57 +00:00