feat(detector): add Windows native installer fallback detection

- Check common Windows installation paths when where.exe fails
- Improve error messages with Windows-specific guidance
- Suggest running 'claude install' for native installer users

Closes #447
This commit is contained in:
kaitranntt
2026-02-04 11:06:32 -05:00
parent 2b84322249
commit 3336736154
2 changed files with 66 additions and 8 deletions
+47 -2
View File
@@ -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;
}
+19 -6
View File
@@ -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);