You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
tui: ctrl+j and ctrl+return insert a newline even when unbound from input.newline #50684
Ctrl+J and Ctrl+Return insert a newline into the prompt input regardless of cli.json keybind configuration. Even when explicitly removed from input.newline and rebound to an unrelated command, they still insert a newline and never trigger the newly bound command — indicating they bypass the configurable keybind dispatch entirely for this purpose.
Environment
opencode version: 2.0.14
OS: Linux 6.18.33.2-microsoft-standard-WSL2 (WSL2 Ubuntu on Windows 11), x86_64
Terminal: Windows Terminal (host), TERM=xterm-256color inside WSL
This replaces the default input.newline list (shift+return,ctrl+return,ctrl+j) so it no longer includes ctrl+j/ctrl+return, and instead binds those two combinations to app.debug (Toggle debug panel).
Launch the TUI (opencode) and start typing in the prompt.
Press Ctrl+J.
Press Ctrl+Return.
Expected Behavior
Since input.newline no longer lists these keys, and they are now bound to app.debug, pressing them should toggle the debug panel and not insert a newline.
Actual Behavior
Both Ctrl+J and Ctrl+Return insert a newline into the prompt exactly as before. The debug panel never appears. The rebinding has no observable effect for either key.
Additional Context
Also reproduced with input.newline set to "shift+return" alone (dropping ctrl+return/ctrl+j with no replacement binding) — same result.
This is distinct from the separate, known terminal-capability issue where shift+return itself is indistinguishable from Enter on terminals without Kitty-protocol/CSI-u support (worked around at the terminal level, not related to this report).
This issue might be a duplicate of existing issues. Please check:
Cannot rebind input_submit #26074: Cannot rebind input_submit — specifically involves ctrl+j not working as a rebound keybind for newline/submit actions (closed, but same symptom)
Thanks for the detailed report. I can reproduce this on 2.0.14, and it still happens on the latest dev (fa1260d).
Steps: I used your cli.json (input.newline set to shift+return, app.debug bound to ctrl+j and ctrl+return), typed in the prompt, then sent Ctrl+J the way a terminal without the Kitty keyboard protocol sends it: as a raw line-feed byte (0x0a). A newline was inserted and the debug panel did not open. The recording and screenshots below show it, and the script below reproduces it.
For comparison, when the same keys arrive Kitty-encoded (CSI-u), your bindings work: Ctrl+J opens the debug panel, Ctrl+Return closes it, and no newline is inserted. So the problem looks limited to the legacy line-feed byte, which Windows Terminal sends for Ctrl+J (and, as far as I know, for Ctrl+Enter too, though I couldn't check that in a real Windows Terminal).
Likely cause: the underlying terminal UI library (OpenTUI) reads that byte as a linefeed key rather than ctrl+j. Its textarea has a built-in linefeed → newline binding, which runs no matter what input.newline is set to, so your ctrl+j binding never matches. I've passed this to the maintainers.
recording.mp4
Reproduction script (drive.ts)
// Repro for anomalyco/opencode#50684: with Ctrl+J / Ctrl+Return removed from// input.newline and bound to app.debug, a terminal without the Kitty keyboard// protocol (e.g. Windows Terminal) still gets a newline and never toggles debug.//// Drive's simulated terminal speaks the Kitty protocol, so ui.press("j", {ctrl})// arrives as CSI-u "ctrl+j" and the custom binding works (control case).// A legacy terminal sends Ctrl+J (and Windows Terminal's Ctrl+Enter) as a raw// LF byte 0x0a; ui.type("\n") writes exactly that byte to stdin.import{Effect}from"effect"import{OpenCodeDriver}from"opencode-drive"exportdefaultOpenCodeDriver.use({
...(process.env.OC_DEV ? {opencode: {dev: process.env.OC_DEV}} : {}),tui: {recording: true,keypressOverlay: true},tuiConfig: {keybinds: {"input.newline": "shift+return","app.debug": ["ctrl+j","ctrl+return"],},},},({ ui })=>Effect.gen(function*(){yield*Effect.sleep("1500 millis")yield*ui.type("first")// Control: Kitty-encoded ctrl+j -> debug panel opens, no newlineyield*ui.press("j",{ctrl: true})yield*Effect.sleep("700 millis")yield*ui.screenshot("1-kitty-ctrl-j-opens-debug")// Kitty-encoded ctrl+return -> debug panel closes, no newlineyield*ui.press("return",{ctrl: true})yield*Effect.sleep("700 millis")yield*ui.screenshot("2-kitty-ctrl-return-closes-debug")// Bug: legacy Ctrl+J = raw LF -> newline inserted, debug panel does not openyield*ui.type("second\n")yield*Effect.sleep("700 millis")yield*ui.type("third")yield*Effect.sleep("1000 millis")yield*ui.screenshot("3-legacy-lf-inserts-newline")}),)
Run it with opencode-drive: opencode-drive run ./drive.ts. It drives opencode from your PATH; set OC_DEV to the path of an OpenCode checkout to run that from source instead.
Activity
github-actions commentedon Sep 22, 2026
This issue might be a duplicate of existing issues. Please check:
ctrl+jnot working as a rebound keybind for newline/submit actions (closed, but same symptom)input.newlinerebinding ignored across terminals (closed)For keybind-related issues, please also check our pinned keybinds documentation: #4997
opencodejr commentedon Oct 28, 2026
Thanks for the detailed report. I can reproduce this on 2.0.14, and it still happens on the latest
dev(fa1260d).Steps: I used your
cli.json(input.newlineset toshift+return,app.debugbound toctrl+jandctrl+return), typed in the prompt, then sent Ctrl+J the way a terminal without the Kitty keyboard protocol sends it: as a raw line-feed byte (0x0a). A newline was inserted and the debug panel did not open. The recording and screenshots below show it, and the script below reproduces it.For comparison, when the same keys arrive Kitty-encoded (CSI-u), your bindings work: Ctrl+J opens the debug panel, Ctrl+Return closes it, and no newline is inserted. So the problem looks limited to the legacy line-feed byte, which Windows Terminal sends for Ctrl+J (and, as far as I know, for Ctrl+Enter too, though I couldn't check that in a real Windows Terminal).
Likely cause: the underlying terminal UI library (OpenTUI) reads that byte as a
linefeedkey rather thanctrl+j. Its textarea has a built-inlinefeed→ newline binding, which runs no matter whatinput.newlineis set to, so yourctrl+jbinding never matches. I've passed this to the maintainers.recording.mp4
Reproduction script (drive.ts)
Run it with opencode-drive:
opencode-drive run ./drive.ts. It drivesopencodefrom yourPATH; setOC_DEVto the path of an OpenCode checkout to run that from source instead.