ai-sprint
Version:
AI-powered sprint management and SDLC tracking with automatic IDE integration
229 lines • 7.45 kB
JavaScript
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