Bug description
In the classic Hermes CLI, Ctrl+Enter should insert a newline for multiline prompts in Windows Terminal / WSL / SSH workflows. After the recent Shift+Enter/newline changes, Ctrl+Enter can instead submit the prompt when Hermes is running under WSL or over SSH.
This is especially painful for Windows Terminal -> SSH/WSL users because Alt+Enter is often intercepted by Windows Terminal for fullscreen, so Ctrl+Enter is the discoverable Enter-involving multiline shortcut.
Reproduction / observed behavior
Environment observed locally:
- Host: WSL2 / Linux (
Linux ... microsoft-standard-WSL2)
- Hermes checkout:
NousResearch/hermes-agent main
- Terminal behavior: Windows Terminal sends:
- plain Enter: CR /
c-m
- Ctrl+Enter: LF /
c-j
Before the fix:
- Start
hermes in WSL or via SSH from Windows Terminal.
- Type a prompt.
- Press
Ctrl+Enter intending to insert a newline.
- The prompt submits instead of inserting a newline, or the newline handler is not installed for the active platform.
Root cause
There are two related cases:
-
Raw LF case:
- Windows Terminal sends
Ctrl+Enter as c-j.
- Under WSL/SSH, Python sees
sys.platform == "linux".
- POSIX fallback binds
c-j to submit so thin PTYs whose Enter arrives as LF still work.
- That steals
Ctrl+Enter from prompt_toolkit's multiline input path.
-
Enhanced terminal protocol case:
- Over SSH from modern terminals with Kitty keyboard protocol / xterm modifyOtherKeys enabled,
Ctrl+Enter may arrive as enhanced CSI sequences instead of raw LF:
\x1b[13;5u
\x1b[27;5;13~
\x1b[27;5;13u
- prompt_toolkit does not map these to Hermes' existing newline handler by default.
A previous WSL-only fix avoided binding c-j as submit in WSL, but the actual c-j newline handler was still only registered on native win32, so WSL/SSH still had a gap.
Expected behavior
- Plain Enter submits.
Ctrl+Enter inserts a newline in Windows/WSL/SSH contexts where terminals deliver it as raw LF / c-j.
- Enhanced Ctrl+Enter CSI-u / modifyOtherKeys sequences reach the same newline handler as
Alt+Enter.
- Local POSIX fallback can still bind
c-j as submit outside Windows/WSL/SSH so thin PTYs are not regressed.
Proposed fix
Tested locally:
- Add a
_preserve_ctrl_enter_newline() predicate in cli.py that returns true for:
- native Windows
- WSL (including scrubbed env detection via
/proc/* containing microsoft)
- SSH sessions (
SSH_CONNECTION, SSH_CLIENT, or SSH_TTY)
WT_SESSION
- Only bind
c-j to submit when that predicate is false.
- Register the
c-j newline handler whenever that predicate is true, not only on sys.platform == "win32".
- Add
install_ctrl_enter_alias() in hermes_cli/pt_input_extras.py mapping enhanced Ctrl+Enter sequences to (Keys.Escape, Keys.ControlM), reusing the existing Alt+Enter newline handler.
- Add regression tests for WSL, SSH, raw-LF Ctrl+Enter, and enhanced Ctrl+Enter sequences.
Local validation:
python -m pytest tests/cli/test_cli_shift_enter_newline.py \
tests/hermes_cli/test_prompt_submit_keys.py \
tests/cli/test_cli_init.py::TestPromptToolkitTerminalCompatibility -q
# 17 passed
python -m pytest tests/cli/test_cli_shift_enter_newline.py \
tests/hermes_cli/test_prompt_submit_keys.py tests/cli -q
# 649 passed
Local parser sanity check after the fix:
plain_enter -> [Keys.ControlM]
raw_ctrl_enter_lf -> [Keys.ControlJ]
csiu_ctrl_enter -> [Keys.Escape, Keys.ControlM]
mok_ctrl_enter -> [Keys.Escape, Keys.ControlM]
alt_enter -> [Keys.Escape, Keys.ControlM]
Local commit with the tested patch:
66942189a fix(cli): preserve Ctrl+Enter newline over SSH
Bug description
In the classic Hermes CLI,
Ctrl+Entershould insert a newline for multiline prompts in Windows Terminal / WSL / SSH workflows. After the recent Shift+Enter/newline changes,Ctrl+Entercan instead submit the prompt when Hermes is running under WSL or over SSH.This is especially painful for Windows Terminal -> SSH/WSL users because
Alt+Enteris often intercepted by Windows Terminal for fullscreen, soCtrl+Enteris the discoverable Enter-involving multiline shortcut.Reproduction / observed behavior
Environment observed locally:
Linux ... microsoft-standard-WSL2)NousResearch/hermes-agentmainc-mc-jBefore the fix:
hermesin WSL or via SSH from Windows Terminal.Ctrl+Enterintending to insert a newline.Root cause
There are two related cases:
Raw LF case:
Ctrl+Enterasc-j.sys.platform == "linux".c-jto submit so thin PTYs whose Enter arrives as LF still work.Ctrl+Enterfrom prompt_toolkit's multiline input path.Enhanced terminal protocol case:
Ctrl+Entermay arrive as enhanced CSI sequences instead of raw LF:\x1b[13;5u\x1b[27;5;13~\x1b[27;5;13uA previous WSL-only fix avoided binding
c-jas submit in WSL, but the actualc-jnewline handler was still only registered on nativewin32, so WSL/SSH still had a gap.Expected behavior
Ctrl+Enterinserts a newline in Windows/WSL/SSH contexts where terminals deliver it as raw LF /c-j.Alt+Enter.c-jas submit outside Windows/WSL/SSH so thin PTYs are not regressed.Proposed fix
Tested locally:
_preserve_ctrl_enter_newline()predicate incli.pythat returns true for:/proc/*containingmicrosoft)SSH_CONNECTION,SSH_CLIENT, orSSH_TTY)WT_SESSIONc-jto submit when that predicate is false.c-jnewline handler whenever that predicate is true, not only onsys.platform == "win32".install_ctrl_enter_alias()inhermes_cli/pt_input_extras.pymapping enhanced Ctrl+Enter sequences to(Keys.Escape, Keys.ControlM), reusing the existing Alt+Enter newline handler.Local validation:
Local parser sanity check after the fix:
Local commit with the tested patch: