[FEATURE] Desktop app: option to make Enter insert a newline and Ctrl+Enter submit in the chat composer

Status Open
Maintainer reply None cached
Activity 9 comments · opened Aug 26, 2026

Feature request

Add a way to make Enter insert a newline and Ctrl+Enter (or Cmd+Enter) submit in the Desktop app's chat composer.

Current behavior

  • In the Desktop app, Enter always submits the message; the only way to get a newline is Shift+Enter.
  • ~/.claude/keybindings.json (e.g. {"context": "Chat", "bindings": {"enter": "chat:newline", "ctrl+enter": "chat:submit"}}) works in the terminal TUI as documented, but is completely ignored by the Desktop app's composer.
  • This was reported in #25087, which was closed without a fix landing — the thread ends with an OS-level Karabiner-Elements workaround that only helps macOS users. There is no equivalent workaround on Windows.

Why

When writing longer, structured prompts (multi-line lists, pasted context plus instructions), it's very easy to accidentally send an incomplete message with a reflexive Enter. Enter-for-newline with a modifier-to-send is the standard convention in many chat/messenger apps, so muscle memory works against the current default.

Proposed solutions (either would work)

  1. Make the Desktop composer respect the Chat context in ~/.claude/keybindings.json, or
  2. Add a simple composer setting in the Desktop app: "Enter sends / Enter inserts newline (use Ctrl+Enter to send)".

Environment

  • Claude Code Desktop app on Windows 11 (also affects macOS per #25087)

🤖 Generated with Claude Code

View original on GitHub ↗

9 Comments

JakubSirek · 1 month ago

+1, though a mechanism for this already exists: keybindings.json with "enter": "chat:newline" in the Chat context works in the terminal TUI and the VS Code extension — the Desktop composer just ignores it (#90878). Honoring it there would fix both at once and keep behavior consistent across all three surfaces.

yasact · 1 month ago

Adding a data point from the macOS Desktop app (Claude 1.46388.4), and one failure mode I don't think has been raised yet: Enter-to-send is materially worse for IME users, in a way that care and habit cannot fix.

The IME failure mode

With Enter-to-send, one keystroke carries two meanings: "commit the IME conversion" and "send the message". The dangerous case is not a reflexive Enter — it is a mode mismatch:

  1. I start typing believing the IME is ON.
  2. It is actually OFF, so raw romaji lands in the composer.
  3. I press Enter to convert — and the half-finished romaji is sent instead.

The keystroke was correct for the mode I believed I was in, so there is no amount of attention that prevents this. Note that an isComposing guard does not help, because nothing is composing at that moment. Only decoupling "send" from bare Enter removes the failure. This applies to Japanese, Chinese and Korean input alike.

Confirming that keybindings.json is structurally ignored, not merely unimplemented

Worth stating explicitly, because the natural assumption ("the Desktop app is the TUI in a window") sends people down a dead end — I spent an afternoon there. The Desktop app does not render the CLI's TUI at all. It spawns the bundled binary headless:

~/Library/Application Support/Claude/claude-code/<version>/claude.app/Contents/MacOS/claude --output-format ...

The composer is an Electron/React component, so ~/.claude/keybindings.json and editorMode: "vim" — both TUI-layer features — cannot reach it by construction. I wrote a keybindings.json with {"enter": "chat:newline", "meta+enter": "chat:submit"}, restarted, and nothing changed. cmd+g just opens Electron's find bar.

Two observations from the app bundle

In the shortcuts modal, send is a literal while other entries are ID-based:

{shortcut:"enter",       ... "Send message"}
{shortcut:"shift+enter", ... "New line in message"}
{shortcutId:"extended_thinking", ...}

Separately, the bundle already ships an input component taking a submitOnEnter prop that implements both modes, including a guard tied to a timestamp recorded in onCompositionEnd:

h ? e.key==="Enter" && !e.shiftKey && !e.altKey && !l(e.nativeEvent)
  : e.key==="Enter" && (e.metaKey||e.ctrlKey)

To be clear, that component is used for small inline inputs, not the main composer, so this is not "the feature is already built" — but the two-mode behavior and its IME handling do already exist in the codebase.

On the Karabiner workaround from #25087

Restating that it is not a fix, from someone who was in a position to take it. I have Karabiner-Elements installed and already run frontmost_application_if rules for other apps, so scoping enter → shift+enter to com.anthropic.claudefordesktop was a few lines away. I rejected it anyway: I use Claude Code on this Mac and on two Windows machines, and a keybinding that exists on exactly one of them makes the UX less predictable, not more. I would rather keep a bad default that is identical everywhere than hold two different muscle memories. That is the same conclusion as the OP's "no equivalent workaround on Windows", reached from the macOS side.

For that reason I lean toward proposal 2 (a composer setting): honoring keybindings.json only helps people who already sync their dotfiles, whereas a setting in the app is reproducible by the same steps on every platform — which is exactly what the Karabiner workaround is not. If it could ride the existing account sync, better still (plugins already do: "This plugin is now enabled for your account... the next time Claude syncs your plugins"), though I have no idea whether composer settings are in scope for that — config.json currently keeps even theme and locale local, so I would not assume it. Same steps on every platform is the part that matters.

abustamam · 27 days ago

Adding a concrete root-cause detail I don't think is in this thread yet, in case it helps route the fix.

The desktop app ships the CLI as a separate binary and renders its own composer from the web front end, which is why ~/.claude/keybindings.json has no effect here (as #25087 reported, and as #74655 assumes).

macOS 15.7.4, Claude Desktop 2.110.0, bundled CLI 2.1.271:

# bundled CLI binary — the keybinding system lives here
$ grep -ac "keybindings.json" \
    ~/Library/"Application Support"/Claude/claude-code/2.1.271/claude.app/Contents/MacOS/claude
11
$ grep -ac "chat:newline" .../MacOS/claude
3

# desktop app bundle — no trace of it
$ grep -ac "keybindings.json" /Applications/Claude.app/Contents/Resources/app.asar
0
$ grep -ac "chat:newline" /Applications/Claude.app/Contents/Resources/app.asar
0

app.asar also contains only a handful of metaKey / onKeyDown references and points at https://claude.ai, so the Code tab composer is the web UI in an Electron shell with the bundled CLI running headless behind it. The only prompt-input binding option in the desktop bundle's settings schema is editorMode (vim/emacs), which is CLI-only.

Practical consequence for this request: it can't be satisfied by keybindings.json support alone — either the composer's Enter handling changes on the claude.ai side, or the desktop shell reads the same config and intercepts before the web input gets the key. Might be worth confirming which team owns it, since that may be part of why this cluster has stayed open so long.

Workaround in the meantime: run claude in a real terminal (including the desktop app's own Terminal panel), where keybindings.json is honored:

{ "context": "Chat", "bindings": { "enter": "chat:newline", "cmd+enter": "chat:submit" } }
ogawamasato · 17 days ago

I add "IME reason" too.
He explains the use-case and the issue very well in English. Thank you.
And basically, sometimes I use multiple lines to communicate with Clause.
"Sending" is a little bit special action. Something such like command+return / Shift+return / Cntrl+return seems better.
For example, ChatGPT can do this kind of key assignment. (like this comment, with "return" strokes...)

nadyahakkinen · 13 days ago

+1 from macOS: Enter for newline, Cmd+Enter to send.

Small addition to the VS Code point earlier in the thread: the VS Code extension handles this with its own setting, "claudeCode.useCtrlEnterToSend": true

That's a precedent for proposal 2: the same kind of simple on/off setting in the Desktop composer would cover it, and it wouldn't depend on keybindings.json, which (as explained above) can't reach the Desktop composer anyway.

owenoak · 13 days ago

Strong +1 for macos claude app. Make a setting, this shouldn't be that hard.
Claude firing on enter is wasting my money -- I have to kill the session when I meant to give additional input.
Having to run a system extension to change this is lame for a product I'm paying $200/month for!

soychicka · 10 days ago
Strong +1 for macos claude app. Make a setting, this shouldn't be that hard. Claude firing on enter is wasting my money -- I have to kill the session when I meant to give additional input. Having to run a system extension to change this is lame for a product I'm paying $200/month for!

exactly. Shouldn't have to use external tools or compose outside the app and copy-past to make sure entire message isn't prematurely evaluated.

i drafted an overly detailed feature spec over here :)

https://github.com/anthropics/claude-code/issues/74655#issuecomment-5484657361

dandv-pwd · 4 days ago

The inability to assign Cmd+Enter to submit in Claude Desktop is quite annoying, given that ever other desktop agent I use allow this.

LukasWillin · 20 hours ago

I hate whoever started introducing this in chat apps etc. in General. The amount of times I have sent messages by accident, because I didn't quite hit shift hard enough or forgot about it... It is so annoying.