Skip to content

fix(tui): enable Kitty keyboard protocol so Shift+Enter inserts a newline#13782

Merged
harryalbert merged 6 commits into
masterfrom
factory/tui-shift-enter-kitty-protocol
Jul 15, 2026
Merged

fix(tui): enable Kitty keyboard protocol so Shift+Enter inserts a newline#13782
harryalbert merged 6 commits into
masterfrom
factory/tui-shift-enter-kitty-protocol

Conversation

@warp-dev-github-integration

@warp-dev-github-integration warp-dev-github-integration Bot commented Jul 15, 2026

Copy link
Copy Markdown
Contributor

Description

In Warp's headless TUI (crates/warp_tui, ./script/run-tui), pressing Shift+Enter did not insert a newline in the input when running inside terminals that require the Kitty keyboard protocol ("progressive keyboard enhancement") — e.g. Ghostty. It submitted instead. It worked in the Warp terminal and for Codex/Claude Code in Ghostty.

Root cause: the TUI terminal setup in crates/warpui_core/src/runtime/mod.rs (enter_terminal_screen / leave_terminal_screen) never pushed/popped the keyboard enhancement flags. Without that opt-in, protocol terminals send a bare CR (0x0d) for both Enter and Shift+Enter, so crossterm delivers KeyCode::Enter with no SHIFT modifier for both and the keymap runs enter→Submit instead of shift-enter→InsertNewline. It worked in the Warp terminal only because that path sends LF (0x0a), which crossterm decodes in raw mode as Ctrl+J — caught by the existing ctrl-j→InsertNewline binding.

Fix: push PushKeyboardEnhancementFlags(KeyboardEnhancementFlags::DISAMBIGUATE_ESCAPE_CODES) when entering the alternate screen and PopKeyboardEnhancementFlags when leaving — the same opt-in Codex/Claude Code use. The shift-enter→InsertNewline binding and the SHIFT-modifier conversion already exist, so no keymap or feature-flag change is needed. Terminals that don't support the protocol silently ignore the sequence, and the existing RawModeGuard already runs the pop on drop/unwind.

Testing

  • Added regression test terminal_screen_lifecycle_toggles_keyboard_enhancement in crates/warpui_core/src/runtime/mod_tests.rs — asserts entering the TUI emits the push sequence (CSI >1u) and leaving emits the pop sequence (CSI <1u). Fails before the fix, passes after.
  • cargo test -p warpui_core --features tui runtime::tests::terminal_screen_lifecycle — passes.
  • ./script/format — clean; cargo clippy -p warpui_core --features tui --all-targets --tests -- -D warnings — clean.

UI verification limitation

This fix is user-visible, but its observable effect only manifests in a Kitty-protocol terminal (Ghostty/kitty/foot/WezTerm). Ghostty is a GUI terminal emulator and this fix targets the headless warp_tui, neither of which can be driven in the headless cloud runner used to author this PR, so I could not perform a live computer_use verification of Shift+Enter in Ghostty. The byte-level regression test is the primary automated guard. Please manually verify in Ghostty: run ./script/run-tui, type text, press Shift+Enter → a newline is inserted and the message is not submitted; plain Enter still submits; Ctrl+J / Alt+Enter still insert newlines; Ctrl+C still exits and Esc still closes menus. Also confirm no regression in the Warp terminal (Shift+Enter still inserts a newline).

Agent Mode

  • Warp Agent Mode - This PR was created via Warp's AI Agent Mode

Conversation: https://staging.warp.dev/conversation/72206894-95ac-4379-b316-9542ef8efd73
Run: https://oz.staging.warp.dev/runs/019f6706-0179-7a2d-900a-9619b27361f0

This PR was generated with Oz.

…line

The headless TUI never opted into the Kitty keyboard protocol
("progressive keyboard enhancement"). In terminals that require the
opt-in (e.g. Ghostty), Enter and Shift+Enter both arrive as a bare CR,
so the input couldn't distinguish "submit" from "insert newline" and
Shift+Enter submitted instead of adding a line. It worked in the Warp
terminal only because that path sends LF (decoded as Ctrl+J, which an
existing binding catches).

Push `PushKeyboardEnhancementFlags(DISAMBIGUATE_ESCAPE_CODES)` when
entering the alternate screen and `PopKeyboardEnhancementFlags` when
leaving, mirroring what Codex/Claude Code do. The shift-enter->InsertNewline
binding and the SHIFT-modifier conversion already exist, so no keymap or
feature-flag change is needed. Unsupported terminals ignore the sequence.

Adds a regression test asserting the enter/leave lifecycle emits the
push (CSI >1u) and pop (CSI <1u) sequences.

CHANGELOG-BUG-FIX: Fixed Shift+Enter not inserting a newline in the Warp TUI when run in terminals using the Kitty keyboard protocol (e.g. Ghostty).

Co-Authored-By: Oz <oz-agent@warp.dev>
@oz-for-oss

oz-for-oss Bot commented Jul 15, 2026

Copy link
Copy Markdown
Contributor

@warp-dev-github-integration[bot]

I'm starting a first review of this pull request.

You can view the conversation on Warp.

I completed the review and no human review was requested for this pull request.

Comment /oz-review on this pull request to retrigger a review (up to 3 times on the same pull request).

Powered by Oz

@oz-for-oss oz-for-oss Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Overview

This PR enables crossterm's Kitty keyboard protocol enhancement flag when entering the headless TUI alternate screen and pops it on exit, with a regression test covering the emitted push/pop escape sequences. I did not find code-level correctness or security issues in the changed lines, and there is no spec context to validate against.

Concerns

  • This is a user-facing TUI input behavior change, but the PR does not include acceptable TUI verification evidence such as a terminal transcript, a render snapshot diff, or a ./script/run-tui capture demonstrating Shift+Enter inserting a newline end to end. The byte-level escape-sequence test is useful automated coverage, but it does not replace the repository-required evidence for behavioral TUI changes; the stated headless-runner limitation is not an exemption.

Verdict

Found: 0 critical, 1 important, 0 suggestions

Request changes

Comment /oz-review on this pull request to retrigger a review (up to 3 times on the same pull request).

Powered by Oz

oz-agent added 4 commits July 15, 2026 19:43
crossterm hard-codes `is_ansi_code_supported() -> false` for
Push/PopKeyboardEnhancementFlags on Windows, forcing the legacy console
API path which returns `Unsupported`. Putting them inside the main
`execute!` made `enter_terminal_screen`/`leave_terminal_screen` return
Err on Windows (breaking the Windows unit tests, and TUI startup).

Issue the push/pop as best-effort (`let _ = execute!(...)`) so a failure
never aborts terminal setup/restore, mirroring how Codex handles it.
Gate the byte-level assertions in the regression test to non-Windows,
where the ANSI sequences are actually emitted; the enter/leave calls are
still asserted to succeed on every platform.

Co-Authored-By: Oz <oz-agent@warp.dev>
Adds a runtime-level test that pushes a Shift+Enter crossterm KeyEvent
(the distinct event the Kitty protocol enables) through event conversion
and the keymap responder chain, asserting it dispatches its bound action.
This is the exact path the TUI input's shift-enter -> insert-newline
binding relies on, giving durable behavioral coverage beyond the
byte-level push/pop sequence test.

Co-Authored-By: Oz <oz-agent@warp.dev>
`test_handle_pty_read_event_while_not_batching` waits on the real ~50ms
PTY batch timer via `assert_eventually!`. Its own comment documents this
as a Windows timing flake; the prior 200ms budget still timed out on
loaded Windows CI runners (coarse ~15.6ms timer granularity + a loaded
single-threaded executor), which was the only failing check on this PR.

Raise both waits to a 1s budget. `assert_eventually!` returns as soon as
the condition holds, so this keeps the real batch-timer path under test
without slowing the passing case, and eliminates the flake. Unrelated to
this PR's TUI change otherwise — surfaced by, not caused by, its CI runs.

Co-Authored-By: Oz <oz-agent@warp.dev>
Make the enter_terminal_screen comment more concise and state explicitly
that the Kitty keyboard-protocol opt-in only affects the TUI's own host
terminal (the GUI never enters raw mode / the alt screen and never runs
this). Also add a blank line after the alternate-screen setup.

Co-Authored-By: Oz <oz-agent@warp.dev>
@harryalbert
harryalbert enabled auto-merge (squash) July 15, 2026 21:26
@harryalbert
harryalbert merged commit 8c7b514 into master Jul 15, 2026
26 checks passed
@harryalbert
harryalbert deleted the factory/tui-shift-enter-kitty-protocol branch July 15, 2026 21:36
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants