FA Dev Tools

English中文

claude-code-shift-enter

ai/claude-code-shift-enter · Updated · Tags: ai

正在用 AI 翻譯成中文,可能需要一分鐘… 以下暫時顯示英文原文。


Shift+Enter in Claude Code — setup, and where /terminal-setup matters

Verified against Claude Code 2.1.220 on macOS (Darwin 24.6.0), 2026-07-28.

Colour key: CC extension panel CC CLI in a standalone terminal CC CLI in an editor's integrated terminal

TL;DR

  • Claude Code extension panel (VS Code / Cursor / desktop app): no setup. Shift+Enter inserts a newline out of the box, because the input is a real UI textbox, not a terminal.
  • Claude Code CLI in any terminal: setup required. Terminals send the same byte for Enter and Shift+Enter, so the key must be remapped. Run /terminal-setup once inside a Claude Code session running in that terminal.
  • Cursor's integrated terminal counts as a terminal — it needs the same keybindings.json entry as VS Code's. Cursor and VS Code keep separate keybinding files, so setting one up does not set up the other.
  • On this machine, both VS Code and Cursor already have the binding installed (verified). iTerm2 could not be verified from a sandboxed shell.
  • Universal fallbacks that never need setup: \ then Enter, or Ctrl+J.

Comparison: the three ways you run Claude Code

CC extension panel (VS Code / Cursor / desktop app)CC CLI in a standalone terminal (iTerm2, Ghostty, Terminal.app…)CC CLI in Cursor / VS Code integrated terminal
Input surfaceNative UI textboxTTYTTY (VS Code's xterm.js)
Shift+Enter works by default?YesNoNo
Setup neededNone/terminal-setup/terminal-setup
What setup changes—The terminal app's own key-mapping config (iTerm2 plist, Ghostty/Alacritty/Kitty/WezTerm/Zed config file)keybindings.json of that editor
Where the config lands—e.g. iTerm2 prefs, ~/.config/ghostty/config~/Library/Application Support/{Code,Cursor}/User/keybindings.json
Shared between VS Code and Cursor?n/an/aNo — separate files, set up each one
Terminal.app special case—Shift+Enter is not bindable; /terminal-setup enables Option+Enter instead—
Survives an SSH / remote session?n/aBinding lives on the local machine, so yes — but you must run /terminal-setup locally, not over SSHSame

The extension can be configured to run Claude in a terminal instead of the native panel (claudeCode.useTerminal). If you turn that on, you are in the third column, not the first.


Do I need setup?

Answer the one question: is my prompt box a terminal?

  • Typing into the Claude panel in VS Code / Cursor / the desktop app → no setup.
  • Typing into a shell where you ran claude → setup, regardless of which app hosts that shell.

Where to run /terminal-setup

Run it from a Claude Code session inside the terminal you actually type in, on your local machine.

claude
> /terminal-setup
  • In Cursor's integrated terminal → run it there; it edits Cursor's keybindings.json.
  • In VS Code's integrated terminal → run it there; it edits VS Code's keybindings.json.
  • In iTerm2 / Ghostty / Kitty / WezTerm / Alacritty / Zed → run it in that app; it edits that app's config.
  • Over SSH or in a container → the keybinding belongs to the terminal emulator on your laptop, so run /terminal-setup in a local session of the same app. Running it on the remote box does nothing useful.
  • After it runs, restart or reload the terminal app (iTerm2 in particular) before the key takes effect.

Terminals /terminal-setup knows how to configure

vscode, cursor, windsurf, zed, iterm2, ghostty, kitty, wezterm, alacritty — plus Terminal.app via the Option+Enter path.

Anything else (Warp, Hyper, Konsole, …): bind Shift+Enter manually to send ESC + CR, or use the fallbacks below.


What it actually installs (editor terminals)

/terminal-setup appends this to your editor's keybindings.json:

{
  "key": "shift+enter",
  "command": "workbench.action.terminal.sendSequence",
  "args": { "text": "\u001b\r" },
  "when": "terminalFocus"
}

\u001b\r is ESC followed by carriage return — the "meta+Enter" sequence Claude Code reads as newline, don't submit. The when: terminalFocus clause keeps Shift+Enter unchanged everywhere else in the editor.

If a Shift+Enter terminal binding already exists with different args, Claude Code leaves it alone and tells you so rather than overwriting it.


Current state on this machine (verified)

LocationStatusEvidence
VS Code integrated terminalConfigured~/Library/Application Support/Code/User/keybindings.json — shift+enter → sendSequence \u001b\r, when: terminalFocus
Cursor integrated terminalConfigured~/Library/Application Support/Cursor/User/keybindings.json — same binding
Claude extension panelN/A — works nativelyNo config needed
iTerm2 (installed at /Applications/iTerm.app)UnverifiediTerm2 preferences are not readable from a sandboxed shell. Run /terminal-setup inside iTerm2 to be sure — it is a no-op if already configured.

Fallbacks that always work (no setup)

KeysNotes
\ then EnterBackslash at end of line, then Enter. Works in every terminal.
Ctrl+JSends a raw linefeed. Works in every terminal.
Option+EnterWorks once "Option as Meta" is enabled — the path /terminal-setup uses for Terminal.app.

Troubleshooting

SymptomLikely causeFix
Shift+Enter submits the messageRunning the CLI in a terminal without the bindingRun /terminal-setup in that terminal
Works in VS Code, not in Cursor (or vice versa)Separate keybindings.json per editorRun /terminal-setup in the other one too
Ran /terminal-setup, still nothingTerminal not reloaded, or an existing conflicting binding was left in placeRestart the app; check keybindings.json / the terminal's key map for a competing shift+enter entry
Ran it over SSH, no effectBinding must live on the local terminal emulatorRe-run in a local session of the same terminal app
Terminal.app: Shift+Enter never worksTerminal.app cannot bind Shift+EnterUse Option+Enter (after /terminal-setup), or \+Enter / Ctrl+J

Disclaimer: These documents are personal notes. The information may be incomplete, out of date or wrong, so check it before you rely on it.