Repository navigation
fix(terminal): Shift+Enter inserts a newline instead of submitting - #546
Merged
chaitanyagiri merged 1 commit intoOct 2, 2026
Merged
Conversation
xterm.js encodes Shift+Enter exactly like Enter — a bare CR — so a TUI cannot tell the two apart. At a Claude Code prompt inside an agent's terminal pane, Shift+Enter therefore submits the line instead of opening a new one, and writing a multi-line prompt by hand means typing a trailing backslash. `/terminal-setup` installs the right mapping for iTerm2 and VS Code, but there is no way to apply it to our pane, so the pane has to send the sequence itself. Shift+Enter now writes ESC CR, the sequence /terminal-setup configures. This is provider-neutral: it is the same sequence Alt+Enter has always produced, so any TUI that honours one honours the other. The mapping is deliberately narrow, and lives in its own structural module so it is unit-testable without xterm or a window. Plain Enter still submits. Alt+Enter is untouched, since it already produces this sequence natively and intercepting it would double-encode. Ctrl+Enter and Cmd+Enter stay with the TUI and the app's own shortcuts. Only keydown answers — xterm's custom-key hook also sees keypress and keyup, and answering twice would insert two newlines. The check sits BEFORE the existing Ctrl/Cmd gate in the handler, because Shift+Enter holds neither modifier and was returning early into xterm's default. Writing to the pty is the path the OSC colour replies alongside it already use, and is skipped once the pty has exited. Five tests in test/terminal-keys.test.cjs. Closes HarnessMD#481
snehithareddy28
force-pushed
the
fix/terminal-shift-enter
branch
from
September 17, 2026 05:32
6a81926 to
46bce68
Compare
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What & why
Closes #481, which is on the 0.5.2 incident log.
xterm.js encodes Shift+Enter exactly like Enter — a bare CR — so a TUI cannot tell the two apart. At a Claude Code prompt inside an agent's terminal pane, Shift+Enter therefore submits the line instead of opening a new one, and the only way to write a multi-line prompt by hand is to end each line with a backslash. Terminals that get this right send a distinct sequence; the one
/terminal-setupinstalls for iTerm2 and VS Code is ESC CR. Nothing configures that for our pane, so the pane has to send it.Shift+Enter now writes ESC CR. That is provider-neutral on purpose: it is the same sequence Alt+Enter has always produced, so any TUI honouring one honours the other. As the issue says, this is about how the terminal encodes a modifier, not about Claude Code.
The mapping is deliberately narrow, and it is the part worth reviewing:
keypressandkeyup, and answering on more than one would insert the newline two or three times.The check sits before the existing Ctrl/Cmd gate in the handler. That gate is why this was broken: Shift+Enter holds neither modifier, so it returned early into xterm's default. Writing to the pty is the same path the OSC colour replies immediately below already use, and is skipped once the pty has exited.
The mapping lives in its own structural module with no xterm and no
window, so it is unit-testable on its own — the same shapeaskMeOrder.tsandqueueDelivery.tsuse.Type of change
Evidence
Before
After
Notes for review:
test/terminal-keys.test.cjs, one per rule above. They fail onmainbecause the module does not exist there.trueexactly as before./terminal-setupactually installs today, so it fixes the reported case without committing the pane to a protocol.npm run typecheckand the fullnpm run test:focusedsuite (839/839 on this branch) pass locally.Discord: asr2805