claude-agents-manager
Version:
Elite AI research and development platform with 60+ specialized agents, comprehensive research workflows, citation-backed reports, and advanced multi-agent coordination for Claude Code. Features deep research capabilities, concurrent execution, shared mem
378 lines (322 loc) • 12.7 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`;
}