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: session.child.next/previous keybind defaults are dead commands #56153
session.child.next / session.child.previous keybind defaults (right/left) are dead commands — no command with those IDs is registered anywhere in packages/tui/src.
Root cause
packages/tui/src/config/keybind.ts:139-140 defines the keybinds, but no command with those IDs is registered in packages/tui/src (grep confirms only the definitions exist).
Meanwhile down/up toggle the composer/navigate to parent session (routes/session/index.tsx:1261-1294), which is surprising for plain arrow keys.
Suggested fix
Either register commands for session.child.next/session.child.previous, or remove the dead keybind defaults.
Thanks for the report. I reproduced this on v2.0.31 with two subagent sessions. I opened one child from the subagent picker (down, then ctrl+a to show finished subagents, then return) and pressed right/left. The view stayed on the same child. With the picker open, the arrows only switch its tabs (Subagents/Shell). After closing it with escape, which goes back to the parent, they do nothing. The recording and the script below show this.
The code matches what you describe: packages/tui/src/config/keybind.ts binds session.child.next/session.child.previous, but no command with those IDs is registered in packages/tui/src. I haven't re-run this on the latest dev build yet; the dev checkout at 582c974 still has the same definitions with no matching commands.
Related: #56154 covers the up/down behaviour you mention.
recording.mp4
Reproduction script (drive.ts)
// Repro for #56153: `right`/`left` (session.child.next/previous) do nothing in a child session.import{Effect,Stream}from"effect"import{Llm,OpenCodeDriver}from"opencode-drive"exportdefaultOpenCodeDriver.use({
...(process.env.OC_DEV ? {opencode: {dev: process.env.OC_DEV}} : {}),tui: {recording: true,keypressOverlay: true},},({ ui, llm })=>Effect.gen(function*(){yield*llm.serve((_req,index)=>index===0
? Stream.make(Llm.toolCall({index: 0,id: "call_a",name: "subagent",input: {agent: "general",description: "Alpha child task",prompt: "Say alpha"}}),Llm.toolCall({index: 1,id: "call_b",name: "subagent",input: {agent: "general",description: "Beta child task",prompt: "Say beta"}}),Llm.finish("tool-calls"),)
: Stream.make(Llm.text(`Done ${index}.`)),)yield*ui.submit("Run two subagents")yield*ui.waitFor("Beta child task",{timeout: 30000})yield*Effect.sleep(3000)yield*ui.screenshot("01-parent-with-children")// open subagent picker and enter the first childyield*ui.press("down")yield*Effect.sleep(800)yield*ui.press("a",{ctrl: true})// show inactive (finished) subagentsyield*Effect.sleep(1000)yield*ui.screenshot("02-subagent-picker")yield*ui.press("return")yield*Effect.sleep(1500)constbefore=yield*ui.capture()yield*ui.screenshot("03-in-child")// session.child.next default = right: expected to go to the other child (Alpha); instead it only switches the picker tabyield*ui.press("right")yield*Effect.sleep(1500)constafterRight=yield*ui.capture()yield*ui.screenshot("04-after-right")yield*ui.press("left")yield*Effect.sleep(1500)constafterLeft=yield*ui.capture()yield*ui.screenshot("05-after-left")consttext=(f: unknown)=>JSON.stringify(f)yield*Effect.log(`screen unchanged after right: ${text(before)===text(afterRight)}`)yield*Effect.log(`screen unchanged after left: ${text(afterRight)===text(afterLeft)}`)}),)
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.
The child session view keeps the subagent picker open, where left/right switch composer tabs. Adding handlers only to the session’s base keymap would still leave them unreachable there. I’m taking the suggested alternative: disable these two unused defaults and mark them deprecated, while retaining their configuration names for compatibility. The picker continues to provide child-session navigation.
Activity
opencode-agent commentedon Oct 16, 2026
Thanks for the report. I reproduced this on v2.0.31 with two subagent sessions. I opened one child from the subagent picker (
down, thenctrl+ato show finished subagents, thenreturn) and pressedright/left. The view stayed on the same child. With the picker open, the arrows only switch its tabs (Subagents/Shell). After closing it withescape, which goes back to the parent, they do nothing. The recording and the script below show this.The code matches what you describe:
packages/tui/src/config/keybind.tsbindssession.child.next/session.child.previous, but no command with those IDs is registered inpackages/tui/src. I haven't re-run this on the latestdevbuild yet; thedevcheckout at 582c974 still has the same definitions with no matching commands.Related: #56154 covers the
up/downbehaviour you mention.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.Dante-dan commentedon Oct 16, 2026
The child session view keeps the subagent picker open, where left/right switch composer tabs. Adding handlers only to the session’s base keymap would still leave them unreachable there. I’m taking the suggested alternative: disable these two unused defaults and mark them deprecated, while retaining their configuration names for compatibility. The picker continues to provide child-session navigation.