When a terminal with xterm modifyOtherKeys level 2 is active (tmux over SSH, Ghostty, iTerm2, and others), modified keys that Hermes does not explicitly alias arrive as raw CSI sequences that are not in prompt_toolkit's ANSI_SEQUENCES. Unmapped sequences fall through to literal insertion, so the user sees the raw code — with the ESC byte rendered as ? — typed into the prompt, e.g. ?[27;2;32~ for Shift+Space.
Reproduced on v0.20.1, tmux 3.4 over SSH, prompt_toolkit 3.0.52.
Affected sequences (verified unmapped in prompt_toolkit 3.0.52 + pt_input_extras.py)
| Keystroke |
xterm modifyOtherKeys |
CSI-u (Kitty) |
Intended result |
| Shift+Space |
ESC[27;2;32~ |
ESC[32;2u |
insert a space |
| Ctrl+K |
ESC[27;5;107~ |
ESC[107;5u |
Keys.ControlK (kill-line) |
Both are easy to trigger:
- Shift+Space — extremely common when typing ? or ! and tapping Space quickly while Shift is still physically held (any fast typist, especially over SSH). The user sees ?[27;2;32~ inserted.
- Ctrl+K — the standard "delete to end of line" shortcut; with modifyOtherKeys active the plain \x0b byte is never sent, so the shortcut silently stops working and the user sees ?[27;5;107~ inserted.
Only the plain (unmodified) bytes are mapped: \x0b → Keys.ControlK, bare Space → space. hermes_cli/pt_input_extras.py already aliases Shift+Enter, Ctrl+Enter, and Cmd+Backspace/Cmd+ForwardDelete for the same protocol, but coverage is per-sequence rather than systematic.
Root cause
Vt100Parser splits an unmapped CSI sequence into component characters and feeds each as a literal KeyPress (verified: ESC[27;2;32~ → ESC, [, 2, 7, ;, 2, ;, 3, 2, ~), so the ESC byte renders as ? and the rest lands in the buffer verbatim.
Suggested fix
In hermes_cli/pt_input_extras.py, following the existing install_*_alias() pattern:
- ESC[27;5;107~ and ESC[107;5u → Keys.ControlK. Verified working in a real PromptSession under a pty (line cut, no garbage).
- ESC[27;2;32~ and ESC[32;2u → a plain " " mapping is NOT sufficient: Vt100Parser._call_handler(match, prefix) passes the full raw matched prefix as the KeyPress payload, and self-insert inserts event.data, so the raw bytes would be inserted literally (verified under pty). The fix needs a real key binding that inserts a space for this key (e.g. map to a dedicated token and register a handler calling event.current_buffer.insert_text(" ")), or a parser-level transformation.
A broader long-term fix could translate the whole modifyOtherKeys/CSI-u space to base key + modifier where no specific binding exists, instead of aliasing one sequence at a time.
Environment
- Hermes Agent v0.20.1 (2026.8.13), git install
- tmux 3.4 over SSH
- prompt_toolkit 3.0.52
- Ubuntu 24.04, Python 3.11.16
When a terminal with xterm modifyOtherKeys level 2 is active (tmux over SSH, Ghostty, iTerm2, and others), modified keys that Hermes does not explicitly alias arrive as raw CSI sequences that are not in prompt_toolkit's ANSI_SEQUENCES. Unmapped sequences fall through to literal insertion, so the user sees the raw code — with the ESC byte rendered as ? — typed into the prompt, e.g. ?[27;2;32~ for Shift+Space.
Reproduced on v0.20.1, tmux 3.4 over SSH, prompt_toolkit 3.0.52.
Affected sequences (verified unmapped in prompt_toolkit 3.0.52 + pt_input_extras.py)
Both are easy to trigger:
Only the plain (unmodified) bytes are mapped: \x0b → Keys.ControlK, bare Space → space. hermes_cli/pt_input_extras.py already aliases Shift+Enter, Ctrl+Enter, and Cmd+Backspace/Cmd+ForwardDelete for the same protocol, but coverage is per-sequence rather than systematic.
Root cause
Vt100Parser splits an unmapped CSI sequence into component characters and feeds each as a literal KeyPress (verified: ESC[27;2;32~ → ESC, [, 2, 7, ;, 2, ;, 3, 2, ~), so the ESC byte renders as ? and the rest lands in the buffer verbatim.
Suggested fix
In hermes_cli/pt_input_extras.py, following the existing install_*_alias() pattern:
A broader long-term fix could translate the whole modifyOtherKeys/CSI-u space to base key + modifier where no specific binding exists, instead of aliasing one sequence at a time.
Environment