Baike.dev
All toolsAI codingTrendingOpen sourceNewsSubmit
Log in
Back to tool/Back to issues
#1363·sapling

bug: builtin pager ignores Shift keys in Ghostty

Author: vegerotCreated Jul 21, 2026Updated Jul 21, 2026

Description

When using Sapling's internal pager (pager=internal:streampager, the default for sl log), any key that requires Shift does not work when running outside of tmux in Ghostty.app (and cmux.app which uses libghostty).

Observed failures:

  • G (Shift+g) to go to bottom of pager does nothing
  • Typing @ (Shift+2 on US layout) in search prompt (/) results in empty input
  • Searching for any capital letter (e.g. Foo) does not insert the capital
  • All shifted punctuation / symbols affected

Inside tmux it works (tmux re-encodes keys as plain chars), and inside Terminal.app it works. Only Ghostty (and libghostty-based terms) outside tmux reproduces.

Repro steps (Ghostty, no tmux)

  1. cd ~/code/github.com/facebook/sapling && sl log -l 5000 --pager=always
  2. Press lowercase g -> goes to top (works)
  3. Press uppercase G (Shift+g) -> should go to bottom, stays at top
  4. Press / to search
  5. Type @ (Shift+2) -> prompt stays empty, should show @
  6. Type ABC -> nothing inserted or only lowercase

Repro with hex injection (works inside tmux too, to avoid needing Ghostty)

Ghostty with modifyOtherKeys=2 enabled (which Sapling enables via termwiz ESC[>4;2m in set_raw_mode) encodes shifted keys as xterm modifyOtherKeys:

  • Shift+G: ESC[27;2;71~ hex 1b 5b 32 37 3b 32 3b 37 31 7e
  • Shift+@: ESC[27;2;64~ hex 1b 5b 32 37 3b 32 3b 36 34 7e
bash
tmux new -d -s repro -x 200 -y 20
tmux send-keys -t repro "sl log -l 5000 --pager=always" C-m; sleep 2
tmux send-keys -t repro -l "g"; sleep 0.5    # top works
tmux send-keys -t repro -H '1b5b32373b323b37317e'; sleep 0.8  # Shift+G Ghostty
# expected bottom, actual stays at top -> bug
tmux send-keys -t repro -l "/"; sleep 0.3
tmux send-keys -t repro -H '1b5b32373b323b36347e'; sleep 0.6  # @ shift
# expected Search: @, actual empty
tmux send-keys -t repro "q"; tmux kill-session -t repro

Technical overview

Sapling's pager enables xterm modifyOtherKeys and Ghostty sends Shift+G as ESC[27;2;71~ which termwiz decodes as Char('G')+SHIFT. The pager's keymap expects Char('G')+NONE and prompt only accepts NONE, so the exact modifier check fails. tmux hides this by re-encoding to plain G.

Disclosure: Written by Meta Muse Spark 1.1

Source: facebook/sapling

View original on GitHubView discussion on GitHub