Skip to content

Keybinding portability across terminals

TL;DR. Hex1b can fire any binding the terminal actually delivers. But many terminals (and operating systems) intercept popular combos before the app sees a single byte — and a few combos can't be encoded by the standard ANSI protocol at all. This page lists the known offenders per terminal so you can pick bindings that work everywhere your app ships.

Want to confirm what your terminal does? Run the KeyBindingTester sample.

Why combos go missing

Three independent layers can swallow a key before Hex1b sees it:

  1. The terminal emulator. Most terminals own a small set of UI shortcuts (Ctrl+Shift+T for new tab, Ctrl+Shift+C for copy, Ctrl+Shift+↑/ for scroll, etc.). When you press an intercepted combo, the terminal handles it and sends nothing to the running app.

  2. The OS / window manager. Windows reserves Win+<key>, GNOME may steal Ctrl+Alt+<arrow> for workspace switching, the Mac dock owns Cmd+<...> entirely. macOS doesn't even forward Cmd to terminal apps under any circumstance.

  3. The ANSI protocol itself. A few combos are fundamentally indistinguishable in the byte stream:

    • Ctrl+Backspace and Ctrl+H are both 0x08.
    • Ctrl+Shift+<letter> and Ctrl+<letter> are both the same control byte (Ctrl strips ASCII bit 6; Shift then has no effect).
    • Ctrl+I and Tab are both 0x09; Ctrl+M and Enter are both 0x0D.

    The kitty keyboard protocol solves all of these by sending explicit keypress events with full modifier bitmasks, but it must be enabled per-terminal and Hex1b doesn't yet speak it (tracked separately).

Special keys (arrows, function keys, Home/End/PgUp/PgDn) carry their modifiers explicitly in CSI parameters — those are unambiguous on the wire and only fail when a terminal/OS intercepts them.

Windows Terminal

Windows Terminal's default keybindings intercept the following combos. Bindings can be cleared/remapped in Settings → Actions (or by editing your settings.json); for combos you need in your Hex1b app, instruct users to add { "command": null, "keys": "..." } to free the keys.

Keyboard

ComboWindows Terminal actionWorkaround
Alt+Shift+←/→/↑/↓Resize active paneUnbind Terminal.ResizePane*
Alt+←/→/↑/↓Move pane focusUnbind Terminal.MoveFocus*
Ctrl+Alt+←/→Move focus previous/nextUnbind Terminal.MoveFocusPrevious
Ctrl+Shift+↑/↓Scroll up/down by lineUnbind Terminal.ScrollUp/Down
Ctrl+Shift+PgUp/PgDnScroll up/down by pageUnbind Terminal.ScrollUpPage/DownPage
Ctrl+Shift+Home/EndScroll to top/bottom of bufferUnbind Terminal.ScrollToTop/Bottom
Ctrl+Shift+TNew tabUnbind Terminal.OpenNewTab
Ctrl+Shift+WClose paneUnbind Terminal.ClosePane
Ctrl+Shift+NNew windowUnbind Terminal.OpenNewWindow
Ctrl+Shift+DDuplicate tabUnbind Terminal.DuplicateTab
Ctrl+Shift+FFindUnbind Terminal.FindText
Ctrl+Shift+PCommand paletteUnbind Terminal.ToggleCommandPalette
Ctrl+Shift+MMark modeUnbind Terminal.ToggleMarkMode
Ctrl+Shift+KClear bufferUnbind Terminal.ClearBuffer
Ctrl+Shift+ASelect allUnbind Terminal.SelectAll
Ctrl+Shift+C/VCopy / pasteUnbind copy/paste actions
Ctrl+Shift+1..9Open profile NUnbind Terminal.OpenNewTabProfileN
Ctrl+Shift+TabPrevious tabUnbind Terminal.PrevTab
Ctrl+TabNext tabUnbind Terminal.NextTab
Ctrl+Alt+1..9Switch to tab NUnbind Terminal.SwitchToTabN
Ctrl+,Open settings UIUnbind Terminal.OpenSettingsUI
Ctrl++ / Ctrl+-Increase / decrease fontUnbind font-size actions
Ctrl+0Reset font sizeUnbind Terminal.ResetFontSize
Alt+F4Close windowOS-level too — usually leave alone
Alt+Enter / F11Toggle full-screenUnbind Terminal.ToggleFullscreen
Alt+SpaceOpen system menuOS-level — usually leave alone

Subtle case — Ctrl+Shift+←/→. Windows Terminal's Selection docs bind these to "expand existing selection by word". The combos are only consumed when a selection exists; otherwise they fall through to the app. This is why a Hex1b binding on Ctrl+Shift+← appears to work — it does, until the user happens to have a terminal selection active.

Mouse

Windows Terminal's Selection docs explain the mouse interceptions:

ComboWindows Terminal actionWorkaround
Shift+ClickExtend selection to the click pointHold Shift is "magic" — no app-side override
Ctrl+Shift+ClickMulti-select extendSame as above
Alt+ClickBlock (column) selectionSame as above
Right ClickCopy if selection exists, else pasteDisable in Settings → Interaction
Ctrl+ClickOpen URL only when the cell has a detected URLOtherwise forwarded to the app

The selection-related Shift/Ctrl+Shift mouse behaviour is non-configurable per the official docs — those combos cannot be reclaimed. Plan your bindings around them.

ConPTY / conhost.exe (legacy Windows console)

The "old" Windows console (the black box that hosts cmd.exe when Windows Terminal isn't available) is much more permissive — most arrow/function-key combos pass through cleanly. Known caveats:

ComboBehaviour
Alt+SpaceOpens the system menu (OS, can't override)
Alt+F4Closes the window (OS, can't override)
Alt+EnterToggle full-screen on older Windows
Ctrl+Shift+letterFalls into the universal ANSI ambiguity (see top)

When Hex1b runs through Hex1b.WindowsConsoleDriver (the direct driver), it reads from the Win32 console API and sees explicit modifier bits, so it synthesises CSI sequences that include the modifiers. Bindings like Ctrl+Shift+↑ do work end-to-end on legacy conhost.

macOS Terminal.app (Apple's built-in)

The shipped-with-macOS terminal handles most modifier combos cleanly, but because macOS itself never forwards Cmd to terminal apps, every Cmd+<key> is consumed by Terminal.app or the OS:

ComboTerminal.app action
Cmd+NNew window
Cmd+TNew tab
Cmd+WClose tab
Cmd+Shift+WClose window
Cmd+Shift+] / Ctrl+TabNext tab
Cmd+Shift+[ / Ctrl+Shift+TabPrevious tab
Cmd+1..9Switch to tab N
Cmd+DSplit window vertically
Cmd+Shift+DSplit window horizontally
Cmd+KClear screen (keeps scrollback)
Cmd+FFind
Cmd+C / Cmd+V / Cmd+ACopy / paste / select-all
Cmd+,Open Preferences
Cmd++ / Cmd+- / Cmd+0Font size (in/out/reset)
Cmd+↑/↓ / Cmd+PgUp/PgDnScroll one line / page
Cmd+QQuit Terminal.app

Plus OS-level interceptions that affect every terminal on macOS:

ComboOS action
Cmd+Tab / Cmd+~App / window switcher
Cmd+SpaceSpotlight (configurable)
Ctrl+Cmd+QLock screen
Ctrl+↑/↓Mission Control / show desktop (if enabled)
Ctrl+←/→Move between Spaces (if enabled)

Notable Terminal.app quirk: Option is not sent as a modifier by default — instead Option+<key> produces a Mac-specific glyph (e.g. Option+E types é's combining accent). To get xterm-style Alt+<key> delivery, enable Settings → Profiles → Keyboard → Use Option as Meta key. Without that toggle, none of Hex1b's Alt+<arrow> / Alt+<letter> bindings will fire on Terminal.app.

Ghostty (cross-platform)

Ghostty ships with a fairly large default keybinding set, and the macOS bindings differ from the Linux/Windows bindings because macOS Ghostty uses Cmd+<key> while Linux/Windows Ghostty uses Ctrl+Shift+<key>. Both sets are intercepted before they reach the running app. The complete list lives in ghostty +list-keybinds --default; the most common offenders:

ActionLinux / WindowsmacOS
New windowCtrl+Shift+NCmd+N
New tabCtrl+Shift+TCmd+T
Close tab / surfaceCtrl+Shift+WCmd+W
Previous / next tabCtrl+Shift+Tab / Ctrl+TabCmd+Shift+[ / Cmd+Shift+]
Tab 1..9Alt+1..9Cmd+1..9
New split (right/down)Ctrl+Shift+O / Ctrl+Shift+ECmd+D / Cmd+Shift+D
Focus splitCtrl+Alt+arrowsCmd+Option+arrows
Resize splitCtrl+Super+Shift+arrowsCmd+Ctrl+arrows
Toggle fullscreenCtrl+Enter / F11Cmd+Enter
Copy / pasteCtrl+Shift+C/VCmd+C/V
FindCtrl+Shift+FCmd+F
Open / reload configCtrl+, / Ctrl+Shift+,Cmd+, / Cmd+Shift+,
InspectorCtrl+Shift+ICmd+Option+I
QuitCtrl+Shift+QCmd+Q
Scroll to top / bottomShift+Home / Shift+EndCmd+Home / Cmd+End

Note that Ghostty's Linux defaults overlap heavily with GNOME Terminal / Ptyxis (Ctrl+Shift+T/N/W/F/C/V) — so an app that targets "Linux terminals" should treat that whole row as off-limits regardless of which terminal the user runs.

Ghostty supports the kitty keyboard protocol (opt-in via keybind = ...:disambiguate-escape-codes and friends), which makes the cross-cutting ANSI ambiguities below resolvable on this terminal — but Hex1b doesn't yet negotiate it.

kitty (cross-platform)

kitty gates almost every binding behind a single configurable modifier called kitty_mod. The default value is Ctrl+Shift, which means the entire Ctrl+Shift+<letter/key> keyspace is owned by kitty itself out of the box. Users who want apps to receive these combos need to either change kitty_mod (commonly to Super or Cmd) or unbind the specific combos they want.

Default kitty_mod (= Ctrl+Shift) bindings:

Combokitty action
Ctrl+Shift+C/VCopy / paste
Ctrl+Shift+EnterNew OS window
Ctrl+Shift+TNew tab
Ctrl+Shift+WClose window
Ctrl+Shift+] / [Next / previous tab
Ctrl+Shift+1..9Go to tab N
Ctrl+Shift+LNext layout
Ctrl+Shift+FToggle fullscreen
Ctrl+Shift+, / .Move tab left / right
Ctrl+Shift+arrowsMove window focus between splits
Ctrl+Shift+SSelection mode
Ctrl+Shift+QShow all key bindings
Ctrl+Shift+BackspaceClear scrollback
Ctrl+Shift+RInteractive Unicode input
Ctrl+Shift+EEdit current command line in $EDITOR
Ctrl+Shift++ / -Font bigger / smaller
Ctrl+Shift+/Search

kitty's saving grace: it implements (and pioneered) the kitty keyboard protocol, which sends explicit modifier bitmasks for every key. When an app negotiates the protocol via CSI > 1 u, every cross-cutting limit at the bottom of this page goes away — Ctrl+Backspace, Ctrl+Shift+<letter>, Ctrl+I vs Tab, etc. all become unambiguous. Hex1b doesn't negotiate the protocol today, so kitty currently behaves like any other terminal as far as those limits go.

iTerm2 (macOS)

ComboiTerm2 actionWorkaround
Cmd+<anything>iTerm2 / macOS handles it; never reaches the appmacOS doesn't forward Cmd to terminal apps. Use a different modifier.
Cmd+T/Cmd+W/Cmd+NNew tab / close / new windown/a
Cmd+C/Cmd+VCopy / pasten/a
Option+<arrow>Word jump (sent to app as Esc+<arrow>)Works as Alt+<arrow> in Hex1b
Ctrl+TabCycle tabs (Profiles → Keys → Show/Hide tabs)Remap in iTerm2 prefs

iTerm2 also supports modifyOtherKeys=2 and the kitty keyboard protocol — when those are enabled, Ctrl+Shift+<letter> and friends do deliver unambiguously. Hex1b doesn't yet enable either, so today the ANSI caveats apply.

GNOME Terminal

ComboGNOME Terminal actionWorkaround
Ctrl+Shift+C/VCopy / pastePreferences → Shortcuts → unset
Ctrl+Shift+TNew tabSame
Ctrl+Shift+NNew windowSame
Ctrl+Shift+W/QClose tab / windowSame
Ctrl+Shift+FFindSame
Ctrl+PgUp/PgDnSwitch tabsSame
Ctrl+Shift+letterVarious menu shortcutsSame

GNOME Terminal also overlaps with the GNOME shell:

ComboShell action
Ctrl+Alt+<arrow>Switch workspace (some distros)
Ctrl+Alt+TOpen new terminal (some distros)
Alt+F2Run dialog

Ptyxis (Ubuntu 25.10+ / 26.04 LTS default)

Starting with Ubuntu 25.10, the default terminal is no longer GNOME Terminal — it's Ptyxis (a GTK4/Libadwaita terminal built around Podman/Toolbox containers, also the default on Fedora). For binding-interception purposes Ptyxis behaves near-identically to GNOME Terminal: the same Ctrl+Shift+<letter> family is owned by the terminal UI.

ComboPtyxis action
Ctrl+Shift+TNew tab
Ctrl+Shift+NNew window
Ctrl+Shift+WClose tab
Ctrl+Shift+C / VCopy / paste
Ctrl+Shift+FFind
Ctrl+Shift+,Open Preferences (Settings)
Ctrl+PgUp / PgDnSwitch tabs
Ctrl+TabNext tab
F11Toggle fullscreen

GNOME shell-level interceptions (workspace switching, etc.) listed under GNOME Terminal apply equally to Ptyxis, since they're owned by the desktop environment, not the terminal.

If your app targets Ubuntu and you previously planned around GNOME Terminal's defaults, the binding picture is essentially unchanged on Ubuntu 26.04 LTS — but the application the user runs is now Ptyxis by default, so error messages and screenshots in your docs should reflect that.

xterm

xterm is the closest you can get to a "pure" baseline. Almost every combo passes through. The notable exceptions are the universal ANSI limits at the top of this page, plus:

  • Ctrl+Click, Shift+Click, Right Click open the xterm popup menus by default (configurable in ~/.Xresources).
  • The classic xterm defaults don't enable modifyOtherKeys — so Ctrl+Shift+<letter> collapses to Ctrl+<letter> unless you set XTerm.VT100.modifyOtherKeys: 2 in your X resources.

tmux

When running inside tmux, everything is filtered through tmux's own binding system. The leader key (default Ctrl+B) sits in front of every key and tmux owns its own list of bindings on top. Some implications:

  • Ctrl+B itself never reaches the app.
  • tmux can be configured to enable extended-keys mode (set -g extended-keys always and set -as terminal-features ',*:extkeys') which forwards xterm-style modifier sequences to the inner app — without that, modified-keys handling depends on tmux version.
  • The mouse mode toggle (set -g mouse on) is required for any mouse events to reach Hex1b through tmux.

ssh sessions (PuTTY, MobaXterm, etc.)

Over ssh, you're at the mercy of the client-side terminal emulator (PuTTY, MobaXterm, the Windows Terminal hosting ssh.exe, the Mac Terminal hosting ssh, etc.) — every interception the client does still happens before the bytes hit the wire. Additional client-specific quirks:

  • PuTTY rebinds Ctrl+Tab/Ctrl+Shift+Tab (window-switching), and its defaults for Backspace (DEL vs BS) are configurable per-session.
  • MobaXterm intercepts a long list of combos for its own MobaXterm features (search, log, etc.).

Cross-cutting limitations (every terminal)

These three are protocol-level — no terminal can deliver them through the standard ANSI/xterm encoding regardless of settings:

ComboWhy it fails
Ctrl+BackspaceEncoded as 0x08, identical to Ctrl+H
Ctrl+H vs Backspace0x08 vs 0x7F — tagged as Backspace either way in Hex1b's tokenizer
Ctrl+I vs TabBoth 0x09
Ctrl+M vs EnterBoth 0x0D
Ctrl+[ vs EscBoth 0x1B
Ctrl+Shift+<letter>Ctrl strips ASCII bit 6; Shift has no remaining effect (unless the terminal speaks modifyOtherKeys=2 or kitty keyboard protocol)

Special keys (arrows, function keys, Home/End/PgUp/PgDn, Insert, Delete) carry their modifier as an explicit CSI parameter, so Ctrl+Shift+<arrow> etc. are unambiguous and reliable when the terminal forwards them.

Recommendations for Hex1b authors

  1. Default to special keys + modifiers. Ctrl+Shift+<arrow>, Alt+<arrow>, Ctrl+Home/End, F<n>+<modifier> are the most portable shortcuts.
  2. Avoid Ctrl+Shift+<letter> for primary bindings — pair it with a fallback (e.g. also bind a function key or arrow combo) for the same action.
  3. Avoid Windows Terminal's table above if your app primarily targets Windows Terminal users — or document that they need to unbind these in their settings.json.
  4. Treat Ctrl+Backspace as unsupported on standard ANSI terminals until Hex1b adds the kitty keyboard protocol.
  5. Run KeyBindingTester on every terminal you target and ship the resulting markdown report alongside your app's release notes.

See also

Released under the MIT License.