Skip to content

Commit 44b9d7b

Browse files
authored
feat: Add Gemini CLI Integration (#271)
1 parent 429a3d4 commit 44b9d7b

File tree

3 files changed

+72
-2
lines changed

3 files changed

+72
-2
lines changed

tools/installer/bin/bmad.js

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,7 @@ program
5050
.option('-t, --team <team>', 'Install specific team with required agents and dependencies')
5151
.option('-x, --expansion-only', 'Install only expansion packs (no bmad-core)')
5252
.option('-d, --directory <path>', 'Installation directory (default: .bmad-core)')
53-
.option('-i, --ide <ide...>', 'Configure for specific IDE(s) - can specify multiple (cursor, claude-code, windsurf, roo, cline, other)')
53+
.option('-i, --ide <ide...>', 'Configure for specific IDE(s) - can specify multiple (cursor, claude-code, windsurf, roo, cline, gemini, other)')
5454
.option('-e, --expansion-packs <packs...>', 'Install specific expansion packs (can specify multiple)')
5555
.action(async (options) => {
5656
try {
@@ -314,7 +314,8 @@ async function promptInstallation() {
314314
{ name: 'Claude Code', value: 'claude-code' },
315315
{ name: 'Windsurf', value: 'windsurf' },
316316
{ name: 'Roo Code', value: 'roo' },
317-
{ name: 'Cline', value: 'cline' }
317+
{ name: 'Cline', value: 'cline' },
318+
{ name: 'Gemini CLI', value: 'gemini' }
318319
]
319320
}
320321
]);

tools/installer/config/install.config.yml

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -101,6 +101,16 @@ ide-configurations:
101101
# 2. Type @agent-name (e.g., "@dev", "@pm", "@architect")
102102
# 3. The agent will adopt that persona for the conversation
103103
# 4. Rules are stored in .clinerules/ directory in your project
104+
gemini:
105+
name: Gemini CLI
106+
rule-dir: .gemini/agents/
107+
format: context-files
108+
instructions: |
109+
# To use BMAD agents with the Gemini CLI:
110+
# 1. The installer creates a .gemini/ directory in your project.
111+
# 2. It also configures .gemini/settings.json to load all agent files.
112+
# 3. Simply mention the agent in your prompt (e.g., "As @dev, ...").
113+
# 4. The Gemini CLI will automatically have the context for that agent.
104114
available-agents:
105115
- id: analyst
106116
name: Business Analyst

tools/installer/lib/ide-setup.js

Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,8 @@ class IdeSetup {
3333
return this.setupRoo(installDir, selectedAgent);
3434
case "cline":
3535
return this.setupCline(installDir, selectedAgent);
36+
case "gemini":
37+
return this.setupGeminiCli(installDir, selectedAgent);
3638
default:
3739
console.log(chalk.yellow(`\nIDE ${ide} not yet supported`));
3840
return false;
@@ -411,6 +413,63 @@ class IdeSetup {
411413

412414
return true;
413415
}
416+
417+
async setupGeminiCli(installDir, selectedAgent) {
418+
await initializeModules();
419+
const geminiDir = path.join(installDir, ".gemini");
420+
const agentsContextDir = path.join(geminiDir, "agents");
421+
await fileManager.ensureDirectory(agentsContextDir);
422+
423+
// Get all available agents
424+
const agents = await this.getAllAgentIds(installDir);
425+
const agentContextFiles = [];
426+
427+
for (const agentId of agents) {
428+
// Find the source agent file
429+
let agentPath = path.join(installDir, ".bmad-core", "agents", `${agentId}.md`);
430+
if (!(await fileManager.pathExists(agentPath))) {
431+
agentPath = path.join(installDir, "agents", `${agentId}.md`);
432+
}
433+
434+
if (await fileManager.pathExists(agentPath)) {
435+
const agentContent = await fileManager.readFile(agentPath);
436+
const contextFilePath = path.join(agentsContextDir, `${agentId}.md`);
437+
438+
// Copy the agent content directly into its own context file
439+
await fileManager.writeFile(contextFilePath, agentContent);
440+
441+
// Store the relative path for settings.json
442+
const relativePath = path.relative(geminiDir, contextFilePath);
443+
agentContextFiles.push(relativePath.replace(/\\/g, '/')); // Ensure forward slashes for consistency
444+
console.log(chalk.green(`✓ Created context file for @${agentId}`));
445+
}
446+
}
447+
448+
console.log(chalk.green(`\n✓ Created individual agent context files in ${agentsContextDir}`));
449+
450+
// Create or update settings.json
451+
const settingsPath = path.join(geminiDir, "settings.json");
452+
let settings = {};
453+
454+
if (await fileManager.pathExists(settingsPath)) {
455+
try {
456+
const existingSettings = await fileManager.readFile(settingsPath);
457+
settings = JSON.parse(existingSettings);
458+
console.log(chalk.yellow("Found existing .gemini/settings.json. Merging settings..."));
459+
} catch (e) {
460+
console.error(chalk.red("Error parsing existing settings.json. It will be overwritten."), e);
461+
settings = {};
462+
}
463+
}
464+
465+
// Set contextFileName to our new array of files
466+
settings.contextFileName = agentContextFiles;
467+
468+
await fileManager.writeFile(settingsPath, JSON.stringify(settings, null, 2));
469+
console.log(chalk.green(`✓ Configured .gemini/settings.json to load all agent context files.`));
470+
471+
return true;
472+
}
414473
}
415474

416475
module.exports = new IdeSetup();

0 commit comments

Comments
 (0)