1jehuang / 1jehuang/jcode

[Regression v0.80.1] Windows/VS Code: focus regain enables kitty CSI u that crossterm cannot decode; every keystroke leaks `[97;1;3u`

Open
#1,064 1 comment 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

autonomous: no bug triage: needs-decision
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

  1. Start jcode in the VS Code integrated terminal on Windows.
  2. Click into the terminal so the TUI receives a FocusGained event.
  3. Type any letter.

Actual behavior

Every keystroke produces its letter plus one stray literal escape sequence:

  • typing a yields [97;1;3u
  • typing b yields [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

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. 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

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.