UNPKG

@codemafia0000/d0

Version:

Claude Multi-Agent Automated Development AI - Revolutionary development environment where multiple AI agents collaborate to automate software development

1,509 lines (1,266 loc) 106 kB
#!/usr/bin/env node const { Command } = require('commander'); const chalk = require('chalk'); const ora = require('ora'); const fs = require('fs'); const path = require('path'); const { execSync, spawn } = require('child_process'); const os = require('os'); const program = new Command(); // Read version from package.json const packageJson = JSON.parse(fs.readFileSync(path.join(__dirname, '..', 'package.json'), 'utf8')); // Version information program .name('d0') .description('Claude Multi-Agent Automated Development AI - Revolutionary collaborative AI development environment') .version(packageJson.version); // Global configuration const CONFIG_DIR = path.join(os.homedir(), '.d0'); const PROJECT_TEMPLATE_DIR = path.join(__dirname, '..', 'templates'); // Helper functions function ensureConfigDir() { if (!fs.existsSync(CONFIG_DIR)) { fs.mkdirSync(CONFIG_DIR, { recursive: true }); } } // Setup project function (shared by init and setup commands) async function setupProject(options) { const spinner = ora('Setting up Claude agents environment...').start(); try { // Validate number of workers const numWorkers = parseInt(options.workers, 10); if (isNaN(numWorkers) || numWorkers < 1 || numWorkers > 10) { spinner.fail('Number of workers must be between 1 and 10'); process.exit(1); } // Check prerequisites (Claude CLI only, no tmux required) spinner.text = 'Checking prerequisites...'; if (!checkClaudeCLI()) { spinner.fail('Claude CLI is not installed. Please install Claude CLI first.'); console.log(chalk.yellow('Install Claude CLI: https://docs.anthropic.com/en/docs/claude-code')); process.exit(1); } // Create .d0 directory first const currentDir = process.cwd(); const d0Dir = path.join(currentDir, '.d0'); // Handle existing .d0 (file or directory) if (fs.existsSync(d0Dir)) { const stats = fs.statSync(d0Dir); if (stats.isFile()) { // Remove existing .d0 file to create directory fs.unlinkSync(d0Dir); fs.mkdirSync(d0Dir); } else if (stats.isDirectory()) { // Directory already exists, that's fine } } else { fs.mkdirSync(d0Dir); } // Check and setup Claude CLI authentication (shared across all agents) spinner.text = 'Setting up Claude CLI authentication...'; const claudeConfigDir = path.join(d0Dir, 'claude'); if (!fs.existsSync(claudeConfigDir)) { fs.mkdirSync(claudeConfigDir, { recursive: true }); } let claudeAuth = false; try { // Try to run a simple claude command to check auth status with timeout execSync('claude auth status', { stdio: 'ignore', timeout: 5000 }); claudeAuth = true; spinner.text = 'Claude CLI already authenticated'; // Copy Claude config to project for sharing const homeClaudeDir = path.join(os.homedir(), '.claude'); if (fs.existsSync(homeClaudeDir)) { fs.cpSync(homeClaudeDir, claudeConfigDir, { recursive: true, force: true }); spinner.text = 'Claude CLI configuration shared with project'; } } catch { claudeAuth = false; spinner.warn('Claude CLI authentication required'); console.log(chalk.yellow('\n⚠️ Setting up Claude CLI authentication...')); console.log(chalk.blue('This will open your browser for one-time authentication.')); try { // Use spawn for interactive auth const authProcess = spawn('claude', ['auth', 'login'], { stdio: 'inherit' }); // Wait for auth process to complete await new Promise((resolve, reject) => { authProcess.on('exit', (code) => { if (code === 0) { resolve(); } else { reject(new Error(`Authentication failed with code ${code}`)); } }); }); // Copy the new authentication to project const homeClaudeDir = path.join(os.homedir(), '.claude'); if (fs.existsSync(homeClaudeDir)) { fs.cpSync(homeClaudeDir, claudeConfigDir, { recursive: true, force: true }); spinner.text = 'Authentication completed and shared'; claudeAuth = true; } } catch (authError) { spinner.warn('Authentication setup failed'); console.log(chalk.yellow('\n⚠️ Manual setup required:')); console.log(chalk.gray('Please run: claude auth login')); console.log(chalk.gray('Then run: d0 init again')); } } // Check existing project if (isProjectSetup() && !options.force) { spinner.fail('Claude agents environment already exists in this directory.'); console.log(chalk.yellow('Use --force to overwrite existing setup.')); process.exit(1); } spinner.text = 'Copying template files...'; // Copy template files const templatePath = path.join(__dirname, '..', 'templates'); // Copy main files const filesToCopy = [ 'CLAUDE.md' ]; for (const file of filesToCopy) { const srcPath = path.join(templatePath, file); const destPath = path.join(currentDir, file); if (fs.existsSync(srcPath)) { fs.copyFileSync(srcPath, destPath); console.log(` ✓ Copied ${file}`); } } // .d0 directory already created above // Create tmp subdirectory const setupTmpDir = path.join(d0Dir, 'tmp'); if (!fs.existsSync(setupTmpDir)) { fs.mkdirSync(setupTmpDir); } // Create instructions subdirectory and copy instructions files const instructionsDir = path.join(d0Dir, 'instructions'); if (!fs.existsSync(instructionsDir)) { fs.mkdirSync(instructionsDir); } // Copy instructions files to .d0/instructions/ const templateInstructionsPath = path.join(__dirname, '..', 'templates', 'instructions'); if (fs.existsSync(templateInstructionsPath)) { fs.cpSync(templateInstructionsPath, instructionsDir, { recursive: true, force: true }); } // Dynamic files are no longer needed - using file-based communication fs.writeFileSync(path.join(d0Dir, 'config.json'), JSON.stringify({ created: new Date().toISOString(), version: '1.0.0', workers: numWorkers }, null, 2)); // Legacy marker is not needed since we're using the .d0 directory structure // The directory itself serves as the project marker // Initialize history management getHistoryDir(); hookAgentCommunication(); // Update .gitignore to exclude temporary files const gitignoreUpdated = updateGitignore(currentDir); // Log session start await logSessionEvent('setup', { type: 'basic' }); spinner.succeed('Claude agents environment setup completed!'); console.log(chalk.green('\n✅ Setup completed successfully!')); if (gitignoreUpdated) { console.log(chalk.blue('📝 Updated .gitignore to exclude temporary files')); } // Setup shell completion await setupShellCompletion(); console.log(chalk.green('\n🔧 Configuration complete:')); console.log(chalk.gray(' • Claude CLI authentication: ') + (claudeAuth ? chalk.green('✓ Configured') : chalk.yellow('⚠ Requires manual setup'))); console.log(chalk.gray(' • Agent configuration: ') + chalk.green('✓ Ready')); console.log(chalk.gray(' • Communication system: ') + chalk.green('✓ Initialized')); console.log(chalk.yellow('\n🚀 Ready to start:')); console.log(chalk.blue(' d0 start') + chalk.gray(' - Launch all agents automatically')); console.log(chalk.gray('\nThen:')); console.log(chalk.blue(' d0 tell "Create a todo app"') + chalk.gray(' - Start your first project')); } catch (error) { spinner.fail('Setup failed'); console.error(chalk.red(error.message)); process.exit(1); } } function updateGitignore(projectDir) { const gitignorePath = path.join(projectDir, '.gitignore'); // Define what should be ignored in .d0 directory const d0IgnoreEntries = [ '', '# Claude Agents - temporary and local files', '.d0/tmp/', '.d0/history/', '# Keep config.json and instructions but ignore sensitive data', '# .d0/config.json # Uncomment this line if config contains sensitive data', '# .d0/instructions/ # Uncomment this line if you want to exclude instructions from git', '' ]; let gitignoreContent = ''; // Read existing .gitignore if it exists if (fs.existsSync(gitignorePath)) { gitignoreContent = fs.readFileSync(gitignorePath, 'utf8'); } // Check if our entries already exist const hasD0Entries = gitignoreContent.includes('# Claude Agents - temporary and local files'); if (!hasD0Entries) { // Add our entries to .gitignore if (gitignoreContent && !gitignoreContent.endsWith('\n')) { gitignoreContent += '\n'; } gitignoreContent += d0IgnoreEntries.join('\n'); fs.writeFileSync(gitignorePath, gitignoreContent); return true; // Indicates .gitignore was updated } return false; // No update needed } // Setup shell completion automatically async function setupShellCompletion() { try { // Detect user's shell const userShell = process.env.SHELL || ''; let shellType = ''; if (userShell.includes('bash')) { shellType = 'bash'; } else if (userShell.includes('zsh')) { shellType = 'zsh'; } else { // Skip automatic setup for unknown shells console.log(chalk.blue('\n💡 Shell completion available:')); console.log(chalk.gray(' Run: d0 completion bash (for Bash)')); console.log(chalk.gray(' Run: d0 completion zsh (for Zsh)')); return; } console.log(chalk.blue(`\n🔧 Setting up ${shellType} completion...`)); const completionDir = path.join(__dirname, '..', 'completions'); const homeDir = os.homedir(); if (shellType === 'bash') { const bashCompletionSource = path.join(completionDir, 'd0-completion.bash'); const bashCompletionTarget = path.join(homeDir, '.bash_completion.d', 'd0'); // Check if completion is already installed if (fs.existsSync(bashCompletionTarget)) { console.log(chalk.blue(' ℹ️ Bash completion already installed')); return; } // Create .bash_completion.d directory if it doesn't exist const bashCompletionDir = path.join(homeDir, '.bash_completion.d'); if (!fs.existsSync(bashCompletionDir)) { fs.mkdirSync(bashCompletionDir, { recursive: true }); } // Copy completion script fs.copyFileSync(bashCompletionSource, bashCompletionTarget); console.log(chalk.green(' ✅ Bash completion installed')); console.log(chalk.yellow(' 💡 To activate: source ~/.bash_completion.d/d0')); console.log(chalk.gray(' Or restart your terminal')); } else if (shellType === 'zsh') { const zshCompletionSource = path.join(completionDir, '_d0'); // Find zsh completion directory let zshCompletionDir = ''; const zshDirs = [ '/opt/homebrew/share/zsh/site-functions', '/usr/local/share/zsh/site-functions', path.join(homeDir, '.oh-my-zsh', 'custom', 'completions'), path.join(homeDir, '.zsh', 'completions') ]; // Check if completion is already installed in any of these directories let alreadyInstalled = false; for (const dir of zshDirs) { const targetPath = path.join(dir, '_d0'); if (fs.existsSync(targetPath)) { console.log(chalk.blue(' ℹ️ Zsh completion already installed')); alreadyInstalled = true; break; } } if (alreadyInstalled) { return; } // Find writable directory for installation for (const dir of zshDirs) { if (fs.existsSync(dir)) { zshCompletionDir = dir; break; } } if (!zshCompletionDir) { // Create custom completion directory zshCompletionDir = path.join(homeDir, '.zsh', 'completions'); fs.mkdirSync(zshCompletionDir, { recursive: true }); } const zshCompletionTarget = path.join(zshCompletionDir, '_d0'); fs.copyFileSync(zshCompletionSource, zshCompletionTarget); console.log(chalk.green(' ✅ Zsh completion installed')); console.log(chalk.yellow(` 💡 To activate: Add to ~/.zshrc:`)); console.log(chalk.blue(` fpath=(${zshCompletionDir} $fpath)`)); console.log(chalk.blue(' autoload -U compinit && compinit')); console.log(chalk.gray(' Or restart your terminal')); } } catch (error) { console.log(chalk.yellow('\n⚠️ Could not setup shell completion automatically')); console.log(chalk.gray(`Error: ${error.message}`)); console.log(chalk.blue('💡 You can setup completion manually:')); console.log(chalk.gray(' d0 completion bash (for Bash)')); console.log(chalk.gray(' d0 completion zsh (for Zsh)')); } } // Send message directly to agent (Node.js version) function sendMessageToAgent(recipient, message, numWorkers = 3) { const timestamp = new Date().toISOString(); // Log the message to .d0/history const historyDir = getHistoryDir(); const logMessage = `[${timestamp}] TO ${recipient}: ${message}`; const logFile = path.join(historyDir, 'agent_messages.log'); try { fs.appendFileSync(logFile, logMessage + '\n'); } catch (error) { console.warn(chalk.yellow(`Warning: Could not log message: ${error.message}`)); } // Check if sessions are active const sessionFile = path.join(process.cwd(), '.d0', 'tmp', 'sessions.json'); if (!fs.existsSync(sessionFile)) { console.error(chalk.red('❌ No active sessions found. Run "d0 start" first.')); return false; } // Validate recipient const sessionInfo = JSON.parse(fs.readFileSync(sessionFile, 'utf8')); if (!sessionInfo.sessions.includes(recipient.toLowerCase())) { console.error(chalk.red(`❌ Unknown recipient: ${recipient}`)); console.log(chalk.yellow('Available recipients:'), sessionInfo.sessions.join(', ')); return false; } // For Node.js version, we simulate message delivery const displayName = recipient.toUpperCase(); try { console.log(chalk.blue(`📤 Sending to ${displayName}...`)); // Write message to agent's inbox for them to see when they connect const agentInboxDir = path.join(process.cwd(), '.d0', 'tmp', 'inbox'); if (!fs.existsSync(agentInboxDir)) { fs.mkdirSync(agentInboxDir, { recursive: true }); } const inboxFile = path.join(agentInboxDir, `${recipient.toLowerCase()}.txt`); const messageEntry = `[${timestamp}] ${message}\n`; fs.appendFileSync(inboxFile, messageEntry); // Create notification marker for agent communication const notificationFile = path.join(agentInboxDir, `${recipient.toLowerCase()}_notification.txt`); fs.writeFileSync(notificationFile, timestamp); // Create communication status tracking const statusFile = path.join(process.cwd(), '.d0', 'tmp', 'message_status.json'); let messageStatus = {}; if (fs.existsSync(statusFile)) { try { messageStatus = JSON.parse(fs.readFileSync(statusFile, 'utf8')); } catch (e) { messageStatus = {}; } } const messageId = `${timestamp}_${recipient}`; messageStatus[messageId] = { recipient, message: message.substring(0, 100) + (message.length > 100 ? '...' : ''), timestamp, status: 'sent', delivered: false }; fs.writeFileSync(statusFile, JSON.stringify(messageStatus, null, 2)); console.log(chalk.green(`✅ Message sent to ${displayName}`)); console.log(chalk.gray(`💡 Agent will see message when they connect with: d0 hi ${recipient.toLowerCase()}`)); // Show enhanced communication tips for different delegation paths if (recipient.toLowerCase() === 'boss') { console.log(chalk.yellow('\n💡 Communication Tips:')); console.log(chalk.gray(' • Boss will delegate tasks to workers automatically')); console.log(chalk.gray(' • Use specific deliverables and deadlines for best results')); console.log(chalk.gray(' • Boss will report progress back to you')); } else if (recipient.toLowerCase().startsWith('worker')) { console.log(chalk.yellow('\n💡 Worker Communication Tips:')); console.log(chalk.gray(' • Include specific task requirements and deadlines')); console.log(chalk.gray(' • Worker will report progress every 30 minutes')); console.log(chalk.gray(' • Specify working directory and deliverable files')); console.log(chalk.gray(' • Worker will notify boss upon completion')); } return true; } catch (error) { console.error(chalk.red(`❌ Failed to send to ${displayName}: ${error.message}`)); return false; } } // Dynamic file generation async function generateDynamicFiles(numWorkers, projectDir) { // Generate worker instructions const instructionsDir = path.join(projectDir, '.d0', 'instructions'); for (let i = 1; i <= numWorkers; i++) { const workerInstruction = generateWorkerInstruction(i); fs.writeFileSync(path.join(instructionsDir, `worker${i}.md`), workerInstruction); } // Update CLAUDE.md dynamically updateClaudeConfig(numWorkers, projectDir); } // Worker specialization definition function getWorkerSpecialization(workerNum) { const specializations = [ { title: 'Frontend Developer', emoji: '🎨', description: 'creating beautiful and responsive user interfaces, implementing UI/UX designs, and optimizing frontend performance', focus: 'UI/UX, React/Vue/Angular, CSS/SCSS, responsive design, accessibility', tasks: 'Build components, implement designs, optimize performance, handle user interactions' }, { title: 'Backend Developer', emoji: '⚙️', description: 'developing robust server-side logic, APIs, and database integrations', focus: 'REST/GraphQL APIs, databases, authentication, server architecture, performance optimization', tasks: 'Create APIs, design databases, implement business logic, handle security' }, { title: 'DevOps Engineer', emoji: '🚀', description: 'managing infrastructure, deployments, and continuous integration/delivery pipelines', focus: 'CI/CD, Docker, cloud platforms (AWS/GCP/Azure), monitoring, automation', tasks: 'Setup deployment pipelines, configure infrastructure, monitor applications, automate processes' }, { title: 'QA Engineer', emoji: '🧪', description: 'ensuring code quality through comprehensive testing and quality assurance', focus: 'automated testing, test frameworks, quality assurance, performance testing', tasks: 'Write tests, perform QA, setup test automation, validate functionality' }, { title: 'Data Engineer', emoji: '📊', description: 'handling data processing, analytics, and machine learning implementations', focus: 'data pipelines, analytics, ML/AI, data visualization, ETL processes', tasks: 'Process data, create analytics, implement ML models, build data pipelines' }, { title: 'Mobile Developer', emoji: '📱', description: 'creating native and cross-platform mobile applications', focus: 'React Native, Flutter, iOS/Android, mobile UI/UX, app store deployment', tasks: 'Build mobile apps, implement mobile-specific features, optimize for mobile platforms' }, { title: 'Security Engineer', emoji: '🛡️', description: 'implementing security measures and ensuring application safety', focus: 'security audits, vulnerability assessment, secure coding, authentication/authorization', tasks: 'Perform security reviews, implement security measures, audit code for vulnerabilities' }, { title: 'Database Specialist', emoji: '🗄️', description: 'designing and optimizing database systems and data architecture', focus: 'database design, query optimization, data modeling, database administration', tasks: 'Design schemas, optimize queries, manage data migrations, ensure data integrity' }, { title: 'Integration Specialist', emoji: '🔗', description: 'integrating third-party services and managing system interconnections', focus: 'API integrations, webhooks, microservices, service mesh, external APIs', tasks: 'Integrate external services, manage API connections, ensure system interoperability' }, { title: 'Performance Engineer', emoji: '⚡', description: 'optimizing application performance and monitoring system efficiency', focus: 'performance optimization, monitoring, profiling, caching strategies, load testing', tasks: 'Optimize performance, setup monitoring, analyze bottlenecks, implement caching' } ]; // Return specialization based on worker number (cycle through if more than 10 workers) return specializations[(workerNum - 1) % specializations.length]; } // Worker instruction generation function generateWorkerInstruction(workerNum) { const specialization = getWorkerSpecialization(workerNum); return `# ${specialization.emoji} worker${workerNum} Instructions - ${specialization.title} ## Your Role As worker${workerNum}, you are a **${specialization.title}** specialist responsible for ${specialization.description}. ## Execution Flow After Receiving Instructions from BOSS 1. **Task Understanding (within 5 minutes)** - Confirm requirements, ask questions immediately for unclear points - Understand success criteria numerically - Confirm dependencies 2. **Implementation Plan Creation (within 10 minutes)** - Break down task into subtasks - Estimate effort for each subtask - Include test plan 3. **Start Implementation** - Follow coding conventions - Record progress every 30 minutes - Report blockers immediately 4. **Completion Report** - List deliverables - Attach test results - Propose next actions ## Communication Send messages to other agents using: \`\`\`bash ./agent-send.sh boss "Your message" ./agent-send.sh president "Direct message to president" \`\`\` ## Your Specialization: ${specialization.title} **Focus Areas**: ${specialization.focus} **Primary Responsibilities**: ${specialization.tasks} ## Work Approach 1. **Stay in your lane**: Focus on your specialization area 2. **Collaborate actively**: Coordinate with other specialists 3. **Quality first**: Maintain high standards in your domain 4. **Document decisions**: Explain technical choices clearly ## Collaboration Guidelines - **With Frontend**: Ensure proper API contracts and data formats - **With Backend**: Coordinate on data structures and endpoints - **With DevOps**: Align on deployment and environment needs - **With QA**: Provide testable implementations - **With other specialists**: Share insights and coordinate dependencies ## Success Metrics 1. **Specialization Excellence**: Deep expertise in your domain 2. **Integration Success**: Seamless work with other specialists 3. **Quality Delivery**: High-standard outputs with proper documentation 4. **Communication**: Clear progress updates and technical discussions --- *Generated by Claude Agents v1.0.0* `; } // Update CLAUDE.md configuration function updateClaudeConfig(numWorkers, projectDir) { let workerList = ''; for (let i = 1; i <= numWorkers; i++) { const spec = getWorkerSpecialization(i); workerList += `- **${spec.emoji} worker${i}** (multiagent:0.${i}): ${spec.title} - ${spec.description}\n`; } let roleInstructions = ''; for (let i = 1; i <= numWorkers; i++) { const spec = getWorkerSpecialization(i); roleInstructions += `- **${spec.emoji} worker${i}**: @.d0/instructions/worker${i}.md (${spec.title})\n`; } const claudeConfig = `# Agent Communication System ## Agent Configuration - **PRESIDENT** (separate session): Project manager and overall supervisor - **boss** (multiagent:0.0): Team leader and tech lead ${workerList}## Your Role - **PRESIDENT**: @.d0/instructions/president.md - **boss**: @.d0/instructions/boss.md ${roleInstructions}## Message Sending \`\`\`bash d0 tell [recipient] "[message]" # Or use the script directly: ./agent-send.sh [recipient] "[message]" \`\`\` ## Basic Flow PRESIDENT → boss → workers → boss → PRESIDENT `; const claudePath = path.join(projectDir, 'CLAUDE.md'); // Check if CLAUDE.md already exists if (fs.existsSync(claudePath)) { // Read existing content const existingContent = fs.readFileSync(claudePath, 'utf8'); // Check if our agent configuration already exists if (existingContent.includes('# Agent Communication System')) { // Replace the existing agent configuration section const lines = existingContent.split('\n'); let startIndex = -1; let endIndex = -1; for (let i = 0; i < lines.length; i++) { if (lines[i].includes('# Agent Communication System')) { startIndex = i; } if (startIndex !== -1 && lines[i].trim() === '' && i > startIndex + 5) { endIndex = i; break; } } if (startIndex !== -1) { // Replace the section const beforeSection = lines.slice(0, startIndex); const afterSection = endIndex !== -1 ? lines.slice(endIndex + 1) : []; const newContent = beforeSection.join('\n') + '\n' + claudeConfig + '\n' + afterSection.join('\n'); fs.writeFileSync(claudePath, newContent.trim()); } else { // Append if no clear section found fs.appendFileSync(claudePath, '\n\n' + claudeConfig); } } else { // Append to existing file fs.appendFileSync(claudePath, '\n\n' + claudeConfig); } } else { // Create new file fs.writeFileSync(claudePath, claudeConfig); } } function isProjectSetup() { // Check for new directory structure first if (fs.existsSync('./.d0')) { const stats = fs.statSync('./.d0'); if (stats.isDirectory()) { return true; // New structure with .d0 directory } else if (stats.isFile()) { return true; // Legacy structure with .d0 file } } // Fall back to checking other markers return fs.existsSync('./CLAUDE.md') || fs.existsSync('./instructions') || fs.existsSync('./.d0/instructions'); } function getProjectConfig() { // Try new config location first const newConfigPath = path.join(process.cwd(), '.d0', 'config.json'); if (fs.existsSync(newConfigPath)) { return JSON.parse(fs.readFileSync(newConfigPath, 'utf8')); } // Fall back to legacy location const legacyConfigPath = path.join(process.cwd(), '.d0'); if (fs.existsSync(legacyConfigPath)) { try { const content = fs.readFileSync(legacyConfigPath, 'utf8'); if (content.trim()) { return JSON.parse(content); } } catch { // If parsing fails, return default config } } // Default config return { workers: 3, version: '1.0.0' }; } // Analyze project structure and determine agent roles function analyzeProjectStructure(projectPath = process.cwd()) { const analysis = { hasBackend: false, hasFrontend: false, hasDatabase: false, hasMobile: false, hasDevOps: false, hasAI: false, hasDesign: false, technologies: [], projectType: 'general', suggestedRoles: [] }; try { // Parse package.json const packageJsonPath = path.join(projectPath, 'package.json'); if (fs.existsSync(packageJsonPath)) { const packageJson = JSON.parse(fs.readFileSync(packageJsonPath, 'utf8')); const dependencies = { ...packageJson.dependencies, ...packageJson.devDependencies }; // Detect frontend technologies if (dependencies.react || dependencies.vue || dependencies.angular || dependencies.svelte) { analysis.hasFrontend = true; analysis.technologies.push('Frontend'); } // Detect backend technologies if (dependencies.express || dependencies.fastify || dependencies.koa || dependencies.nest) { analysis.hasBackend = true; analysis.technologies.push('Backend'); } // Detect database technologies if (dependencies.mongoose || dependencies.sequelize || dependencies.prisma || dependencies.mysql2) { analysis.hasDatabase = true; analysis.technologies.push('Database'); } // Detect mobile technologies if (dependencies['react-native'] || dependencies['@ionic/angular'] || dependencies.expo) { analysis.hasMobile = true; analysis.technologies.push('Mobile'); } // Detect AI/ML technologies if (dependencies.tensorflow || dependencies.pytorch || dependencies['@anthropic-ai/sdk'] || dependencies.openai) { analysis.hasAI = true; analysis.technologies.push('AI/ML'); } } // Analyze file structure const files = fs.readdirSync(projectPath); // Detect DevOps/infrastructure files if (files.includes('Dockerfile') || files.includes('docker-compose.yml') || files.includes('.github') || files.includes('terraform') || files.includes('k8s')) { analysis.hasDevOps = true; analysis.technologies.push('DevOps'); } // Detect design files if (files.some(f => f.includes('design') || f.includes('figma') || f.includes('assets'))) { analysis.hasDesign = true; analysis.technologies.push('Design'); } // Determine project type if (analysis.hasFrontend && analysis.hasBackend) { analysis.projectType = 'fullstack'; } else if (analysis.hasFrontend) { analysis.projectType = 'frontend'; } else if (analysis.hasBackend) { analysis.projectType = 'backend'; } else if (analysis.hasMobile) { analysis.projectType = 'mobile'; } else if (analysis.hasAI) { analysis.projectType = 'ai'; } // Decide suggested roles analysis.suggestedRoles = generateSuggestedRoles(analysis); } catch (error) { console.warn('Warning: Could not fully analyze project structure:', error.message); } return analysis; } // Generate suggested roles from project analysis results function generateSuggestedRoles(analysis) { const roles = []; if (analysis.hasFrontend) { roles.push({ name: 'frontend', displayName: 'Frontend Developer', emoji: '🎨', description: 'UI/UX implementation specialist focusing on user interface development' }); } if (analysis.hasBackend) { roles.push({ name: 'backend', displayName: 'Backend Developer', emoji: '⚙️', description: 'Server-side development specialist focusing on APIs and business logic' }); } if (analysis.hasDatabase) { roles.push({ name: 'database', displayName: 'Database Engineer', emoji: '🗄️', description: 'Database design and optimization specialist' }); } if (analysis.hasDevOps) { roles.push({ name: 'devops', displayName: 'DevOps Engineer', emoji: '🚀', description: 'Infrastructure and deployment automation specialist' }); } if (analysis.hasMobile) { roles.push({ name: 'mobile', displayName: 'Mobile Developer', emoji: '📱', description: 'Mobile application development specialist' }); } if (analysis.hasAI) { roles.push({ name: 'ai', displayName: 'AI Engineer', emoji: '🧠', description: 'Artificial intelligence and machine learning specialist' }); } if (analysis.hasDesign) { roles.push({ name: 'designer', displayName: 'UX/UI Designer', emoji: '🎯', description: 'User experience and interface design specialist' }); } // Always add at least a test role roles.push({ name: 'tester', displayName: 'Quality Assurance', emoji: '🔍', description: 'Quality assurance and testing specialist' }); return roles; } // History management functions function getHistoryDir() { const d0Dir = path.join(process.cwd(), '.d0'); const historyDir = path.join(d0Dir, 'history'); if (!fs.existsSync(d0Dir)) { fs.mkdirSync(d0Dir, { recursive: true }); } if (!fs.existsSync(historyDir)) { fs.mkdirSync(historyDir, { recursive: true }); } return historyDir; } async function logAgentMessage(from, to, message) { const historyDir = getHistoryDir(); const messageLog = { timestamp: new Date().toISOString(), from, to, message, type: 'message' }; const logFile = path.join(historyDir, 'messages.jsonl'); fs.appendFileSync(logFile, JSON.stringify(messageLog) + '\n'); } async function logTaskAction(action, agent, task, details = '') { const historyDir = getHistoryDir(); const taskLog = { timestamp: new Date().toISOString(), action, // start, complete, block, progress agent, task, details, type: 'task' }; const logFile = path.join(historyDir, 'tasks.jsonl'); fs.appendFileSync(logFile, JSON.stringify(taskLog) + '\n'); } async function logSessionEvent(event, details = {}) { const historyDir = getHistoryDir(); const sessionLog = { timestamp: new Date().toISOString(), event, // start, stop, agent_join, agent_leave details, type: 'session' }; const logFile = path.join(historyDir, 'sessions.jsonl'); fs.appendFileSync(logFile, JSON.stringify(sessionLog) + '\n'); } async function logProgress(agent, taskId, progress, description = '') { const historyDir = getHistoryDir(); const progressLog = { timestamp: new Date().toISOString(), agent, taskId, progress, // 0-100 description, type: 'progress' }; const logFile = path.join(historyDir, 'progress.jsonl'); fs.appendFileSync(logFile, JSON.stringify(progressLog) + '\n'); } async function getProjectHistory(type = 'all', agent = null, days = 7) { const historyDir = getHistoryDir(); const cutoffDate = new Date(); cutoffDate.setDate(cutoffDate.getDate() - days); let history = { messages: [], tasks: [], sessions: [], progress: [] }; const logTypes = type === 'all' ? ['messages', 'tasks', 'sessions', 'progress'] : [type]; for (const logType of logTypes) { const logFile = path.join(historyDir, `${logType}.jsonl`); if (fs.existsSync(logFile)) { const lines = fs.readFileSync(logFile, 'utf8').split('\n').filter(line => line.trim()); const logs = lines .map(line => { try { return JSON.parse(line); } catch { return null; } }) .filter(log => log && new Date(log.timestamp) > cutoffDate) .filter(log => !agent || log.agent === agent || log.from === agent || log.to === agent); history[logType] = logs; } } return history; } function displayHistory(history, type) { console.log(chalk.blue(`📚 Project History (${type})\n`)); if (type === 'all' || type === 'messages') { console.log(chalk.yellow('💬 Messages:')); history.messages.slice(-10).forEach(msg => { const time = new Date(msg.timestamp).toLocaleString(); console.log(chalk.gray(` ${time} ${chalk.cyan(msg.from)} → ${chalk.green(msg.to)}`)); console.log(chalk.gray(` ${msg.message.substring(0, 80)}${msg.message.length > 80 ? '...' : ''}`)); }); console.log(); } if (type === 'all' || type === 'tasks') { console.log(chalk.yellow('📋 Tasks:')); history.tasks.slice(-10).forEach(task => { const time = new Date(task.timestamp).toLocaleString(); const actionEmoji = { start: '🟡', complete: '✅', block: '🔴', progress: '🔄' }[task.action] || '⚪'; console.log(chalk.gray(` ${time} ${actionEmoji} ${chalk.cyan(task.agent)} - ${task.task}`)); if (task.details) { console.log(chalk.gray(` ${task.details}`)); } }); console.log(); } if (type === 'all' || type === 'sessions') { console.log(chalk.yellow('🎮 Sessions:')); history.sessions.slice(-10).forEach(session => { const time = new Date(session.timestamp).toLocaleString(); console.log(chalk.gray(` ${time} ${session.event}`)); if (session.details && Object.keys(session.details).length > 0) { console.log(chalk.gray(` ${JSON.stringify(session.details)}`)); } }); console.log(); } if (type === 'all' || type === 'progress') { console.log(chalk.yellow('📊 Progress:')); history.progress.slice(-10).forEach(prog => { const time = new Date(prog.timestamp).toLocaleString(); const progressBar = '█'.repeat(Math.floor(prog.progress / 10)) + '░'.repeat(10 - Math.floor(prog.progress / 10)); console.log(chalk.gray(` ${time} ${chalk.cyan(prog.agent)} [${progressBar}] ${prog.progress}%`)); if (prog.description) { console.log(chalk.gray(` ${prog.description}`)); } }); } } async function generateAnalytics(period = 'week') { const days = { day: 1, week: 7, month: 30 }[period] || 7; const history = await getProjectHistory('all', null, days); const analytics = { period, summary: { totalMessages: history.messages.length, totalTasks: history.tasks.length, completedTasks: history.tasks.filter(t => t.action === 'complete').length, blockedTasks: history.tasks.filter(t => t.action === 'block').length, activeAgents: new Set([ ...history.messages.map(m => m.from), ...history.messages.map(m => m.to), ...history.tasks.map(t => t.agent) ].filter(Boolean)).size }, agentActivity: {}, taskCompletion: {}, hourlyActivity: new Array(24).fill(0), productivity: {} }; // Activity by agent for (const msg of history.messages) { analytics.agentActivity[msg.from] = (analytics.agentActivity[msg.from] || 0) + 1; } for (const task of history.tasks) { if (!analytics.taskCompletion[task.agent]) { analytics.taskCompletion[task.agent] = { started: 0, completed: 0, blocked: 0 }; } analytics.taskCompletion[task.agent][task.action === 'start' ? 'started' : task.action === 'complete' ? 'completed' : 'blocked']++; } // Time-based activity for (const item of [...history.messages, ...history.tasks]) { const hour = new Date(item.timestamp).getHours(); analytics.hourlyActivity[hour]++; } // Productivity calculation for (const agent in analytics.taskCompletion) { const tc = analytics.taskCompletion[agent]; analytics.productivity[agent] = { completionRate: tc.started > 0 ? Math.round((tc.completed / tc.started) * 100) : 0, blockRate: tc.started > 0 ? Math.round((tc.blocked / tc.started) * 100) : 0 }; } return analytics; } function displayAnalytics(analytics) { console.log(chalk.blue(`📊 Project Analytics (${analytics.period})\n`)); // Summary console.log(chalk.yellow('📈 Summary:')); console.log(chalk.gray(` Messages: ${analytics.summary.totalMessages}`)); console.log(chalk.gray(` Tasks: ${analytics.summary.totalTasks} (${analytics.summary.completedTasks} completed, ${analytics.summary.blockedTasks} blocked)`)); console.log(chalk.gray(` Active Agents: ${analytics.summary.activeAgents}`)); console.log(); // Activity by agent console.log(chalk.yellow('👥 Agent Activity:')); Object.entries(analytics.agentActivity) .sort(([,a], [,b]) => b - a) .forEach(([agent, count]) => { console.log(chalk.gray(` ${chalk.cyan(agent)}: ${count} messages`)); }); console.log(); // Task completion rate console.log(chalk.yellow('✅ Task Completion:')); Object.entries(analytics.productivity).forEach(([agent, stats]) => { const completionBar = '█'.repeat(Math.floor(stats.completionRate / 10)) + '░'.repeat(10 - Math.floor(stats.completionRate / 10)); console.log(chalk.gray(` ${chalk.cyan(agent)}: [${completionBar}] ${stats.completionRate}% completion, ${stats.blockRate}% blocked`)); }); console.log(); // Most active time of day const peakHour = analytics.hourlyActivity.indexOf(Math.max(...analytics.hourlyActivity)); console.log(chalk.yellow(`⏰ Peak Activity: ${peakHour}:00 (${analytics.hourlyActivity[peakHour]} events)`)); } // Hook agent communication (enhanced for better message flow) function hookAgentCommunication() { // Create communication channels and status tracking const d0Dir = path.join(process.cwd(), '.d0'); const commDir = path.join(d0Dir, 'tmp', 'communication'); if (!fs.existsSync(commDir)) { fs.mkdirSync(commDir, { recursive: true }); } // Create communication guidelines file for agents const guidelinesFile = path.join(commDir, 'communication_guidelines.md'); const guidelines = `# Agent Communication Guidelines ## Message Flow 1. PRESIDENT → boss (via \`d0 tell boss "message"\`) 2. boss → workers (via \`d0 tell worker1 "message"\`) 3. workers → boss (progress reports) 4. boss → PRESIDENT (status updates) ## Important Notes for Agents - Always check your inbox file: \`.d0/tmp/inbox/[your-role].txt\` - Acknowledge messages by creating completion files - Report progress every 30 minutes - Escalate blockers immediately ## Notification System - Notification files indicate new messages: \`.d0/tmp/inbox/[role]_notification.txt\` - Message status tracking: \`.d0/tmp/message_status.json\` Generated: ${new Date().toISOString()} `; fs.writeFileSync(guidelinesFile, guidelines); // Set up periodic communication health check const healthCheckFile = path.join(commDir, 'health_check.sh'); const healthCheck = `#!/bin/bash # Communication Health Check echo "🔄 Checking agent communication health..." INBOX_DIR=".d0/tmp/inbox" if [ -d "$INBOX_DIR" ]; then echo "📬 Inbox status:" for role in president boss worker1 worker2 worker3; do if [ -f "$INBOX_DIR/$role.txt" ]; then count=$(wc -l < "$INBOX_DIR/$role.txt") if [ -f "$INBOX_DIR/$role_notification.txt" ]; then echo " • $role: $count messages (🔔 unread)" else echo " • $role: $count messages" fi fi done else echo "⚠️ No inbox directory found" fi echo "📊 Communication status: \$(date)" `; fs.writeFileSync(healthCheckFile, healthCheck); fs.chmodSync(healthCheckFile, '755'); } // Instruction template generation function function generateInstructionTemplate(role, roleName, emoji, description) { const currentYear = new Date().getFullYear(); return `# ${emoji} ${roleName} Instructions ## Your Role As ${description}, develop high-quality deliverables quickly and contribute to team success. ## Immediate Actions 1. **Task Understanding (within 5 minutes)** - Confirm requirements, ask questions immediately for unclear points - Understand success criteria numerically - Confirm dependencies 2. **Implementation Plan Creation (within 10 minutes)** - Break down task into subtasks - Estimate effort for each subtask - Include test plan 3. **Start Implementation** - Follow coding conventions - Record progress every 30 minutes - Report blockers immediately ## Practical Task Management ### Task Breakdown Template \`\`\`markdown ## Task: [${role} Implementation] ### Subtasks and Effort - [ ] Requirements analysis and design (0.5h) - [ ] Basic implementation (2h) - [ ] Test creation (1h) - [ ] Quality check (0.5h) - [ ] Documentation creation (0.5h) - [ ] Code review response (0.5h) ### Total: 5h ### With buffer: 6h \`\`\` ### Progress Report Format \`\`\`bash # 30-minute progress recording echo "[\$(date +%H:%M)] Task: [task name] - Progress: [X]% - Status: [smooth/problematic]" >> progress.log # Standard progress report d0 tell boss "【Progress Report】${roleName} \$(date +%H:%M) Task: [task name] Progress: [X]% completed Completed items: ✅ [completed subtask] Working on: 🔄 [currently working subtask] Next action: → [next subtask to work on] Scheduled completion time: [HH:MM] Issues: [none/present (details)]" \`\`\` ## Blocker Response Process ### Immediate Report When Blocker Occurs \`\`\`bash # Report within 5 minutes after blocker detection d0 tell boss "【Blocker Report】${roleName} \$(date +%H:%M) ## Problem [Specific error content or issue] ## Attempts Made 1. [Trial 1 and result] 2. [Trial 2 and result] ## Impact - Task impact: [estimated delay time] - Impact on other tasks: [yes/no] ## Proposals - Option A: [alternative plan, effort, risk] - Option B: [alternative plan, effort, risk] Please make decision." \`\`\` ## Completion Report Template ### Task Completion Report \`\`\`bash # Create completion marker touch ./.d0/tmp/${role}_done.txt # Send completion report d0 tell boss "【Completion Report】${roleName} \$(date +%H:%M) ## Task: [${role} Implementation] ✅ Completed ## Deliverables 1. [deliverable 1 path] 2. [deliverable 2 path] 3. [test file path] ## Quality Indicators - Test coverage: [X]% - Performance: [indicator value] - Quality standards: [compliance status] ## Technical Points - [Implementation innovation 1] - [Implementation innovation 2] - [Future improvement proposals] ## Next Actions - [Next required work] - [Dependent tasks] Effort: Planned [X]h → Actual [Y]h" \`\`\` ## ${role} Specialized Skills ### Core Skills - [Technology 1]: [Detailed description] - [Technology 2]: [Detailed description] - [Technology 3]: [Detailed description] ### Quality Standards - [Quality indicator 1]: [Target value] - [Quality indicator 2]: [Target value] - [Quality indicator 3]: [Target value] ### Best Practices 1. **[Practice item 1]** - [Specific method] - [Checkpoint] 2. **[Practice item 2]** - [Specific method] - [Checkpoint] ## Practical Success Principles ### Communication - 📢 Progress reports every 30 minutes - 🚨 Report blockers within 5 minutes - ✅ Detailed reports upon completion - 🤝 Information sharing between teams ### Quality Management - Test coverage 80%+ - Code review required - Simultaneous documentation creation - Performance indicator compliance ### Time Management - 1.2x estimate for buffer - Early blocker reporting - Maximize parallel work - Minimize waiting time ## Checklist \`\`\`bash # Task start echo "□ Completely understood requirements" echo "□ Created effort estimates" echo "□ Environment setup completed" echo "□ Reported start to boss" # Task completion echo "□ All functions verified working" echo "□ All tests pass" echo "□ Documentation creation completed" echo "□ Completion report sent" \`\`\` ## Continuous Improvement ### Retrospective Items - Today's learnings: [Technical discoveries] - Improvement points: [Improvement proposals for next time] - Team contribution: [Support to other members] - Efficiency: [Work efficiency improvement ideas] --- *Generated by Claude Agents v1.0.0 - ${currentYear}* `; } // Session management using Node.js processes instead of tmux function checkClaudeCLI() { try { const platform = os.platform(); if (platform === 'win32') { // Try WSL first, then native Windows try { execSync('wsl claude --version', { stdio: 'ignore' }); return true; } catch { try { execSync('claude --version', { stdio: 'ignore' }); return true; } catch { return false; } } } else { execSync('which claude', { stdio: 'ignore' }); return true; } } catch { return false; } } // Session management using Node.js child processes (cross-platform) const activeSessions = new Map(); function createAgentSessions(numWorkers = 3) { try { // Stop existing sessions stopAllSessions(); console.log(chalk.green('✅ Node.js agent sessions created!')); console.log(chalk.yellow('💡 Available sessions:')); console.log(chalk.gray(' • president - Project manager and overall supervisor')); console.log(chalk.gray(' • boss - Team leader and tech lead')); for (let i = 1; i <= numWorkers; i++) { const workerSpec = getWorkerSpecialization(i); console.log(chalk.gray(` • worker${i} - ${workerSpec.title}`)); } console.log(chalk.yellow('\n💡 Next steps:')); console.log(chalk.blue(' d0 hi president') + chalk.gray(' - Connect to project manager')); console.log(chalk.blue(' d0 tell "Create a todo app"') + chalk.gray(' - Start your project')); // Save session info to .d0/tmp const sessionInfo = { sessions: ['president', 'boss'].concat(Array.from({length: numWorkers}, (_, i) => `worker${i + 1}`)), created: new Date().toISOString(), numWorkers }; const tmpDir = path.join(process.cwd(), '.d0', 'tmp'); if (!fs.existsSync(tmpDir)) { fs.mkdirSync(tmpDir, { recursive: true }); } fs.writeFileSync(path.join(tmpDir, 'sessions.json'), JSON.stringify(sessionInfo, null, 2)); return true; } catch (error) { console.error('Failed to create agent sessions:', error.message); return false; } } function stopAllSessions() { activeSessions.forEach((session, name) => { try { session.process.kill('SIGTERM'); } catch (error) { // Ignore if process is already dead } }); activeSessions.clear(); // Clean up session file const sessionFile = path.join(process.cwd(), '.d0', 'tmp', 'sessions.json'); if (fs.existsSync(sessionFile)) { fs.unlinkSync(sessionFile); } } function connectToSession(sessionName) { // Check if session