@webdevtoday/claude-agents
Version:
AI-powered development shop with 15 specialized agents for Claude Code. Features concurrent execution, shared memory, context-forge integration, and web dashboard for 80% faster development.
323 lines (267 loc) • 12.5 kB
JavaScript
import chalk from 'chalk';
import ora from 'ora';
import { writeFileSync, copyFileSync, existsSync, mkdirSync, readdirSync, readFileSync, appendFileSync } from 'fs';
import { join, dirname } from 'path';
import { fileURLToPath } from 'url';
import inquirer from 'inquirer';
import {
getAgentsDir,
getCommandsDir,
ensureProjectDirectories,
CLAUDE_PROJECT_DIR
} from '../utils/paths.js';
import {
getAvailableAgents,
getAgentDetails,
formatAgentForInstall
} from '../utils/agents.js';
import { detectContextForge } from '../utils/contextForgeDetector.js';
import { addInstalledAgent, saveConfig, DEFAULT_CONFIG } from '../utils/config.js';
const __filename = fileURLToPath(import.meta.url);
const __dirname = dirname(__filename);
export async function initCommand(options) {
const spinner = ora();
try {
console.log(chalk.bold.blue('🚀 Initializing Claude Sub-Agents\n'));
// Detect context-forge project
const contextForgeInfo = detectContextForge();
const isContextForge = contextForgeInfo.hasContextForge;
if (isContextForge) {
console.log(chalk.cyan('🛠️ Context-Forge project detected!'));
console.log(chalk.gray(' Sub-agents will be integrated with your existing setup.'));
console.log(chalk.gray(' • Preserving existing CLAUDE.md'));
console.log(chalk.gray(' • Preserving existing commands and hooks'));
console.log(chalk.gray(' • Adding agents to .claude/agents/\n'));
}
// Confirm initialization
const confirmMessage = isContextForge
? 'Initialize sub-agents in this context-forge project?'
: 'Initialize sub-agents in this project?';
const { confirmed } = await inquirer.prompt([{
type: 'confirm',
name: 'confirmed',
message: confirmMessage,
default: true
}]);
if (!confirmed) {
console.log(chalk.yellow('Initialization cancelled.'));
return;
}
// Create project directories
spinner.start('Creating project structure...');
ensureProjectDirectories();
// Create agents directory
const agentsDir = join(CLAUDE_PROJECT_DIR, 'agents');
if (!existsSync(agentsDir)) {
mkdirSync(agentsDir, { recursive: true });
}
spinner.succeed('Project structure created');
// Get available agents
spinner.start('Loading available agents...');
const availableAgents = getAvailableAgents();
spinner.stop();
// Copy all agents
spinner.start('Installing agents...');
let installedCount = 0;
for (const agent of availableAgents) {
try {
const agentDetails = getAgentDetails(agent.name);
if (!agentDetails) continue;
// Write agent file
const agentPath = join(agentsDir, `${agent.name}.md`);
const formattedContent = formatAgentForInstall(agentDetails);
writeFileSync(agentPath, formattedContent);
// Add to config
addInstalledAgent(agent.name, agentDetails, true);
installedCount++;
} catch (error) {
console.error(chalk.red(`Failed to install ${agent.name}: ${error.message}`));
}
}
spinner.succeed(`Installed ${installedCount} agents`);
// Handle commands - always install but in different locations for context-forge
spinner.start('Installing agent commands...');
const commandsDir = getCommandsDir(true);
const commandsSourceDir = join(__dirname, '..', '..', 'commands');
// Create commands directory structure
if (!existsSync(commandsDir)) {
mkdirSync(commandsDir, { recursive: true });
}
// Copy all command files
const commandFiles = readdirSync(commandsSourceDir).filter(f => f.endsWith('.md'));
// For context-forge projects, put commands in agents subdirectory
const targetDir = isContextForge ? join(commandsDir, 'agents') : commandsDir;
if (isContextForge && !existsSync(targetDir)) {
mkdirSync(targetDir, { recursive: true });
}
for (const file of commandFiles) {
const srcPath = join(commandsSourceDir, file);
const destName = isContextForge ? `agent-${file}` : file;
const destPath = join(targetDir, destName);
copyFileSync(srcPath, destPath);
}
spinner.succeed('Agent commands installed');
if (isContextForge) {
console.log(chalk.gray(' Commands placed in .claude/commands/agents/ to avoid conflicts'));
}
// Handle CLAUDE.md
if (isContextForge && options.merge !== false) {
spinner.start('Updating CLAUDE.md...');
const claudeMdPath = join(process.cwd(), 'CLAUDE.md');
if (existsSync(claudeMdPath)) {
const existingContent = readFileSync(claudeMdPath, 'utf-8');
// Check if sections already exist
const hasConcurrentSection = existingContent.includes('Claude Code Sub Agent Configuration');
const hasAgentsSection = existingContent.includes('Claude Sub-Agents Integration');
let updatedContent = existingContent;
// Add concurrent execution section at the top if not present
if (!hasConcurrentSection) {
const concurrentSection = generateConcurrentExecutionSection();
// Insert after the first line (usually the main title)
const lines = existingContent.split('\n');
lines.splice(1, 0, '\n' + concurrentSection);
updatedContent = lines.join('\n');
}
// Add sub-agents section after concurrent section if not present
if (!hasAgentsSection) {
const subAgentsSection = generateSubAgentsSection(installedCount);
// Find where to insert (after concurrent section or at end)
if (hasConcurrentSection || !hasConcurrentSection) {
// Insert after the concurrent execution section
const insertPoint = updatedContent.indexOf('### 🎯 CONCURRENT EXECUTION CHECKLIST:');
if (insertPoint !== -1) {
// Find the end of the checklist section
const checklistEnd = updatedContent.indexOf('\n\n', insertPoint + 200);
if (checklistEnd !== -1) {
updatedContent = updatedContent.slice(0, checklistEnd + 2) +
subAgentsSection + '\n' +
updatedContent.slice(checklistEnd + 2);
} else {
updatedContent += '\n\n' + subAgentsSection;
}
} else {
updatedContent += '\n\n' + subAgentsSection;
}
}
}
// Write updated content
writeFileSync(claudeMdPath, updatedContent);
spinner.succeed('Updated CLAUDE.md with sub-agents configuration');
if (!hasConcurrentSection) {
console.log(chalk.gray(' • Added concurrent execution rules'));
}
if (!hasAgentsSection) {
console.log(chalk.gray(' • Added sub-agents integration section'));
}
if (hasConcurrentSection && hasAgentsSection) {
console.log(chalk.gray(' • Sections already present, skipped duplicate'));
}
}
}
// Create memory directory
const memoryDir = join(process.cwd(), '.swarm');
if (!existsSync(memoryDir)) {
mkdirSync(memoryDir, { recursive: true });
}
// Final message
console.log('');
console.log(chalk.green('✨ Initialization complete!'));
console.log('');
console.log(chalk.bold('Next steps:'));
console.log(chalk.gray('1. Run'), chalk.cyan('claude-agents list'), chalk.gray('to see installed agents'));
console.log(chalk.gray('2. Use'), chalk.cyan('claude-agents run <agent> --task "..."'), chalk.gray('to run agents'));
if (isContextForge) {
console.log(chalk.gray('3. Agents can work with your PRPs via Task() tool'));
console.log(chalk.gray('4. Check .claude/commands/agents/ for agent-specific commands'));
} else {
console.log(chalk.gray('3. Use slash commands in Claude Code (e.g., /review)'));
}
} catch (error) {
spinner.fail('Initialization failed');
console.error(chalk.red('Error:'), error.message);
process.exit(1);
}
}
function generateConcurrentExecutionSection() {
return `# Claude Code Sub Agent Configuration
## 🚨 CRITICAL: CONCURRENT EXECUTION FOR ALL ACTIONS
**ABSOLUTE RULE**: ALL operations MUST be concurrent/parallel in a single message:
### 🔴 MANDATORY CONCURRENT PATTERNS:
1. **TodoWrite**: ALWAYS batch ALL todos in ONE call (5-10+ todos minimum)
2. **Task tool**: ALWAYS spawn ALL agents in ONE message with full instructions
3. **File operations**: ALWAYS batch ALL reads/writes/edits in ONE message
4. **Bash commands**: ALWAYS batch ALL terminal operations in ONE message
5. **Memory operations**: ALWAYS batch ALL memory store/retrieve in ONE message
### ⚡ GOLDEN RULE: "1 MESSAGE = ALL RELATED OPERATIONS"
**Examples of CORRECT concurrent execution:**
\`\`\`javascript
// ✅ CORRECT: Everything in ONE message
[Single Message]:
- TodoWrite { todos: [10+ todos with all statuses/priorities] }
- Task("Agent 1 with full instructions and hooks")
- Task("Agent 2 with full instructions and hooks")
- Task("Agent 3 with full instructions and hooks")
- Read("file1.js")
- Read("file2.js")
- Write("output1.js", content)
- Write("output2.js", content)
- Bash("npm install")
- Bash("npm test")
- Bash("npm run build")
\`\`\`
**Examples of WRONG sequential execution:**
\`\`\`javascript
// ❌ WRONG: Multiple messages (NEVER DO THIS)
Message 1: TodoWrite { todos: [single todo] }
Message 2: Task("Agent 1")
Message 3: Task("Agent 2")
Message 4: Read("file1.js")
Message 5: Write("output1.js")
Message 6: Bash("npm install")
// This is 6x slower and breaks coordination!
\`\`\`
### 🎯 CONCURRENT EXECUTION CHECKLIST:
Before sending ANY message, ask yourself:
- ✅ Are ALL related TodoWrite operations batched together?
- ✅ Are ALL Task spawning operations in ONE message?
- ✅ Are ALL file operations (Read/Write/Edit) batched together?
- ✅ Are ALL bash commands grouped in ONE message?
- ✅ Are ALL memory operations concurrent?
If ANY answer is "No", you MUST combine operations into a single message!`;
}
function generateSubAgentsSection(agentCount) {
return `## 🤖 Claude Sub-Agents Integration
This project includes ${agentCount} specialized AI sub-agents for enhanced development.
### Available Agents
The following agents are installed in \`.claude/agents/\`:
- **project-planner**: Strategic planning and task decomposition specialist
- **api-developer**: Backend API development specialist with PRP awareness
- **frontend-developer**: Modern web interface implementation specialist
- **tdd-specialist**: Test-driven development and comprehensive testing expert
- **code-reviewer**: Code quality, security, and best practices analyst
- **debugger**: Error analysis and debugging specialist
- **refactor**: Code refactoring and improvement specialist
- **doc-writer**: Technical documentation specialist
- **security-scanner**: Security vulnerability detection specialist
- **devops-engineer**: CI/CD and deployment automation specialist
- **product-manager**: Product requirements and user story specialist
- **marketing-writer**: Technical marketing content specialist
- **api-documenter**: OpenAPI/Swagger documentation specialist
- **test-runner**: Automated test execution specialist
- **shadcn-ui-builder**: UI/UX implementation with ShadCN components
### Using Sub-Agents
Agents work alongside your existing PRPs and can be invoked in several ways:
1. **Direct execution**: \`claude-agents run <agent> --task "description"\`
2. **Task tool in Claude Code**: \`Task("agent-name: task description")\`
3. **Agent slash commands**: Located in \`.claude/commands/agents/\`
### Memory System
Agents share context and coordinate through:
- **Memory Store**: \`.swarm/memory.json\` for persistent agent memory
- **Context Sharing**: Agents can access shared project context
- **PRP Integration**: Agents are aware of and can work with your PRPs
### Best Practices
- Use agents for specialized tasks that match their expertise
- Agents can read and understand your PRPs for context
- Multiple agents can work on different aspects of the same feature
- Memory system allows agents to build on each other's work`;
}