From ff92c66b64cb902e6faf9cc54f2973a96d29173a Mon Sep 17 00:00:00 2001 From: kaitranntt Date: Thu, 5 Feb 2026 10:24:43 -0500 Subject: [PATCH] fix(doctor): use cmd.exe compatible quoting for Windows shell execution The escapeShellArg function was using PowerShell-style single quotes, but spawn({ shell: true }) uses cmd.exe by default on Windows. cmd.exe does not recognize single quotes as string delimiters, causing 'claude' '--version' to fail. Changed to use double quotes which work correctly in cmd.exe. --- src/utils/shell-executor.ts | 29 +++++++++-------------------- 1 file changed, 9 insertions(+), 20 deletions(-) diff --git a/src/utils/shell-executor.ts b/src/utils/shell-executor.ts index 9ee00511..4718e2e6 100644 --- a/src/utils/shell-executor.ts +++ b/src/utils/shell-executor.ts @@ -9,33 +9,22 @@ import { ErrorManager } from './error-manager'; import { getWebSearchHookEnv } from './websearch-manager'; /** - * Escape arguments for shell execution (Windows compatibility) - * Handles PowerShell special characters: backticks, $variables, double quotes + * Escape arguments for shell execution (cross-platform) + * + * IMPORTANT: On Windows, spawn({ shell: true }) uses cmd.exe by default, + * NOT PowerShell. cmd.exe does NOT recognize single quotes as string delimiters. + * We must use double quotes for cmd.exe compatibility. */ export function escapeShellArg(arg: string): string { const isWindows = process.platform === 'win32'; if (isWindows) { - // PowerShell: Use single quotes for literal strings to prevent variable expansion - // Escape single quotes by doubling them (PowerShell syntax) - // Fallback to double quotes with escapes if single quotes present - if (arg.includes("'")) { - // Contains single quote - use double quotes with escape sequences - return ( - '"' + - String(arg) - .replace(/\$/g, '`$') // Escape $ to prevent variable expansion - .replace(/`/g, '``') // Escape backticks - .replace(/"/g, '`"') + // Escape double quotes - '"' - ); - } else { - // No single quotes - use single quotes for literal string (safest) - return "'" + String(arg) + "'"; - } + // cmd.exe: Use double quotes, escape inner double quotes with backslash + // cmd.exe interprets "" as escaped double quote inside quoted string + return '"' + String(arg).replace(/"/g, '""') + '"'; } else { // Unix/macOS: Double quotes with escaped inner quotes - return '"' + String(arg).replace(/"/g, '""') + '"'; + return '"' + String(arg).replace(/"/g, '\\"') + '"'; } }