From 44f2ca803e2061b2f1dd027c472ce5640640c3c0 Mon Sep 17 00:00:00 2001 From: Noah Masur <7386960+nmasur@users.noreply.github.com> Date: Thu, 27 Aug 2026 11:26:00 -0600 Subject: [PATCH] fix(ghostty/zellij): translate mac super and ctrl shortcuts to alt sequences for zellij --- docs/CHANGELOG.md | 5 +++++ .../nmasur/presets/programs/ghostty.nix | 18 +++++++++--------- .../modules/nmasur/presets/programs/zellij.nix | 15 +++++++++++++-- 3 files changed, 27 insertions(+), 11 deletions(-) diff --git a/docs/CHANGELOG.md b/docs/CHANGELOG.md index 5341919d..7083fc97 100644 --- a/docs/CHANGELOG.md +++ b/docs/CHANGELOG.md @@ -2,6 +2,11 @@ ## 2026-08-26 +- Fixed macOS shortcuts (`Cmd+T`, `Ctrl+Tab`, `Cmd+Shift+]`, `Cmd+Shift+[`, `Cmd+K`, `Cmd+Shift+E`) in Zellij + Ghostty after disabling the Kitty keyboard protocol: + - Mapped Ghostty keybindings (`super+t`, `super+shift+]`, `super+shift+[`, `ctrl+tab`, `ctrl+shift+tab`, `super+k`, `super+shift+e`) to send standard `Alt` (`ESC`-prefix) text sequences (`\x1bt`, `\x1b}`, `\x1b{`, `\x1bK`, `\x1bE`). + - Added matching unconditional `Alt` keybindings (`Alt t`, `Alt Shift ]`, `Alt Shift [`, `Alt Shift k`, `Alt Shift e`) in `zellij.nix` for tab creation, tab navigation, scroll mode, and scrollback editing. + - Keeps Kitty keyboard protocol disabled in Zellij (`support_kitty_keyboard_protocol = false`) so no CSI-u flags leak into Fish shell, guaranteeing zero post-TUI typing lag while restoring all shortcuts. + - Fixed persistent Fish typing lag after long TUI sessions (Neovim, jjui, Yazi) inside Zellij + Ghostty, which the `no-query-term` / Ghostty-integration fixes from 2026-08-25 did not resolve: - Verified on Fish 4.8.1 that the `query-term` feature already defaults to `off`, so exporting `fish_features = no-query-term` is a no-op on this Fish version — it isn't the cause of (or fix for) this class of lag. - Set `support_kitty_keyboard_protocol = false` in `zellij.nix`. Zellij and Ghostty have several open upstream bugs (zellij-org/zellij#3887, #3723, #4178) where the Kitty keyboard protocol's enhancement-flag stack is left in an elevated state after a full-screen TUI exits without properly popping it. Every subsequent keystroke then arrives as a CSI-u sequence that Fish must wait out an escape-disambiguation timeout to parse, which reads as typing lag that worsens the longer the TUI session ran, and persists until the pane's protocol state resets (e.g. a fresh shell/pane). Disabling the protocol support in Zellij avoids the whole bug class; trades off precise modifier reporting (e.g. distinguishing Ctrl+Shift+key) for TUIs running inside Zellij panes, which this setup doesn't otherwise depend on (Shift+Enter is handled via a literal Ghostty `text:` keybind, not the Kitty protocol). diff --git a/platforms/home-manager/modules/nmasur/presets/programs/ghostty.nix b/platforms/home-manager/modules/nmasur/presets/programs/ghostty.nix index 1ed652c6..9be005b9 100644 --- a/platforms/home-manager/modules/nmasur/presets/programs/ghostty.nix +++ b/platforms/home-manager/modules/nmasur/presets/programs/ghostty.nix @@ -36,15 +36,15 @@ in quit-after-last-window-closed = lib.mkIf pkgs.stdenv.hostPlatform.isDarwin true; fullscreen = if pkgs.stdenv.hostPlatform.isDarwin then true else false; keybind = [ - "super+t=unbind" # Pass super-t to underlying tool (e.g. zellij tabs) - "super+shift+]=unbind" - "super+shift+[=unbind" - "ctrl+tab=unbind" - "ctrl+shift+tab=unbind" - "ctrl+tab=text:\\x1b[9;5u" - "ctrl+shift+tab=text:\\x1b[9;6u" - "super+k=unbind" - "super+shift+e=unbind" + # Translate Mac Super & Ctrl combinations into Alt (ESC prefix) sequences + # so Zellij receives them without needing Kitty keyboard protocol + "super+t=text:\\x1bt" + "super+shift+]=text:\\x1b}" + "super+shift+[=text:\\x1b{" + "ctrl+tab=text:\\x1b}" + "ctrl+shift+tab=text:\\x1b{" + "super+k=text:\\x1bK" + "super+shift+e=text:\\x1bE" ]; }; themes."gruvbox" = { diff --git a/platforms/home-manager/modules/nmasur/presets/programs/zellij.nix b/platforms/home-manager/modules/nmasur/presets/programs/zellij.nix index 0baa2c92..3f6969e0 100644 --- a/platforms/home-manager/modules/nmasur/presets/programs/zellij.nix +++ b/platforms/home-manager/modules/nmasur/presets/programs/zellij.nix @@ -295,9 +295,15 @@ in "bind \"Super Shift ]\"" = { GoToNextTab = { }; }; + "bind \"Alt Shift ]\"" = { + GoToNextTab = { }; + }; "bind \"Super Shift [\"" = { GoToPreviousTab = { }; }; + "bind \"Alt Shift [\"" = { + GoToPreviousTab = { }; + }; "bind \"Ctrl Tab\"" = { GoToNextTab = { }; }; @@ -307,7 +313,7 @@ in "bind \"Super t\"" = lib.mkIf pkgs.stdenv.hostPlatform.isDarwin { NewTab = { }; }; - "bind \"Alt t\"" = lib.mkIf pkgs.stdenv.hostPlatform.isLinux { + "bind \"Alt t\"" = { NewTab = { }; }; "bind \"Super k\"" = lib.mkIf pkgs.stdenv.hostPlatform.isDarwin { @@ -315,13 +321,18 @@ in _args = [ "scroll" ]; }; }; + "bind \"Alt Shift k\"" = { + SwitchToMode = { + _args = [ "scroll" ]; + }; + }; "bind \"Super Shift e\"" = lib.mkIf pkgs.stdenv.hostPlatform.isDarwin { EditScrollback = { }; SwitchToMode = { _args = [ "locked" ]; }; }; - "bind \"Alt Shift e\"" = lib.mkIf pkgs.stdenv.hostPlatform.isLinux { + "bind \"Alt Shift e\"" = { EditScrollback = { }; SwitchToMode = { _args = [ "locked" ];