refactor(gemini-cli): change agent storage from multiple files to single (#308)

* refactor(gemini-cli): change agent storage from multiple files to single concatenated file

- Update configuration to use .gemini/bmad-method/ directory instead of .gemini/agents/
- Implement new logic to concatenate all agent files into single GEMINI.md
- Add backward compatibility for existing settings.json
- Remove old agents directory and update related documentation
- Ensure all agent settings are properly loaded

* fix(ide-setup): change agent trigger symbol from @ to *

The change was made to standardize the agent trigger symbol across the system and avoid confusion with other special characters.

* docs: update gemini cli syntax and file structure

- Change agent mention syntax from @ to * in docs and config
- Update file structure documentation from .gemini/agents/ to .gemini/bmad-method/
- Add gemini cli syntax to workflow guide

* fix(ide-setup): remove redundant contextFileNames handling
This commit is contained in:
Davor Racic
2025-07-12 16:55:12 +02:00
committed by GitHub
parent b5cbffd608
commit c42002f1ea
4 changed files with 94 additions and 49 deletions

View File

@@ -6,23 +6,22 @@ For the complete workflow, see the [BMad Workflow Guide](../bmad-workflow-guide.
When running `npx bmad-method install`, select **Gemini CLI** as your IDE. This creates: When running `npx bmad-method install`, select **Gemini CLI** as your IDE. This creates:
- `.gemini/agents/` directory with all agent context files - `.gemini/bmad-method/` directory with all agent context in GEMINI.md file
- `.gemini/settings.json` configured to load all agents automatically
## Using BMad Agents with Gemini CLI ## Using BMad Agents with Gemini CLI
Simply mention the agent in your prompt: Simply mention the agent in your prompt:
- "As @dev, implement the login feature" - "As \*dev, implement the login feature"
- "Acting as @architect, review this system design" - "Acting as \*architect, review this system design"
- "@sm, create the next story for our project" - "\*sm, create the next story for our project"
The Gemini CLI automatically loads the appropriate agent context. The Gemini CLI automatically loads the appropriate agent context.
## Gemini CLI-Specific Features ## Gemini CLI-Specific Features
- **Context files**: All agents loaded as context in `.gemini/agents/` - **Context files**: All agents loaded as context in `.gemini/bmad-method/GEMINI.md`
- **Automatic loading**: Settings.json ensures agents are always available - **Automatic loading**: GEMINI.md ensures agents are always available
- **Natural language**: No special syntax needed, just mention the agent - **Natural language**: No special syntax needed, just mention the agent
## Tips for Gemini CLI Users ## Tips for Gemini CLI Users

View File

@@ -111,6 +111,7 @@ Follow the SM → Dev cycle for systematic story development:
- **Claude Code**: `/agent-name` (e.g., `/bmad-master`) - **Claude Code**: `/agent-name` (e.g., `/bmad-master`)
- **Cursor**: `@agent-name` (e.g., `@bmad-master`) - **Cursor**: `@agent-name` (e.g., `@bmad-master`)
- **Gemini CLI**: `*agent-name` (e.g., `*bmad-master`)
- **Windsurf**: `@agent-name` (e.g., `@bmad-master`) - **Windsurf**: `@agent-name` (e.g., `@bmad-master`)
- **Trae**: `@agent-name` (e.g., `@bmad-master`) - **Trae**: `@agent-name` (e.g., `@bmad-master`)
- **Roo Code**: Select mode from mode selector (e.g., `bmad-bmad-master`) - **Roo Code**: Select mode from mode selector (e.g., `bmad-bmad-master`)

View File

@@ -68,13 +68,14 @@ ide-configurations:
# 4. Rules are stored in .clinerules/ directory in your project # 4. Rules are stored in .clinerules/ directory in your project
gemini: gemini:
name: Gemini CLI name: Gemini CLI
rule-dir: .gemini/agents/ rule-dir: .gemini/bmad-method/
format: context-files format: single-file
command-suffix: .md
instructions: | instructions: |
# To use BMad agents with the Gemini CLI: # To use BMad agents with the Gemini CLI:
# 1. The installer creates a .gemini/ directory in your project. # 1. The installer creates a .gemini/bmad-method/ directory in your project.
# 2. It also configures .gemini/settings.json to load all agent files. # 2. It concatenates all agent files into a single GEMINI.md file.
# 3. Simply mention the agent in your prompt (e.g., "As @dev, ..."). # 3. Simply mention the agent in your prompt (e.g., "As *dev, ...").
# 4. The Gemini CLI will automatically have the context for that agent. # 4. The Gemini CLI will automatically have the context for that agent.
github-copilot: github-copilot:
name: Github Copilot name: Github Copilot

View File

@@ -512,12 +512,53 @@ class IdeSetup {
async setupGeminiCli(installDir, selectedAgent) { async setupGeminiCli(installDir, selectedAgent) {
await initializeModules(); await initializeModules();
const geminiDir = path.join(installDir, ".gemini"); const geminiDir = path.join(installDir, ".gemini");
const agentsContextDir = path.join(geminiDir, "agents"); const bmadMethodDir = path.join(geminiDir, "bmad-method");
await fileManager.ensureDirectory(agentsContextDir); await fileManager.ensureDirectory(bmadMethodDir);
// Update logic for existing settings.json
const settingsPath = path.join(geminiDir, "settings.json");
if (await fileManager.pathExists(settingsPath)) {
try {
const settingsContent = await fileManager.readFile(settingsPath);
const settings = JSON.parse(settingsContent);
let updated = false;
// Handle contextFileName property
if (settings.contextFileName && Array.isArray(settings.contextFileName)) {
const originalLength = settings.contextFileName.length;
settings.contextFileName = settings.contextFileName.filter(
(fileName) => !fileName.startsWith("agents/")
);
if (settings.contextFileName.length !== originalLength) {
updated = true;
}
}
if (updated) {
await fileManager.writeFile(
settingsPath,
JSON.stringify(settings, null, 2)
);
console.log(chalk.green("✓ Updated .gemini/settings.json - removed agent file references"));
}
} catch (error) {
console.warn(
chalk.yellow("Could not update .gemini/settings.json"),
error
);
}
}
// Remove old agents directory
const agentsDir = path.join(geminiDir, "agents");
if (await fileManager.pathExists(agentsDir)) {
await fileManager.removeDirectory(agentsDir);
console.log(chalk.green("✓ Removed old .gemini/agents directory"));
}
// Get all available agents // Get all available agents
const agents = await this.getAllAgentIds(installDir); const agents = await this.getAllAgentIds(installDir);
const agentContextFiles = []; let concatenatedContent = "";
for (const agentId of agents) { for (const agentId of agents) {
// Find the source agent file // Find the source agent file
@@ -525,43 +566,46 @@ class IdeSetup {
if (agentPath) { if (agentPath) {
const agentContent = await fileManager.readFile(agentPath); const agentContent = await fileManager.readFile(agentPath);
const contextFilePath = path.join(agentsContextDir, `${agentId}.md`);
// Create properly formatted agent rule content (similar to trae)
// Copy the agent content directly into its own context file let agentRuleContent = `# ${agentId.toUpperCase()} Agent Rule\n\n`;
await fileManager.writeFile(contextFilePath, agentContent); agentRuleContent += `This rule is triggered when the user types \`*${agentId}\` and activates the ${await this.getAgentTitle(
agentId,
// Store the relative path for settings.json installDir
const relativePath = path.relative(geminiDir, contextFilePath); )} agent persona.\n\n`;
agentContextFiles.push(relativePath.replace(/\\/g, '/')); // Ensure forward slashes for consistency agentRuleContent += "## Agent Activation\n\n";
console.log(chalk.green(`✓ Created context file for @${agentId}`)); agentRuleContent +=
"CRITICAL: Read the full YAML, start activation to alter your state of being, follow startup section instructions, stay in this being until told to exit this mode:\n\n";
agentRuleContent += "```yaml\n";
// Extract just the YAML content from the agent file
const yamlContent = extractYamlFromAgent(agentContent);
if (yamlContent) {
agentRuleContent += yamlContent;
}
else {
// If no YAML found, include the whole content minus the header
agentRuleContent += agentContent.replace(/^#.*$/m, "").trim();
}
agentRuleContent += "\n```\n\n";
agentRuleContent += "## File Reference\n\n";
const relativePath = path.relative(installDir, agentPath).replace(/\\/g, '/');
agentRuleContent += `The complete agent definition is available in [${relativePath}](${relativePath}).\n\n`;
agentRuleContent += "## Usage\n\n";
agentRuleContent += `When the user types \`*${agentId}\`, activate this ${await this.getAgentTitle(
agentId,
installDir
)} persona and follow all instructions defined in the YAML configuration above.\n`;
// Add to concatenated content with separator
concatenatedContent += agentRuleContent + "\n\n---\n\n";
console.log(chalk.green(`✓ Added context for @${agentId}`));
} }
} }
console.log(chalk.green(`\n✓ Created individual agent context files in ${agentsContextDir}`)); // Write the concatenated content to GEMINI.md
const geminiMdPath = path.join(bmadMethodDir, "GEMINI.md");
// Add GEMINI.md to the context files array await fileManager.writeFile(geminiMdPath, concatenatedContent);
agentContextFiles.push("GEMINI.md"); console.log(chalk.green(`\n✓ Created GEMINI.md in ${bmadMethodDir}`));
// Create or update settings.json
const settingsPath = path.join(geminiDir, "settings.json");
let settings = {};
if (await fileManager.pathExists(settingsPath)) {
try {
const existingSettings = await fileManager.readFile(settingsPath);
settings = JSON.parse(existingSettings);
console.log(chalk.yellow("Found existing .gemini/settings.json. Merging settings..."));
} catch (e) {
console.error(chalk.red("Error parsing existing settings.json. It will be overwritten."), e);
settings = {};
}
}
// Set contextFileName to our new array of files
settings.contextFileName = agentContextFiles;
await fileManager.writeFile(settingsPath, JSON.stringify(settings, null, 2));
console.log(chalk.green(`✓ Configured .gemini/settings.json to load all agent context files.`));
return true; return true;
} }