Skip to content

[Bug] Unmapped xterm modifyOtherKeys / CSI-u sequences insert literal text into the prompt (Shift+Space, Ctrl+K, …) #86866

Description

@tireiron

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

Metadata

Metadata

Assignees

No one assigned

    Labels

    P2Medium — degraded but workaround existscomp/cliCLI entry point, hermes_cli/, setup wizardtype/bugSomething isn't working

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions