diff --git a/src/utils/claude-detector.ts b/src/utils/claude-detector.ts index 02d548c8..8649163a 100644 --- a/src/utils/claude-detector.ts +++ b/src/utils/claude-detector.ts @@ -3,6 +3,42 @@ import { execSync } from 'child_process'; import { expandPath } from './helpers'; import { ClaudeCliInfo } from '../types'; +/** + * Common Windows installation paths for Claude CLI native installer + * These are checked as fallback when 'where.exe claude' fails + */ +const WINDOWS_NATIVE_PATHS = [ + // Native installer locations (Anthropic/Claude branded) + '%LOCALAPPDATA%\\Programs\\Claude\\claude.exe', + '%LOCALAPPDATA%\\AnthropicClaude\\claude.exe', + '%PROGRAMFILES%\\Claude\\claude.exe', + '%PROGRAMFILES%\\Anthropic\\Claude\\claude.exe', + // npm/bun global install locations (already in PATH, but check as fallback) + '%APPDATA%\\npm\\claude.cmd', + '%USERPROFILE%\\.bun\\bin\\claude.exe', +]; + +/** + * Expand Windows environment variables in path + */ +function expandWindowsPath(p: string): string { + return p.replace(/%([^%]+)%/g, (_, name) => process.env[name] || ''); +} + +/** + * Check common Windows installation paths for Claude CLI + * Returns the first valid path found, or null + */ +function findClaudeInWindowsPaths(): string | null { + for (const template of WINDOWS_NATIVE_PATHS) { + const expanded = expandWindowsPath(template); + if (fs.existsSync(expanded)) { + return expanded; + } + } + return null; +} + /** * Detect Claude CLI executable */ @@ -57,10 +93,19 @@ export function detectClaudeCli(): string | null { } } catch (_err) { // Command failed - claude not in PATH - // Fall through to return null + // Fall through to Windows fallback or return null } - // Priority 3: Claude not found + // Priority 3 (Windows only): Check common native installer locations + // This helps users who installed via Windows MSI/EXE but haven't run 'claude install' + if (isWindows) { + const nativePath = findClaudeInWindowsPaths(); + if (nativePath) { + return nativePath; + } + } + + // Priority 4: Claude not found return null; } diff --git a/src/utils/error-manager.ts b/src/utils/error-manager.ts index 65d364b8..6bd8626c 100644 --- a/src/utils/error-manager.ts +++ b/src/utils/error-manager.ts @@ -51,12 +51,25 @@ export class ErrorManager { console.error(' 1. Install Claude CLI'); console.error(` ${color('https://docs.claude.com/install', 'path')}`); console.error(''); - console.error(' 2. Verify installation'); - console.error(` ${color('command -v claude', 'command')} (Unix)`); - console.error(` ${color('Get-Command claude', 'command')} (Windows)`); - console.error(''); - console.error(' 3. Custom path (if installed elsewhere)'); - console.error(` ${color('export CCS_CLAUDE_PATH="/path/to/claude"', 'command')}`); + + // Windows-specific guidance for native installer users + if (process.platform === 'win32') { + console.error(' 2. If you used the Windows installer, run:'); + console.error(` ${color('claude install', 'command')}`); + console.error(dim(' This adds Claude to your PATH')); + console.error(''); + console.error(' 3. Verify installation'); + console.error(` ${color('Get-Command claude', 'command')}`); + console.error(''); + console.error(' 4. Custom path (if installed elsewhere)'); + console.error(` ${color('$env:CCS_CLAUDE_PATH="C:\\path\\to\\claude.exe"', 'command')}`); + } else { + console.error(' 2. Verify installation'); + console.error(` ${color('command -v claude', 'command')}`); + console.error(''); + console.error(' 3. Custom path (if installed elsewhere)'); + console.error(` ${color('export CCS_CLAUDE_PATH="/path/to/claude"', 'command')}`); + } console.error(''); this.showErrorCode(ERROR_CODES.CLAUDE_NOT_FOUND);