diff --git a/packages/opencode/src/cli/cmd/tui/attach.ts b/packages/opencode/src/cli/cmd/tui/attach.ts index e892f9922d1b..04bfe48dd938 100644 --- a/packages/opencode/src/cli/cmd/tui/attach.ts +++ b/packages/opencode/src/cli/cmd/tui/attach.ts @@ -6,6 +6,16 @@ import { TuiConfig } from "@/config/tui" import { Instance } from "@/project/instance" import { existsSync } from "fs" +function resetTerminal() { + if (!process.stdout.isTTY) return + process.stdout.write( + "\x1b[0m" + // reset all attributes (colors, bold, etc.) + "\x1b[?25h" + // show cursor + "\x1b[?1049l" + // exit alternate screen buffer + "\x1b[?7h", // re-enable auto-wrap + ) +} + export const AttachCommand = cmd({ command: "attach ", describe: "attach to a running opencode server", @@ -83,6 +93,7 @@ export const AttachCommand = cmd({ }) } finally { unguard?.() + resetTerminal() } }, }) diff --git a/packages/opencode/src/cli/cmd/tui/thread.ts b/packages/opencode/src/cli/cmd/tui/thread.ts index 3bb56937a6cb..9f26f39b69a7 100644 --- a/packages/opencode/src/cli/cmd/tui/thread.ts +++ b/packages/opencode/src/cli/cmd/tui/thread.ts @@ -21,6 +21,19 @@ declare global { const OPENCODE_WORKER_PATH: string } +function resetTerminal() { + if (!process.stdout.isTTY) return + process.stdout.write( + "\x1b[0m" + // reset all attributes (colors, bold, etc.) + "\x1b[?25h" + // show cursor + "\x1b[?1049l" + // exit alternate screen buffer + "\x1b[?7h", // re-enable auto-wrap + ) +} + +// Backstop: runs even on process.exit() or uncaught crash +process.on("exit", resetTerminal) + type RpcClient = ReturnType> function createWorkerFetch(client: RpcClient): typeof fetch { @@ -226,6 +239,7 @@ export const TuiThreadCommand = cmd({ } } finally { unguard?.() + resetTerminal() } process.exit(0) },