Skip to content
This repository was archived by the owner on Feb 25, 2026. It is now read-only.
Closed
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 9 additions & 2 deletions packages/opencode/src/cli/cmd/tui/thread.ts
Original file line number Diff line number Diff line change
Expand Up @@ -128,11 +128,18 @@ export const TuiThreadCommand = cmd({
await client.call("reload", undefined)
})
// kilocode_change start - graceful shutdown on external signals
let shuttingDown = false
const shutdown = async () => {
if (shuttingDown) return
shuttingDown = true
await client.call("shutdown", undefined).catch(() => {})
}
process.on("SIGHUP", shutdown)
process.on("SIGTERM", shutdown)
process.once("SIGHUP", shutdown)
process.once("SIGTERM", shutdown)
process.once("SIGINT", shutdown)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

WARNING: Handling SIGINT here may conflict with the TUI's own Ctrl+C handling.

The TUI (ink-based) typically intercepts SIGINT to manage its own exit flow (e.g., prompting to confirm exit, cleaning up the terminal). By registering process.once("SIGINT", shutdown) at this level, the signal handler will call client.call("shutdown") immediately when the user presses Ctrl+C, potentially racing with or bypassing the TUI's normal onExit cleanup path (line 188-190).

Consider removing the SIGINT handler and relying on the TUI's existing onExit callback for user-initiated exits. The other signal handlers (SIGHUP, SIGTERM, disconnect, stdin close) are appropriate for external/non-interactive termination scenarios.

Comment on lines +137 to +139
Copy link

Copilot AI Feb 22, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The use of process.once() here is inconsistent with the existing signal handlers in the codebase. The serve and web commands (packages/opencode/src/cli/cmd/serve.ts:28-30 and packages/opencode/src/cli/cmd/web.ts:89-91) use process.on() for SIGTERM, SIGINT, and SIGHUP handlers.

While process.once() is appropriate for this use case due to the shuttingDown guard preventing duplicate shutdowns, this inconsistency may be confusing. Consider documenting why once() is used here versus on() in other commands, or standardizing the approach across all commands.

Suggested change
process.once("SIGHUP", shutdown)
process.once("SIGTERM", shutdown)
process.once("SIGINT", shutdown)
process.on("SIGHUP", shutdown)
process.on("SIGTERM", shutdown)
process.on("SIGINT", shutdown)

Copilot uses AI. Check for mistakes.
process.once("disconnect", shutdown)
process.stdin.once("end", shutdown)
process.stdin.once("close", shutdown)
Comment on lines +141 to +142
Copy link

Copilot AI Feb 22, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The stdin event listeners may cause premature shutdown when stdin is piped. On line 146, Bun.stdin.text() reads stdin completely when !process.stdin.isTTY, which will trigger the "end" event immediately after reading. This means the TUI would shut down right after starting when input is piped.

Consider registering the stdin event handlers only when process.stdin.isTTY is true, or register them after the stdin read at line 146 completes.

Suggested change
process.stdin.once("end", shutdown)
process.stdin.once("close", shutdown)
if (process.stdin.isTTY) {
process.stdin.once("end", shutdown)
process.stdin.once("close", shutdown)
}

Copilot uses AI. Check for mistakes.
// kilocode_change end

const prompt = await iife(async () => {
Expand Down
Loading