From 98342f21743b6a2cabc20040b6bb1324af83f451 Mon Sep 17 00:00:00 2001 From: Brian Madison Date: Sat, 22 Nov 2025 16:55:37 -0600 Subject: [PATCH] feat: add custom agent support to more IDEs MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ## Added installCustomAgentLauncher function to: ✅ Cline (.clinerules/workflows/) - Creates workflow files with custom agent launchers - Format: bmad-custom-{agent-name}.md ✅ Crush (.crush/commands/bmad/) - Creates command files with custom agent launchers - Format: custom-{agent-name}.md ✅ Gemini (.gemini/commands/) - Creates TOML command files with custom agent launchers - Format: bmad-custom-{agent-name}.toml ✅ iFlow (.iflow/commands/bmad/) - Creates command files with custom agent launchers - Format: custom-{agent-name}.md ## All Custom Agent Launchers Include: - @agentPath reference to load complete agent - Usage instructions for loading first, then activating - Proper IDE-specific formatting and file structure - Return values for tracking installations Now custom agents install to 8+ IDEs instead of just 4! --- tools/cli/installers/lib/ide/cline.js | 49 ++++++++++++++++++++++++++ tools/cli/installers/lib/ide/crush.js | 46 ++++++++++++++++++++++++ tools/cli/installers/lib/ide/gemini.js | 47 ++++++++++++++++++++++++ tools/cli/installers/lib/ide/iflow.js | 46 ++++++++++++++++++++++++ 4 files changed, 188 insertions(+) diff --git a/tools/cli/installers/lib/ide/cline.js b/tools/cli/installers/lib/ide/cline.js index 4840a625..9a9ceba6 100644 --- a/tools/cli/installers/lib/ide/cline.js +++ b/tools/cli/installers/lib/ide/cline.js @@ -209,6 +209,55 @@ class ClineSetup extends BaseIdeSetup { console.log(chalk.dim(`Removed ${this.name} BMAD configuration`)); } + /** + * Install a custom agent launcher for Cline + * @param {string} projectDir - Project directory + * @param {string} agentName - Agent name (e.g., "fred-commit-poet") + * @param {string} agentPath - Path to compiled agent (relative to project root) + * @param {Object} metadata - Agent metadata + * @returns {Object} Installation result + */ + async installCustomAgentLauncher(projectDir, agentName, agentPath, metadata) { + const clineDir = path.join(projectDir, this.configDir); + const workflowsDir = path.join(clineDir, this.workflowsDir); + + // Create .clinerules/workflows directory if it doesn't exist + await fs.ensureDir(workflowsDir); + + // Create custom agent launcher workflow + const launcherContent = `name: ${agentName} +description: Custom BMAD agent: ${agentName} + +# ${agentName} Custom Agent + +**⚠️ IMPORTANT**: Run @${agentPath} first to load the complete agent! + +This is a launcher for the custom BMAD agent "${agentName}". + +## Usage +1. First run: \`${agentPath}\` to load the complete agent +2. Then use this workflow as ${agentName} + +The agent will follow the persona and instructions from the main agent file. + +--- + +*Generated by BMAD Method*`; + + const fileName = `bmad-custom-${agentName.toLowerCase()}.md`; + const launcherPath = path.join(workflowsDir, fileName); + + // Write the launcher file + await fs.writeFile(launcherPath, launcherContent, 'utf8'); + + return { + ide: 'cline', + path: path.relative(projectDir, launcherPath), + command: agentName, + type: 'custom-agent-launcher', + }; + } + /** * Utility: Ensure directory exists */ diff --git a/tools/cli/installers/lib/ide/crush.js b/tools/cli/installers/lib/ide/crush.js index 49b050e2..446e3031 100644 --- a/tools/cli/installers/lib/ide/crush.js +++ b/tools/cli/installers/lib/ide/crush.js @@ -235,6 +235,52 @@ Part of the BMAD ${workflow.module.toUpperCase()} module. console.log(chalk.dim(`Removed BMAD commands from Crush`)); } } + + /** + * Install a custom agent launcher for Crush + * @param {string} projectDir - Project directory + * @param {string} agentName - Agent name (e.g., "fred-commit-poet") + * @param {string} agentPath - Path to compiled agent (relative to project root) + * @param {Object} metadata - Agent metadata + * @returns {Object} Installation result + */ + async installCustomAgentLauncher(projectDir, agentName, agentPath, metadata) { + const crushDir = path.join(projectDir, this.configDir); + const bmadCommandsDir = path.join(crushDir, this.commandsDir, 'bmad'); + + // Create .crush/commands/bmad directory if it doesn't exist + await fs.ensureDir(bmadCommandsDir); + + // Create custom agent launcher + const launcherContent = `# ${agentName} Custom Agent + +**⚠️ IMPORTANT**: Run @${agentPath} first to load the complete agent! + +This is a launcher for the custom BMAD agent "${agentName}". + +## Usage +1. First run: \`${agentPath}\` to load the complete agent +2. Then use this command to activate ${agentName} + +The agent will follow the persona and instructions from the main agent file. + +--- + +*Generated by BMAD Method*`; + + const fileName = `custom-${agentName.toLowerCase()}.md`; + const launcherPath = path.join(bmadCommandsDir, fileName); + + // Write the launcher file + await fs.writeFile(launcherPath, launcherContent, 'utf8'); + + return { + ide: 'crush', + path: path.relative(projectDir, launcherPath), + command: agentName, + type: 'custom-agent-launcher', + }; + } } module.exports = { CrushSetup }; diff --git a/tools/cli/installers/lib/ide/gemini.js b/tools/cli/installers/lib/ide/gemini.js index 794f287f..bcc5202b 100644 --- a/tools/cli/installers/lib/ide/gemini.js +++ b/tools/cli/installers/lib/ide/gemini.js @@ -201,6 +201,53 @@ ${contentWithoutFrontmatter} } } } + + /** + * Install a custom agent launcher for Gemini + * @param {string} projectDir - Project directory + * @param {string} agentName - Agent name (e.g., "fred-commit-poet") + * @param {string} agentPath - Path to compiled agent (relative to project root) + * @param {Object} metadata - Agent metadata + * @returns {Object} Installation result + */ + async installCustomAgentLauncher(projectDir, agentName, agentPath, metadata) { + const geminiDir = path.join(projectDir, this.configDir); + const commandsDir = path.join(geminiDir, this.commandsDir); + + // Create .gemini/commands directory if it doesn't exist + await fs.ensureDir(commandsDir); + + // Create custom agent launcher in TOML format + const launcherContent = `description = "Custom BMAD Agent: ${agentName}" +prompt = """ +**⚠️ IMPORTANT**: Run @${agentPath} first to load the complete agent! + +This is a launcher for the custom BMAD agent "${agentName}". + +## Usage +1. First run: \`${agentPath}\` to load the complete agent +2. Then use this command to activate ${agentName} + +The agent will follow the persona and instructions from the main agent file. + +--- + +*Generated by BMAD Method* +"""`; + + const fileName = `bmad-custom-${agentName.toLowerCase()}.toml`; + const launcherPath = path.join(commandsDir, fileName); + + // Write the launcher file + await fs.writeFile(launcherPath, launcherContent, 'utf8'); + + return { + ide: 'gemini', + path: path.relative(projectDir, launcherPath), + command: agentName, + type: 'custom-agent-launcher', + }; + } } module.exports = { GeminiSetup }; diff --git a/tools/cli/installers/lib/ide/iflow.js b/tools/cli/installers/lib/ide/iflow.js index 6462a9f4..36abd71a 100644 --- a/tools/cli/installers/lib/ide/iflow.js +++ b/tools/cli/installers/lib/ide/iflow.js @@ -120,6 +120,52 @@ Part of the BMAD ${task.module.toUpperCase()} module. console.log(chalk.dim(`Removed BMAD commands from iFlow CLI`)); } } + + /** + * Install a custom agent launcher for iFlow + * @param {string} projectDir - Project directory + * @param {string} agentName - Agent name (e.g., "fred-commit-poet") + * @param {string} agentPath - Path to compiled agent (relative to project root) + * @param {Object} metadata - Agent metadata + * @returns {Object} Installation result + */ + async installCustomAgentLauncher(projectDir, agentName, agentPath, metadata) { + const iflowDir = path.join(projectDir, this.configDir); + const bmadCommandsDir = path.join(iflowDir, this.commandsDir, 'bmad'); + + // Create .iflow/commands/bmad directory if it doesn't exist + await fs.ensureDir(bmadCommandsDir); + + // Create custom agent launcher + const launcherContent = `# ${agentName} Custom Agent + +**⚠️ IMPORTANT**: Run @${agentPath} first to load the complete agent! + +This is a launcher for the custom BMAD agent "${agentName}". + +## Usage +1. First run: \`${agentPath}\` to load the complete agent +2. Then use this command to activate ${agentName} + +The agent will follow the persona and instructions from the main agent file. + +--- + +*Generated by BMAD Method*`; + + const fileName = `custom-${agentName.toLowerCase()}.md`; + const launcherPath = path.join(bmadCommandsDir, fileName); + + // Write the launcher file + await fs.writeFile(launcherPath, launcherContent, 'utf8'); + + return { + ide: 'iflow', + path: path.relative(projectDir, launcherPath), + command: agentName, + type: 'custom-agent-launcher', + }; + } } module.exports = { IFlowSetup };