From 9c93fc5775c872d9a10b5b56c3b9fcc59946f742 Mon Sep 17 00:00:00 2001 From: liuhao1024 Date: Mon, 4 May 2026 00:04:58 +0800 Subject: [PATCH] fix(tui): call process.exit(0) after Ink exit to trigger terminal cleanup MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Ink's exit() calls unmount() which resets terminal modes (kitty keyboard, mouse, etc.) but does NOT call process.exit(). The Node process stays alive because stdin is still open (Ink listens on it), so the process.on('exit') handler in entry.tsx — which sends the final resetTerminalModes() — never fires. This left kitty keyboard protocol and other terminal modes enabled in the parent shell after /quit, Ctrl+C, or Ctrl+D, breaking arrow keys and other input in subsequent programs. Add explicit process.exit(0) after exit() in die() so the process actually terminates and the exit handler runs. Fixes #19194 --- ui-tui/src/app/useMainApp.ts | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/ui-tui/src/app/useMainApp.ts b/ui-tui/src/app/useMainApp.ts index 9ec18337bb..17924ca4a6 100644 --- a/ui-tui/src/app/useMainApp.ts +++ b/ui-tui/src/app/useMainApp.ts @@ -358,6 +358,13 @@ export function useMainApp(gw: GatewayClient) { const die = useCallback(() => { gw.kill() exit() + // Ink's exit() calls unmount() which resets terminal modes but does NOT + // call process.exit(). Without an explicit exit the Node process stays + // alive (stdin listener keeps the event loop open), so the process.on('exit') + // handler in entry.tsx — which sends the final resetTerminalModes() — never + // fires. This leaves kitty keyboard protocol, mouse modes, etc. enabled + // in the parent shell. See issue #19194. + process.exit(0) }, [exit, gw]) const session = useSessionLifecycle({