Skip to content

OpenCode Desktop starts multiple windows when launched once from a script #7085

Closed

Description

@andrey-golovko

Summary

OpenCode Desktop can start multiple Desktop windows and multiple backend instances
when it is launched once from a script.

This happens without:

  • double-clicking
  • running the script multiple times
  • hotkeys
  • parallel execution

The script starts OpenCode.exe exactly once, yet multiple Desktop windows appear.


Environment

  • OS: Windows 10 / Windows 11
  • OpenCode Desktop: latest Windows build
  • Installation paths:
    %LOCALAPPDATA%\OpenCode\OpenCode.exe
    %LOCALAPPDATA%\OpenCode\opencode-cli.exe
    
  • Launch method:
    • PowerShell script
  • Script execution count:
    • once

Steps to Reproduce (single run)

  1. Create a PowerShell script with a single launch command:

    & "$env:LOCALAPPDATA\OpenCode\OpenCode.exe" "C:\project"
  2. Run the script once from PowerShell.

  3. Observe that multiple OpenCode Desktop windows may open.


Observed Behavior

  • More than one Desktop window is shown.

  • Process list contains multiple instances:

    OpenCode.exe
    OpenCode.exe
    
  • Multiple backend instances are spawned:

    opencode-cli.exe serve --port=64840
    opencode-cli.exe serve --port=64854
    opencode-cli.exe serve --port=64870
    
  • The script itself launches OpenCode.exe only once.


Expected Behavior

  • A single script execution should result in:
    • exactly one Desktop window
    • exactly one backend instance

Analysis / Findings

Investigation shows that OpenCode Desktop appears to re-launch or self-spawn
during startup.

Indicators:

  • Multiple OpenCode.exe processes exist even though the parent script started it once.
  • At least one OpenCode.exe instance has another OpenCode.exe as its parent.
  • Desktop seems to perform an internal restart / re-exec (possibly for setup,
    update, or backend initialization), but the original instance does not exit.

This results in multiple UI windows instead of a clean handoff.


Why This Is a Bug

Even if Desktop needs to restart itself internally:

  • the original instance should exit, or
  • the new instance should take over,

but multiple visible Desktop windows must not remain active.

Single-instance behavior should be enforced inside the application, not in user scripts.


Workaround

Users must implement a global OS-level mutex in their launcher scripts, for example:

$mutex = New-Object System.Threading.Mutex($false, "Global\OpenCodeDesktopSingleton")
if (-not $mutex.WaitOne(0)) { exit }

This workaround prevents the issue, confirming that the problem is related to missing
single-instance protection in Desktop.


Proposed Fix

Implement a single-instance guard inside OpenCode Desktop:

  • Use a global named mutex on Windows (e.g. Global\OpenCodeDesktop)
  • On detecting an existing instance:
    • bring the existing window to foreground
    • exit immediately

This is standard behavior for IDEs and desktop developer tools.


Impact

  • Confusing user experience (multiple windows from one launch)
  • Difficult automation and scripting
  • Backend and MCP duplication
  • Unnecessary resource usage

Additional Notes

  • The issue reproduces without any bootstrap backend.
  • The issue reproduces without proxy configuration.
  • The issue is not caused by user double-clicking or concurrent launches.

Activity

  1. github-actions commented on Jan 6, 2026

    @github-actions
    Contributor

    This issue might be a duplicate of existing issues. Please check:

    Both issues report the same core problem: OpenCode Desktop opening multiple windows on Windows when launched once, due to a missing single-instance guard. The root cause and proposed fix are identical (lacking single-instance protection).

    Feel free to ignore if this doesn't match your specific case.

  2. andrey-golovko commented on Jan 6, 2026

    @andrey-golovko
    Author

    Solution. Remove proxies if you don't need them.

    # OpenCode Desktop bootstrap (single-instance launcher)
    # - global mutex to prevent double-run -> prevents multiple windows
    # - proxy + no_proxy
    # - bootstrap: opencode-cli serve --port 4096 (headless)
    # - start Desktop only once
    # - wait a bit, then kill ONLY bootstrap process tree
    # ============================
    
    Set-StrictMode -Version Latest
    $ErrorActionPreference = "Stop"
    
    $DesktopExe = "$env:LOCALAPPDATA\OpenCode\OpenCode.exe"
    $CliExe     = "$env:LOCALAPPDATA\OpenCode\opencode-cli.exe"
    
    $BootstrapPort = 4096
    $HostName      = "127.0.0.1"
    $ProjectPath   = "C:\Code\sever\crm"
    
    # ---------- Global mutex (critical) ----------
    $mutexName = "Global\OpenCodeDesktopLauncherSingleton"
    $mutex = New-Object System.Threading.Mutex($false, $mutexName)
    
    if (-not $mutex.WaitOne(0, $false)) {
      # another launcher instance is running
      exit 0
    }
    
    try {
      # ---------- sanity ----------
      if (!(Test-Path $DesktopExe)) { throw "OpenCode.exe not found: $DesktopExe" }
      if (!(Test-Path $CliExe))     { throw "opencode-cli.exe not found: $CliExe" }
    
      # ---------- proxy ----------
      $proxy = "http://127.0.0.1:8118"
      $env:HTTP_PROXY  = $proxy
      $env:HTTPS_PROXY = $proxy
      $env:http_proxy  = $proxy
      $env:https_proxy = $proxy
    
      $no = @(
        "localhost",
        "127.0.0.1",
        "tauri.localhost",
        ".localhost",
        "::1",
        "localhost:$BootstrapPort",
        "127.0.0.1:$BootstrapPort",
        "localhost:0",
        "127.0.0.1/8",
        "10.0.0.0/8",
        "172.16.0.0/12",
        "192.168.0.0/16"
      ) -join ","
      $env:NO_PROXY = $no
      $env:no_proxy = $no
    
      function Get-ProcessTree {
        param([int]$RootPid)
        $children = Get-CimInstance Win32_Process | Where-Object { $_.ParentProcessId -eq $RootPid }
        foreach ($c in $children) { $c; Get-ProcessTree -RootPid $c.ProcessId }
      }
    
      # ---------- 1) Start bootstrap serve:4096 (headless, no browser) ----------
      $bootstrap = Get-CimInstance Win32_Process |
        Where-Object {
          $_.Name -eq "opencode-cli.exe" -and
          $_.CommandLine -match "serve\s+--port\s+$BootstrapPort\b"
        } |
        Select-Object -First 1
    
      if (-not $bootstrap) {
        Start-Process -FilePath $CliExe `
          -ArgumentList @("serve","--port",$BootstrapPort,"--hostname",$HostName) `
          -WindowStyle Hidden | Out-Null
      }
    
      # ---------- 2) Start Desktop ONLY if not running ----------
      if (-not (Get-Process -Name "OpenCode" -ErrorAction SilentlyContinue)) {
        Start-Process -FilePath $DesktopExe `
          -ArgumentList @($ProjectPath) `
          -WorkingDirectory (Split-Path $DesktopExe) | Out-Null
      }
    
      # ---------- 3) Give Desktop time to fully start ----------
      Start-Sleep -Seconds 15
    
      # ---------- 4) Kill ONLY bootstrap tree (strict match by port) ----------
      $bootstrap = Get-CimInstance Win32_Process |
        Where-Object {
          $_.Name -eq "opencode-cli.exe" -and
          $_.CommandLine -match "serve\s+--port\s+$BootstrapPort\b"
        } |
        Select-Object -First 1
    
      if ($bootstrap) {
        $tree = @(Get-ProcessTree -RootPid $bootstrap.ProcessId)
    
        foreach ($p in ($tree | Sort-Object ProcessId -Descending)) {
          try { Stop-Process -Id $p.ProcessId -Force -ErrorAction SilentlyContinue } catch {}
        }
        try { Stop-Process -Id $bootstrap.ProcessId -Force -ErrorAction SilentlyContinue } catch {}
      }
    
    } finally {
      try { $mutex.ReleaseMutex() | Out-Null } catch {}
      $mutex.Dispose()
    }
    
  3. umirza-geo commented on Feb 18, 2026

    @umirza-geo

    Hi @andrey-golovko ,
    Your solution didn't work on my Windows machine. FYI

  4. github-actions commented on Apr 20, 2026

    @github-actions
    Contributor

    To stay organized issues are automatically closed after 60 days of no activity. If the issue is still relevant please open a new one.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Labels

webRelates to opencode on web / desktopwindows

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions