UNPKG

claude-flow

Version:

Ruflo - Enterprise AI agent orchestration for Claude Code. Deploy 60+ specialized agents in coordinated swarms with self-learning, fault-tolerant consensus, vector memory, and MCP integration

1,261 lines (1,245 loc) 66 kB
/** * Init Executor * Main execution logic for V3 initialization */ import * as fs from 'fs'; import * as path from 'path'; import { fileURLToPath } from 'url'; import { createRequire } from 'module'; import { dirname } from 'path'; // ESM-compatible __dirname const __filename = fileURLToPath(import.meta.url); const __dirname = dirname(__filename); import { detectPlatform, DEFAULT_INIT_OPTIONS } from './types.js'; import { generateSettingsJson, generateSettings } from './settings-generator.js'; import { generateMCPJson } from './mcp-generator.js'; import { generateStatuslineScript } from './statusline-generator.js'; import { generatePreCommitHook, generatePostCommitHook, generateSessionManager, generateAgentRouter, generateMemoryHelper, generateHookHandler, generateIntelligenceStub, generateAutoMemoryHook, } from './helpers-generator.js'; import { generateClaudeMd } from './claudemd-generator.js'; /** * Skills to copy based on configuration */ const SKILLS_MAP = { core: [ 'swarm-orchestration', 'swarm-advanced', 'sparc-methodology', 'hooks-automation', 'pair-programming', 'verification-quality', 'stream-chain', 'skill-builder', ], browser: ['browser'], // agent-browser integration dualMode: ['dual-mode'], // Claude Code + Codex hybrid execution agentdb: [ 'agentdb-advanced', 'agentdb-learning', 'agentdb-memory-patterns', 'agentdb-optimization', 'agentdb-vector-search', 'reasoningbank-agentdb', 'reasoningbank-intelligence', ], github: [ 'github-code-review', 'github-multi-repo', 'github-project-management', 'github-release-management', 'github-workflow-automation', ], flowNexus: [ 'flow-nexus-neural', 'flow-nexus-platform', 'flow-nexus-swarm', ], v3: [ 'v3-cli-modernization', 'v3-core-implementation', 'v3-ddd-architecture', 'v3-integration-deep', 'v3-mcp-optimization', 'v3-memory-unification', 'v3-performance-optimization', 'v3-security-overhaul', 'v3-swarm-coordination', ], }; /** * Commands to copy based on configuration */ const COMMANDS_MAP = { core: ['claude-flow-help.md', 'claude-flow-swarm.md', 'claude-flow-memory.md'], analysis: ['analysis'], automation: ['automation'], github: ['github'], hooks: ['hooks'], monitoring: ['monitoring'], optimization: ['optimization'], sparc: ['sparc'], }; /** * Agents to copy based on configuration */ const AGENTS_MAP = { core: ['core'], consensus: ['consensus'], github: ['github'], hiveMind: ['hive-mind'], sparc: ['sparc'], swarm: ['swarm'], browser: ['browser'], // agent-browser integration dualMode: ['dual-mode'], // Claude Code + Codex hybrid execution // V3-specific agents v3: ['v3'], optimization: ['optimization'], templates: ['templates'], testing: ['testing'], sublinear: ['sublinear'], flowNexus: ['flow-nexus'], analysis: ['analysis'], architecture: ['architecture'], development: ['development'], devops: ['devops'], documentation: ['documentation'], specialized: ['specialized'], goal: ['goal'], sona: ['sona'], payments: ['payments'], data: ['data'], custom: ['custom'], }; /** * Directory structure to create */ const DIRECTORIES = { claude: [ '.claude', '.claude/skills', '.claude/commands', '.claude/agents', '.claude/helpers', ], runtime: [ '.claude-flow', '.claude-flow/data', '.claude-flow/logs', '.claude-flow/sessions', '.claude-flow/hooks', '.claude-flow/agents', '.claude-flow/workflows', ], }; /** * Execute initialization */ export async function executeInit(options) { // Detect platform const platform = detectPlatform(); const result = { success: true, platform, created: { directories: [], files: [], }, skipped: [], errors: [], summary: { skillsCount: 0, commandsCount: 0, agentsCount: 0, hooksEnabled: 0, }, }; const targetDir = options.targetDir; try { // Create directory structure await createDirectories(targetDir, options, result); // Generate and write settings.json if (options.components.settings) { await writeSettings(targetDir, options, result); } // Generate and write .mcp.json if (options.components.mcp) { await writeMCPConfig(targetDir, options, result); } // Copy skills if (options.components.skills) { await copySkills(targetDir, options, result); } // Copy commands if (options.components.commands) { await copyCommands(targetDir, options, result); } // Copy agents if (options.components.agents) { await copyAgents(targetDir, options, result); } // Generate helpers if (options.components.helpers) { await writeHelpers(targetDir, options, result); } // Generate statusline if (options.components.statusline) { await writeStatusline(targetDir, options, result); } // Generate runtime config if (options.components.runtime) { await writeRuntimeConfig(targetDir, options, result); } // Create initial metrics for statusline (prevents "all zeros" display) if (options.components.statusline) { await writeInitialMetrics(targetDir, options, result); } // Generate CLAUDE.md if (options.components.claudeMd) { await writeClaudeMd(targetDir, options, result); } // Count enabled hooks result.summary.hooksEnabled = countEnabledHooks(options); } catch (error) { result.success = false; result.errors.push(error instanceof Error ? error.message : String(error)); } return result; } /** * Merge new settings into existing settings.json * Preserves user customizations while adding new features like Agent Teams * Uses platform-specific commands for Mac, Linux, and Windows */ function mergeSettingsForUpgrade(existing) { const merged = { ...existing }; const platform = detectPlatform(); const isWindows = platform.os === 'windows'; // Platform-specific command wrappers // Windows: Use PowerShell-compatible commands // Mac/Linux: Use bash-compatible commands with 2>/dev/null // NOTE: teammateIdleCmd and taskCompletedCmd were removed. // TeammateIdle/TaskCompleted are not valid Claude Code hook events and caused warnings. // Agent Teams hook config lives in claudeFlow.agentTeams.hooks instead. // 1. Merge env vars (preserve existing, add new) const existingEnv = existing.env || {}; merged.env = { ...existingEnv, CLAUDE_CODE_EXPERIMENTAL_AGENT_TEAMS: '1', CLAUDE_FLOW_V3_ENABLED: existingEnv.CLAUDE_FLOW_V3_ENABLED || 'true', CLAUDE_FLOW_HOOKS_ENABLED: existingEnv.CLAUDE_FLOW_HOOKS_ENABLED || 'true', }; // 2. Merge hooks (preserve existing, add new Agent Teams + auto-memory hooks) const existingHooks = existing.hooks || {}; merged.hooks = { ...existingHooks }; // Platform-specific auto-memory hook commands const autoMemoryImportCmd = isWindows ? 'node .claude/helpers/auto-memory-hook.mjs import 2>$null; exit 0' : 'node .claude/helpers/auto-memory-hook.mjs import 2>/dev/null || true'; const autoMemorySyncCmd = isWindows ? 'node .claude/helpers/auto-memory-hook.mjs sync 2>$null; exit 0' : 'node .claude/helpers/auto-memory-hook.mjs sync 2>/dev/null || true'; // Add auto-memory import to SessionStart (if not already present) const sessionStartHooks = existingHooks.SessionStart; const hasAutoMemoryImport = sessionStartHooks?.some(group => group.hooks?.some(h => h.command?.includes('auto-memory-hook'))); if (!hasAutoMemoryImport) { const startHooks = merged.hooks; if (!startHooks.SessionStart) { startHooks.SessionStart = [{ hooks: [] }]; } const startGroup = startHooks.SessionStart[0]; if (!startGroup.hooks) startGroup.hooks = []; startGroup.hooks.push({ type: 'command', command: autoMemoryImportCmd, timeout: 6000, continueOnError: true, }); } // Add auto-memory sync to SessionEnd (if not already present) const sessionEndHooks = existingHooks.SessionEnd; const hasAutoMemorySync = sessionEndHooks?.some(group => group.hooks?.some(h => h.command?.includes('auto-memory-hook'))); if (!hasAutoMemorySync) { const endHooks = merged.hooks; if (!endHooks.SessionEnd) { endHooks.SessionEnd = [{ hooks: [] }]; } const endGroup = endHooks.SessionEnd[0]; if (!endGroup.hooks) endGroup.hooks = []; // Insert at beginning so sync runs before other cleanup endGroup.hooks.unshift({ type: 'command', command: autoMemorySyncCmd, timeout: 8000, continueOnError: true, }); } // NOTE: TeammateIdle and TaskCompleted are NOT valid Claude Code hook events. // They cause warnings when present in settings.json hooks. // Remove them if they exist from a previous init. delete merged.hooks.TeammateIdle; delete merged.hooks.TaskCompleted; // Their configuration lives in claudeFlow.agentTeams.hooks instead. // 3. Fix statusLine config (remove invalid fields, ensure correct format) // Claude Code only supports: type, command, padding const existingStatusLine = existing.statusLine; if (existingStatusLine) { merged.statusLine = { type: 'command', command: existingStatusLine.command || 'node .claude/helpers/statusline.cjs', // Remove invalid fields: refreshMs, enabled (not supported by Claude Code) }; } // 4. Merge claudeFlow settings (preserve existing, add agentTeams + memory) const existingClaudeFlow = existing.claudeFlow || {}; const existingMemory = existingClaudeFlow.memory || {}; merged.claudeFlow = { ...existingClaudeFlow, version: existingClaudeFlow.version || '3.0.0', enabled: existingClaudeFlow.enabled !== false, agentTeams: { enabled: true, teammateMode: 'auto', taskListEnabled: true, mailboxEnabled: true, coordination: { autoAssignOnIdle: true, trainPatternsOnComplete: true, notifyLeadOnComplete: true, sharedMemoryNamespace: 'agent-teams', }, hooks: { teammateIdle: { enabled: true, autoAssign: true, checkTaskList: true }, taskCompleted: { enabled: true, trainPatterns: true, notifyLead: true }, }, }, memory: { ...existingMemory, learningBridge: existingMemory.learningBridge ?? { enabled: true }, memoryGraph: existingMemory.memoryGraph ?? { enabled: true }, agentScopes: existingMemory.agentScopes ?? { enabled: true }, }, }; return merged; } /** * Execute upgrade - updates helpers and creates missing metrics without losing data * This is safe for existing users who want the latest statusline fixes * @param targetDir - Target directory * @param upgradeSettings - If true, merge new settings into existing settings.json */ export async function executeUpgrade(targetDir, upgradeSettings = false) { const result = { success: true, updated: [], created: [], preserved: [], errors: [], settingsUpdated: [], }; try { // Ensure required directories exist const dirs = [ '.claude/helpers', '.claude-flow/metrics', '.claude-flow/security', '.claude-flow/learning', ]; for (const dir of dirs) { const fullPath = path.join(targetDir, dir); if (!fs.existsSync(fullPath)) { fs.mkdirSync(fullPath, { recursive: true }); } } // 0. ALWAYS update critical helpers (force overwrite) const sourceHelpersForUpgrade = findSourceHelpersDir(); if (sourceHelpersForUpgrade) { const criticalHelpers = ['auto-memory-hook.mjs', 'hook-handler.cjs', 'intelligence.cjs']; for (const helperName of criticalHelpers) { const targetPath = path.join(targetDir, '.claude', 'helpers', helperName); const sourcePath = path.join(sourceHelpersForUpgrade, helperName); if (fs.existsSync(sourcePath)) { if (fs.existsSync(targetPath)) { result.updated.push(`.claude/helpers/${helperName}`); } else { result.created.push(`.claude/helpers/${helperName}`); } fs.copyFileSync(sourcePath, targetPath); try { fs.chmodSync(targetPath, '755'); } catch { } } } } else { // Source not found (npx with broken paths) — use generated fallbacks const generatedCritical = { 'hook-handler.cjs': generateHookHandler(), 'intelligence.cjs': generateIntelligenceStub(), 'auto-memory-hook.mjs': generateAutoMemoryHook(), }; for (const [helperName, content] of Object.entries(generatedCritical)) { const targetPath = path.join(targetDir, '.claude', 'helpers', helperName); if (fs.existsSync(targetPath)) { result.updated.push(`.claude/helpers/${helperName}`); } else { result.created.push(`.claude/helpers/${helperName}`); } fs.writeFileSync(targetPath, content, 'utf-8'); try { fs.chmodSync(targetPath, '755'); } catch { } } } // 1. ALWAYS update statusline helper (force overwrite) const statuslinePath = path.join(targetDir, '.claude', 'helpers', 'statusline.cjs'); // Use default options with statusline config const upgradeOptions = { ...DEFAULT_INIT_OPTIONS, targetDir, force: true, statusline: { ...DEFAULT_INIT_OPTIONS.statusline, refreshInterval: 5000, }, }; const statuslineContent = generateStatuslineScript(upgradeOptions); if (fs.existsSync(statuslinePath)) { result.updated.push('.claude/helpers/statusline.cjs'); } else { result.created.push('.claude/helpers/statusline.cjs'); } fs.writeFileSync(statuslinePath, statuslineContent, 'utf-8'); // 2. Create MISSING metrics files only (preserve existing data) const metricsDir = path.join(targetDir, '.claude-flow', 'metrics'); const securityDir = path.join(targetDir, '.claude-flow', 'security'); // v3-progress.json const progressPath = path.join(metricsDir, 'v3-progress.json'); if (!fs.existsSync(progressPath)) { const progress = { version: '3.0.0', initialized: new Date().toISOString(), domains: { completed: 0, total: 5, status: 'INITIALIZING' }, ddd: { progress: 0, modules: 0, totalFiles: 0, totalLines: 0 }, swarm: { activeAgents: 0, maxAgents: 15, topology: 'hierarchical-mesh' }, learning: { status: 'READY', patternsLearned: 0, sessionsCompleted: 0 }, _note: 'Metrics will update as you use Claude Flow' }; fs.writeFileSync(progressPath, JSON.stringify(progress, null, 2), 'utf-8'); result.created.push('.claude-flow/metrics/v3-progress.json'); } else { result.preserved.push('.claude-flow/metrics/v3-progress.json'); } // swarm-activity.json const activityPath = path.join(metricsDir, 'swarm-activity.json'); if (!fs.existsSync(activityPath)) { const activity = { timestamp: new Date().toISOString(), processes: { agentic_flow: 0, mcp_server: 0, estimated_agents: 0 }, swarm: { active: false, agent_count: 0, coordination_active: false }, integration: { agentic_flow_active: false, mcp_active: false }, _initialized: true }; fs.writeFileSync(activityPath, JSON.stringify(activity, null, 2), 'utf-8'); result.created.push('.claude-flow/metrics/swarm-activity.json'); } else { result.preserved.push('.claude-flow/metrics/swarm-activity.json'); } // learning.json const learningPath = path.join(metricsDir, 'learning.json'); if (!fs.existsSync(learningPath)) { const learning = { initialized: new Date().toISOString(), routing: { accuracy: 0, decisions: 0 }, patterns: { shortTerm: 0, longTerm: 0, quality: 0 }, sessions: { total: 0, current: null }, _note: 'Intelligence grows as you use Claude Flow' }; fs.writeFileSync(learningPath, JSON.stringify(learning, null, 2), 'utf-8'); result.created.push('.claude-flow/metrics/learning.json'); } else { result.preserved.push('.claude-flow/metrics/learning.json'); } // audit-status.json const auditPath = path.join(securityDir, 'audit-status.json'); if (!fs.existsSync(auditPath)) { const audit = { initialized: new Date().toISOString(), status: 'PENDING', cvesFixed: 0, totalCves: 3, lastScan: null, _note: 'Run: npx @claude-flow/cli@latest security scan' }; fs.writeFileSync(auditPath, JSON.stringify(audit, null, 2), 'utf-8'); result.created.push('.claude-flow/security/audit-status.json'); } else { result.preserved.push('.claude-flow/security/audit-status.json'); } // 3. Merge settings if requested if (upgradeSettings) { const settingsPath = path.join(targetDir, '.claude', 'settings.json'); if (fs.existsSync(settingsPath)) { try { const existingSettings = JSON.parse(fs.readFileSync(settingsPath, 'utf-8')); const mergedSettings = mergeSettingsForUpgrade(existingSettings); fs.writeFileSync(settingsPath, JSON.stringify(mergedSettings, null, 2), 'utf-8'); result.updated.push('.claude/settings.json'); result.settingsUpdated = [ 'env.CLAUDE_CODE_EXPERIMENTAL_AGENT_TEAMS', 'hooks.SessionStart (auto-memory import)', 'hooks.SessionEnd (auto-memory sync)', 'hooks.TeammateIdle (removed — not a valid Claude Code hook)', 'hooks.TaskCompleted (removed — not a valid Claude Code hook)', 'claudeFlow.agentTeams', 'claudeFlow.memory (learningBridge, memoryGraph, agentScopes)', ]; } catch (settingsError) { result.errors.push(`Settings merge failed: ${settingsError instanceof Error ? settingsError.message : String(settingsError)}`); } } else { // Create new settings.json with defaults const defaultSettings = generateSettings(DEFAULT_INIT_OPTIONS); fs.writeFileSync(settingsPath, JSON.stringify(defaultSettings, null, 2), 'utf-8'); result.created.push('.claude/settings.json'); result.settingsUpdated = ['Created new settings.json with Agent Teams']; } } } catch (error) { result.success = false; result.errors.push(error instanceof Error ? error.message : String(error)); } return result; } /** * Execute upgrade with --add-missing flag * Adds any new skills, agents, and commands that don't exist yet * @param targetDir - Target directory * @param upgradeSettings - If true, merge new settings into existing settings.json */ export async function executeUpgradeWithMissing(targetDir, upgradeSettings = false) { // First do the normal upgrade (pass through upgradeSettings) const result = await executeUpgrade(targetDir, upgradeSettings); if (!result.success) { return result; } // Initialize tracking arrays result.addedSkills = []; result.addedAgents = []; result.addedCommands = []; try { // Ensure target directories exist const skillsDir = path.join(targetDir, '.claude', 'skills'); const agentsDir = path.join(targetDir, '.claude', 'agents'); const commandsDir = path.join(targetDir, '.claude', 'commands'); for (const dir of [skillsDir, agentsDir, commandsDir]) { if (!fs.existsSync(dir)) { fs.mkdirSync(dir, { recursive: true }); } } // Find source directories const sourceSkillsDir = findSourceDir('skills'); const sourceAgentsDir = findSourceDir('agents'); const sourceCommandsDir = findSourceDir('commands'); // Debug: Log source directories found if (process.env.DEBUG || process.env.CLAUDE_FLOW_DEBUG) { console.log('[DEBUG] Source directories:'); console.log(` Skills: ${sourceSkillsDir || 'NOT FOUND'}`); console.log(` Agents: ${sourceAgentsDir || 'NOT FOUND'}`); console.log(` Commands: ${sourceCommandsDir || 'NOT FOUND'}`); } // Add missing skills if (sourceSkillsDir) { const allSkills = Object.values(SKILLS_MAP).flat(); const debugMode = process.env.DEBUG || process.env.CLAUDE_FLOW_DEBUG; if (debugMode) { console.log(`[DEBUG] Checking ${allSkills.length} skills from SKILLS_MAP`); } for (const skillName of [...new Set(allSkills)]) { const sourcePath = path.join(sourceSkillsDir, skillName); const targetPath = path.join(skillsDir, skillName); const sourceExists = fs.existsSync(sourcePath); const targetExists = fs.existsSync(targetPath); if (debugMode) { console.log(`[DEBUG] Skill '${skillName}': source=${sourceExists}, target=${targetExists}`); } if (sourceExists && !targetExists) { copyDirRecursive(sourcePath, targetPath); result.addedSkills.push(skillName); result.created.push(`.claude/skills/${skillName}`); } } } // Add missing agents if (sourceAgentsDir) { const allAgents = Object.values(AGENTS_MAP).flat(); for (const agentCategory of [...new Set(allAgents)]) { const sourcePath = path.join(sourceAgentsDir, agentCategory); const targetPath = path.join(agentsDir, agentCategory); if (fs.existsSync(sourcePath) && !fs.existsSync(targetPath)) { copyDirRecursive(sourcePath, targetPath); result.addedAgents.push(agentCategory); result.created.push(`.claude/agents/${agentCategory}`); } } } // Add missing commands if (sourceCommandsDir) { const allCommands = Object.values(COMMANDS_MAP).flat(); for (const cmdName of [...new Set(allCommands)]) { const sourcePath = path.join(sourceCommandsDir, cmdName); const targetPath = path.join(commandsDir, cmdName); if (fs.existsSync(sourcePath) && !fs.existsSync(targetPath)) { if (fs.statSync(sourcePath).isDirectory()) { copyDirRecursive(sourcePath, targetPath); } else { fs.copyFileSync(sourcePath, targetPath); } result.addedCommands.push(cmdName); result.created.push(`.claude/commands/${cmdName}`); } } } } catch (error) { result.errors.push(`Add missing failed: ${error instanceof Error ? error.message : String(error)}`); } return result; } /** * Create directory structure */ async function createDirectories(targetDir, options, result) { const dirs = [ ...DIRECTORIES.claude, ...(options.components.runtime ? DIRECTORIES.runtime : []), ]; for (const dir of dirs) { const fullPath = path.join(targetDir, dir); if (!fs.existsSync(fullPath)) { fs.mkdirSync(fullPath, { recursive: true }); result.created.directories.push(dir); } } } /** * Write settings.json */ async function writeSettings(targetDir, options, result) { const settingsPath = path.join(targetDir, '.claude', 'settings.json'); if (fs.existsSync(settingsPath) && !options.force) { result.skipped.push('.claude/settings.json'); return; } const content = generateSettingsJson(options); fs.writeFileSync(settingsPath, content, 'utf-8'); result.created.files.push('.claude/settings.json'); } /** * Write .mcp.json */ async function writeMCPConfig(targetDir, options, result) { const mcpPath = path.join(targetDir, '.mcp.json'); if (fs.existsSync(mcpPath) && !options.force) { result.skipped.push('.mcp.json'); return; } const content = generateMCPJson(options); fs.writeFileSync(mcpPath, content, 'utf-8'); result.created.files.push('.mcp.json'); } /** * Copy skills from source */ async function copySkills(targetDir, options, result) { const skillsConfig = options.skills; const targetSkillsDir = path.join(targetDir, '.claude', 'skills'); // Determine which skills to copy const skillsToCopy = []; if (skillsConfig.all) { // Copy all available skills Object.values(SKILLS_MAP).forEach(skills => skillsToCopy.push(...skills)); } else { if (skillsConfig.core) skillsToCopy.push(...SKILLS_MAP.core); if (skillsConfig.agentdb) skillsToCopy.push(...SKILLS_MAP.agentdb); if (skillsConfig.github) skillsToCopy.push(...SKILLS_MAP.github); if (skillsConfig.flowNexus) skillsToCopy.push(...SKILLS_MAP.flowNexus); if (skillsConfig.browser) skillsToCopy.push(...SKILLS_MAP.browser); if (skillsConfig.v3) skillsToCopy.push(...SKILLS_MAP.v3); if (skillsConfig.dualMode) skillsToCopy.push(...SKILLS_MAP.dualMode); } // Find source skills directory const sourceSkillsDir = findSourceDir('skills', options.sourceBaseDir); if (!sourceSkillsDir) { result.errors.push('Could not find source skills directory'); return; } // Copy each skill for (const skillName of [...new Set(skillsToCopy)]) { const sourcePath = path.join(sourceSkillsDir, skillName); const targetPath = path.join(targetSkillsDir, skillName); if (fs.existsSync(sourcePath)) { if (!fs.existsSync(targetPath) || options.force) { copyDirRecursive(sourcePath, targetPath); result.created.files.push(`.claude/skills/${skillName}`); result.summary.skillsCount++; } else { result.skipped.push(`.claude/skills/${skillName}`); } } } } /** * Copy commands from source */ async function copyCommands(targetDir, options, result) { const commandsConfig = options.commands; const targetCommandsDir = path.join(targetDir, '.claude', 'commands'); // Determine which commands to copy const commandsToCopy = []; if (commandsConfig.all) { Object.values(COMMANDS_MAP).forEach(cmds => commandsToCopy.push(...cmds)); } else { if (commandsConfig.core) commandsToCopy.push(...COMMANDS_MAP.core); if (commandsConfig.analysis) commandsToCopy.push(...COMMANDS_MAP.analysis); if (commandsConfig.automation) commandsToCopy.push(...COMMANDS_MAP.automation); if (commandsConfig.github) commandsToCopy.push(...COMMANDS_MAP.github); if (commandsConfig.hooks) commandsToCopy.push(...COMMANDS_MAP.hooks); if (commandsConfig.monitoring) commandsToCopy.push(...COMMANDS_MAP.monitoring); if (commandsConfig.optimization) commandsToCopy.push(...COMMANDS_MAP.optimization); if (commandsConfig.sparc) commandsToCopy.push(...COMMANDS_MAP.sparc); } // Find source commands directory const sourceCommandsDir = findSourceDir('commands', options.sourceBaseDir); if (!sourceCommandsDir) { result.errors.push('Could not find source commands directory'); return; } // Copy each command/directory for (const cmdName of [...new Set(commandsToCopy)]) { const sourcePath = path.join(sourceCommandsDir, cmdName); const targetPath = path.join(targetCommandsDir, cmdName); if (fs.existsSync(sourcePath)) { if (!fs.existsSync(targetPath) || options.force) { if (fs.statSync(sourcePath).isDirectory()) { copyDirRecursive(sourcePath, targetPath); } else { fs.copyFileSync(sourcePath, targetPath); } result.created.files.push(`.claude/commands/${cmdName}`); result.summary.commandsCount++; } else { result.skipped.push(`.claude/commands/${cmdName}`); } } } } /** * Copy agents from source */ async function copyAgents(targetDir, options, result) { const agentsConfig = options.agents; const targetAgentsDir = path.join(targetDir, '.claude', 'agents'); // Determine which agents to copy const agentsToCopy = []; if (agentsConfig.all) { Object.values(AGENTS_MAP).forEach(agents => agentsToCopy.push(...agents)); } else { if (agentsConfig.core) agentsToCopy.push(...AGENTS_MAP.core); if (agentsConfig.consensus) agentsToCopy.push(...AGENTS_MAP.consensus); if (agentsConfig.github) agentsToCopy.push(...AGENTS_MAP.github); if (agentsConfig.hiveMind) agentsToCopy.push(...AGENTS_MAP.hiveMind); if (agentsConfig.sparc) agentsToCopy.push(...AGENTS_MAP.sparc); if (agentsConfig.swarm) agentsToCopy.push(...AGENTS_MAP.swarm); if (agentsConfig.browser) agentsToCopy.push(...AGENTS_MAP.browser); // V3-specific agent categories if (agentsConfig.v3) agentsToCopy.push(...(AGENTS_MAP.v3 || [])); if (agentsConfig.optimization) agentsToCopy.push(...(AGENTS_MAP.optimization || [])); if (agentsConfig.testing) agentsToCopy.push(...(AGENTS_MAP.testing || [])); // Dual-mode agents (Claude Code + Codex hybrid) if (agentsConfig.dualMode) agentsToCopy.push(...(AGENTS_MAP.dualMode || [])); } // Find source agents directory const sourceAgentsDir = findSourceDir('agents', options.sourceBaseDir); if (!sourceAgentsDir) { result.errors.push('Could not find source agents directory'); return; } // Copy each agent category for (const agentCategory of [...new Set(agentsToCopy)]) { const sourcePath = path.join(sourceAgentsDir, agentCategory); const targetPath = path.join(targetAgentsDir, agentCategory); if (fs.existsSync(sourcePath)) { if (!fs.existsSync(targetPath) || options.force) { copyDirRecursive(sourcePath, targetPath); // Count agent files (.yaml and .md) const yamlFiles = countFiles(sourcePath, '.yaml'); const mdFiles = countFiles(sourcePath, '.md'); result.summary.agentsCount += yamlFiles + mdFiles; result.created.files.push(`.claude/agents/${agentCategory}`); } else { result.skipped.push(`.claude/agents/${agentCategory}`); } } } } /** * Find source helpers directory. * Validates that the directory contains hook-handler.cjs to avoid * returning the target directory or an incomplete source. */ function findSourceHelpersDir(sourceBaseDir) { const possiblePaths = []; const SENTINEL_FILE = 'hook-handler.cjs'; // Must exist in valid source // If explicit source base directory is provided, check it first if (sourceBaseDir) { possiblePaths.push(path.join(sourceBaseDir, '.claude', 'helpers')); } // Strategy 1: require.resolve to find package root (most reliable for npx) try { const esmRequire = createRequire(import.meta.url); const pkgJsonPath = esmRequire.resolve('@claude-flow/cli/package.json'); const pkgRoot = path.dirname(pkgJsonPath); possiblePaths.push(path.join(pkgRoot, '.claude', 'helpers')); } catch { // Not installed as a package — skip } // Strategy 2: __dirname-based (dist/src/init -> package root) const packageRoot = path.resolve(__dirname, '..', '..', '..'); const packageHelpers = path.join(packageRoot, '.claude', 'helpers'); possiblePaths.push(packageHelpers); // Strategy 3: Walk up from __dirname looking for package root let currentDir = __dirname; for (let i = 0; i < 10; i++) { const parentDir = path.dirname(currentDir); if (parentDir === currentDir) break; // hit filesystem root const helpersPath = path.join(parentDir, '.claude', 'helpers'); possiblePaths.push(helpersPath); currentDir = parentDir; } // Strategy 4: Check cwd-relative paths (for local dev) const cwdBased = [ path.join(process.cwd(), '.claude', 'helpers'), path.join(process.cwd(), '..', '.claude', 'helpers'), path.join(process.cwd(), '..', '..', '.claude', 'helpers'), ]; possiblePaths.push(...cwdBased); // Return first path that exists AND contains the sentinel file for (const p of possiblePaths) { if (fs.existsSync(p) && fs.existsSync(path.join(p, SENTINEL_FILE))) { return p; } } return null; } /** * Write helper scripts */ async function writeHelpers(targetDir, options, result) { const helpersDir = path.join(targetDir, '.claude', 'helpers'); // Find source helpers directory (works for npm package and local dev) const sourceHelpersDir = findSourceHelpersDir(options.sourceBaseDir); // Try to copy existing helpers from source first if (sourceHelpersDir && fs.existsSync(sourceHelpersDir)) { const helperFiles = fs.readdirSync(sourceHelpersDir); let copiedCount = 0; for (const file of helperFiles) { const sourcePath = path.join(sourceHelpersDir, file); const destPath = path.join(helpersDir, file); // Skip directories and only copy files if (!fs.statSync(sourcePath).isFile()) continue; if (!fs.existsSync(destPath) || options.force) { fs.copyFileSync(sourcePath, destPath); // Make shell scripts and mjs files executable if (file.endsWith('.sh') || file.endsWith('.mjs')) { fs.chmodSync(destPath, '755'); } result.created.files.push(`.claude/helpers/${file}`); copiedCount++; } else { result.skipped.push(`.claude/helpers/${file}`); } } if (copiedCount > 0) { return; // Skip generating if we copied from source } } // Fall back to generating helpers if source not available const helpers = { 'pre-commit': generatePreCommitHook(), 'post-commit': generatePostCommitHook(), 'session.js': generateSessionManager(), 'router.js': generateAgentRouter(), 'memory.js': generateMemoryHelper(), 'hook-handler.cjs': generateHookHandler(), 'intelligence.cjs': generateIntelligenceStub(), 'auto-memory-hook.mjs': generateAutoMemoryHook(), }; for (const [name, content] of Object.entries(helpers)) { const filePath = path.join(helpersDir, name); if (!fs.existsSync(filePath) || options.force) { fs.writeFileSync(filePath, content, 'utf-8'); // Make shell scripts executable if (!name.endsWith('.js')) { fs.chmodSync(filePath, '755'); } result.created.files.push(`.claude/helpers/${name}`); } else { result.skipped.push(`.claude/helpers/${name}`); } } } /** * Find source .claude directory for statusline files */ function findSourceClaudeDir(sourceBaseDir) { const possiblePaths = []; // If explicit source base directory is provided, check it first if (sourceBaseDir) { possiblePaths.push(path.join(sourceBaseDir, '.claude')); } // IMPORTANT: Check the package's own .claude directory // Go up 3 levels: dist/src/init -> dist/src -> dist -> root const packageRoot = path.resolve(__dirname, '..', '..', '..'); const packageClaude = path.join(packageRoot, '.claude'); if (fs.existsSync(packageClaude)) { possiblePaths.unshift(packageClaude); // Add to beginning (highest priority) } // From dist/src/init -> go up to project root let currentDir = __dirname; for (let i = 0; i < 10; i++) { const parentDir = path.dirname(currentDir); const claudePath = path.join(parentDir, '.claude'); if (fs.existsSync(claudePath)) { possiblePaths.push(claudePath); } currentDir = parentDir; } for (const p of possiblePaths) { if (fs.existsSync(p)) { return p; } } return null; } /** * Write statusline configuration */ async function writeStatusline(targetDir, options, result) { const claudeDir = path.join(targetDir, '.claude'); const helpersDir = path.join(targetDir, '.claude', 'helpers'); // Find source .claude directory (works for npm package and local dev) const sourceClaudeDir = findSourceClaudeDir(options.sourceBaseDir); // Try to copy existing advanced statusline files from source const advancedStatuslineFiles = [ { src: 'statusline.sh', dest: 'statusline.sh', dir: claudeDir }, { src: 'statusline.mjs', dest: 'statusline.mjs', dir: claudeDir }, ]; if (sourceClaudeDir) { for (const file of advancedStatuslineFiles) { const sourcePath = path.join(sourceClaudeDir, file.src); const destPath = path.join(file.dir, file.dest); if (fs.existsSync(sourcePath)) { if (!fs.existsSync(destPath) || options.force) { fs.copyFileSync(sourcePath, destPath); // Make shell scripts and mjs executable if (file.src.endsWith('.sh') || file.src.endsWith('.mjs')) { fs.chmodSync(destPath, '755'); } result.created.files.push(`.claude/${file.dest}`); } else { result.skipped.push(`.claude/${file.dest}`); } } } } // ALWAYS generate statusline.cjs — settings.json references this path // regardless of whether advanced statusline files were also copied. const statuslineScript = generateStatuslineScript(options); const statuslinePath = path.join(helpersDir, 'statusline.cjs'); if (!fs.existsSync(statuslinePath) || options.force) { fs.writeFileSync(statuslinePath, statuslineScript, 'utf-8'); result.created.files.push('.claude/helpers/statusline.cjs'); } else { result.skipped.push('.claude/helpers/statusline.cjs'); } } /** * Write runtime configuration (.claude-flow/) */ async function writeRuntimeConfig(targetDir, options, result) { const configPath = path.join(targetDir, '.claude-flow', 'config.yaml'); if (fs.existsSync(configPath) && !options.force) { result.skipped.push('.claude-flow/config.yaml'); return; } const config = `# Claude Flow V3 Runtime Configuration # Generated: ${new Date().toISOString()} version: "3.0.0" swarm: topology: ${options.runtime.topology} maxAgents: ${options.runtime.maxAgents} autoScale: true coordinationStrategy: consensus memory: backend: ${options.runtime.memoryBackend} enableHNSW: ${options.runtime.enableHNSW} persistPath: .claude-flow/data cacheSize: 100 # ADR-049: Self-Learning Memory learningBridge: enabled: ${options.runtime.enableLearningBridge ?? options.runtime.enableNeural} sonaMode: balanced confidenceDecayRate: 0.005 accessBoostAmount: 0.03 consolidationThreshold: 10 memoryGraph: enabled: ${options.runtime.enableMemoryGraph ?? true} pageRankDamping: 0.85 maxNodes: 5000 similarityThreshold: 0.8 agentScopes: enabled: ${options.runtime.enableAgentScopes ?? true} defaultScope: project neural: enabled: ${options.runtime.enableNeural} modelPath: .claude-flow/neural hooks: enabled: true autoExecute: true mcp: autoStart: ${options.mcp.autoStart} port: ${options.mcp.port} `; fs.writeFileSync(configPath, config, 'utf-8'); result.created.files.push('.claude-flow/config.yaml'); // Write .gitignore const gitignorePath = path.join(targetDir, '.claude-flow', '.gitignore'); const gitignore = `# Claude Flow runtime files data/ logs/ sessions/ neural/ *.log *.tmp `; if (!fs.existsSync(gitignorePath) || options.force) { fs.writeFileSync(gitignorePath, gitignore, 'utf-8'); result.created.files.push('.claude-flow/.gitignore'); } // Write CAPABILITIES.md with full system overview await writeCapabilitiesDoc(targetDir, options, result); } /** * Write initial metrics files for statusline * Creates baseline data so statusline shows meaningful state instead of all zeros */ async function writeInitialMetrics(targetDir, options, result) { const metricsDir = path.join(targetDir, '.claude-flow', 'metrics'); const learningDir = path.join(targetDir, '.claude-flow', 'learning'); const securityDir = path.join(targetDir, '.claude-flow', 'security'); // Ensure directories exist for (const dir of [metricsDir, learningDir, securityDir]) { if (!fs.existsSync(dir)) { fs.mkdirSync(dir, { recursive: true }); } } // Create initial v3-progress.json const progressPath = path.join(metricsDir, 'v3-progress.json'); if (!fs.existsSync(progressPath) || options.force) { const progress = { version: '3.0.0', initialized: new Date().toISOString(), domains: { completed: 0, total: 5, status: 'INITIALIZING' }, ddd: { progress: 0, modules: 0, totalFiles: 0, totalLines: 0 }, swarm: { activeAgents: 0, maxAgents: options.runtime.maxAgents, topology: options.runtime.topology }, learning: { status: 'READY', patternsLearned: 0, sessionsCompleted: 0 }, _note: 'Metrics will update as you use Claude Flow. Run: npx @claude-flow/cli@latest daemon start' }; fs.writeFileSync(progressPath, JSON.stringify(progress, null, 2), 'utf-8'); result.created.files.push('.claude-flow/metrics/v3-progress.json'); } // Create initial swarm-activity.json const activityPath = path.join(metricsDir, 'swarm-activity.json'); if (!fs.existsSync(activityPath) || options.force) { const activity = { timestamp: new Date().toISOString(), processes: { agentic_flow: 0, mcp_server: 0, estimated_agents: 0 }, swarm: { active: false, agent_count: 0, coordination_active: false }, integration: { agentic_flow_active: false, mcp_active: false }, _initialized: true }; fs.writeFileSync(activityPath, JSON.stringify(activity, null, 2), 'utf-8'); result.created.files.push('.claude-flow/metrics/swarm-activity.json'); } // Create initial learning.json const learningPath = path.join(metricsDir, 'learning.json'); if (!fs.existsSync(learningPath) || options.force) { const learning = { initialized: new Date().toISOString(), routing: { accuracy: 0, decisions: 0 }, patterns: { shortTerm: 0, longTerm: 0, quality: 0 }, sessions: { total: 0, current: null }, _note: 'Intelligence grows as you use Claude Flow' }; fs.writeFileSync(learningPath, JSON.stringify(learning, null, 2), 'utf-8'); result.created.files.push('.claude-flow/metrics/learning.json'); } // Create initial audit-status.json const auditPath = path.join(securityDir, 'audit-status.json'); if (!fs.existsSync(auditPath) || options.force) { const audit = { initialized: new Date().toISOString(), status: 'PENDING', cvesFixed: 0, totalCves: 3, lastScan: null, _note: 'Run: npx @claude-flow/cli@latest security scan' }; fs.writeFileSync(auditPath, JSON.stringify(audit, null, 2), 'utf-8'); result.created.files.push('.claude-flow/security/audit-status.json'); } } /** * Write CAPABILITIES.md - comprehensive overview of all Claude Flow features */ async function writeCapabilitiesDoc(targetDir, options, result) { const capabilitiesPath = path.join(targetDir, '.claude-flow', 'CAPABILITIES.md'); if (fs.existsSync(capabilitiesPath) && !options.force) { result.skipped.push('.claude-flow/CAPABILITIES.md'); return; } const capabilities = `# Claude Flow V3 - Complete Capabilities Reference > Generated: ${new Date().toISOString()} > Full documentation: https://github.com/ruvnet/claude-flow ## 📋 Table of Contents 1. [Overview](#overview) 2. [Swarm Orchestration](#swarm-orchestration) 3. [Available Agents (60+)](#available-agents) 4. [CLI Commands (26 Commands, 140+ Subcommands)](#cli-commands) 5. [Hooks System (27 Hooks + 12 Workers)](#hooks-system) 6. [Memory & Intelligence (RuVector)](#memory--intelligence) 7. [Hive-Mind Consensus](#hive-mind-consensus) 8. [Performance Targets](#performance-targets) 9. [Integration Ecosystem](#integration-ecosystem) --- ## Overview Claude Flow V3 is a domain-driven design architecture for multi-agent AI coordination with: - **15-Agent Swarm Coordination** with hierarchical and mesh topologies - **HNSW Vector Search** - 150x-12,500x faster pattern retrieval - **SONA Neural Learning** - Self-optimizing with <0.05ms adaptation - **Byzantine Fault Tolerance** - Queen-led consensus mechanisms - **MCP Server Integration** - Model Context Protocol support ### Current Configuration | Setting | Value | |---------|-------| | Topology | ${options.runtime.topology} | | Max Agents | ${options.runtime.maxAgents} | | Memory Backend | ${options.runtime.memoryBackend} | | HNSW Indexing | ${options.runtime.enableHNSW ? 'Enabled' : 'Disabled'} | | Neural Learning | ${options.runtime.enableNeural ? 'Enabled' : 'Disabled'} | | LearningBridge | ${options.runtime.enableLearningBridge ? 'Enabled (SONA + ReasoningBank)' : 'Disabled'} | | Knowledge Graph | ${options.runtime.enableMemoryGraph ? 'Enabled (PageRank + Communities)' : 'Disabled'} | | Agent Scopes | ${options.runtime.enableAgentScopes ? 'Enabled (project/local/user)' : 'Disabled'} | --- ## Swarm Orchestration ### Topologies | Topology | Description | Best For | |----------|-------------|----------| | \`hierarchical\` | Queen controls workers directly | Anti-drift, tight control | | \`mesh\` | Fully connected peer network | Distributed tasks | | \`hierarchical-mesh\` | V3 hybrid (recommended) | 10+ agents | | \`ring\` | Circular communication | Sequential workflows | | \`star\` | Central coordinator | Simple coordin