feat(tui): add /title terminal title configuration#12334
feat(tui): add /title terminal title configuration#12334yvolovich-cyber wants to merge 13 commits intomainfrom
Conversation
|
@codex review |
|
@codex review |
|
@codex review security in codex-rs/tui/src/terminal_title.rs |
|
Codex Review: Didn't find any major issues. Bravo. ℹ️ About Codex in GitHubYour team has set up Codex to review pull requests in this repo. Reviews are triggered when you
If Codex has suggestions, it will comment; otherwise it will react with 👍. Codex can also answer questions or update the PR. Try commenting "@codex address that feedback". |
There was a problem hiding this comment.
Pull request overview
Adds a first-class /title configuration flow to the TUI so terminal tabs/windows can be distinguished across concurrent Codex sessions, including secure OSC 0 title rendering and persisted ordering of title “items”. Also includes an app-server fix to make running-thread resume status reporting consistent.
Changes:
- Introduces terminal-title OSC writer with sanitization + tests, and wires dynamic title refresh into
ChatWidget. - Adds
/titleslash command + bottom-pane picker UI (with live preview + rollback on cancel) and persists config viatui.terminal_title. - Fixes a thread resume race in app-server so a running thread reliably reports
Activewhen an active turn snapshot exists.
Reviewed changes
Copilot reviewed 15 out of 15 changed files in this pull request and generated 2 comments.
Show a summary per file
| File | Description |
|---|---|
| codex-rs/tui/src/terminal_title.rs | Implements OSC 0 title writing with sanitization and unit tests. |
| codex-rs/tui/src/slash_command.rs | Adds /title to the slash-command set and help text. |
| codex-rs/tui/src/lib.rs | Registers the new terminal_title module. |
| codex-rs/tui/src/chatwidget.rs | Adds terminal title config/defaults, live rendering, preview/rollback mechanics, and refresh hooks. |
| codex-rs/tui/src/chatwidget/tests.rs | Adds tests for preview rollback and status text mapping for title rendering. |
| codex-rs/tui/src/bottom_pane/title_setup.rs | Adds the terminal title picker UI (multi-select + ordering + live preview events). |
| codex-rs/tui/src/bottom_pane/mod.rs | Exposes terminal title picker view + item enum. |
| codex-rs/tui/src/bottom_pane/snapshots/...terminal_title_setup_basic.snap | Adds snapshot coverage for the new picker UI. |
| codex-rs/tui/src/app_event.rs | Adds events for terminal title setup/preview/cancel. |
| codex-rs/tui/src/app.rs | Handles new events and persists tui.terminal_title edits. |
| codex-rs/core/src/config/types.rs | Adds tui.terminal_title to typed config. |
| codex-rs/core/src/config/mod.rs | Plumbs config field into runtime Config and defaults/tests. |
| codex-rs/core/src/config/edit.rs | Adds a config edit helper to persist terminal title items. |
| codex-rs/core/config.schema.json | Adds schema documentation for tui.terminal_title. |
| codex-rs/app-server/src/codex_message_processor.rs | Fixes resume-status race by preferring active turn snapshot over idle watch status. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
|
@codex review |
There was a problem hiding this comment.
💡 Codex Review
codex/codex-rs/tui/src/chatwidget.rs
Lines 1135 to 1137 in 4082887
Update request_status_line_branch_refresh to consider terminal-title config too. It currently returns unless the status line includes git-branch, but terminal titles now also use the same cached branch value. If a user enables git-branch in /title only, branch lookup is never re-triggered after turn completion, so the title can show a stale branch after git checkout/branch-changing commands.
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 15 out of 15 changed files in this pull request and generated 1 comment.
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
There was a problem hiding this comment.
💡 Codex Review
codex/codex-rs/tui/src/chatwidget.rs
Lines 1135 to 1137 in 4082887
Refresh git-branch title when only /title enables it
Updaterequest_status_line_branch_refreshto consider terminal-title config too. It currently returns unless the status line includesgit-branch, but terminal titles now also use the same cached branch value. If a user enablesgit-branchin/titleonly, branch lookup is never re-triggered after turn completion, so the title can show a stale branch aftergit checkout/branch-changing commands.
Addressed it in 2cf7abd05.
What changed:
request_status_line_branch_refresh()now refreshes whengit-branchis configured in either/statuslineor/title- added a regression test for the title-only
git-branchcase afterTurnComplete
|
@codex review |
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 15 out of 15 changed files in this pull request and generated 1 comment.
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 2cf7abd055
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
800268f to
9f62b39
Compare
|
@yvolovich-cyber really great to see the I just took this branch for a test drive and it worked beautifully with tmux. I use a configuration where I explicitly show the pane titles and it's so much easier to spot what's happening with this feature in place:
Specially for someone who has ten thousand codex worktrees like myself, and I'm pretty sure I'm not the only one 😄 I also did a pass on the code changes and they look good to me 👍 |
jif-oai
left a comment
There was a problem hiding this comment.
I don't see anything that reset the title after a CMD + C. Can you make sure the title always get reset when we exit Codex?
Good catch. I added best effort terminal-title cleanup in |
be6d8f3 to
c81ce88
Compare
|
@codex review |
|
Codex Review: Didn't find any major issues. Breezy! ℹ️ About Codex in GitHubYour team has set up Codex to review pull requests in this repo. Reviews are triggered when you
If Codex has suggestions, it will comment; otherwise it will react with 👍. Codex can also answer questions or update the PR. Try commenting "@codex address that feedback". |
| return Ok(()); | ||
| } | ||
|
|
||
| execute!(stdout(), SetWindowTitle(String::new())) |
There was a problem hiding this comment.
this is not the same thing as restoring the previous one
There was a problem hiding this comment.
There is no portable and reliable way to restore (specifically read) terminal title.
We only clear the title Codex set, not to restore whatever title was there before, which keeps the behavior portable across terminals.
I also changed set_terminal_title() so "sanitized to no visible content" is no longer treated as an implicit clear_terminal_title().
codex-rs/tui/src/chatwidget.rs
Outdated
| fn set_status(&mut self, header: String, details: Option<String>) { | ||
| self.current_status_header = header.clone(); | ||
| self.bottom_pane.update_status(header, details); | ||
| self.refresh_terminal_title(); |
There was a problem hiding this comment.
I think in the end this should become async. Can be done as follow-up
There was a problem hiding this comment.
Agreed. I kept this synchronous for now, but I narrowed the hot path so set_status() only refreshes the terminal title when /title actually includes status, and the shared status-surface path now reuses cached/shared state instead of recomputing it. I think making the remaining title refresh path async can be a follow-up.
| .iter() | ||
| .map(|id| id.parse::<TerminalTitleItem>()) | ||
| .collect::<Result<Vec<_>, _>>() | ||
| .unwrap_or_default(); |
There was a problem hiding this comment.
We shouldn't call app_event.send() if the parsing fail
There was a problem hiding this comment.
Agreed. on_change() and on_confirm() now return early on parse failure instead of sending an app event. I also factored the parsing into parse_terminal_title_items() so preview, change, and confirm all share the same validation path.
| self.warn_invalid_terminal_title_items_once(&selections.invalid_terminal_title_items); | ||
| self.sync_status_surface_shared_state(&selections); | ||
| self.refresh_status_line_from_selections(&selections); | ||
| self.refresh_terminal_title_from_selections(&selections); |
There was a problem hiding this comment.
strange to update the title in a function named "..._status_line"
There was a problem hiding this comment.
Renamed the shared entrypoint to refresh_status_surfaces() so the name matches what it does. refresh_status_line_from_selections() stays as the footer-only renderer.
e8db1a6 to
1ae8fc2
Compare
1ae8fc2 to
f7bc129
Compare

Why
We want a first class way to make terminal tabs/windows distinguishable when multiple Codex sessions are open.
This adds
/titleas a separate command from/statusline, with secure terminal title rendering and a configurable title item order.What changed
/titleslash command and terminal title picker UI.tui.terminal_titlewith default orderproject | status.project,status,thread,git-branch,model,task-progress./titlepreview while the picker is open, and rollback onEsc/cancel.Waiting....thread/resumerace in app-server so a running thread resume response reportsActiveconsistently when an active turn snapshot exists (this was the CI failure on Linux Bazel jobs).Security
The terminal title path sanitizes untrusted text before writing OSC 0:
ST,ESC \\)References used while implementing this:
Verification
Ran:
cargo test -p codex-tuicargo test -p codex-app-server --test all thread_resume_rejoins_running_thread_even_with_override_mismatch -- --nocapturecargo test -p codex-core(earlier during feature work; localcore/tests/allstill had unrelated failures in this checkout)cargo check -p codex-tuijust fix -p codex-tuijust fix -p codex-app-serverjust fmtDid not run:
cargo test --all-features(shared crates changed earlier in the feature; asking before running the full workspace suite)