Skip to content

Feature Request: configurable keybindings; Option+Enter cannot be bound to newline (insert-newline is fixed to Shift/Ctrl/backslash+Enter) #25

Description

@brendandebeasi

Summary

There is no way to change which keys insert a newline in the composer. The bindings are fixed at Shift+Enter, Ctrl+Enter and \+Enter, and nothing in ~/.factory/settings.json or the CLI overrides them. Option+Enter in particular cannot be bound at all, which is the one that costs me: it is the newline key I have muscle memory for from other terminal agents, and on the hosts I run droid on it is also the only modified-Enter that reliably survives the terminal chain.

Current behaviour (droid 0.204.0)

The composer's newline handler accepts exactly two byte sequences:

  • \x1b[13;2u (Shift+Enter, CSI-u / xterm modifyOtherKeys=2)
  • \x1b[27;2;13~ (Shift+Enter, CSI 27 form)

The help label confirms the set: insert-newline is documented as Shift+Enter / Ctrl+Enter / \+Enter.

There is no handler for a meta-modified Return anywhere in the input path, so the Option+Enter encodings do nothing useful:

  • \x1b[13;3u and \x1b[27;3;13~ (Option+Enter under the kitty keyboard protocol) fall through unhandled
  • \x1b\r (classic ESC-prefixed Alt+Enter) hits the composer as ESC followed by CR

The submit guard is return && !ctrl && !meta && !input.includes("\x1b"), so a meta Return is at least not treated as submit, but it is not treated as a newline either.

Why a fixed set is a problem

Shift+Enter is the fragile one to depend on, because it only exists as a distinct key at all if the whole chain negotiates an extended-key protocol. Mine is:

Ghostty -> mosh -> tmux 3.6 -> ssh -> tmux 3.4 -> droid

The middle pane there is ssh, which never requests extended keys, so tmux -s extended-keys on collapses Shift+Enter to a bare CR before it reaches droid and the message submits. I fixed that by setting extended-keys always on both tmux servers, which forces the CSI-u form down the chain whether or not anything asked for it. That works, but it is a blunt setting that also hands CSI-u to every other TUI in those panes, and it is not something a user should need to reason about to get a newline.

Option+Enter has none of that fragility: every terminal I use emits something distinct for it out of the box. droid just does not listen for it.

Request

Either of these would solve it, in preference order:

  1. A keymap section in ~/.factory/settings.json mapping intents to key names, e.g.
{
  "keybindings": {
    "insert-newline": ["shift+enter", "alt+enter", "ctrl+enter"]
  }
}
  1. Failing that, add \x1b[13;3u, \x1b[27;3;13~ and \x1b\r to the sequences that insert-newline already accepts. That covers Option+Enter across kitty-protocol and legacy terminals with no configuration at all, and no other droid binding claims those bytes today.

Broader keymap support would also cover the neighbouring cases people hit (rebinding submit, escape, history navigation), but the newline set is the one that is actively unusable as shipped.

Workaround for anyone else hitting this

Remap the key in the terminal so droid sees the Shift+Enter form it already accepts. Ghostty:

keybind = shift+enter=text:\x1b[13;2u
keybind = alt+enter=text:\x1b[13;2u

Plus set -s extended-keys always in tmux if droid runs on the far side of an ssh hop.

Environment

  • droid 0.204.0 (Homebrew cask, macOS arm64)
  • macOS 15 / Darwin 25.5.0
  • Ghostty 1.3.1
  • tmux 3.6b (mac), tmux 3.4 (Ubuntu VMs)

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions