UNPKG

ai-sprint

Version:

AI-powered sprint management and SDLC tracking with automatic IDE integration

229 lines 7.45 kB
import { promises as fs } from 'fs'; import path from 'path'; import os from 'os'; export class IDEDetector { homeDir = os.homedir(); projectDir; constructor(projectDir = process.cwd()) { this.projectDir = projectDir; } /** * Detect the current IDE based on environment and file system */ async detect() { // Check for Claude Code if (await this.isClaudeCode()) { return { type: 'claude', name: 'Claude Code', configPath: path.join(this.homeDir, '.claude', 'mcp.json'), commandPath: path.join(this.projectDir, '.claude', 'commands'), features: ['mcp', 'commands', 'ai-native'], configFormat: 'mcpServers' }; } // Check for Cursor if (await this.isCursor()) { return { type: 'cursor', name: 'Cursor', configPath: path.join(this.homeDir, '.cursor', 'mcp.json'), features: ['mcp', 'ai-native'], configFormat: 'mcpServers' }; } // Check for Windsurf if (await this.isWindsurf()) { return { type: 'windsurf', name: 'Windsurf', configPath: path.join(this.homeDir, '.codeium', 'windsurf', 'mcp_config.json'), features: ['mcp', 'ai-native'], configFormat: 'mcpServers' }; } // Check for VS Code if (await this.isVSCode()) { return { type: 'vscode', name: 'Visual Studio Code', configPath: path.join(this.projectDir, '.vscode', 'mcp.json'), features: ['mcp', 'extensions'], configFormat: 'servers' }; } // Default to generic MCP support return { type: 'generic', name: 'Generic MCP IDE', configPath: path.join(this.projectDir, 'mcp.json'), features: ['mcp'], configFormat: 'mcpServers' }; } /** * Get all detected IDEs (for multi-IDE projects) */ async detectAll() { const detected = []; if (await this.isClaudeCode()) { detected.push(await this.getClaudeInfo()); } if (await this.isCursor()) { detected.push(await this.getCursorInfo()); } if (await this.isWindsurf()) { detected.push(await this.getWindsurfInfo()); } if (await this.isVSCode()) { detected.push(await this.getVSCodeInfo()); } return detected; } async isClaudeCode() { // Check for Claude-specific environment variables if (process.env.CLAUDE_CODE || process.env.CLAUDE_IDE || process.env.CLAUDE_DESKTOP || process.env.CLAUDECODE) { return true; } // Check if running in Claude Code by looking for specific process indicators if (process.env.USER_AGENT && process.env.USER_AGENT.includes('Claude')) { return true; } // Check for .claude directory in project try { await fs.access(path.join(this.projectDir, '.claude')); return true; } catch { // Continue checking } // Check for Claude config in home directory try { await fs.access(path.join(this.homeDir, '.claude', 'mcp.json')); return true; } catch { // Continue checking } // Check for Claude Code specific config locations try { await fs.access(path.join(this.homeDir, 'Library', 'Application Support', 'Claude', 'mcp.json')); return true; } catch { // Continue checking } // Check if we're in a Claude Code terminal if (process.env.TERM_PROGRAM === 'Claude' || process.env.TERMINAL_EMULATOR === 'Claude') { return true; } return false; } async isCursor() { // Check for Cursor-specific environment if (process.env.CURSOR_IDE) { return true; } // Check for Cursor config try { await fs.access(path.join(this.homeDir, '.cursor', 'mcp.json')); return true; } catch { return false; } } async isWindsurf() { // Check for Windsurf config try { await fs.access(path.join(this.homeDir, '.codeium', 'windsurf', 'mcp_config.json')); return true; } catch { return false; } } async isVSCode() { // Check for VS Code workspace try { await fs.access(path.join(this.projectDir, '.vscode')); return true; } catch { return false; } } async getClaudeInfo() { // Check multiple possible config locations const possibleConfigPaths = [ path.join(this.homeDir, '.claude', 'mcp.json'), path.join(this.homeDir, 'Library', 'Application Support', 'Claude', 'mcp.json'), ]; let configPath = possibleConfigPaths[0]; // default for (const p of possibleConfigPaths) { try { await fs.access(p); configPath = p; break; } catch { // Continue checking } } return { type: 'claude', name: 'Claude Code', configPath, commandPath: path.join(this.projectDir, '.claude', 'commands'), features: ['mcp', 'commands', 'ai-native'], configFormat: 'mcpServers' }; } async getCursorInfo() { return { type: 'cursor', name: 'Cursor', configPath: path.join(this.homeDir, '.cursor', 'mcp.json'), features: ['mcp', 'ai-native'], configFormat: 'mcpServers' }; } async getWindsurfInfo() { return { type: 'windsurf', name: 'Windsurf', configPath: path.join(this.homeDir, '.codeium', 'windsurf', 'mcp_config.json'), features: ['mcp', 'ai-native'], configFormat: 'mcpServers' }; } async getVSCodeInfo() { return { type: 'vscode', name: 'Visual Studio Code', configPath: path.join(this.projectDir, '.vscode', 'mcp.json'), features: ['mcp', 'extensions'], configFormat: 'servers' }; } /** * Check if an IDE supports command files */ hasCommandSupport(ide) { return ide.features.includes('commands'); } /** * Get the appropriate config file path for an IDE */ getConfigPath(ideType) { const paths = { claude: path.join(this.homeDir, '.claude', 'mcp.json'), cursor: path.join(this.homeDir, '.cursor', 'mcp.json'), windsurf: path.join(this.homeDir, '.codeium', 'windsurf', 'mcp_config.json'), vscode: path.join(this.projectDir, '.vscode', 'mcp.json'), generic: path.join(this.projectDir, 'mcp.json') }; return paths[ideType] || paths.generic; } } //# sourceMappingURL=ide-detector.js.map