From eb92ba9448c7bfde23da7c05e86ee86deb10ebcf Mon Sep 17 00:00:00 2001 From: Neil <4138956+nwparker@users.noreply.github.com> Date: Tue, 28 Apr 2026 23:56:29 -0700 Subject: [PATCH] fix(terminal): advertise kitty keyboard protocol for Shift+Enter (#1247) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Orca's terminal already encodes Shift+Enter as the kitty CSI-u sequence `\x1b[13;2u`, but without `vtExtensions.kittyKeyboard` xterm.js never answers the `CSI ? u` probe. CLIs that gate enhanced input on that handshake (Claude Code, Codex, etc.) therefore drop the extended bytes and treat Shift+Enter as a plain Enter — most visibly when running inside tmux, which strips extended-key encodings by default. - Enable `vtExtensions.kittyKeyboard` in the default terminal options (matches VS Code's xtermTerminal). - Lock in the flag with a regression test in pane-lifecycle.test.ts. - Add docs/terminal-extended-keys.md explaining the Orca side and the tmux-side `set -s extended-keys on` + `terminal-features xterm*:extkeys` users need for nested Shift+Enter to reach a CLI. Verified end-to-end in Electron: `cat -v` + Shift+Enter now prints `^[[13;2u`, and `printf '\e[?u'` elicits the expected `CSI ? 0 u` reply from xterm.js. Co-authored-by: Orca --- docs/terminal-extended-keys.md | 66 +++++++++++++++++++ .../lib/pane-manager/pane-lifecycle.test.ts | 10 +++ .../lib/pane-manager/pane-terminal-options.ts | 12 +++- 3 files changed, 87 insertions(+), 1 deletion(-) create mode 100644 docs/terminal-extended-keys.md diff --git a/docs/terminal-extended-keys.md b/docs/terminal-extended-keys.md new file mode 100644 index 000000000..7b4ea52a2 --- /dev/null +++ b/docs/terminal-extended-keys.md @@ -0,0 +1,66 @@ +# Extended Key Chords in the Terminal (Shift+Enter, etc.) + +## What Orca sends + +Orca's built‑in terminal already encodes extended key chords using the +[kitty keyboard protocol][kitty] (CSI‑u). For example, **Shift+Enter** is sent +as the byte sequence: + +``` +ESC [ 1 3 ; 2 u (i.e. \x1b[13;2u) +``` + +See `src/renderer/src/components/terminal-pane/terminal-shortcut-policy.ts` +for the full table. + +Orca also advertises kitty‑protocol support to the running program via +`vtExtensions.kittyKeyboard` on xterm.js (see +`src/renderer/src/lib/pane-manager/pane-terminal-options.ts`), so CLIs that +probe with `CSI ? u` learn that the terminal speaks CSI‑u and enable their +enhanced input handlers. + +## Why Shift+Enter may not reach your CLI inside tmux + +tmux, by default, strips both extended‑key encodings (modifyOtherKeys +`CSI 27 ; 2 ; 13 ~` *and* kitty‑style `CSI 13 ; 2 u`). If you run Claude +Code, Codex, or any other CLI under tmux, Shift+Enter will look like a +plain `Enter` unless tmux is told to pass those bytes through. + +Add this to `~/.tmux.conf` (tmux 3.2+): + +```tmux +set -s extended-keys on +set -as terminal-features 'xterm*:extkeys' +``` + +Then reload: `tmux source-file ~/.tmux.conf` (or restart the tmux server). + +- `extended-keys on` — tell tmux to accept and forward the extended + encodings instead of collapsing them to the unshifted key. +- `terminal-features 'xterm*:extkeys'` — tell tmux that the surrounding + terminal (Orca, in this case) understands those encodings, so tmux is + willing to emit them. + +## Verifying end‑to‑end + +Inside an Orca terminal (no tmux), run: + +``` +cat -v +``` + +Press **Shift+Enter**. You should see: + +``` +^[[13;2u +``` + +That's caret notation for `\x1b[13;2u` — the expected CSI‑u encoding. If +you see `^M` (or a blank newline) instead, either the chord isn't reaching +the terminal (check `keyboard-handlers.ts` / `terminal-shortcut-policy.ts`) +or you're inside tmux without the config above. + +Inside tmux after the config, the same `cat -v` test should print the same +`^[[13;2u`. + +[kitty]: https://sw.kovidgoyal.net/kitty/keyboard-protocol/ diff --git a/src/renderer/src/lib/pane-manager/pane-lifecycle.test.ts b/src/renderer/src/lib/pane-manager/pane-lifecycle.test.ts index 223a7380f..41e3f02ce 100644 --- a/src/renderer/src/lib/pane-manager/pane-lifecycle.test.ts +++ b/src/renderer/src/lib/pane-manager/pane-lifecycle.test.ts @@ -53,6 +53,16 @@ describe('buildDefaultTerminalOptions', () => { it('leaves macOS Option available for keyboard layout characters', () => { expect(buildDefaultTerminalOptions().macOptionIsMeta).toBe(false) }) + + it('advertises kitty keyboard protocol so CLIs enable enhanced key reporting', () => { + // Why: Orca already writes CSI-u bytes for extended key chords like + // Shift+Enter (see terminal-shortcut-policy.ts). CLIs that gate + // enhanced input on a CSI ? u handshake only read those bytes once the + // terminal advertises support. Regressing this flag silently breaks + // Shift+Enter (and other extended chords) in apps like Claude Code and + // Codex, especially when running inside tmux. + expect(buildDefaultTerminalOptions().vtExtensions?.kittyKeyboard).toBe(true) + }) }) describe('attachWebgl', () => { diff --git a/src/renderer/src/lib/pane-manager/pane-terminal-options.ts b/src/renderer/src/lib/pane-manager/pane-terminal-options.ts index 64d485e69..27e7c802e 100644 --- a/src/renderer/src/lib/pane-manager/pane-terminal-options.ts +++ b/src/renderer/src/lib/pane-manager/pane-terminal-options.ts @@ -16,6 +16,16 @@ export function buildDefaultTerminalOptions(): ITerminalOptions { // Why: on macOS, non-US layouts rely on Option to compose characters like @ and €. macOptionIsMeta: false, macOptionClickForcesSelection: true, - drawBoldTextInBrightColors: true + drawBoldTextInBrightColors: true, + // Why: advertise kitty keyboard protocol support so CLIs that probe + // (CSI ? u) know Orca accepts enhanced key reporting. Without this, + // Orca already writes \x1b[13;2u for Shift+Enter (see + // terminal-shortcut-policy.ts), but programs that respect the protocol + // handshake fall back to legacy encodings and ignore the CSI-u byte, + // making chords like Shift+Enter invisible to the app — especially + // noticeable inside tmux. Matches VS Code's xtermTerminal.ts. + vtExtensions: { + kittyKeyboard: true + } } }