From 64a36881718f1479359a60c1c6275e7e5d2acdf4 Mon Sep 17 00:00:00 2001 From: Dmitry Lyalin Date: Fri, 13 Feb 2026 20:24:34 -0500 Subject: [PATCH] Restore terminal state on startup and resume failures --- packages/cli/index.ts | 4 +++- packages/cli/src/gemini.tsx | 23 +++++++++++++++++------ 2 files changed, 20 insertions(+), 7 deletions(-) diff --git a/packages/cli/index.ts b/packages/cli/index.ts index 29a83b2337..dbcff0f169 100644 --- a/packages/cli/index.ts +++ b/packages/cli/index.ts @@ -32,7 +32,9 @@ process.on('uncaughtException', (error) => { } else { writeToStderr(String(error) + '\n'); } - process.exit(1); + void runExitCleanup().finally(() => { + process.exit(1); + }); }); main().catch(async (error) => { diff --git a/packages/cli/src/gemini.tsx b/packages/cli/src/gemini.tsx index 7b092d2d5a..5de617bb88 100644 --- a/packages/cli/src/gemini.tsx +++ b/packages/cli/src/gemini.tsx @@ -641,16 +641,27 @@ export async function main() { const wasRaw = process.stdin.isRaw; if (config.isInteractive() && !wasRaw && process.stdin.isTTY) { + const restoreRawMode = () => { + if ( + process.stdin.isTTY && + process.stdin.isRaw !== wasRaw && + typeof process.stdin.setRawMode === 'function' + ) { + process.stdin.setRawMode(wasRaw); + } + }; + // Set this as early as possible to avoid spurious characters from // input showing up in the output. process.stdin.setRawMode(true); + registerCleanup(restoreRawMode); - // This cleanup isn't strictly needed but may help in certain situations. - process.on('SIGTERM', () => { - process.stdin.setRawMode(wasRaw); - }); - process.on('SIGINT', () => { - process.stdin.setRawMode(wasRaw); + // Best-effort terminal restoration if terminated by signals. + process.on('SIGTERM', restoreRawMode); + process.on('SIGINT', restoreRawMode); + registerCleanup(() => { + process.off('SIGTERM', restoreRawMode); + process.off('SIGINT', restoreRawMode); }); }