added gemini cli custom commands! (#549)
* added gemini cli custom commands! * improvements and changes post review * updated bmad to BMad * removed gemini-extension.json --------- Co-authored-by: Brian <bmadcode@gmail.com>
This commit is contained in:
@@ -78,15 +78,15 @@ 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/bmad-method/
|
rule-dir: .gemini/commands/BMad/
|
||||||
format: single-file
|
format: multi-file
|
||||||
command-suffix: .md
|
command-suffix: .toml
|
||||||
instructions: |
|
instructions: |
|
||||||
# To use BMad agents with the Gemini CLI:
|
# To use BMad agents with the Gemini CLI:
|
||||||
# 1. The installer creates a .gemini/bmad-method/ directory in your project.
|
# 1. The installer creates a `BMad` folder in `.gemini/commands`.
|
||||||
# 2. It concatenates all agent files into a single GEMINI.md file.
|
# 2. This adds custom commands for each agent and task.
|
||||||
# 3. Simply mention the agent in your prompt (e.g., "As *dev, ...").
|
# 3. Type /BMad:agents:<agent-name> (e.g., "/BMad:agents:dev", "/BMad:agents:pm") or /BMad:tasks:<task-name> (e.g., "/BMad:tasks:create-doc").
|
||||||
# 4. The Gemini CLI will automatically have the context for that agent.
|
# 4. The agent will adopt that persona for the conversation or preform the task.
|
||||||
github-copilot:
|
github-copilot:
|
||||||
name: Github Copilot
|
name: Github Copilot
|
||||||
rule-dir: .github/chatmodes/
|
rule-dir: .github/chatmodes/
|
||||||
|
|||||||
@@ -1208,97 +1208,77 @@ class IdeSetup extends BaseIdeSetup {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
async setupGeminiCli(installDir) {
|
async setupGeminiCli(installDir, selectedAgent) {
|
||||||
const geminiDir = path.join(installDir, '.gemini');
|
const ideConfig = await configLoader.getIdeConfiguration('gemini');
|
||||||
const bmadMethodDir = path.join(geminiDir, 'bmad-method');
|
const bmadCommandsDir = path.join(installDir, ideConfig['rule-dir']);
|
||||||
await fileManager.ensureDirectory(bmadMethodDir);
|
|
||||||
|
|
||||||
// Update logic for existing settings.json
|
const agentCommandsDir = path.join(bmadCommandsDir, 'agents');
|
||||||
const settingsPath = path.join(geminiDir, 'settings.json');
|
const taskCommandsDir = path.join(bmadCommandsDir, 'tasks');
|
||||||
if (await fileManager.pathExists(settingsPath)) {
|
await fileManager.ensureDirectory(agentCommandsDir);
|
||||||
try {
|
await fileManager.ensureDirectory(taskCommandsDir);
|
||||||
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
|
|
||||||
const agents = await this.getAllAgentIds(installDir);
|
|
||||||
let concatenatedContent = '';
|
|
||||||
|
|
||||||
|
// Process Agents
|
||||||
|
const agents = selectedAgent ? [selectedAgent] : await this.getAllAgentIds(installDir);
|
||||||
for (const agentId of agents) {
|
for (const agentId of agents) {
|
||||||
// Find the source agent file
|
|
||||||
const agentPath = await this.findAgentPath(agentId, installDir);
|
const agentPath = await this.findAgentPath(agentId, installDir);
|
||||||
|
if (!agentPath) {
|
||||||
if (agentPath) {
|
console.log(chalk.yellow(`✗ Agent file not found for ${agentId}, skipping.`));
|
||||||
const agentContent = await fileManager.readFile(agentPath);
|
continue;
|
||||||
|
|
||||||
// Create properly formatted agent rule content (similar to trae)
|
|
||||||
let agentRuleContent = `# ${agentId.toUpperCase()} Agent Rule\n\n`;
|
|
||||||
agentRuleContent += `This rule is triggered when the user types \`*${agentId}\` and activates the ${await this.getAgentTitle(
|
|
||||||
agentId,
|
|
||||||
installDir,
|
|
||||||
)} agent persona.\n\n`;
|
|
||||||
agentRuleContent += '## Agent Activation\n\n';
|
|
||||||
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).replaceAll('\\', '/');
|
|
||||||
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}`));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const agentTitle = await this.getAgentTitle(agentId, installDir);
|
||||||
|
const commandPath = path.join(agentCommandsDir, `${agentId}.toml`);
|
||||||
|
|
||||||
|
// Get relative path from installDir to agent file for @{file} reference
|
||||||
|
const relativeAgentPath = path.relative(installDir, agentPath).replaceAll('\\', '/');
|
||||||
|
|
||||||
|
const tomlContent = `description = "Activates the ${agentTitle} agent from the BMad Method."
|
||||||
|
prompt = """
|
||||||
|
CRITICAL: You are now the BMad '${agentTitle}' agent. Adopt its persona, follow its instructions, and use its capabilities. The full agent definition is below.
|
||||||
|
|
||||||
|
@{${relativeAgentPath}}
|
||||||
|
"""`;
|
||||||
|
|
||||||
|
await fileManager.writeFile(commandPath, tomlContent);
|
||||||
|
console.log(chalk.green(`✓ Created agent command: /bmad:agents:${agentId}`));
|
||||||
}
|
}
|
||||||
|
|
||||||
// Write the concatenated content to GEMINI.md
|
// Process Tasks
|
||||||
const geminiMdPath = path.join(bmadMethodDir, 'GEMINI.md');
|
const tasks = await this.getAllTaskIds(installDir);
|
||||||
await fileManager.writeFile(geminiMdPath, concatenatedContent);
|
for (const taskId of tasks) {
|
||||||
console.log(chalk.green(`\n✓ Created GEMINI.md in ${bmadMethodDir}`));
|
const taskPath = await this.findTaskPath(taskId, installDir);
|
||||||
|
if (!taskPath) {
|
||||||
|
console.log(chalk.yellow(`✗ Task file not found for ${taskId}, skipping.`));
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
const taskTitle = taskId
|
||||||
|
.split('-')
|
||||||
|
.map((word) => word.charAt(0).toUpperCase() + word.slice(1))
|
||||||
|
.join(' ');
|
||||||
|
const commandPath = path.join(taskCommandsDir, `${taskId}.toml`);
|
||||||
|
|
||||||
|
// Get relative path from installDir to task file for @{file} reference
|
||||||
|
const relativeTaskPath = path.relative(installDir, taskPath).replaceAll('\\', '/');
|
||||||
|
|
||||||
|
const tomlContent = `description = "Executes the BMad Task: ${taskTitle}"
|
||||||
|
prompt = """
|
||||||
|
CRITICAL: You are to execute the BMad Task defined below.
|
||||||
|
|
||||||
|
@{${relativeTaskPath}}
|
||||||
|
"""`;
|
||||||
|
|
||||||
|
await fileManager.writeFile(commandPath, tomlContent);
|
||||||
|
console.log(chalk.green(`✓ Created task command: /bmad:tasks:${taskId}`));
|
||||||
|
}
|
||||||
|
|
||||||
|
console.log(
|
||||||
|
chalk.green(`
|
||||||
|
✓ Created Gemini CLI extension in ${bmadCommandsDir}`),
|
||||||
|
);
|
||||||
|
console.log(
|
||||||
|
chalk.dim('You can now use commands like /bmad:agents:dev or /bmad:tasks:create-doc.'),
|
||||||
|
);
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user