all repos — dot @ 65d3da052dcecba82f05e4244f33c3f489b575c5

Shell, editor and terminal configuration, and the tools that go with them

tmux: Shift+Enter reaches pi, Neovim and Claude Code under Ghostty

With extended-keys off, tmux hands every pane a plain CR for Shift+Enter and
Ctrl+Enter, so pi submits where it should add a line, and warns about it at
every start.

Turning it on is not enough on its own, though pi's warning then goes quiet:
tmux asks the outer terminal for modified keys only when it knows the
terminal can send them, and tmux does not recognise Ghostty, whose terminfo
does not declare it either. So Ghostty also gets the extkeys feature, and
the format is csi-u, the one pi asks for. `on`, not `always`, which would
send zsh ESC[13;2u for Shift+Enter.

The paste corruption the old comment blamed on extended keys shows up only
in a display-popup, where tmux re-encodes the newlines of a paste for an app
that asked for modified keys; normal panes get the pasted bytes unchanged.
Nothing here opens popups.

Checked on tmux 3.7c against a pty answering as Ghostty 1.3.1, with pi
itself in the pane, and by hand in Ghostty on a separate tmux server. The
csi-u line is set with -q, since extended-keys-format arrived in tmux 3.5;
3.4 was not tried, only an unknown option name standing in for it.
Igor Soarez igor@soarez.org
Mon, 26 Oct 2026 16:20:45 +0200
commit

65d3da052dcecba82f05e4244f33c3f489b575c5

parent

4f40b8ea2f224132dddde4f505191c3662620741

1 files changed, 20 insertions(+), 5 deletions(-)

jump to
M config/tmux.conf → config/tmux.conf

@@ -149,11 +149,26 @@ # Let OSC escape sequences through to the outer terminal; without this tmux

# swallows Claude Code's desktop notifications and progress updates. set -g allow-passthrough on -# Extended key sequences - disabled for Ghostty compatibility -# Ghostty implements the Kitty keyboard protocol natively, and tmux's extended-keys -# conflicts with paste operations (causes escape sequences like ^[[27;5;106~ to appear) -# See: https://github.com/ghostty-org/ghostty/issues/7997 -set -g extended-keys off +# Modified keys -- Shift+Enter, Ctrl+Enter, Ctrl+J -- reach the apps that ask +# for them (pi, Neovim, Claude Code) instead of arriving as a plain Enter. All +# three lines are needed: +# +# - extended-keys on: a pane may request xterm modifyOtherKeys. Not `always`, +# which forces it on every pane and hands zsh ESC[13;2u for Shift+Enter. +# - extended-keys-format csi-u: the format pi asks for, and the one it can +# decode in the misfire below. tmux 3.5 and later; -q lets 3.4 skip it. +# - extkeys for Ghostty: tmux asks the outer terminal for modified keys only +# when it knows the terminal can send them, and it does not recognise +# Ghostty, whose terminfo does not say so either. Without this the two lines +# above change nothing there: Shift+Enter still arrives as a bare CR. +# +# Panes that ask for nothing, shells included, still get plain bytes, pastes +# too. One known misfire: in a display-popup tmux re-encodes the newlines of a +# paste, so an app there that asked for modified keys sees ESC[106;5u in +# their place. Nothing here opens popups. +set -g extended-keys on +set -gq extended-keys-format csi-u +set -as terminal-features 'xterm-ghostty:extkeys' # Caps Lock is F20 (hammerspoon). What reaches tmux for it is read as S-F10 and # passed on as ESC[21;2~, which Neovim takes for F22 and types out as text. Wispr