Skip to content

TUI: Shift+Enter submits instead of newline on macOS Terminal.app and Alacritty #24890

Description

@ivrylobs

Issue

In the Hermes interactive TUI on macOS, Shift+Enter submits the message instead of inserting a newline. The only working multi-line input method is Escape then Enter.

Ctrl+Enter has the same problem — it submits rather than inserting a newline.

Expected behavior

  • Shift+Enter → insert newline (standard convention across chat apps and most AI agent CLIs)
  • Ctrl+Enter → insert newline
  • Alt/Option+Enter → insert newline (works with Option-as-Meta terminal setting)
  • Esc then Enter → insert newline (currently works, but not discoverable)
  • Enter → submit

Actual behavior

Shift+Enter and Ctrl+Enter are not distinguished from plain Enter — all three submit immediately.

Root Cause Analysis

macOS Terminal.app and Alacritty send the same byte (\\r) for Enter, Shift+Enter, and Ctrl+Enter. The key modifier is lost at the terminal/OS layer and never reaches prompt_toolkit. So there is no byte sequence for Hermes to intercept and rebind.

The existing ANSI escape aliases in hermes_cli/pt_input_extras.py (for \\x1b[13;2u, \\x1b[27;2;13~, etc.) only fire in terminals that implement the Kitty keyboard protocol or xterm modifyOtherKeys — which macOS Terminal.app and Alacritty do not enable by default.

Alt/Option+Enter works because macOS terminals can send Option as "Meta" (Escape prefix), producing \\x1b\\r (Escape + Enter), which prompt_toolkit sees as (Escape, Enter) and triggers the existing kb.add('escape', 'enter') newline handler.

Terminals Tested

Terminal OS Shift+Enter Ctrl+Enter Alt/Option+Enter Esc+Enter
Terminal.app macOS 26.4.1 Submit Submit Newline (Meta enabled) Newline
Alacritty macOS 26.4.1 Submit Submit Newline (Meta enabled) Newline

Note: _preserve_ctrl_enter_newline() in cli.py (line 1913) returns False on native macOS, so c-j is bound to submit (line 1959) rather than newline. This is correct for SSH/docker-over-TTY where \\n IS the Enter key, but it means Ctrl+Enter has no newline path on POSIX.

Proposed Solutions

Option 1: Document a workaround (lowest effort)

Add a note to the docs / /help output explaining that on macOS Terminal.app and Alacritty, users must either:

  1. Enable Option-as-Meta for Alt+Enter newline
  2. Use Esc then Enter

This is honest but does not improve the UX.

Option 2: Add a config setting for a dedicated newline key (medium effort)

Allow users to bind an additional key to "insert newline" in config.yaml:

tui:
  newline_key: c-n   # or "c-o", "m-enter", etc.

Users who find Esc+Enter awkward could pick Ctrl+N (or another unused key) as their newline. This would require adding a config knob and wiring it into the keybinding section of cli.py (_bind_prompt_submit_keys area, around line 1944-1960).

Option 3: Double-Enter for multi-line (highest UX impact)

Detect when the user types Enter on an empty line or at the end of their input to insert a newline, and only submit on a second Enter. This is how some chat apps work (e.g., Slack in certain modes). Would require a small change to the submit handler logic.

Option 4: Kitty keyboard protocol support in TUI

Enable the Kitty keyboard protocol in the prompt_appkit TUI (the app already enables some kitty features at line 1906-1908). If prompt_toolkit supports Kitty keyboard mode natively or via a plugin, enabling it could make Shift+Enter/Ctrl+Enter emit distinct CSI-u sequences, making the existing pt_input_extras.py mappings work.

Related Issues

Metadata

Metadata

Assignees

No one assigned

    Labels

    P3Low — cosmetic, nice to havecomp/cliCLI entry point, hermes_cli/, setup wizardduplicateThis issue or pull request already existstype/bugSomething isn't working

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions