From 7cf97bcd98c6c56c0162ea9b7898ac230c5d2c54 Mon Sep 17 00:00:00 2001 From: Lex Christopherson Date: Wed, 18 Mar 2026 09:54:19 -0600 Subject: [PATCH] fix: move TTY check before heavy initialization to prevent process hang The no-TTY check at the end of cli.ts ran after full session/extension initialization, which opens handles that prevent process.exit(1) from completing promptly (15s hang on Node 24). Move the check right after arg parsing, before any heavy initialization. Co-Authored-By: Claude Opus 4.6 (1M context) --- src/cli.ts | 23 +++++++++++++---------- 1 file changed, 13 insertions(+), 10 deletions(-) diff --git a/src/cli.ts b/src/cli.ts index c9e1728a2..55dec9df3 100644 --- a/src/cli.ts +++ b/src/cli.ts @@ -94,6 +94,19 @@ function parseCliArgs(argv: string[]): CliFlags { const cliFlags = parseCliArgs(process.argv) const isPrintMode = cliFlags.print || cliFlags.mode !== undefined +// Early TTY check — must come before heavy initialization to avoid dangling +// handles that prevent process.exit() from completing promptly. +const hasSubcommand = cliFlags.messages.length > 0 +if (!process.stdin.isTTY && !isPrintMode && !hasSubcommand && !cliFlags.listModels) { + process.stderr.write('[gsd] Error: Interactive mode requires a terminal (TTY).\n') + process.stderr.write('[gsd] Non-interactive alternatives:\n') + process.stderr.write('[gsd] gsd --print "your message" Single-shot prompt\n') + process.stderr.write('[gsd] gsd --mode rpc JSON-RPC over stdin/stdout\n') + process.stderr.write('[gsd] gsd --mode mcp MCP server over stdin/stdout\n') + process.stderr.write('[gsd] gsd --mode text "message" Text output mode\n') + process.exit(1) +} + // `gsd --help` — show subcommand-specific help const subcommand = cliFlags.messages[0] if (subcommand && process.argv.includes('--help')) { @@ -492,15 +505,5 @@ if (enabledModelPatterns && enabledModelPatterns.length > 0) { } } -if (!process.stdin.isTTY) { - process.stderr.write('[gsd] Error: Interactive mode requires a terminal (TTY).\n') - process.stderr.write('[gsd] Non-interactive alternatives:\n') - process.stderr.write('[gsd] gsd --print "your message" Single-shot prompt\n') - process.stderr.write('[gsd] gsd --mode rpc JSON-RPC over stdin/stdout\n') - process.stderr.write('[gsd] gsd --mode mcp MCP server over stdin/stdout\n') - process.stderr.write('[gsd] gsd --mode text "message" Text output mode\n') - process.exit(1) -} - const interactiveMode = new InteractiveMode(session) await interactiveMode.run()