fix(ui): launch a CODEGRAPH_BROWSER override through cmd on Windows

CreateProcess — which node's spawn uses without a shell — only launches a real
.exe, so a `.cmd`/`.bat` browser shim (how most Windows wrappers are written)
silently launched nothing. Routing the override through `cmd /c`, the way the
default `start` opener already goes, makes .exe, .cmd and .bat all work and
keeps node's per-argument quoting so a path with spaces survives.

Caught on the Windows VM.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
Colby McHenry
2026-08-26 16:20:54 -05:00
co-authored by Claude Opus 5
parent 0196c2e53a
commit bcfe52efa5
2 changed files with 14 additions and 0 deletions
+6
View File
@@ -523,6 +523,12 @@ describe('browserOpenCommand', () => {
command: 'firefox',
args: ['http://x'],
});
// Windows routes the override through cmd so a `.cmd`/`.bat` shim — which
// CreateProcess cannot launch directly — still works.
expect(browserOpenCommand('http://x', 'win32', 'C:\\tools\\open.cmd')).toEqual({
command: 'cmd',
args: ['/c', 'C:\\tools\\open.cmd', 'http://x'],
});
for (const off of ['none', 'NONE', '0', 'false', 'off', '', ' ']) {
expect(browserOpenCommand('http://x', 'darwin', off), off).toBeNull();
}
+8
View File
@@ -32,6 +32,14 @@ export function browserOpenCommand(
if (override !== undefined) {
const trimmed = override.trim();
if (SUPPRESS_VALUES.has(trimmed.toLowerCase())) return null;
// Windows: go through `cmd /c` rather than spawning the override directly.
// `spawn` there is CreateProcess, which only ever launches a real .exe — a
// `.cmd`/`.bat` browser shim (how most Windows wrappers are written) fails
// outright, and an extension-less name only resolves because CreateProcess
// appends `.exe`. Routing through cmd makes .exe, .cmd and .bat all work,
// and node quotes each argument, so a path with spaces survives. Caught on
// the Windows VM, where the direct spawn silently launched nothing.
if (platform === 'win32') return { command: 'cmd', args: ['/c', trimmed, url] };
return { command: trimmed, args: [url] };
}
if (platform === 'darwin') return { command: 'open', args: [url] };