What version of Codex CLI is running?
codex-cli 0.128.0
What subscription do you have?
Not relevant / not captured.
Which model were you using?
Not model-specific.
What platform is your computer?
macOS / Darwin on Apple Silicon (aarch64-apple-darwin binary from Homebrew cask).
What terminal emulator and version are you using (if applicable)?
Original terminal details were not captured. The failure appears tied to the TUI alternate-screen/backtrack flow rather than model output.
What issue are you seeing?
After using the Codex CLI double-Esc rewind/backtrack flow, terminal rendering can remain broken after exiting Codex. The shell prompt appears to render over stale TUI content / with an incorrectly restored screen state, requiring a terminal reset or a new terminal session to recover cleanly.
This looks like Codex can exit while the transcript/backtrack overlay has used the alternate screen, but process-level terminal restoration does not defensively leave the alternate screen. There is also a plausible redraw-cache issue when leaving the transcript overlay: the inline viewport is restored, but the terminal diff buffer can still contain the previous alternate-screen frame, allowing the next normal-buffer draw to be computed against stale overlay state.
What steps can reproduce the bug?
- Start an interactive Codex CLI session.
- Send at least one user message so there is a rewind target.
- Press
Esc once to prime backtrack.
- Press
Esc again to open the transcript/backtrack overlay.
- Exit Codex from this flow, or close the overlay and then exit.
- Observe the shell/terminal after Codex exits.
What is the expected behavior?
After Codex exits, the terminal should always be restored to a normal shell-rendering state:
- not left in the alternate screen,
- alternate-scroll mode disabled,
- cursor visible/default,
- no stale Codex overlay content affecting subsequent shell rendering.
What happens instead?
The terminal can remain visually corrupted after exit, with shell output/prompt rendering over stale Codex TUI content or otherwise appearing as if the screen state was not fully restored.
Additional information
I inspected codex-rs/tui/src/tui.rs and found two likely hardening points:
restore_common(...) currently restores bracketed paste, focus, raw mode, keyboard reporting, and cursor state, but does not defensively emit DisableAlternateScroll / LeaveAlternateScreen. If the app exits while an overlay or alternate-screen transition is active, the parent shell may inherit the wrong screen state.
Tui::leave_alt_screen() restores the saved inline viewport but does not invalidate the terminal diff buffer. Since the alternate-screen overlay and normal inline UI use different backing screen contents, the next normal-buffer draw should be forced to repaint rather than diffing against the overlay frame.
A local minimal patch that appears appropriate is:
// in restore_common(...)
if let Err(err) = execute!(stdout(), DisableAlternateScroll, LeaveAlternateScreen) {
first_error.get_or_insert(err);
}
// in Tui::leave_alt_screen(), after restoring alt_saved_viewport
self.terminal.invalidate_viewport();
Local validation on a checkout of openai/codex main:
cargo fmt --manifest-path codex-rs/Cargo.toml --all
cargo test --manifest-path codex-rs/tui/Cargo.toml app_backtrack --lib
cargo check --manifest-path codex-rs/Cargo.toml -p codex-tui
Results:
cargo test --manifest-path codex-rs/tui/Cargo.toml app_backtrack --lib: passed, 8 tests.
cargo check --manifest-path codex-rs/Cargo.toml -p codex-tui: passed.
cargo fmt completed; stable rustfmt emitted existing warnings about the repository's nightly-only imports_granularity setting.
Per docs/contributing.md, external PRs are by invitation only, so I am opening this issue first with the repro, root-cause hypothesis, and patch outline instead of sending an unsolicited PR.
What version of Codex CLI is running?
codex-cli 0.128.0What subscription do you have?
Not relevant / not captured.
Which model were you using?
Not model-specific.
What platform is your computer?
macOS / Darwin on Apple Silicon (
aarch64-apple-darwinbinary from Homebrew cask).What terminal emulator and version are you using (if applicable)?
Original terminal details were not captured. The failure appears tied to the TUI alternate-screen/backtrack flow rather than model output.
What issue are you seeing?
After using the Codex CLI double-Esc rewind/backtrack flow, terminal rendering can remain broken after exiting Codex. The shell prompt appears to render over stale TUI content / with an incorrectly restored screen state, requiring a terminal reset or a new terminal session to recover cleanly.
This looks like Codex can exit while the transcript/backtrack overlay has used the alternate screen, but process-level terminal restoration does not defensively leave the alternate screen. There is also a plausible redraw-cache issue when leaving the transcript overlay: the inline viewport is restored, but the terminal diff buffer can still contain the previous alternate-screen frame, allowing the next normal-buffer draw to be computed against stale overlay state.
What steps can reproduce the bug?
Esconce to prime backtrack.Escagain to open the transcript/backtrack overlay.What is the expected behavior?
After Codex exits, the terminal should always be restored to a normal shell-rendering state:
What happens instead?
The terminal can remain visually corrupted after exit, with shell output/prompt rendering over stale Codex TUI content or otherwise appearing as if the screen state was not fully restored.
Additional information
I inspected
codex-rs/tui/src/tui.rsand found two likely hardening points:restore_common(...)currently restores bracketed paste, focus, raw mode, keyboard reporting, and cursor state, but does not defensively emitDisableAlternateScroll/LeaveAlternateScreen. If the app exits while an overlay or alternate-screen transition is active, the parent shell may inherit the wrong screen state.Tui::leave_alt_screen()restores the saved inline viewport but does not invalidate the terminal diff buffer. Since the alternate-screen overlay and normal inline UI use different backing screen contents, the next normal-buffer draw should be forced to repaint rather than diffing against the overlay frame.A local minimal patch that appears appropriate is:
Local validation on a checkout of
openai/codexmain:Results:
cargo test --manifest-path codex-rs/tui/Cargo.toml app_backtrack --lib: passed, 8 tests.cargo check --manifest-path codex-rs/Cargo.toml -p codex-tui: passed.cargo fmtcompleted; stable rustfmt emitted existing warnings about the repository's nightly-onlyimports_granularitysetting.Per
docs/contributing.md, external PRs are by invitation only, so I am opening this issue first with the repro, root-cause hypothesis, and patch outline instead of sending an unsolicited PR.