Description
When the OpenCode Desktop app prompts the user to "Install and Restart" after detecting an update, it forcefully kills all running opencode.exe processes on the system — including external CLI TUI sessions that were launched independently from the terminal. These CLI sessions are killed without any graceful shutdown, leaving the terminal in a corrupted state with mouse tracking enabled, which floods the prompt with raw escape sequences like ^[[<35;77;46M.
Steps to reproduce
- Open two terminal tabs in Windows Terminal
- Launch
opencode (CLI TUI) in both tabs — confirm they are running
- Launch OpenCode Desktop app
- If an update is available, the Desktop app shows an "Install and Restart" prompt
- Click "Install and Restart"
- Observe: Both CLI TUI sessions are immediately killed
- Observe: The terminal tabs where the CLI was running now show mouse escape sequences spamming the prompt (
^[[<35;77;46M, ^[[<35;62;19M, etc.) and the shell becomes unresponsive
Expected behavior
- The Desktop app should only terminate its own embedded sidecar (
opencode-cli), not external opencode.exe CLI TUI processes
- If external processes must be terminated, they should receive a graceful shutdown signal (SIGTERM) allowing the TUI to restore terminal state (disable mouse tracking, restore cooked mode, etc.)
- Active user sessions should be preserved or the user should be warned before killing them
Actual behavior
- All
opencode.exe processes are forcefully killed (no graceful shutdown)
- Terminal state is left corrupted: mouse tracking remains enabled, raw escape sequences flood the prompt
- The shell in the affected terminal tab may become completely unresponsive, requiring the tab to be closed
- Any active work in the CLI TUI sessions is lost
Technical Analysis
Root cause: The Desktop app's update flow calls killSidecar() (which correctly targets only the embedded sidecar child process) before update.install(). However, update.install() triggers the NSIS installer, which uses nsProcess::KillProcess to terminate the main application binary. Since the Desktop binary is named OpenCode.exe and the CLI binary is named opencode.exe, and nsProcess::KillProcess is case-insensitive on Windows, the NSIS installer matches and kills both OpenCode.exe (Desktop) AND opencode.exe (CLI TUI).
Evidence from source:
packages/desktop/src/updater.ts lines 41-50: The updater only calls commands.killSidecar() for its embedded sidecar
packages/desktop/src-tauri/tauri.conf.json: NSIS config has no custom hooks — relies on Tauri's default NSIS template behavior
packages/desktop/src-tauri/src/cli.rs lines 131-134: install_cli is explicitly disabled on Windows ("CLI installation is only supported on macOS & Linux")
- The TUI has a
win32InstallCtrlCGuard() for clean SIGINT handling, but this is bypassed by NSIS's forceful process termination
Suggested fixes:
- In the NSIS configuration, constrain the process kill to the exact binary name (case-sensitive match) or PID of the Desktop process specifically, rather than matching all
opencode* processes
- Before triggering the NSIS installer, enumerate and gracefully terminate external
opencode.exe processes with a SIGTERM + timeout, allowing them to clean up terminal state
- At minimum, show a confirmation dialog warning the user that other opencode sessions will be closed
Plugins
N/A
OpenCode version
- Desktop:
SST.OpenCodeDesktop 1.14.24 (via winget)
- CLI:
SST.opencode 1.14.22 (via winget)
Operating System
Windows 11
Terminal
Windows Terminal
Related Issues
Description
When the OpenCode Desktop app prompts the user to "Install and Restart" after detecting an update, it forcefully kills all running
opencode.exeprocesses on the system — including external CLI TUI sessions that were launched independently from the terminal. These CLI sessions are killed without any graceful shutdown, leaving the terminal in a corrupted state with mouse tracking enabled, which floods the prompt with raw escape sequences like^[[<35;77;46M.Steps to reproduce
opencode(CLI TUI) in both tabs — confirm they are running^[[<35;77;46M,^[[<35;62;19M, etc.) and the shell becomes unresponsiveExpected behavior
opencode-cli), not externalopencode.exeCLI TUI processesActual behavior
opencode.exeprocesses are forcefully killed (no graceful shutdown)Technical Analysis
Root cause: The Desktop app's update flow calls
killSidecar()(which correctly targets only the embedded sidecar child process) beforeupdate.install(). However,update.install()triggers the NSIS installer, which usesnsProcess::KillProcessto terminate the main application binary. Since the Desktop binary is namedOpenCode.exeand the CLI binary is namedopencode.exe, andnsProcess::KillProcessis case-insensitive on Windows, the NSIS installer matches and kills bothOpenCode.exe(Desktop) ANDopencode.exe(CLI TUI).Evidence from source:
packages/desktop/src/updater.tslines 41-50: The updater only callscommands.killSidecar()for its embedded sidecarpackages/desktop/src-tauri/tauri.conf.json: NSIS config has no custom hooks — relies on Tauri's default NSIS template behaviorpackages/desktop/src-tauri/src/cli.rslines 131-134:install_cliis explicitly disabled on Windows ("CLI installation is only supported on macOS & Linux")win32InstallCtrlCGuard()for clean SIGINT handling, but this is bypassed by NSIS's forceful process terminationSuggested fixes:
opencode*processesopencode.exeprocesses with a SIGTERM + timeout, allowing them to clean up terminal statePlugins
N/A
OpenCode version
SST.OpenCodeDesktop1.14.24 (via winget)SST.opencode1.14.22 (via winget)Operating System
Windows 11
Terminal
Windows Terminal
Related Issues