feat(tui): push DISAMBIGUATE_ESCAPE_CODES on startup (#442)

Opt into the Kitty keyboard protocol's escape-code disambiguation
so terminals that support it (Kitty, Ghostty, Alacritty 0.13+,
WezTerm, recent Konsole / xterm) report unambiguous events for
Option/Alt-modified keys, plain Esc, and multi-byte sequences.

Push happens after `enable_raw_mode` and the alt-screen /
mouse-capture / bracketed-paste setup so the order matches
shutdown's reverse-order pop. Only the disambiguation tier is
pushed — `REPORT_EVENT_TYPES` and the higher tiers emit release
events that the existing key handlers would mis-route as
duplicate presses.

Pop on exit was already wired in main.rs (panic) and ui.rs
(normal shutdown) per #443; the recent #443 follow-up extended
that to the suspend paths so editor / shell-suspend children
inherit a clean keyboard mode. The push + the four pops form
a complete pair.

Failure to push is logged at debug level and ignored — a quirky
terminal can't block startup. On terminals without protocol
support the escape sequence is silently discarded and behaviour
is identical to today (iTerm2, Terminal.app, Windows 10 conhost).

No new dependency; everything runs through crossterm's existing
`PushKeyboardEnhancementFlags` command.
This commit is contained in:
Hunter Bown
2026-05-03 05:45:52 -05:00
parent e8af3cd37d
commit 8290b136e1
2 changed files with 36 additions and 0 deletions
+11
View File
@@ -165,6 +165,17 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
the same hierarchy `App::new` uses (`.agents/skills`
`skills``~/.deepseek/skills`). Available in Plan and
Agent/Yolo modes.
- **Kitty keyboard protocol opt-in** (#442) — pushes
`DISAMBIGUATE_ESCAPE_CODES` at startup so terminals that
support the protocol (Kitty, Ghostty, Alacritty 0.13+,
WezTerm, recent Konsole / xterm) report unambiguous events
for Option/Alt-modified keys, plain Esc, and multi-byte
sequences. Legacy terminals silently discard the escape and
see no change. Only the disambiguation tier is pushed —
release-event reporting was deliberately skipped because the
existing handlers would mis-route releases as duplicate
presses. The flags are popped on shutdown / panic / suspend
paths (#443).
- **RLM tool family** (#512) — `rlm` tool cards map to
`ToolFamily::Rlm` and render `rlm`, not `swarm`. Stale "swarm"
wording cleaned out of docs / comments / tests.
+25
View File
@@ -180,6 +180,31 @@ pub async fn run_tui(config: &Config, options: TuiOptions) -> Result<()> {
if use_bracketed_paste {
execute!(stdout, EnableBracketedPaste)?;
}
// #442: opt into the Kitty keyboard protocol's escape-code
// disambiguation so terminals that support it (Kitty, Ghostty,
// Alacritty 0.13+, WezTerm, recent Konsole, recent xterm) report
// unambiguous events for Option/Alt-modified keys, plain Esc, and
// multi-byte sequences. Terminals that don't recognise the escape
// silently discard it; behaviour is identical to today on legacy
// terminals (iTerm2, Terminal.app, Windows 10 conhost).
//
// Only `DISAMBIGUATE_ESCAPE_CODES` is pushed — the higher tiers
// (`REPORT_EVENT_TYPES`, `REPORT_ALL_KEYS_AS_ESCAPE_CODES`) emit
// release events that the existing key handlers would mis-route
// as duplicate presses. Best-effort: failure to push is logged
// and ignored so a quirky terminal can't block startup.
if let Err(err) = execute!(
stdout,
crossterm::event::PushKeyboardEnhancementFlags(
crossterm::event::KeyboardEnhancementFlags::DISAMBIGUATE_ESCAPE_CODES
)
) {
tracing::debug!(
target: "kitty_keyboard",
?err,
"PushKeyboardEnhancementFlags ignored (terminal lacks support)"
);
}
let backend = CrosstermBackend::new(stdout);
let mut terminal = Terminal::new(backend)?;
let event_broker = EventBroker::new();