fix(tui): use BEL for terminal title updates (#18261)

## Summary

Fixes #18160.

iTerm2 can append the current foreground process to tab titles, and
Codex's terminal-title updates were causing that decoration to appear as
`(codex")` with a stray trailing quote. Codex was writing OSC 0 title
sequences terminated with ST (`ESC \`). Some terminal title integrations
appear to accept that title update but still expose the ST terminator in
their own process/title decoration.

## Changes

- Update `codex-rs/tui/src/terminal_title.rs` to terminate OSC 0 title
updates with BEL instead of ST.
- Update the focused terminal-title encoding test to assert the
BEL-terminated sequence.

## Compatibility

This should be low risk: the title payload and update timing are
unchanged, and BEL is the form already emitted by
`crossterm::terminal::SetTitle` in the crossterm version used by this
repository. BEL is also the widely supported xterm-family title
terminator used by common terminals and multiplexers. The main
theoretical risk would be a very old or unusual terminal that accepted
only ST and not BEL for OSC title termination, but that is unlikely
compared with the observed iTerm2 issue.

## Verification

- `cargo test -p codex-tui terminal_title`
- `cargo test -p codex-tui`
This commit is contained in:
Eric Traut
2026-04-17 08:39:37 -07:00
committed by GitHub
parent c3ecb557d3
commit 2dd6734dd3

View File

@@ -84,9 +84,10 @@ struct SetWindowTitle(String);
impl Command for SetWindowTitle {
fn write_ansi(&self, f: &mut impl fmt::Write) -> fmt::Result {
// xterm/ctlseqs documents OSC 0/2 title sequences with ST (ESC \) termination.
// Most terminals also accept BEL for compatibility, but ST is the canonical form.
write!(f, "\x1b]0;{}\x1b\\", self.0)
// Match crossterm's SetTitle command and terminate OSC 0 with BEL.
// Some terminal title integrations expose the ST terminator in process
// decorations even though they otherwise accept the title update.
write!(f, "\x1b]0;{}\x07", self.0)
}
#[cfg(windows)]
@@ -214,11 +215,11 @@ mod tests {
}
#[test]
fn writes_osc_title_with_string_terminator() {
fn writes_osc_title_with_bel_terminator() {
let mut out = String::new();
SetWindowTitle("hello".to_string())
.write_ansi(&mut out)
.expect("encode terminal title");
assert_eq!(out, "\x1b]0;hello\x1b\\");
assert_eq!(out, "\x1b]0;hello\x07");
}
}