[Regression v0.80.1] Windows/VS Code: focus regain enables kitty CSI u that crossterm cannot decode; every keystroke leaks `[97;1;3u`
Nobody has claimed this yet.
- Dominant language
- Rust
- Stars
- 19.9k
- Forks
- 2.3k
- Avg merge
- 2d 7h
- Merged PRs (30d)
- 30
Description
Summary
Status update (2 September 2026)
Tested again with jcode v0.81.4 on the affected setup. The issue still reproduces.
Regression in v0.80.1, introduced by commit 2eaadca31 (fix: reapply terminal modes after focus regain (fixes #1043)). Not present in v0.80.0. It reproduces on Windows 11 in the VS Code integrated terminal.
Environment
- jcode v0.80.1
- Windows 11
- VS Code integrated terminal (xterm.js)
- launched via a shell script wrapper
Repro
- Start jcode in the VS Code integrated terminal on Windows.
- Click into the terminal so the TUI receives a
FocusGainedevent. - Type any letter.
Actual behavior
Every keystroke produces its letter plus one stray literal escape sequence:
- typing
ayields[97;1;3u - typing
byields[98;1;3u
These are kitty-protocol CSI u key events arriving as literal text. Keycode 97 is a, modifiers 1 is none, and event type 3 is key release.
Expected behavior
Keystrokes produce only their character. No CSI u sequences leak into the input buffer.
Root cause
Commit 2eaadca31 added reapply_terminal_modes_to in crates/jcode-tui/src/tui/mod.rs, called by Event::FocusGained in the local and remote TUI paths.
That function writes the kitty set sequence directly, bypassing crossterm:
write!(writer, "\x1b[={}u", keyboard_enhancement_flags().bits())
It emits ESC[=7u: DISAMBIGUATE_ESCAPE_CODES | REPORT_EVENT_TYPES | REPORT_ALTERNATE_KEYS.
The write is gated on configuration intent, crate::perf::tui_policy().enable_keyboard_enhancement, rather than the actual result of the runtime push stored in TuiRuntimeState.keyboard_enhanced.
Why Windows diverges
crossterm does not support PushKeyboardEnhancementFlags on Windows. Its Windows input implementation reads Win32 KeyEventRecord values and has no escape-sequence parser, so kitty CSI u input cannot be decoded there.
In the VS Code terminal the policy remains enabled, so the raw focus-regain write switches xterm.js into CSI u reporting while crossterm cannot decode the events. REPORT_EVENT_TYPES produces the observed extra key-release sequence for every keystroke.
Side effect
Because TuiRuntimeState.keyboard_enhanced remains false, cleanup does not issue PopKeyboardEnhancementFlags. The terminal can remain in kitty mode after jcode exits, affecting the shell.
Suggested fix
Gate kitty reassertion on what was actually pushed, rather than policy configuration. Additionally guard the raw write with #[cfg(not(windows))], since crossterm cannot decode CSI u input on Windows.
Workaround
printf '\033[=0u'clears the kitty flags the terminal was left in.- Downgrade to v0.80.0, or revert
2eaadca31.
There is no keyboard-enhancement configuration toggle.
Related
- #1043
- #898
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Start in crates/jcode-tui/src/tui/mod.rs, reading reapply_terminal_modes_to and its FocusGained callers in the local and remote TUI paths, then reproduce the issue in Windows 11's VS Code integrated terminal. Done means focus regain no longer makes keystrokes leak CSI u text and exiting jcode does not leave the terminal in kitty keyboard mode.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- rust, vscode
- Domain
- cli, operating-systems
- Issue type
- Bug
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Active
- Clarity
- Clearly specified
- Newbie friendliness
- 68/100