Windows Terminal focus events [O/[I are inserted into TUI prompt on 0.134.0

Open 💬 6 comments Opened May 28, 2026 by fancyhub

What version of Codex CLI is running?

codex-cli 0.134.0

Installed via winget:

Codex CLI OpenAI.Codex 0.134.0 winget

codex doctor --summary reports:

Codex Doctor v0.134.0 - windows-x86_64
13 ok - 1 idle - 0 warn - 0 fail ok

What platform is your computer?

Microsoft Windows [Version 10.0.26200.8457]

What terminal emulator and version are you using?

Windows Terminal:

Microsoft.WindowsTerminal 1.24.11321.0

Shell:

Windows PowerShell 5.1.26100.8457

What issue are you seeing?

On Windows Terminal + Windows PowerShell, the Codex TUI prompt inserts raw focus-reporting control sequences into the input buffer whenever the Windows Terminal window loses or regains focus.

When I switch focus between Windows Terminal and another app with the mouse, the prompt receives visible text like:

[O[I[O[I[O[I

These appear to be terminal focus out / focus in events (ESC [ O and ESC [ I) that should be consumed by the TUI instead of being inserted into the prompt.

This makes slash commands fail because the control-sequence text becomes part of the command, for example:

Unrecognized command '/update[O[I[O[I[O[I'

The same failure mode was also observed with Backspace not working while the prompt is in this bad input state.

Steps to reproduce

  1. Open Windows Terminal.
  2. Start Windows PowerShell 5.1.
  3. Run:

``powershell
codex
``

  1. Wait for the Codex TUI prompt to appear.
  2. Click another application so Windows Terminal loses focus.
  3. Click back into Windows Terminal.
  4. Repeat a few times.

Expected behavior

The TUI should consume terminal focus events and not insert [O / [I into the prompt.

Actual behavior

The prompt receives visible [O / [I text every time focus changes, so the input buffer becomes polluted with raw terminal control sequences.

Additional context

This still reproduces after upgrading from codex-cli 0.133.0 to 0.134.0 via winget.

This may be related to the Windows TUI/raw control sequence regressions discussed in #23740, but the specific symptom here is focus-reporting input leakage on 0.134.0.

View original on GitHub ↗

6 Comments

Pluviobyte · 3 months ago

Root cause: set_modes() enables terminal focus reporting (?1004h) unconditionally, but crossterm's Windows console input backend doesn't translate the focus replies into focus events, so they leak into the composer as ESC[O/ESC[I.

codex-rs/tui/src/tui.rs, set_modes() (around L187 on 56958f2) enables focus reporting with no platform guard:

let _ = execute!(stdout(), EnableFocusChange);   // unconditional

EnableFocusChange makes the terminal emit ESC[I (focus in) / ESC[O (focus out) on each focus transition. On the Unix/ANSI path crossterm parses these into Event::FocusGained / Event::FocusLost, which the loop consumes without inserting text (tui/src/tui/event_stream.rs L249/L254):

Event::FocusGained => { ...; Some(TuiEvent::Draw) }
Event::FocusLost  => { ...; None }

On Windows, ensure_virtual_terminal_processing() enables VT output processing, but crossterm still reads input through the Windows console backend, which does not turn the ESC[I/ESC[O focus replies into FocusGained/FocusLost. They arrive as raw bytes and get inserted into the composer — exactly the /update[O[I… corruption (and the repeated [O[I[O[I on multiple focus switches) in the report.

This is the only mode in set_modes() enabled without accounting for the Windows backend; the file already cfg-gates Windows-specific behavior elsewhere (e.g. EnableAlternateScroll::execute_winapi). The teardown DisableFocusChange at L259 is likewise unconditional.

Suggested fix (outline): gate EnableFocusChange (L187) and DisableFocusChange (L259) behind #[cfg(not(windows))], or only enable focus reporting when the active input backend actually emits Focus events. The only thing lost on Windows is the focus-triggered palette requery/redraw (a minor cosmetic refresh), which is a good trade for not corrupting input. Likely the same root cause as #23740.

Happy to put up a PR with this + a guard test if a maintainer wants to take it (noting code contributions here are invitation-only).

TomLo-FStack · 2 months ago

Additional data point on 0.137.0: I am seeing the same focus-report tail leakage in Windows Terminal, and it also shows up around an interactive WSL2 handoff.

Environment, generalized to avoid machine-specific details:

  • Windows 11 Pro
  • Windows Terminal 1.24
  • Codex CLI 0.137.0
  • WSL2
  • WSL distro: minimal Linux distro
  • Shell inside WSL: zsh
  • TERM=xterm-256color
  • Launch path: Windows Terminal -> PowerShell -> Codex CLI running as a Windows process -> wsl.exe / WSL interactive shell

Observed behavior:

  • After focus transitions or returning from the WSL2 interactive path, the Codex composer can receive [O[I.
  • Pressing Delete in the composer can insert [3~ instead of deleting forward.
  • The leaked text appears in the Codex composer, not only inside the WSL shell.

The visible fragments line up with VT sequence tails whose leading ESC byte is missing:

  • ESC [ I -> focus-in report, visible tail [I
  • ESC [ O -> focus-out report, visible tail [O
  • ESC [ 3 ~ -> Delete key, visible tail [3~

The WSL shell can handle complete sequences, but it cannot handle orphaned tails after the ESC byte is no longer present. In this environment, complete sequences such as ESC[3~, ESC[I, and ESC[O were handled inside the shell, yet tails such as [3~, [I, and [O still reached the Codex composer after returning to Codex.

In Codex CLI 0.137.0 source, the relevant code still appears to be in the same area:

  • codex-rs/tui/src/tui.rs: set_modes() enables bracketed paste, raw mode, keyboard enhancement, and EnableFocusChange.
  • codex-rs/tui/src/tui/keyboard_modes.rs: keyboard enhancement enables DISAMBIGUATE_ESCAPE_CODES, REPORT_EVENT_TYPES, and REPORT_ALTERNATE_KEYS.
  • codex-rs/tui/src/tui.rs: the external-program handoff restores terminal mode, pauses terminal stderr, runs the external program, resumes, calls set_modes(), then calls flush_terminal_input_buffer().
  • codex-rs/tui/src/keymap.rs and codex-rs/tui/src/bottom_pane/textarea.rs: Delete is already bound and handled when it arrives as KeyCode::Delete.

Given that Delete is handled when parsed correctly, seeing literal [3~ is consistent with the input event parser receiving ordinary characters rather than a parsed Delete key event. This may be the same root cause described above, with the WSL2 interactive handoff adding another timing boundary where focus reports or keyboard-enhancement sequences can cross terminal mode transitions.

Areas that seem worth checking:

  • Whether focus reports or keyboard-enhancement modes are enabled/disabled across the external-program handoff in an order that can leave partial CSI bytes queued.
  • Whether flush_terminal_input_buffer() runs after all terminal-mode transitions that can emit focus reports.
  • Whether parser-side recovery is needed for orphaned CSI tails immediately after mode/focus transitions if the root cause cannot fully prevent them.
inforanger · 2 months ago

I have another data point and a more precise repro from debugging this locally.

Environment:

  • Codex CLI 0.136.0, npm install
  • Windows Terminal 1.24.11321.0
  • PowerShell 7.4.14 launch path on Windows
  • zellij 0.44.3 in the terminal path

Findings:

  1. A complete, uninterrupted focus sequence does not leak in my test.

Injecting ESC [ I / ESC [ O as a continuous sequence is parsed by crossterm as Event::FocusGained / Event::FocusLost.

  1. The visible leak is reproducible when the sequence is split across an input timing boundary.

For example, sending ESC, waiting briefly, then sending [I is reported as:

``text
Key(Esc)
Key(Char('['))
Key(Char('I'))
``

The same happens for [O:

``text
Key(Esc)
Key(Char('['))
Key(Char('O'))
``

This exactly matches the visible composer pollution: the leading ESC is consumed separately, and the remaining [I / [O tail is inserted as text.

  1. So the practical failure mode is not only that complete focus reports are never translated on Windows. Complete reports can be parsed correctly in this setup. The leak happens when focus reports cross timing / terminal handoff boundaries and arrive as split or orphaned CSI tails.

Patch direction tested locally:

+#[cfg(not(windows))]
 use crossterm::event::EnableFocusChange;

+#[cfg(not(windows))]
 let _ = execute!(stdout(), EnableFocusChange);
+#[cfg(windows)]
+let _ = execute!(stdout(), DisableFocusChange);

I also tested a Windows-only defensive filter in tui/event_stream.rs that suppresses split ESC + [I / [O tails and maps them back to focus gained/lost behavior.

Validation:

cargo check -p codex-tui
cargo test -p codex-tui tui::event_stream --lib
cargo build -p codex-cli --bin codex

My read is that the primary fix should be to stop enabling xterm focus reporting on Windows. A split-tail filter is useful defense-in-depth for stale queued reports or terminal/external-program handoff boundaries. This also lines up with the later report above about [3~ Delete tails: complete sequences can be handled, but orphaned CSI tails still reach the composer once the leading ESC has been separated.

I have a local patch with tests if maintainers want the full diff.

alansoft · 2 months ago

Additional data point: this still reproduces on Codex CLI 0.140.0.

Environment:

  • Codex CLI: codex-cli 0.140.0
  • Install/runtime: npm package, Windows x64 vendor binary
  • OS: Windows 11, Microsoft Windows NT 10.0.22631.0
  • Terminal: Windows Terminal 1.24.11321.0
  • Shell: PowerShell 7.5.5
  • codex doctor --summary: 17 ok · 1 idle · 0 warn · 0 fail ok; terminal reported as unknown

Observed behavior:

  • After a normal Codex TUI session in Windows Terminal, the next composer input line visibly contained repeated focus-event tails like [I[O[I[O... before the user's text.
  • The user-visible symptom was that the prompt became effectively unusable for normal input. The typed Chinese text was appended after those leaked control-sequence tails, so the input buffer was polluted.
  • This matches the ESC [ I / ESC [ O focus in/out tail leakage described in this issue.

I am not attaching the screenshot because it includes local paths, but it clearly shows the Codex TUI prompt containing repeated [I / [O fragments immediately before user text on 0.140.0.

ofeliacode · 2 months ago

Still reproducible on Codex CLI 0.141.0.

Environment:

  • Windows 11 x64 (10.0.26200)
  • Windows Terminal 1.24.11321.0
  • Windows PowerShell 5.1.26100.8655
jerrill-johnson-bitwerx · 6 days ago

This is a shot in the dark as I have this happen in only ONE of my terminal tabs consistently and reproducibly. It's the only workspace folder that has a hyphen in it. Could it be some weird regEx parsing error somewhere? I'm still trying to figure out what else makes that working directory special.