Description
Quitting the TUI from inside a session used to print a resume banner to scrollback — the OpenCode wordmark plus:
Session <title>
Continue opencode -s <session-id>
It no longer prints anything on exit. The banner code is still present and still wired to run; the value just gets cleared during teardown before it's written, so nothing reaches the terminal.
This is a logic/ordering bug, independent of terminal or OS. opencode run -i has its own separate exit splash (packages/opencode/src/cli/cmd/run/splash.ts) which still works — only the default opencode TUI is affected.
Root cause
The epilogue is captured into a plain object and printed after the render scope closes:
packages/tui/src/app.tsx:244 — <EpilogueProvider set={(value) => (exit.epilogue = value)}>
packages/tui/src/app.tsx:346 — if (exit.epilogue) process.stdout.write(exit.epilogue + "\n")
The session route both sets and clears it:
packages/tui/src/routes/session/index.tsx:198 — setEpilogue(sessionEpilogue({ title, sessionID }))
packages/tui/src/routes/session/index.tsx:200 — onCleanup(() => setEpilogue()), which sets exit.epilogue = undefined
On exit, ExitProvider.exit calls destroyRenderer(renderer) → renderer.destroy(). @opentui/solid's render registers renderer.once("destroy", runDispose), which disposes the Solid tree and runs that onCleanup, wiping exit.epilogue. The print at app.tsx:346 runs in the Effect continuation gated on the shutdown deferred — which is resolved by the same destroy() event — so it always runs after disposal has cleared the value. if (exit.epilogue) is therefore always false at print time.
Steps to reproduce
opencode
- Start a session (send any message)
- Quit with
ctrl+c
- Expected: scrollback shows the
Session … / Continue opencode -s <id> banner. Actual: nothing prints.
Suggested fix
Snapshot the epilogue when exit() is invoked (before destroyRenderer), so the print reads a value captured before disposal — or skip the onCleanup clear during app teardown.
OpenCode version
1.17.3
Operating System
macOS 26.5.1
Terminal
N/A (terminal-independent; reproduced under tmux)
Description
Quitting the TUI from inside a session used to print a resume banner to scrollback — the OpenCode wordmark plus:
It no longer prints anything on exit. The banner code is still present and still wired to run; the value just gets cleared during teardown before it's written, so nothing reaches the terminal.
This is a logic/ordering bug, independent of terminal or OS.
opencode run -ihas its own separate exit splash (packages/opencode/src/cli/cmd/run/splash.ts) which still works — only the defaultopencodeTUI is affected.Root cause
The epilogue is captured into a plain object and printed after the render scope closes:
packages/tui/src/app.tsx:244—<EpilogueProvider set={(value) => (exit.epilogue = value)}>packages/tui/src/app.tsx:346—if (exit.epilogue) process.stdout.write(exit.epilogue + "\n")The session route both sets and clears it:
packages/tui/src/routes/session/index.tsx:198—setEpilogue(sessionEpilogue({ title, sessionID }))packages/tui/src/routes/session/index.tsx:200—onCleanup(() => setEpilogue()), which setsexit.epilogue = undefinedOn exit,
ExitProvider.exitcallsdestroyRenderer(renderer)→renderer.destroy().@opentui/solid'srenderregistersrenderer.once("destroy", runDispose), which disposes the Solid tree and runs thatonCleanup, wipingexit.epilogue. The print atapp.tsx:346runs in the Effect continuation gated on theshutdowndeferred — which is resolved by the samedestroy()event — so it always runs after disposal has cleared the value.if (exit.epilogue)is therefore always false at print time.Steps to reproduce
opencodectrl+cSession …/Continue opencode -s <id>banner. Actual: nothing prints.Suggested fix
Snapshot the epilogue when
exit()is invoked (beforedestroyRenderer), so the print reads a value captured before disposal — or skip theonCleanupclear during app teardown.OpenCode version
1.17.3
Operating System
macOS 26.5.1
Terminal
N/A (terminal-independent; reproduced under tmux)