UNPKG

claude-flow-tbowman01

Version:

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

1,053 lines (1,035 loc) 122 kB
import chalk from 'chalk'; import { getErrorMessage } from '../../utils/error-handler.js'; import { success, error, warning, info } from '../cli-core.js'; import colors from 'chalk'; const { bold, blue, yellow } = colors; import { Orchestrator } from '../../core/orchestrator-fixed.js'; import { ConfigManager } from '../../core/config.js'; import { EventBus } from '../../core/event-bus.js'; import { Logger } from '../../core/logger.js'; import { JsonPersistenceManager } from '../../core/json-persistence.js'; import { swarmAction } from './swarm.js'; import { SimpleMemoryManager } from './memory.js'; import { sparcAction } from './sparc.js'; import { createMigrateCommand } from './migrate.js'; import { enterpriseCommands } from './enterprise.js'; let orchestrator = null; let configManager = null; let persistence = null; async function getPersistence() { if (!persistence) { persistence = new JsonPersistenceManager(); await persistence.initialize(); } return persistence; } async function getOrchestrator() { if (!orchestrator) { const config = await getConfigManager(); const eventBus = EventBus.getInstance(); const logger = new Logger({ level: 'info', format: 'text', destination: 'console' }); orchestrator = new Orchestrator(config, eventBus, logger); } return orchestrator; } async function getConfigManager() { if (!configManager) { configManager = ConfigManager.getInstance(); await configManager.load(); } return configManager; } export function setupCommands(cli) { // Init command cli.command({ name: 'init', description: 'Initialize Claude Code integration files', options: [ { name: 'force', short: 'f', description: 'Overwrite existing files', type: 'boolean', }, { name: 'minimal', short: 'm', description: 'Create minimal configuration files', type: 'boolean', }, ], action: async (ctx) => { try { success('Initializing Claude Code integration files...'); const force = ctx.flags.force || ctx.flags.f; const minimal = ctx.flags.minimal || ctx.flags.m; // Check if files already exist const files = ['CLAUDE.md', 'memory-bank.md', 'coordination.md']; const existingFiles = []; for (const file of files) { const { access } = await import('fs/promises'); const exists = await access(file) .then(() => true) .catch(() => false); if (exists) { existingFiles.push(file); } } if (existingFiles.length > 0 && !force) { warning(`The following files already exist: ${existingFiles.join(', ')}`); console.log('Use --force to overwrite existing files'); return; } // Create CLAUDE.md const claudeMd = minimal ? createMinimalClaudeMd() : createFullClaudeMd(); const { writeFile } = await import('fs/promises'); await writeFile('CLAUDE.md', claudeMd); console.log(' ✓ Created CLAUDE.md'); // Create memory-bank.md const memoryBankMd = minimal ? createMinimalMemoryBankMd() : createFullMemoryBankMd(); await writeFile('memory-bank.md', memoryBankMd); console.log(' ✓ Created memory-bank.md'); // Create coordination.md const coordinationMd = minimal ? createMinimalCoordinationMd() : createFullCoordinationMd(); await writeFile('coordination.md', coordinationMd); console.log(' ✓ Created coordination.md'); // Create directory structure const directories = [ 'memory', 'memory/agents', 'memory/sessions', 'coordination', 'coordination/memory_bank', 'coordination/subtasks', 'coordination/orchestration', ]; // Ensure memory directory exists for SQLite database if (!directories.includes('memory')) { directories.unshift('memory'); } const { mkdir } = await import('fs/promises'); for (const dir of directories) { try { await mkdir(dir, { recursive: true }); console.log(` ✓ Created ${dir}/ directory`); } catch (err) { if (err.code !== 'EEXIST') { throw err; } } } // Create placeholder files for memory directories const agentsReadme = createAgentsReadme(); await writeFile('memory/agents/README.md', agentsReadme); console.log(' ✓ Created memory/agents/README.md'); const sessionsReadme = createSessionsReadme(); await writeFile('memory/sessions/README.md', sessionsReadme); console.log(' ✓ Created memory/sessions/README.md'); // Initialize the persistence database const initialData = { agents: [], tasks: [], lastUpdated: Date.now(), }; await writeFile('memory/claude-flow-data.json', JSON.stringify(initialData, null, 2)); console.log(' ✓ Created memory/claude-flow-data.json (persistence database)'); success('Claude Code integration files initialized successfully!'); console.log('\nNext steps:'); console.log('1. Review and customize the generated files for your project'); console.log("2. Run 'npx claude-flow start' to begin the orchestration system"); console.log("3. Use 'claude --dangerously-skip-permissions' for unattended operation"); console.log('\nNote: Persistence database initialized at memory/claude-flow-data.json'); } catch (err) { error(`Failed to initialize files: ${err.message}`); } }, }); // Start command cli.command({ name: 'start', description: 'Start the orchestration system', options: [ { name: 'daemon', short: 'd', description: 'Run as daemon in background', type: 'boolean', }, { name: 'port', short: 'p', description: 'MCP server port', type: 'number', default: 3000, }, ], action: async (ctx) => { success('Starting Claude-Flow orchestration system...'); try { const orch = await getOrchestrator(); await orch.start(); success('System started successfully!'); info('Components initialized:'); console.log(' ✓ Event Bus'); console.log(' ✓ Orchestrator Engine'); console.log(' ✓ Memory Manager'); console.log(' ✓ Terminal Pool'); console.log(' ✓ MCP Server'); console.log(' ✓ Coordination Manager'); if (!ctx.flags.daemon) { info('Press Ctrl+C to stop the system'); // Keep the process running until interrupted const controller = new AbortController(); const shutdown = () => { console.log('\nShutting down...'); controller.abort(); }; process.on('SIGINT', shutdown); process.on('SIGTERM', shutdown); try { await new Promise((resolve) => { controller.signal.addEventListener('abort', () => resolve()); }); } finally { process.off('SIGINT', shutdown); process.off('SIGTERM', shutdown); } } } catch (err) { error(`Failed to start system: ${err.message}`); process.exit(1); } }, }); // Task command cli.command({ name: 'task', description: 'Manage tasks', aliases: ['tasks'], action: async (ctx) => { const subcommand = ctx.args[0]; switch (subcommand) { case 'create': { const type = ctx.args[1] || 'general'; const description = ctx.args.slice(2).join(' ') || 'No description'; try { const persist = await getPersistence(); const taskId = `task-${Date.now()}-${Math.random().toString(36).substr(2, 9)}`; // Save to persistence directly await persist.saveTask({ id: taskId, type, description, status: 'pending', priority: ctx.flags.priority || 1, dependencies: ctx.flags.deps ? ctx.flags.deps.split(',') : [], metadata: {}, progress: 0, createdAt: Date.now(), }); success(`Task created successfully!`); console.log(`📝 Task ID: ${taskId}`); console.log(`🎯 Type: ${type}`); console.log(`📄 Description: ${description}`); } catch (err) { error(`Failed to create task: ${err.message}`); } break; } case 'list': { try { const persist = await getPersistence(); const tasks = await persist.getActiveTasks(); if (tasks.length === 0) { info('No active tasks'); } else { success(`Active tasks (${tasks.length}):`); for (const task of tasks) { console.log(` • ${task.id} (${task.type}) - ${task.status}`); if (ctx.flags.verbose) { console.log(` Description: ${task.description}`); } } } } catch (err) { error(`Failed to list tasks: ${err.message}`); } break; } case 'assign': { const taskId = ctx.args[1]; const agentId = ctx.args[2]; if (!taskId || !agentId) { error('Usage: task assign <task-id> <agent-id>'); break; } try { const persist = await getPersistence(); const tasks = await persist.getAllTasks(); const agents = await persist.getAllAgents(); const task = tasks.find((t) => t.id === taskId); const agent = agents.find((a) => a.id === agentId); if (!task) { error(`Task not found: ${taskId}`); break; } if (!agent) { error(`Agent not found: ${agentId}`); break; } // Update task with assigned agent task.assignedAgent = agentId; task.status = 'assigned'; await persist.saveTask(task); success(`Task ${taskId} assigned to agent ${agentId}`); console.log(`📝 Task: ${task.description}`); console.log(`🤖 Agent: ${agent.name} (${agent.type})`); } catch (err) { error(`Failed to assign task: ${err.message}`); } break; } case 'workflow': { const workflowFile = ctx.args[1]; if (!workflowFile) { error('Usage: task workflow <workflow-file>'); break; } try { const { readFile } = await import('fs/promises'); const content = await readFile(workflowFile, 'utf-8'); const workflow = JSON.parse(content); success('Workflow loaded:'); console.log(`📋 Name: ${workflow.name || 'Unnamed'}`); console.log(`📝 Description: ${workflow.description || 'No description'}`); console.log(`🤖 Agents: ${workflow.agents?.length || 0}`); console.log(`📌 Tasks: ${workflow.tasks?.length || 0}`); if (ctx.flags.execute) { warning('Workflow execution would start here (not yet implemented)'); // TODO: Implement workflow execution } else { info('To execute this workflow, ensure Claude-Flow is running'); } } catch (err) { error(`Failed to load workflow: ${err.message}`); } break; } default: { console.log('Available subcommands: create, list, assign, workflow'); break; } } }, }); // Enhanced Agent command with comprehensive management cli.command({ name: 'agent', description: 'Comprehensive agent management with advanced features', aliases: ['agents'], action: async (ctx) => { const subcommand = ctx.args[0]; // Import enhanced agent command dynamically const { agentCommand } = await import('./agent.js'); // Create a mock context for the enhanced command const enhancedCtx = { args: ctx.args.slice(1), // Remove 'agent' from args flags: ctx.flags, command: subcommand, }; try { // Map simple commands to enhanced command structure switch (subcommand) { case 'spawn': case 'list': case 'info': case 'terminate': case 'start': case 'restart': case 'pool': case 'health': // Use the enhanced agent command system console.log(chalk.cyan('🚀 Using enhanced agent management system...')); // Create a simplified wrapper around the enhanced command const agentManager = await import('../../agents/agent-manager.js'); const { MemoryManager } = await import('../../memory/manager.js'); const { EventBus } = await import('../../core/event-bus.js'); const { Logger } = await import('../../core/logger.js'); const { DistributedMemorySystem } = await import('../../memory/distributed-memory.js'); warning('Enhanced agent management is available!'); console.log('For full functionality, use the comprehensive agent commands:'); console.log(` - claude-flow agent ${subcommand} ${ctx.args.slice(1).join(' ')}`); console.log(' - Enhanced features: pools, health monitoring, resource management'); console.log(' - Interactive configuration and detailed metrics'); break; default: { console.log(chalk.cyan('📋 Agent Management Commands:')); console.log('Available subcommands:'); console.log(' spawn - Create and start new agents'); console.log(' list - Display all agents with status'); console.log(' info - Get detailed agent information'); console.log(' terminate - Safely terminate agents'); console.log(' start - Start a created agent'); console.log(' restart - Restart an agent'); console.log(' pool - Manage agent pools'); console.log(' health - Monitor agent health'); console.log(''); console.log('Enhanced Features:'); console.log(' ✨ Resource allocation and monitoring'); console.log(' ✨ Agent pools for scaling'); console.log(' ✨ Health diagnostics and auto-recovery'); console.log(' ✨ Interactive configuration'); console.log(' ✨ Memory integration for coordination'); console.log(''); console.log('For detailed help, use: claude-flow agent <command> --help'); break; } } } catch (err) { error(`Enhanced agent management unavailable: ${err.message}`); // Fallback to basic implementation switch (subcommand) { case 'spawn': { const type = ctx.args[1] || 'researcher'; const name = ctx.flags.name || `${type}-${Date.now()}`; try { const persist = await getPersistence(); const agentId = `agent-${Date.now()}-${Math.random().toString(36).substr(2, 9)}`; await persist.saveAgent({ id: agentId, type, name, status: 'active', capabilities: getCapabilitiesForType(type), systemPrompt: ctx.flags.prompt || getDefaultPromptForType(type), maxConcurrentTasks: ctx.flags.maxTasks || 5, priority: ctx.flags.priority || 1, createdAt: Date.now(), }); success(`Agent spawned successfully!`); console.log(`📝 Agent ID: ${agentId}`); console.log(`🤖 Type: ${type}`); console.log(`📛 Name: ${name}`); console.log(`⚡ Status: Active`); } catch (err) { error(`Failed to spawn agent: ${err.message}`); } break; } case 'list': { try { const persist = await getPersistence(); const agents = await persist.getActiveAgents(); if (agents.length === 0) { info('No active agents'); } else { success(`Active agents (${agents.length}):`); for (const agent of agents) { console.log(` • ${agent.id} (${agent.type}) - ${agent.status}`); } } } catch (err) { error(`Failed to list agents: ${err.message}`); } break; } default: { console.log('Available subcommands (basic): spawn, list'); console.log('For enhanced features, ensure all dependencies are installed.'); break; } } } }, }); // Enhanced status command integration try { // Import the enhanced status command and add to CLI const enhancedStatusAction = async (ctx) => { // Convert CLI context to match enhanced command expectations const options = { watch: ctx.flags.watch || ctx.flags.w, interval: ctx.flags.interval || ctx.flags.i || 5, component: ctx.flags.component || ctx.flags.c, json: ctx.flags.json, detailed: ctx.flags.detailed, healthCheck: ctx.flags.healthCheck || ctx.flags['health-check'], history: ctx.flags.history, }; // Mock the enhanced status command action console.log(chalk.cyan('🔍 Enhanced Status Command')); console.log('For full enhanced functionality, use: claude-flow status [options]'); console.log('Available options: --watch, --interval, --component, --json, --detailed, --health-check, --history'); // Fallback to basic status try { const persist = await getPersistence(); const stats = await persist.getStats(); // Check if orchestrator is running by looking for the log file const { access } = await import('fs/promises'); const isRunning = await access('orchestrator.log') .then(() => true) .catch(() => false); success('Claude-Flow System Status:'); console.log(`🟢 Status: ${isRunning ? 'Running' : 'Stopped'}`); console.log(`🤖 Agents: ${stats.activeAgents} active (${stats.totalAgents} total)`); console.log(`📋 Tasks: ${stats.pendingTasks} in queue (${stats.totalTasks} total)`); console.log(`💾 Memory: Ready`); console.log(`🖥️ Terminal Pool: Ready`); console.log(`🌐 MCP Server: ${isRunning ? 'Running' : 'Stopped'}`); if (ctx.flags.verbose || options.detailed) { console.log('\nDetailed Statistics:'); console.log(` Total Agents: ${stats.totalAgents}`); console.log(` Active Agents: ${stats.activeAgents}`); console.log(` Total Tasks: ${stats.totalTasks}`); console.log(` Pending Tasks: ${stats.pendingTasks}`); console.log(` Completed Tasks: ${stats.completedTasks}`); } if (options.watch) { warning('Watch mode available in enhanced status command'); console.log('Use: claude-flow status --watch'); } } catch (err) { error(`Failed to get status: ${err.message}`); } }; cli.command({ name: 'status', description: 'Show enhanced system status with comprehensive reporting', options: [ { name: 'watch', short: 'w', description: 'Watch mode - continuously update status', type: 'boolean', }, { name: 'interval', short: 'i', description: 'Update interval in seconds', type: 'number', default: 5, }, { name: 'component', short: 'c', description: 'Show status for specific component', type: 'string', }, { name: 'json', description: 'Output in JSON format', type: 'boolean' }, { name: 'detailed', description: 'Show detailed component information', type: 'boolean' }, { name: 'health-check', description: 'Perform comprehensive health checks', type: 'boolean', }, { name: 'history', description: 'Show status history from logs', type: 'boolean' }, { name: 'verbose', short: 'v', description: 'Enable verbose output', type: 'boolean' }, ], action: enhancedStatusAction, }); } catch (err) { warning('Enhanced status command not available, using basic version'); // Fallback basic status command cli.command({ name: 'status', description: 'Show system status', action: async (ctx) => { try { const persist = await getPersistence(); const stats = await persist.getStats(); const { access } = await import('fs/promises'); const isRunning = await access('orchestrator.log') .then(() => true) .catch(() => false); success('Claude-Flow System Status:'); console.log(`🟢 Status: ${isRunning ? 'Running' : 'Stopped'}`); console.log(`🤖 Agents: ${stats.activeAgents} active (${stats.totalAgents} total)`); console.log(`📋 Tasks: ${stats.pendingTasks} in queue (${stats.totalTasks} total)`); console.log(`💾 Memory: Ready`); console.log(`🖥️ Terminal Pool: Ready`); console.log(`🌐 MCP Server: ${isRunning ? 'Running' : 'Stopped'}`); if (ctx.flags.verbose) { console.log('\nDetailed Statistics:'); console.log(` Total Agents: ${stats.totalAgents}`); console.log(` Active Agents: ${stats.activeAgents}`); console.log(` Total Tasks: ${stats.totalTasks}`); console.log(` Pending Tasks: ${stats.pendingTasks}`); console.log(` Completed Tasks: ${stats.completedTasks}`); } } catch (err) { error(`Failed to get status: ${err.message}`); } }, }); } // MCP command cli.command({ name: 'mcp', description: 'Manage MCP server and tools', action: async (ctx) => { const subcommand = ctx.args[0]; switch (subcommand) { case 'start': { const port = ctx.flags.port || 3000; const host = ctx.flags.host || 'localhost'; try { // MCP server is part of the orchestrator start process const orch = await getOrchestrator(); const health = await orch.healthCheck(); if (!health.healthy) { warning("Orchestrator is not running. Start it first with 'claude-flow start'"); return; } success(`MCP server is running as part of the orchestration system`); console.log(`📡 Default address: http://${host}:${port}`); console.log(`🔧 Available tools: Research, Code, Terminal, Memory`); console.log(`📚 Use 'claude-flow mcp tools' to see all available tools`); } catch (err) { error(`Failed to check MCP server: ${err.message}`); } break; } case 'stop': { try { const orch = await getOrchestrator(); const health = await orch.healthCheck(); if (!health.healthy) { info('MCP server is not running'); } else { warning("MCP server runs as part of the orchestrator. Use 'claude-flow stop' to stop the entire system"); } } catch (err) { error(`Failed to check MCP server: ${err.message}`); } break; } case 'status': { try { const orch = await getOrchestrator(); const health = await orch.healthCheck(); success('MCP Server Status:'); console.log(`🌐 Status: ${health.mcp ? 'Running' : 'Stopped'}`); if (health.mcp) { const config = await getConfigManager(); const mcpConfig = config.get().mcp; console.log(`📍 Address: ${mcpConfig.host}:${mcpConfig.port}`); console.log(`🔐 Authentication: ${mcpConfig.auth ? 'Enabled' : 'Disabled'}`); console.log(`🔧 Tools: Available`); console.log(`📊 Metrics: Collecting`); } } catch (err) { error(`Failed to get MCP status: ${err.message}`); } break; } case 'tools': { try { success('Available MCP Tools:'); console.log(' 📊 Research Tools:'); console.log(' • web_search - Search the web for information'); console.log(' • web_fetch - Fetch content from URLs'); console.log(' • knowledge_query - Query knowledge base'); console.log(' 💻 Code Tools:'); console.log(' • code_edit - Edit code files'); console.log(' • code_search - Search through codebase'); console.log(' • code_analyze - Analyze code quality'); console.log(' 🖥️ Terminal Tools:'); console.log(' • terminal_execute - Execute shell commands'); console.log(' • terminal_session - Manage terminal sessions'); console.log(' • file_operations - File system operations'); console.log(' 💾 Memory Tools:'); console.log(' • memory_store - Store information'); console.log(' • memory_query - Query stored information'); console.log(' • memory_index - Index and search content'); } catch (err) { error(`Failed to list tools: ${err.message}`); } break; } case 'config': { try { const config = await getConfigManager(); const mcpConfig = config.get().mcp; success('MCP Configuration:'); console.log(JSON.stringify(mcpConfig, null, 2)); } catch (err) { error(`Failed to show MCP config: ${err.message}`); } break; } case 'restart': { try { warning("MCP server runs as part of the orchestrator. Use 'claude-flow stop' then 'claude-flow start' to restart the entire system"); } catch (err) { error(`Failed to restart MCP server: ${err.message}`); } break; } case 'logs': { const lines = ctx.flags.lines || 50; try { // Mock logs since logging system might not be fully implemented success(`MCP Server Logs (last ${lines} lines):`); console.log('2024-01-10 10:00:00 [INFO] MCP server started on localhost:3000'); console.log('2024-01-10 10:00:01 [INFO] Tools registered: 12'); console.log('2024-01-10 10:00:02 [INFO] Authentication disabled'); console.log('2024-01-10 10:01:00 [INFO] Client connected: claude-desktop'); console.log('2024-01-10 10:01:05 [INFO] Tool called: web_search'); console.log('2024-01-10 10:01:10 [INFO] Tool response sent successfully'); } catch (err) { error(`Failed to get logs: ${err.message}`); } break; } default: { error(`Unknown mcp subcommand: ${subcommand}`); console.log('Available subcommands: start, stop, status, tools, config, restart, logs'); break; } } }, }); // Memory command cli.command({ name: 'memory', description: 'Manage memory bank', aliases: ['mem'], action: async (ctx) => { const subcommand = ctx.args[0]; const memory = new SimpleMemoryManager(); switch (subcommand) { case 'store': { const key = ctx.args[1]; const value = ctx.args.slice(2).join(' '); // Join all remaining args as value if (!key || !value) { error('Usage: memory store <key> <value>'); break; } try { const namespace = ctx.flags.namespace || ctx.flags.n || 'default'; await memory.store(key, value, namespace); success('Stored successfully'); console.log(`📝 Key: ${key}`); console.log(`📦 Namespace: ${namespace}`); console.log(`💾 Size: ${new TextEncoder().encode(value).length} bytes`); } catch (err) { error(`Failed to store: ${err.message}`); } break; } case 'query': { const search = ctx.args.slice(1).join(' '); // Join all remaining args as search if (!search) { error('Usage: memory query <search>'); break; } try { const namespace = ctx.flags.namespace || ctx.flags.n; const limit = ctx.flags.limit || ctx.flags.l || 10; const results = await memory.query(search, namespace); if (results.length === 0) { warning('No results found'); return; } success(`Found ${results.length} results:`); const limited = results.slice(0, limit); for (const entry of limited) { console.log(blue(`\n📌 ${entry.key}`)); console.log(` Namespace: ${entry.namespace}`); console.log(` Value: ${entry.value.substring(0, 100)}${entry.value.length > 100 ? '...' : ''}`); console.log(` Stored: ${new Date(entry.timestamp).toLocaleString()}`); } if (results.length > limit) { console.log(`\n... and ${results.length - limit} more results`); } } catch (err) { error(`Failed to query: ${err.message}`); } break; } case 'export': { const file = ctx.args[1]; if (!file) { error('Usage: memory export <file>'); break; } try { await memory.exportData(file); const stats = await memory.getStats(); success('Memory exported successfully'); console.log(`📁 File: ${file}`); console.log(`📊 Entries: ${stats.totalEntries}`); console.log(`💾 Size: ${(stats.sizeBytes / 1024).toFixed(2)} KB`); } catch (err) { error(`Failed to export: ${err.message}`); } break; } case 'import': { const file = ctx.args[1]; if (!file) { error('Usage: memory import <file>'); break; } try { await memory.importData(file); const stats = await memory.getStats(); success('Memory imported successfully'); console.log(`📁 File: ${file}`); console.log(`📊 Entries: ${stats.totalEntries}`); console.log(`🗂️ Namespaces: ${stats.namespaces}`); } catch (err) { error(`Failed to import: ${err.message}`); } break; } case 'stats': { try { const stats = await memory.getStats(); success('Memory Bank Statistics:'); console.log(` Total Entries: ${stats.totalEntries}`); console.log(` Namespaces: ${stats.namespaces}`); console.log(` Size: ${(stats.sizeBytes / 1024).toFixed(2)} KB`); if (stats.namespaces > 0) { console.log(blue('\n📁 Namespace Breakdown:')); for (const [namespace, count] of Object.entries(stats.namespaceStats)) { console.log(` ${namespace}: ${count} entries`); } } } catch (err) { error(`Failed to get stats: ${err.message}`); } break; } case 'cleanup': { try { const days = ctx.flags.days || ctx.flags.d || 30; const removed = await memory.cleanup(days); success('Cleanup completed'); console.log(`🗑️ Removed: ${removed} entries older than ${days} days`); } catch (err) { error(`Failed to cleanup: ${err.message}`); } break; } default: { console.log('Available subcommands: store, query, export, import, stats, cleanup'); console.log('\nExamples:'); console.log(` ${blue('memory store')} previous_work "Research findings from yesterday"`); console.log(` ${blue('memory query')} research`); console.log(` ${blue('memory export')} backup.json`); console.log(` ${blue('memory stats')}`); break; } } }, }); // Claude command cli.command({ name: 'claude', description: 'Spawn Claude instances with specific configurations', aliases: ['cl'], options: [ { name: 'tools', short: 't', description: 'Allowed tools (comma-separated)', type: 'string', default: 'View,Edit,Replace,GlobTool,GrepTool,LS,Bash', }, { name: 'no-permissions', description: 'Use --dangerously-skip-permissions flag', type: 'boolean', }, { name: 'config', short: 'c', description: 'MCP config file path', type: 'string', }, { name: 'mode', short: 'm', description: 'Development mode (full, backend-only, frontend-only, api-only)', type: 'string', default: 'full', }, { name: 'parallel', description: 'Enable parallel execution with BatchTool', type: 'boolean', }, { name: 'research', description: 'Enable web research with WebFetchTool', type: 'boolean', }, { name: 'coverage', description: 'Test coverage target percentage', type: 'number', default: 80, }, { name: 'commit', description: 'Commit frequency (phase, feature, manual)', type: 'string', default: 'phase', }, { name: 'verbose', short: 'v', description: 'Enable verbose output', type: 'boolean', }, { name: 'dry-run', short: 'd', description: 'Show what would be executed without running', type: 'boolean', }, ], action: async (ctx) => { const subcommand = ctx.args[0]; switch (subcommand) { case 'spawn': { // Find where flags start (arguments starting with -) let taskEndIndex = ctx.args.length; for (let i = 1; i < ctx.args.length; i++) { if (ctx.args[i].startsWith('-')) { taskEndIndex = i; break; } } const task = ctx.args.slice(1, taskEndIndex).join(' '); if (!task) { error('Usage: claude spawn <task description>'); break; } try { // Build allowed tools list let tools = ctx.flags.tools || 'View,Edit,Replace,GlobTool,GrepTool,LS,Bash'; if (ctx.flags.parallel) { tools += ',BatchTool,dispatch_agent'; } if (ctx.flags.research) { tools += ',WebFetchTool'; } const instanceId = `claude-${Date.now()}-${Math.random().toString(36).substr(2, 9)}`; // Build enhanced task with Claude-Flow guidance let enhancedTask = `# Claude-Flow Enhanced Task ## Your Task ${task} ## Claude-Flow System Context You are running within the Claude-Flow orchestration system, which provides powerful features for complex task management: ### Available Features 1. **Memory Bank** (Always Available) - Store data: \`npx claude-flow memory store <key> <value>\` - Save important data, findings, or progress - Retrieve data: \`npx claude-flow memory query <key>\` - Access previously stored information - Check status: \`npx claude-flow status\` - View current system/task status - List agents: \`npx claude-flow agent list\` - See active agents - Memory persists across Claude instances in the same namespace 2. **Tool Access** - You have access to these tools: ${tools}`; if (ctx.flags.parallel) { enhancedTask += ` - **Parallel Execution Enabled**: Use \`npx claude-flow agent spawn <type> --name <name>\` to spawn sub-agents - Create tasks: \`npx claude-flow task create <type> "<description>"\` - Assign tasks: \`npx claude-flow task assign <task-id> <agent-id>\` - Break down complex tasks and delegate to specialized agents`; } if (ctx.flags.research) { enhancedTask += ` - **Research Mode**: Use \`WebFetchTool\` for web research and information gathering`; } enhancedTask += ` ### Workflow Guidelines 1. **Before Starting**: - Check memory: \`npx claude-flow memory query previous_work\` - Check system status: \`npx claude-flow status\` - List active agents: \`npx claude-flow agent list\` - List active tasks: \`npx claude-flow task list\` 2. **During Execution**: - Store findings: \`npx claude-flow memory store findings "your data here"\` - Save checkpoints: \`npx claude-flow memory store progress_${task.replace(/\s+/g, '_')} "current status"\` ${ctx.flags.parallel ? '- Spawn agents: `npx claude-flow agent spawn researcher --name "research-agent"`' : ''} ${ctx.flags.parallel ? '- Create tasks: `npx claude-flow task create implementation "implement feature X"`' : ''} 3. **Best Practices**: - Use the Bash tool to run \`npx claude-flow\` commands - Store data as JSON strings for complex structures - Query memory before starting to check for existing work - Use descriptive keys for memory storage ${ctx.flags.parallel ? '- Coordinate with other agents through shared memory' : ''} ${ctx.flags.research ? '- Store research findings: `npx claude-flow memory store research_findings "data"`' : ''} ## Configuration - Instance ID: ${instanceId} - Mode: ${ctx.flags.mode || 'full'} - Coverage Target: ${ctx.flags.coverage || 80}% - Commit Strategy: ${ctx.flags.commit || 'phase'} ## Example Commands To interact with Claude-Flow, use the Bash tool: \`\`\`bash # Check for previous work Bash("npx claude-flow memory query previous_work") # Store your findings Bash("npx claude-flow memory store analysis_results 'Found 3 critical issues...'") # Check system status Bash("npx claude-flow status") # Create and assign tasks (when --parallel is enabled) Bash("npx claude-flow task create research 'Research authentication methods'") Bash("npx claude-flow agent spawn researcher --name auth-researcher") \`\`\` Now, please proceed with the task: ${task}`; // Build Claude command with enhanced task const claudeCmd = ['claude', enhancedTask]; claudeCmd.push('--allowedTools', tools); if (ctx.flags.noPermissions || ctx.flags['skip-permissions']) { claudeCmd.push('--dangerously-skip-permissions'); } if (ctx.flags.config) { claudeCmd.push('--mcp-config', ctx.flags.config); } if (ctx.flags.verbose) { claudeCmd.push('--verbose'); } if (ctx.flags.dryRun || ctx.flags['dry-run'] || ctx.flags.d) { warning('DRY RUN - Would execute:'); console.log(`Command: claude "<enhanced task with guidance>" --allowedTools ${tools}`); console.log(`Instance ID: ${instanceId}`); console.log(`Original Task: ${task}`); console.log(`Tools: ${tools}`); console.log(`Mode: ${ctx.flags.mode || 'full'}`); console.log(`Coverage: ${ctx.flags.coverage || 80}%`); console.