anomalyco / anomalyco/opencode

[Bug]: "Open in PowerShell" passes the project path as a command on Windows

Open
#40,045 2 comments 0 reactions 1 assignee View on GitHub

@Hona is already working on this.

Since Aug 1, 2026.

Dominant language
TypeScript
Stars
209k
Forks
27.5k
PR merge metrics
PR metrics pending

Description

Description

[Bug]: "Open in PowerShell" passes the project path as a command on Windows

Describe the bug

On Windows, selecting Open in PowerShell from the project picker or session header fails instead of opening a PowerShell window in the selected project directory.

The error is similar to:

Error invoking remote method 'open-path': Error: Command failed:
C:\Windows\System32\WindowsPowerShell\v1.0\powershell.exe C:\path\to\project

C:\path\to\project : The term 'C:\path\to\project' is not recognized
as the name of a cmdlet, function, script file, or operable program.

CategoryInfo          : ObjectNotFound
FullyQualifiedErrorId : CommandNotFoundException

Steps to reproduce

  1. Open OpenCode Desktop on Windows.
  2. Open a project, for example C:\path\to\project.
  3. Select Open in PowerShell from the project or session menu.
  4. Observe that OpenCode reports a CommandNotFoundException instead of opening PowerShell.

Expected behavior

A new PowerShell window should open with its working directory set to the selected project directory.

Environment

  • OpenCode Desktop: 1.18.10, Windows x64
  • Operating system: Windows 11 x64
  • PowerShell: Windows PowerShell 5.1

Related history

This is the same issue as #15111, which was fixed by #15112 for the Tauri-based desktop build (packages/desktop/src-tauri, a Rust open_in_powershell command using CREATE_NEW_CONSOLE). The Electron-based desktop build shipped in 1.18.10 still runs the generic open-path handler below and remains affected.

Root cause

The open-path IPC handler in packages/desktop/src/main/ipc.ts uses the following generic non-macOS behavior:

const [cmd, args] =
  process.platform === "darwin"
    ? (["open", ["-a", app, path]] as const)
    : ([app, [path]] as const)

execFile(cmd, args, ...)

On Windows, selecting PowerShell therefore executes the equivalent of:

powershell.exe C:\path\to\project

PowerShell interprets the positional path argument as a command or script to execute. It does not interpret it as the desired working directory, resulting in CommandNotFoundException.

Suggested direction

PowerShell should use a dedicated Windows launch path rather than the generic application + directory argument behavior.

The implementation should:

  • launch PowerShell in a separate interactive console window;
  • set the selected project as its working directory;
  • support both powershell.exe and pwsh.exe where applicable;
  • avoid interpolating an unescaped project path through multiple command parsers;
  • surface an error when the Windows launcher process itself cannot be created.

Using cmd.exe /c start may be a practical way to create the console window, but the implementation should account for both CMD and PowerShell quoting rules.

A minimal Electron-side fix that works in practice:

diff --git a/packages/desktop/src/main/ipc.ts b/packages/desktop/src/main/ipc.ts
index 1103401c49..27c7d06fd0 100644
--- a/packages/desktop/src/main/ipc.ts
+++ b/packages/desktop/src/main/ipc.ts
@@ -1,4 +1,4 @@
-import { execFile } from "node:child_process"
+import { execFile, spawn } from "node:child_process"
 import { stat } from "node:fs/promises"
 import { basename } from "node:path"
 import { app, BrowserWindow, Notification, clipboard, dialog, ipcMain, shell } from "electron"
@@ -179,6 +179,12 @@ export function registerIpcHandlers(deps: Deps) {
 
   ipcMain.handle("open-path", async (_event: IpcMainInvokeEvent, path: string, app?: string) => {
     if (!app) return shell.openPath(path)
+
+    if (process.platform === "win32") {
+      await openWindowsApp(app, path)
+      return
+    }
+
     await new Promise<void>((resolve, reject) => {
       const [cmd, args] =
         process.platform === "darwin" ? (["open", ["-a", app, path]] as const) : ([app, [path]] as const)
@@ -265,6 +271,26 @@ export function sendMenuCommand(win: BrowserWindow, id: string) {
   win.webContents.send("menu-command", id)
 }
 
+async function openWindowsApp(appPath: string, targetPath: string) {
+  const executable = basename(appPath).toLowerCase()
+  const isPowerShell = ["powershell", "powershell.exe", "pwsh", "pwsh.exe"].includes(executable)
+  const launch = isPowerShell
+    ? {
+        cmd: "cmd.exe",
+        args: ["/d", "/c", "start", "", appPath, "-NoExit", "-Command", `Set-Location -LiteralPath '${targetPath.replace(/'/g, "''")}'`],
+      }
+    : { cmd: appPath, args: [targetPath] }
+
+  await new Promise<void>((resolve, reject) => {
+    const child = spawn(launch.cmd, launch.args, { stdio: "ignore", windowsHide: false })
+    child.once("error", reject)
+    child.once("spawn", () => {
+      child.unref()
+      resolve()
+    })
+  })
+}
+
 export function sendDeepLinks(win: BrowserWindow, urls: string[]) {
   win.webContents.send("deep-link", urls)
 }

Notes on the approach:

  • In the tested Electron/Node runtime, spawn(..., { detached: true }) maps to DETACHED_PROCESS — the child gets no visible console window, so PowerShell never becomes visible.
  • spawn(powershell.exe, ...) without detached inherits no console from the Electron (GUI) parent and the conhost window comes up with a "blocked" icon.
  • cmd.exe /d /c start "" powershell.exe ... is the standard Windows way to spawn a console app in its own new console window (/d disables AutoRun scripts).
  • The targetPath.replace(/'/g, "''") escapes single quotes for PowerShell's -Command.
  • Since the path passes through cmd.exe inside -Command, a path containing a pair of % characters (e.g. C:\Projects\%TEMP%\demo) can be expanded by CMD as an environment variable. A more robust implementation could avoid CMD parsing of the path entirely by passing the script as a Base64 -EncodedCommand argument.
  • Non-PowerShell GUI applications on Windows retain the existing behavior of receiving the target path as an argument.

Suggested test cases

The launcher should be verified with project paths containing:

C:\Projects\simple
C:\Projects\path with spaces
C:\Projects\owner's project
C:\Projects\中文项目
C:\Projects\100% complete
C:\Projects\research & development
C:\Projects\%TEMP%\demo

It should also be tested with:

  • a full powershell.exe path;
  • a bare powershell command;
  • PowerShell 7 pwsh.exe;
  • failure to create the Windows launcher process;
  • an invalid or deleted project directory.
Plugins

No response

OpenCode version

1.18.10

Steps to reproduce
  1. Open OpenCode Desktop on Windows.
  2. Open a project, for example C:\path\to\project.
  3. Select Open in PowerShell from the project picker or session header.
  4. Observe that OpenCode reports a CommandNotFoundException instead of opening a PowerShell window in the selected project directory.
Screenshot and/or share link

No response

Operating System

Windows 11 x64

Terminal

Windows PowerShell 5.1

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.