UNPKG

claude-flow

Version:

Enterprise-grade AI agent orchestration with ruv-swarm integration (Alpha Release)

1,200 lines (1,021 loc) • 45.9 kB
// init/index.js - Initialize Claude Code integration files import { printSuccess, printError, printWarning } from '../../utils.js'; import { Deno, cwd, exit, existsSync } from '../../node-compat.js'; import process from 'process'; import { createLocalExecutable } from './executable-wrapper.js'; import { createSparcStructureManually } from './sparc-structure.js'; import { createClaudeSlashCommands } from './claude-commands/slash-commands.js'; import { createOptimizedClaudeSlashCommands } from './claude-commands/optimized-slash-commands.js'; import { execSync } from 'child_process'; import { promises as fs } from 'fs'; import { createSparcClaudeMd, createFullClaudeMd, createMinimalClaudeMd, createOptimizedSparcClaudeMd } from './templates/claude-md.js'; import { createFullMemoryBankMd, createMinimalMemoryBankMd, createOptimizedMemoryBankMd } from './templates/memory-bank-md.js'; import { createFullCoordinationMd, createMinimalCoordinationMd, createOptimizedCoordinationMd } from './templates/coordination-md.js'; import { createAgentsReadme, createSessionsReadme } from './templates/readme-files.js'; import { createSparcModeTemplates, createSparcModesOverview, createSwarmStrategyTemplates } from './templates/sparc-modes.js'; import { showInitHelp } from './help.js'; import { batchInitCommand, batchInitFromConfig, validateBatchOptions } from './batch-init.js'; import { ValidationSystem, runFullValidation } from './validation/index.js'; import { RollbackSystem, createAtomicOperation } from './rollback/index.js'; import { createEnhancedClaudeMd, createEnhancedSettingsJson, createWrapperScript, createCommandDoc, createHelperScript, COMMAND_STRUCTURE } from './templates/enhanced-templates.js'; import { getIsolatedNpxEnv } from '../../../utils/npx-isolated-cache.js'; /** * Check if Claude Code CLI is installed */ function isClaudeCodeInstalled() { try { execSync('which claude', { stdio: 'ignore' }); return true; } catch { return false; } } /** * Set up MCP servers in Claude Code */ async function setupMcpServers(dryRun = false) { console.log('\nšŸ”Œ Setting up MCP servers for Claude Code...'); const servers = [ { name: 'claude-flow', command: 'npx claude-flow@alpha mcp start', description: 'Claude Flow MCP server with swarm orchestration (alpha)' }, { name: 'ruv-swarm', command: 'npx ruv-swarm mcp start', description: 'ruv-swarm MCP server for enhanced coordination' } ]; for (const server of servers) { try { if (!dryRun) { console.log(` šŸ”„ Adding ${server.name}...`); execSync(`claude mcp add ${server.name} ${server.command}`, { stdio: 'inherit' }); console.log(` āœ… Added ${server.name} - ${server.description}`); } else { console.log(` [DRY RUN] Would add ${server.name} - ${server.description}`); } } catch (err) { console.log(` āš ļø Failed to add ${server.name}: ${err.message}`); console.log(` You can add it manually with: claude mcp add ${server.name} ${server.command}`); } } if (!dryRun) { console.log('\n šŸ“‹ Verifying MCP servers...'); try { execSync('claude mcp list', { stdio: 'inherit' }); } catch (err) { console.log(' āš ļø Could not verify MCP servers'); } } } export async function initCommand(subArgs, flags) { // Show help if requested if (flags.help || flags.h || subArgs.includes('--help') || subArgs.includes('-h')) { showInitHelp(); return; } // Default to enhanced Claude Flow v2 init // Use --basic flag for old behavior if (!flags.basic && !flags.minimal && !flags.sparc) { return await enhancedClaudeFlowInit(flags, subArgs); } // Check for validation and rollback commands if (subArgs.includes('--validate') || subArgs.includes('--validate-only')) { return handleValidationCommand(subArgs, flags); } if (subArgs.includes('--rollback')) { return handleRollbackCommand(subArgs, flags); } if (subArgs.includes('--list-backups')) { return handleListBackups(subArgs, flags); } // Check for batch operations const batchInitFlag = flags['batch-init'] || subArgs.includes('--batch-init'); const configFlag = flags.config || subArgs.includes('--config'); if (batchInitFlag || configFlag) { return handleBatchInit(subArgs, flags); } // Check if enhanced initialization is requested const useEnhanced = subArgs.includes('--enhanced') || subArgs.includes('--safe'); if (useEnhanced) { return enhancedInitCommand(subArgs, flags); } // Parse init options const initForce = subArgs.includes('--force') || subArgs.includes('-f') || flags.force; const initMinimal = subArgs.includes('--minimal') || subArgs.includes('-m') || flags.minimal; const initSparc = subArgs.includes('--sparc') || subArgs.includes('-s') || flags.sparc; const initDryRun = subArgs.includes('--dry-run') || subArgs.includes('-d') || flags.dryRun; const initOptimized = initSparc && initForce; // Use optimized templates when both flags are present const selectedModes = flags.modes ? flags.modes.split(',') : null; // Support selective mode initialization // Get the actual working directory (where the command was run from) // Use PWD environment variable which preserves the original directory const workingDir = process.env.PWD || cwd(); console.log(`šŸ“ Initializing in: ${workingDir}`); // Change to the working directory to ensure all file operations happen there try { process.chdir(workingDir); } catch (err) { printWarning(`Could not change to directory ${workingDir}: ${err.message}`); } try { printSuccess('Initializing Claude Code integration files...'); // Check if files already exist in the working directory const files = ['CLAUDE.md', 'memory-bank.md', 'coordination.md']; const existingFiles = []; for (const file of files) { try { await Deno.stat(`${workingDir}/${file}`); existingFiles.push(file); } catch { // File doesn't exist, which is what we want } } if (existingFiles.length > 0 && !initForce) { printWarning(`The following files already exist: ${existingFiles.join(', ')}`); console.log('Use --force to overwrite existing files'); return; } // Create CLAUDE.md const claudeMd = initOptimized ? await createOptimizedSparcClaudeMd() : initSparc ? createSparcClaudeMd() : initMinimal ? createMinimalClaudeMd() : createFullClaudeMd(); if (!initDryRun) { await Deno.writeTextFile('CLAUDE.md', claudeMd); console.log(` āœ“ Created CLAUDE.md${initOptimized ? ' (Batchtools-optimized SPARC)' : initSparc ? ' (SPARC-enhanced)' : ''}`); } else { console.log(` [DRY RUN] Would create CLAUDE.md${initOptimized ? ' (Batchtools-optimized SPARC)' : initSparc ? ' (SPARC-enhanced)' : ''}`); } // Create memory-bank.md const memoryBankMd = initOptimized ? await createOptimizedMemoryBankMd() : initMinimal ? createMinimalMemoryBankMd() : createFullMemoryBankMd(); if (!initDryRun) { await Deno.writeTextFile('memory-bank.md', memoryBankMd); console.log(' āœ“ Created memory-bank.md' + (initOptimized ? ' (Optimized for parallel operations)' : '')); } else { console.log(' [DRY RUN] Would create memory-bank.md' + (initOptimized ? ' (Optimized for parallel operations)' : '')); } // Create coordination.md const coordinationMd = initOptimized ? await createOptimizedCoordinationMd() : initMinimal ? createMinimalCoordinationMd() : createFullCoordinationMd(); if (!initDryRun) { await Deno.writeTextFile('coordination.md', coordinationMd); console.log(' āœ“ Created coordination.md' + (initOptimized ? ' (Enhanced with batchtools)' : '')); } else { console.log(' [DRY RUN] Would create coordination.md' + (initOptimized ? ' (Enhanced with batchtools)' : '')); } // Create directory structure const directories = [ 'memory', 'memory/agents', 'memory/sessions', 'coordination', 'coordination/memory_bank', 'coordination/subtasks', 'coordination/orchestration', '.claude', '.claude/commands', '.claude/commands/sparc', '.claude/commands/swarm', '.claude/logs', '.swarm' // Add .swarm directory for memory persistence (matching hive-mind pattern) ]; for (const dir of directories) { try { if (!initDryRun) { await Deno.mkdir(dir, { recursive: true }); console.log(` āœ“ Created ${dir}/ directory`); } else { console.log(` [DRY RUN] Would create ${dir}/ directory`); } } catch (err) { if (err.code !== 'EEXIST') { throw err; } } } // Create SPARC command files if --sparc flag is used if (initSparc && !initDryRun) { try { const sparcTargetDir = `${workingDir}/.claude/commands/sparc`; // Get SPARC mode templates const sparcTemplates = createSparcModeTemplates(); console.log(' šŸ“ Creating SPARC command files...'); for (const [filename, content] of Object.entries(sparcTemplates)) { try { await Deno.writeTextFile(`${sparcTargetDir}/${filename}`, content); console.log(` āœ“ Created ${filename}`); } catch (err) { console.log(` āš ļø Could not create ${filename}: ${err.message}`); } } // Also create sparc-modes.md overview file const sparcModesOverview = createSparcModesOverview(); await Deno.writeTextFile(`${sparcTargetDir}/sparc-modes.md`, sparcModesOverview); console.log(` āœ“ Created sparc-modes.md`); console.log(' āœ… SPARC command files created successfully'); } catch (err) { console.log(` āš ļø Could not create SPARC files: ${err.message}`); } // Also create swarm strategy files try { const swarmTargetDir = `${workingDir}/.claude/commands/swarm`; // Get swarm strategy templates const swarmTemplates = createSwarmStrategyTemplates(); console.log(' šŸ“ Creating swarm strategy files...'); for (const [filename, content] of Object.entries(swarmTemplates)) { try { await Deno.writeTextFile(`${swarmTargetDir}/${filename}`, content); console.log(` āœ“ Created ${filename}`); } catch (err) { console.log(` āš ļø Could not create ${filename}: ${err.message}`); } } console.log(' āœ… Swarm strategy files created successfully'); } catch (err) { console.log(` āš ļø Could not create swarm files: ${err.message}`); } // Create .claude/config.json try { const configContent = { "version": "1.0", "sparc": { "enabled": true, "modes": ["orchestrator", "coder", "researcher", "tdd", "architect", "reviewer", "debugger", "tester", "analyzer", "optimizer", "documenter", "designer", "innovator", "swarm-coordinator", "memory-manager", "batch-executor", "workflow-manager"] }, "swarm": { "enabled": true, "strategies": ["research", "development", "analysis", "testing", "optimization", "maintenance"] } }; await Deno.writeTextFile(`${workingDir}/.claude/config.json`, JSON.stringify(configContent, null, 2)); console.log(' āœ“ Created .claude/config.json'); } catch (err) { console.log(` āš ļø Could not create config.json: ${err.message}`); } } // Create placeholder files for memory directories const agentsReadme = createAgentsReadme(); if (!initDryRun) { await Deno.writeTextFile('memory/agents/README.md', agentsReadme); console.log(' āœ“ Created memory/agents/README.md'); } else { console.log(' [DRY RUN] Would create memory/agents/README.md'); } const sessionsReadme = createSessionsReadme(); if (!initDryRun) { await Deno.writeTextFile('memory/sessions/README.md', sessionsReadme); console.log(' āœ“ Created memory/sessions/README.md'); } else { console.log(' [DRY RUN] Would create memory/sessions/README.md'); } // Initialize persistence database const initialData = { agents: [], tasks: [], lastUpdated: Date.now() }; if (!initDryRun) { await Deno.writeTextFile('memory/claude-flow-data.json', JSON.stringify(initialData, null, 2)); console.log(' āœ“ Created memory/claude-flow-data.json (persistence database)'); } else { console.log(' [DRY RUN] Would create memory/claude-flow-data.json (persistence database)'); } // Create local claude-flow executable wrapper if (!initDryRun) { await createLocalExecutable(workingDir); } else { console.log(' [DRY RUN] Would create local claude-flow executable wrapper'); } // SPARC initialization if (initSparc) { console.log('\nšŸš€ Initializing SPARC development environment...'); if (initDryRun) { console.log(' [DRY RUN] Would run: npx -y create-sparc init --force'); console.log(' [DRY RUN] Would create SPARC environment with all modes'); console.log(' [DRY RUN] Would create Claude slash commands' + (initOptimized ? ' (Batchtools-optimized)' : '')); if (selectedModes) { console.log(` [DRY RUN] Would create commands for selected modes: ${selectedModes.join(', ')}`); } } else { // Check if create-sparc exists and run it let sparcInitialized = false; try { // Use isolated NPX cache to prevent concurrent conflicts const createSparcCommand = new Deno.Command('npx', { args: ['-y', 'create-sparc', 'init', '--force'], cwd: workingDir, // Use the original working directory stdout: 'inherit', stderr: 'inherit', env: getIsolatedNpxEnv({ PWD: workingDir, // Ensure PWD is set correctly }), }); console.log(' šŸ”„ Running: npx -y create-sparc init --force'); const createSparcResult = await createSparcCommand.output(); if (createSparcResult.success) { console.log(' āœ… SPARC environment initialized successfully'); sparcInitialized = true; } else { printWarning('create-sparc failed, creating basic SPARC structure manually...'); // Fallback: create basic SPARC structure manually await createSparcStructureManually(); sparcInitialized = true; // Manual creation still counts as initialized } } catch (err) { printWarning('create-sparc not available, creating basic SPARC structure manually...'); // Fallback: create basic SPARC structure manually await createSparcStructureManually(); sparcInitialized = true; // Manual creation still counts as initialized } // Always create Claude slash commands after SPARC initialization if (sparcInitialized) { try { if (initOptimized) { await createOptimizedClaudeSlashCommands(workingDir, selectedModes); } else { await createClaudeSlashCommands(workingDir); } } catch (err) { printWarning(`Could not create Claude Code slash commands: ${err.message}`); } } } } if (initDryRun) { printSuccess('šŸ” Dry run completed! Here\'s what would be created:'); console.log('\nšŸ“‹ Summary of planned initialization:'); console.log(` • Configuration: ${initOptimized ? 'Batchtools-optimized SPARC' : initSparc ? 'SPARC-enhanced' : 'Standard'}`); console.log(` • Template type: ${initOptimized ? 'Optimized for parallel processing' : 'Standard'}`); console.log(' • Core files: CLAUDE.md, memory-bank.md, coordination.md'); console.log(' • Directory structure: memory/, coordination/, .claude/'); console.log(' • Local executable: ./claude-flow'); if (initSparc) { console.log(` • Claude Code slash commands: ${selectedModes ? selectedModes.length : 'All'} SPARC mode commands`); console.log(' • SPARC environment with all development modes'); } if (initOptimized) { console.log(' • Batchtools optimization: Enabled for parallel processing'); console.log(' • Performance enhancements: Smart batching, concurrent operations'); } console.log('\nšŸš€ To proceed with initialization, run the same command without --dry-run'); } else { printSuccess('šŸŽ‰ Claude Code integration files initialized successfully!'); if (initOptimized) { console.log('\n⚔ Batchtools Optimization Enabled!'); console.log(' • Parallel processing capabilities activated'); console.log(' • Performance improvements: 250-500% faster operations'); console.log(' • Smart batching and concurrent operations available'); } console.log('\nšŸ“‹ What was created:'); console.log(` āœ… CLAUDE.md (${initOptimized ? 'Batchtools-optimized' : initSparc ? 'SPARC-enhanced' : 'Standard configuration'})`); console.log(` āœ… memory-bank.md (${initOptimized ? 'With parallel processing' : 'Standard memory system'})`); console.log(` āœ… coordination.md (${initOptimized ? 'Enhanced with batchtools' : 'Standard coordination'})`); console.log(' āœ… Directory structure with memory/ and coordination/'); console.log(' āœ… Local executable at ./claude-flow'); console.log(' āœ… Persistence database at memory/claude-flow-data.json'); if (initSparc) { const modeCount = selectedModes ? selectedModes.length : '20+'; console.log(` āœ… Claude Code slash commands (${modeCount} SPARC modes)`); console.log(' āœ… Complete SPARC development environment'); } console.log('\nšŸš€ Next steps:'); console.log('1. Review and customize the generated files for your project'); console.log('2. Run \'./claude-flow start\' to begin the orchestration system'); console.log('3. Use \'./claude-flow\' instead of \'npx claude-flow\' for all commands'); console.log('4. Use \'claude --dangerously-skip-permissions\' for unattended operation'); if (initSparc) { console.log('5. Use Claude Code slash commands: /sparc, /sparc-architect, /sparc-tdd, etc.'); console.log('6. Explore SPARC modes with \'./claude-flow sparc modes\''); console.log('7. Try TDD workflow with \'./claude-flow sparc tdd "your task"\''); if (initOptimized) { console.log('8. Use batchtools commands: /batchtools, /performance for optimization'); console.log('9. Enable parallel processing with --parallel flags'); console.log('10. Monitor performance with \'./claude-flow performance monitor\''); } } console.log('\nšŸ’” Tips:'); console.log(' • Type \'/\' in Claude Code to see all available slash commands'); console.log(' • Use \'./claude-flow status\' to check system health'); console.log(' • Store important context with \'./claude-flow memory store\''); if (initOptimized) { console.log(' • Use --parallel flags for concurrent operations'); console.log(' • Enable batch processing for multiple related tasks'); console.log(' • Monitor performance with real-time metrics'); } // Check for Claude Code and set up MCP servers (always enabled by default) if (!initDryRun && isClaudeCodeInstalled()) { console.log('\nšŸ” Claude Code CLI detected!'); const skipMcp = subArgs && subArgs.includes && subArgs.includes('--skip-mcp'); if (!skipMcp) { await setupMcpServers(initDryRun); } else { console.log(' ā„¹ļø Skipping MCP setup (--skip-mcp flag used)'); } } else if (!initDryRun && !isClaudeCodeInstalled()) { console.log('\nāš ļø Claude Code CLI not detected!'); console.log(' šŸ“„ Install with: npm install -g @anthropic-ai/claude-code'); console.log(' šŸ“‹ Then add MCP servers manually with:'); console.log(' claude mcp add claude-flow claude-flow mcp start'); console.log(' claude mcp add ruv-swarm npx ruv-swarm mcp start'); } } } catch (err) { printError(`Failed to initialize files: ${err.message}`); } } // Handle batch initialization async function handleBatchInit(subArgs, flags) { try { // Options parsing from flags and subArgs const options = { parallel: !flags['no-parallel'] && flags.parallel !== false, sparc: flags.sparc || flags.s, minimal: flags.minimal || flags.m, force: flags.force || flags.f, maxConcurrency: flags['max-concurrent'] || 5, progressTracking: true, template: flags.template, environments: flags.environments ? flags.environments.split(',').map(env => env.trim()) : ['dev'] }; // Validate options const validationErrors = validateBatchOptions(options); if (validationErrors.length > 0) { printError('Batch options validation failed:'); validationErrors.forEach(error => console.error(` - ${error}`)); return; } // Config file mode if (flags.config) { const configFile = flags.config; printSuccess(`Loading batch configuration from: ${configFile}`); const results = await batchInitFromConfig(configFile, options); if (results) { printSuccess('Batch initialization from config completed'); } return; } // Batch init mode if (flags['batch-init']) { const projectsString = flags['batch-init']; const projects = projectsString.split(',').map(project => project.trim()); if (projects.length === 0) { printError('No projects specified for batch initialization'); return; } printSuccess(`Initializing ${projects.length} projects in batch mode`); const results = await batchInitCommand(projects, options); if (results) { const successful = results.filter(r => r.success).length; const failed = results.filter(r => !r.success).length; if (failed === 0) { printSuccess(`All ${successful} projects initialized successfully`); } else { printWarning(`${successful} projects succeeded, ${failed} failed`); } } return; } printError('No batch operation specified. Use --batch-init <projects> or --config <file>'); } catch (err) { printError(`Batch initialization failed: ${err.message}`); } } /** * Enhanced initialization command with validation and rollback */ async function enhancedInitCommand(subArgs, flags) { console.log('šŸ›”ļø Starting enhanced initialization with validation and rollback...'); // Store parameters to avoid scope issues in async context const args = subArgs || []; const options = flags || {}; // Get the working directory const workingDir = Deno.env.get('PWD') || Deno.cwd(); // Initialize systems const rollbackSystem = new RollbackSystem(workingDir); const validationSystem = new ValidationSystem(workingDir); let atomicOp = null; try { // Parse options const initOptions = { force: args.includes('--force') || args.includes('-f') || options.force, minimal: args.includes('--minimal') || args.includes('-m') || options.minimal, sparc: args.includes('--sparc') || args.includes('-s') || options.sparc, skipPreValidation: args.includes('--skip-pre-validation'), skipBackup: args.includes('--skip-backup'), validateOnly: args.includes('--validate-only') }; // Phase 1: Pre-initialization validation if (!initOptions.skipPreValidation) { console.log('\nšŸ” Phase 1: Pre-initialization validation...'); const preValidation = await validationSystem.validatePreInit(initOptions); if (!preValidation.success) { printError('Pre-initialization validation failed:'); preValidation.errors.forEach(error => console.error(` āŒ ${error}`)); return; } if (preValidation.warnings.length > 0) { printWarning('Pre-initialization warnings:'); preValidation.warnings.forEach(warning => console.warn(` āš ļø ${warning}`)); } printSuccess('Pre-initialization validation passed'); } // Stop here if validation-only mode if (options.validateOnly) { console.log('\nāœ… Validation-only mode completed'); return; } // Phase 2: Create backup if (!options.skipBackup) { console.log('\nšŸ’¾ Phase 2: Creating backup...'); const backupResult = await rollbackSystem.createPreInitBackup(); if (!backupResult.success) { printError('Backup creation failed:'); backupResult.errors.forEach(error => console.error(` āŒ ${error}`)); return; } } // Phase 3: Initialize with atomic operations console.log('\nšŸ”§ Phase 3: Atomic initialization...'); atomicOp = createAtomicOperation(rollbackSystem, 'enhanced-init'); const atomicBegin = await atomicOp.begin(); if (!atomicBegin) { printError('Failed to begin atomic operation'); return; } // Perform initialization steps with checkpoints await performInitializationWithCheckpoints(rollbackSystem, options, workingDir, dryRun); // Phase 4: Post-initialization validation console.log('\nāœ… Phase 4: Post-initialization validation...'); const postValidation = await validationSystem.validatePostInit(); if (!postValidation.success) { printError('Post-initialization validation failed:'); postValidation.errors.forEach(error => console.error(` āŒ ${error}`)); // Attempt automatic rollback console.log('\nšŸ”„ Attempting automatic rollback...'); await atomicOp.rollback(); printWarning('Initialization rolled back due to validation failure'); return; } // Phase 5: Configuration validation console.log('\nšŸ”§ Phase 5: Configuration validation...'); const configValidation = await validationSystem.validateConfiguration(); if (configValidation.warnings.length > 0) { printWarning('Configuration warnings:'); configValidation.warnings.forEach(warning => console.warn(` āš ļø ${warning}`)); } // Phase 6: Health checks console.log('\nšŸ„ Phase 6: System health checks...'); const healthChecks = await validationSystem.runHealthChecks(); if (healthChecks.warnings.length > 0) { printWarning('Health check warnings:'); healthChecks.warnings.forEach(warning => console.warn(` āš ļø ${warning}`)); } // Commit atomic operation await atomicOp.commit(); // Generate and display validation report const fullValidation = await runFullValidation(workingDir, { postInit: true, skipPreInit: options.skipPreValidation }); console.log('\nšŸ“Š Validation Report:'); console.log(fullValidation.report); printSuccess('šŸŽ‰ Enhanced initialization completed successfully!'); console.log('\n✨ Your SPARC environment is fully validated and ready to use'); } catch (error) { printError(`Enhanced initialization failed: ${error.message}`); // Attempt rollback if atomic operation is active if (atomicOp && !atomicOp.completed) { console.log('\nšŸ”„ Performing emergency rollback...'); try { await atomicOp.rollback(); printWarning('Emergency rollback completed'); } catch (rollbackError) { printError(`Rollback also failed: ${rollbackError.message}`); } } } } /** * Handle validation commands */ async function handleValidationCommand(subArgs, flags) { const workingDir = Deno.env.get('PWD') || Deno.cwd(); console.log('šŸ” Running validation checks...'); const options = { skipPreInit: subArgs.includes('--skip-pre-init'), skipConfig: subArgs.includes('--skip-config'), skipModeTest: subArgs.includes('--skip-mode-test'), postInit: !subArgs.includes('--pre-init-only') }; try { const validationResults = await runFullValidation(workingDir, options); console.log('\nšŸ“Š Validation Results:'); console.log(validationResults.report); if (validationResults.success) { printSuccess('āœ… All validation checks passed'); } else { printError('āŒ Some validation checks failed'); process.exit(1); } } catch (error) { printError(`Validation failed: ${error.message}`); process.exit(1); } } /** * Handle rollback commands */ async function handleRollbackCommand(subArgs, flags) { const workingDir = Deno.env.get('PWD') || Deno.cwd(); const rollbackSystem = new RollbackSystem(workingDir); try { // Check for specific rollback options if (subArgs.includes('--full')) { console.log('šŸ”„ Performing full rollback...'); const result = await rollbackSystem.performFullRollback(); if (result.success) { printSuccess('Full rollback completed successfully'); } else { printError('Full rollback failed:'); result.errors.forEach(error => console.error(` āŒ ${error}`)); } } else if (subArgs.includes('--partial')) { const phaseIndex = subArgs.findIndex(arg => arg === '--phase'); if (phaseIndex !== -1 && subArgs[phaseIndex + 1]) { const phase = subArgs[phaseIndex + 1]; console.log(`šŸ”„ Performing partial rollback for phase: ${phase}`); const result = await rollbackSystem.performPartialRollback(phase); if (result.success) { printSuccess(`Partial rollback completed for phase: ${phase}`); } else { printError(`Partial rollback failed for phase: ${phase}`); result.errors.forEach(error => console.error(` āŒ ${error}`)); } } else { printError('Partial rollback requires --phase <phase-name>'); } } else { // Interactive rollback point selection const rollbackPoints = await rollbackSystem.listRollbackPoints(); if (rollbackPoints.rollbackPoints.length === 0) { printWarning('No rollback points available'); return; } console.log('\nšŸ“‹ Available rollback points:'); rollbackPoints.rollbackPoints.forEach((point, index) => { const date = new Date(point.timestamp).toLocaleString(); console.log(` ${index + 1}. ${point.type} - ${date}`); }); // For now, rollback to the most recent point const latest = rollbackPoints.rollbackPoints[0]; if (latest) { console.log(`\nšŸ”„ Rolling back to: ${latest.type} (${new Date(latest.timestamp).toLocaleString()})`); const result = await rollbackSystem.performFullRollback(latest.backupId); if (result.success) { printSuccess('Rollback completed successfully'); } else { printError('Rollback failed'); } } } } catch (error) { printError(`Rollback operation failed: ${error.message}`); } } /** * Handle list backups command */ async function handleListBackups(subArgs, flags) { const workingDir = Deno.env.get('PWD') || Deno.cwd(); const rollbackSystem = new RollbackSystem(workingDir); try { const rollbackPoints = await rollbackSystem.listRollbackPoints(); console.log('\nšŸ“‹ Rollback Points and Backups:'); if (rollbackPoints.rollbackPoints.length === 0) { console.log(' No rollback points available'); } else { console.log('\nšŸ”„ Rollback Points:'); rollbackPoints.rollbackPoints.forEach((point, index) => { const date = new Date(point.timestamp).toLocaleString(); console.log(` ${index + 1}. ${point.type} - ${date} (${point.backupId || 'No backup'})`); }); } if (rollbackPoints.checkpoints.length > 0) { console.log('\nšŸ“ Checkpoints:'); rollbackPoints.checkpoints.slice(-5).forEach((checkpoint, index) => { const date = new Date(checkpoint.timestamp).toLocaleString(); console.log(` ${index + 1}. ${checkpoint.phase} - ${date} (${checkpoint.status})`); }); } } catch (error) { printError(`Failed to list backups: ${error.message}`); } } /** * Perform initialization with checkpoints */ async function performInitializationWithCheckpoints(rollbackSystem, options, workingDir, dryRun = false) { const phases = [ { name: 'file-creation', action: () => createInitialFiles(options, workingDir, dryRun) }, { name: 'directory-structure', action: () => createDirectoryStructure(workingDir, dryRun) }, { name: 'memory-setup', action: () => setupMemorySystem(workingDir, dryRun) }, { name: 'coordination-setup', action: () => setupCoordinationSystem(workingDir, dryRun) }, { name: 'executable-creation', action: () => createLocalExecutable(workingDir, dryRun) } ]; if (options.sparc) { phases.push( { name: 'sparc-init', action: () => createSparcStructureManually() }, { name: 'claude-commands', action: () => createClaudeSlashCommands(workingDir) } ); } for (const phase of phases) { console.log(` šŸ”§ ${phase.name}...`); // Create checkpoint before phase await rollbackSystem.createCheckpoint(phase.name, { timestamp: Date.now(), phase: phase.name }); try { await phase.action(); console.log(` āœ… ${phase.name} completed`); } catch (error) { console.error(` āŒ ${phase.name} failed: ${error.message}`); throw error; } } } // Helper functions for atomic initialization async function createInitialFiles(options, workingDir, dryRun = false) { if (!dryRun) { const claudeMd = options.sparc ? createSparcClaudeMd() : options.minimal ? createMinimalClaudeMd() : createFullClaudeMd(); await Deno.writeTextFile(`${workingDir}/CLAUDE.md`, claudeMd); const memoryBankMd = options.minimal ? createMinimalMemoryBankMd() : createFullMemoryBankMd(); await Deno.writeTextFile(`${workingDir}/memory-bank.md`, memoryBankMd); const coordinationMd = options.minimal ? createMinimalCoordinationMd() : createFullCoordinationMd(); await Deno.writeTextFile(`${workingDir}/coordination.md`, coordinationMd); } } async function createDirectoryStructure(workingDir, dryRun = false) { const directories = [ 'memory', 'memory/agents', 'memory/sessions', 'coordination', 'coordination/memory_bank', 'coordination/subtasks', 'coordination/orchestration', '.claude', '.claude/commands', '.claude/logs' ]; if (!dryRun) { for (const dir of directories) { await Deno.mkdir(`${workingDir}/${dir}`, { recursive: true }); } } } async function setupMemorySystem(workingDir, dryRun = false) { if (!dryRun) { const initialData = { agents: [], tasks: [], lastUpdated: Date.now() }; await Deno.writeTextFile(`${workingDir}/memory/claude-flow-data.json`, JSON.stringify(initialData, null, 2)); await Deno.writeTextFile(`${workingDir}/memory/agents/README.md`, createAgentsReadme()); await Deno.writeTextFile(`${workingDir}/memory/sessions/README.md`, createSessionsReadme()); } } async function setupCoordinationSystem(workingDir, dryRun = false) { // Coordination system is already set up by createDirectoryStructure // This is a placeholder for future coordination setup logic } /** * Enhanced Claude Flow v2.0.0 initialization */ async function enhancedClaudeFlowInit(flags, subArgs = []) { console.log('šŸš€ Initializing Claude Flow v2.0.0 with enhanced features...'); const workingDir = process.cwd(); const force = flags.force || flags.f; const dryRun = flags.dryRun || flags['dry-run'] || flags.d; // Store parameters to avoid scope issues in async context const args = subArgs || []; const options = flags || {}; // Import fs module for Node.js const fs = await import('fs/promises'); const { chmod } = fs; try { // Check existing files const existingFiles = []; const filesToCheck = ['CLAUDE.md', '.claude/settings.json']; for (const file of filesToCheck) { if (existsSync(`${workingDir}/${file}`)) { existingFiles.push(file); } } if (existingFiles.length > 0 && !force) { printWarning(`The following files already exist: ${existingFiles.join(', ')}`); console.log('Use --force to overwrite existing files'); return; } // Create CLAUDE.md if (!dryRun) { await Deno.writeTextFile(`${workingDir}/CLAUDE.md`, createEnhancedClaudeMd()); printSuccess('āœ“ Created CLAUDE.md (Claude Flow v2.0.0)'); } else { console.log('[DRY RUN] Would create CLAUDE.md (Claude Flow v2.0.0)'); } // Create .claude directory structure const claudeDir = `${workingDir}/.claude`; if (!dryRun) { await Deno.mkdir(claudeDir, { recursive: true }); await Deno.mkdir(`${claudeDir}/commands`, { recursive: true }); await Deno.mkdir(`${claudeDir}/helpers`, { recursive: true }); printSuccess('āœ“ Created .claude directory structure'); } else { console.log('[DRY RUN] Would create .claude directory structure'); } // Create settings.json if (!dryRun) { await Deno.writeTextFile(`${claudeDir}/settings.json`, createEnhancedSettingsJson()); printSuccess('āœ“ Created .claude/settings.json with hooks and MCP configuration'); } else { console.log('[DRY RUN] Would create .claude/settings.json'); } // Create settings.local.json with default MCP permissions const settingsLocal = { "permissions": { "allow": [ "mcp__ruv-swarm", "mcp__claude-flow" ], "deny": [] } }; if (!dryRun) { await Deno.writeTextFile(`${claudeDir}/settings.local.json`, JSON.stringify(settingsLocal, null, 2)); printSuccess('āœ“ Created .claude/settings.local.json with default MCP permissions'); } else { console.log('[DRY RUN] Would create .claude/settings.local.json with default MCP permissions'); } // Create command documentation for (const [category, commands] of Object.entries(COMMAND_STRUCTURE)) { const categoryDir = `${claudeDir}/commands/${category}`; if (!dryRun) { await Deno.mkdir(categoryDir, { recursive: true }); // Create category README const categoryReadme = `# ${category.charAt(0).toUpperCase() + category.slice(1)} Commands Commands for ${category} operations in Claude Flow. ## Available Commands ${commands.map(cmd => `- [${cmd}](./${cmd}.md)`).join('\n')} `; await Deno.writeTextFile(`${categoryDir}/README.md`, categoryReadme); // Create individual command docs for (const command of commands) { const doc = createCommandDoc(category, command); if (doc) { await Deno.writeTextFile(`${categoryDir}/${command}.md`, doc); } } console.log(` āœ“ Created ${commands.length} ${category} command docs`); } else { console.log(`[DRY RUN] Would create ${commands.length} ${category} command docs`); } } // Create wrapper scripts if (!dryRun) { // Unix wrapper - now uses universal ES module compatible wrapper const unixWrapper = createWrapperScript('unix'); await Deno.writeTextFile(`${workingDir}/claude-flow`, unixWrapper); await fs.chmod(`${workingDir}/claude-flow`, 0o755); // Windows wrapper await Deno.writeTextFile(`${workingDir}/claude-flow.bat`, createWrapperScript('windows')); // PowerShell wrapper await Deno.writeTextFile(`${workingDir}/claude-flow.ps1`, createWrapperScript('powershell')); printSuccess('āœ“ Created platform-specific wrapper scripts'); } else { console.log('[DRY RUN] Would create wrapper scripts'); } // Create helper scripts const helpers = ['setup-mcp.sh', 'quick-start.sh', 'github-setup.sh']; for (const helper of helpers) { if (!dryRun) { const content = createHelperScript(helper); if (content) { await Deno.writeTextFile(`${claudeDir}/helpers/${helper}`, content); await fs.chmod(`${claudeDir}/helpers/${helper}`, 0o755); } } } if (!dryRun) { printSuccess(`āœ“ Created ${helpers.length} helper scripts`); } else { console.log(`[DRY RUN] Would create ${helpers.length} helper scripts`); } // Create standard directories from original init const standardDirs = [ 'memory', 'memory/agents', 'memory/sessions', 'coordination', 'coordination/memory_bank', 'coordination/subtasks', 'coordination/orchestration', '.swarm' // Add .swarm directory for shared memory ]; for (const dir of standardDirs) { if (!dryRun) { await fs.mkdir(`${workingDir}/${dir}`, { recursive: true }); } } if (!dryRun) { printSuccess('āœ“ Created standard directory structure'); // Initialize memory system const initialData = { agents: [], tasks: [], lastUpdated: Date.now() }; await fs.writeFile(`${workingDir}/memory/claude-flow-data.json`, JSON.stringify(initialData, null, 2)); // Create README files await fs.writeFile(`${workingDir}/memory/agents/README.md`, createAgentsReadme()); await fs.writeFile(`${workingDir}/memory/sessions/README.md`, createSessionsReadme()); printSuccess('āœ“ Initialized memory system'); // Initialize memory database with fallback support try { // Import and initialize FallbackMemoryStore to create the database const { FallbackMemoryStore } = await import('../../../memory/fallback-store.js'); const memoryStore = new FallbackMemoryStore(); await memoryStore.initialize(); if (memoryStore.isUsingFallback()) { printSuccess('āœ“ Initialized memory system (in-memory fallback for npx compatibility)'); console.log(' šŸ’” For persistent storage, install locally: npm install claude-flow@alpha'); } else { printSuccess('āœ“ Initialized memory database (.swarm/memory.db)'); } memoryStore.close(); } catch (err) { console.log(` āš ļø Could not initialize memory system: ${err.message}`); console.log(' Memory will be initialized on first use'); } } // Check for Claude Code and set up MCP servers (always enabled by default) if (!dryRun && isClaudeCodeInstalled()) { console.log('\nšŸ” Claude Code CLI detected!'); const skipMcp = (options && options['skip-mcp']) || (subArgs && subArgs.includes && subArgs.includes('--skip-mcp')); if (!skipMcp) { await setupMcpServers(dryRun); } else { console.log(' ā„¹ļø Skipping MCP setup (--skip-mcp flag used)'); console.log('\n šŸ“‹ To add MCP servers manually:'); console.log(' claude mcp add claude-flow claude-flow mcp start'); console.log(' claude mcp add ruv-swarm npx ruv-swarm mcp start'); } } else if (!dryRun && !isClaudeCodeInstalled()) { console.log('\nāš ļø Claude Code CLI not detected!'); console.log('\n šŸ“„ To install Claude Code:'); console.log(' npm install -g @anthropic-ai/claude-code'); console.log('\n šŸ“‹ After installing, add MCP servers:'); console.log(' claude mcp add claude-flow claude-flow mcp start'); console.log(' claude mcp add ruv-swarm npx ruv-swarm mcp start'); } // Final instructions console.log('\nšŸŽ‰ Claude Flow v2.0.0 initialization complete!'); console.log('\nšŸ“š Quick Start:'); if (isClaudeCodeInstalled()) { console.log('1. View available commands: ls .claude/commands/'); console.log('2. Start a swarm: npx claude-flow swarm init'); console.log('3. Use MCP tools in Claude Code for enhanced coordination'); } else { console.log('1. Install Claude Code: npm install -g @anthropic-ai/claude-code'); console.log('2. Add MCP servers (see instructions above)'); console.log('3. View available commands: ls .claude/commands/'); console.log('4. Start a swarm: npx claude-flow swarm init'); } console.log('\nšŸ’” Tips:'); console.log('• Check .claude/commands/ for detailed documentation'); console.log('• Use --help with any command for options'); console.log('• Enable GitHub integration with .claude/helpers/github-setup.sh'); } catch (err) { printError(`Failed to initialize Claude Flow v2.0.0: ${err.message}`); } }