From a78cbc39544aeceaaf6d9b90a2edcb1338666053 Mon Sep 17 00:00:00 2001 From: Chris Huber Date: Thu, 7 May 2026 21:11:55 -0400 Subject: [PATCH 1/2] fix(cli): forward signals from npm shim --- packages/opencode/bin/opencode | 36 +++++++++++++++++++++++++++++----- 1 file changed, 31 insertions(+), 5 deletions(-) diff --git a/packages/opencode/bin/opencode b/packages/opencode/bin/opencode index a7674ce2f875..d4eb6aa3c4f6 100755 --- a/packages/opencode/bin/opencode +++ b/packages/opencode/bin/opencode @@ -5,16 +5,42 @@ const fs = require("fs") const path = require("path") const os = require("os") +const forwardedSignals = ["SIGINT", "SIGTERM", "SIGHUP", "SIGQUIT", "SIGUSR1", "SIGUSR2"] + function run(target) { - const result = childProcess.spawnSync(target, process.argv.slice(2), { + const child = childProcess.spawn(target, process.argv.slice(2), { stdio: "inherit", }) - if (result.error) { - console.error(result.error.message) + + child.on("error", (error) => { + console.error(error.message) process.exit(1) + }) + + const forwarders = {} + for (const signal of forwardedSignals) { + forwarders[signal] = () => { + try { + child.kill(signal) + } catch { + // The child may have already exited. + } + } + process.on(signal, forwarders[signal]) } - const code = typeof result.status === "number" ? result.status : 0 - process.exit(code) + + child.on("exit", (code, signal) => { + for (const forwardedSignal of forwardedSignals) { + process.removeListener(forwardedSignal, forwarders[forwardedSignal]) + } + + if (signal) { + process.kill(process.pid, signal) + return + } + + process.exit(typeof code === "number" ? code : 0) + }) } const envPath = process.env.OPENCODE_BIN_PATH From d4a40b2f8cfba48fb0ef280668fb7706d792532c Mon Sep 17 00:00:00 2001 From: Aiden Cline Date: Fri, 8 May 2026 13:54:44 -0500 Subject: [PATCH 2/2] fix(cli): preserve shim target selection Resolve the wrapper target before spawning so async signal forwarding cannot fall through into another binary lookup. Match Codex by forwarding only common termination signals. --- packages/opencode/bin/opencode | 10 ++-------- 1 file changed, 2 insertions(+), 8 deletions(-) diff --git a/packages/opencode/bin/opencode b/packages/opencode/bin/opencode index d4eb6aa3c4f6..a7101f42b0fe 100755 --- a/packages/opencode/bin/opencode +++ b/packages/opencode/bin/opencode @@ -5,7 +5,7 @@ const fs = require("fs") const path = require("path") const os = require("os") -const forwardedSignals = ["SIGINT", "SIGTERM", "SIGHUP", "SIGQUIT", "SIGUSR1", "SIGUSR2"] +const forwardedSignals = ["SIGINT", "SIGTERM", "SIGHUP"] function run(target) { const child = childProcess.spawn(target, process.argv.slice(2), { @@ -44,18 +44,12 @@ function run(target) { } const envPath = process.env.OPENCODE_BIN_PATH -if (envPath) { - run(envPath) -} const scriptPath = fs.realpathSync(__filename) const scriptDir = path.dirname(scriptPath) // const cached = path.join(scriptDir, ".opencode") -if (fs.existsSync(cached)) { - run(cached) -} const platformMap = { darwin: "darwin", @@ -192,7 +186,7 @@ function findBinary(startDir) { } } -const resolved = findBinary(scriptDir) +const resolved = envPath || (fs.existsSync(cached) ? cached : findBinary(scriptDir)) if (!resolved) { console.error( "It seems that your package manager failed to install the right version of the opencode CLI for your platform. You can try manually installing " +