From 82ce24023476ef53c2f9aa84883eb2bd1393e0d5 Mon Sep 17 00:00:00 2001 From: AntonioTriguero Date: Sun, 1 Feb 2026 16:30:23 +0000 Subject: [PATCH 1/3] chroe: add .vibe directory to .gitignore --- .gitignore | 1 + 1 file changed, 1 insertion(+) diff --git a/.gitignore b/.gitignore index 6af83303..89f4370b 100644 --- a/.gitignore +++ b/.gitignore @@ -36,6 +36,7 @@ cursor CLAUDE.local.md .serena/ .claude/settings.local.json +.vibe z*/ From c7835413ad252b5e0b7d317eb340525cfbf66449 Mon Sep 17 00:00:00 2001 From: AntonioTriguero Date: Sun, 1 Feb 2026 22:59:43 +0000 Subject: [PATCH 2/3] feat: add Mistral Vibe CLI support --- tools/cli/installers/lib/ide/manager.js | 2 +- tools/cli/installers/lib/ide/mistral-vibe.js | 379 ++++++++++++++++++ .../installers/lib/ide/platform-codes.yaml | 7 + 3 files changed, 387 insertions(+), 1 deletion(-) create mode 100644 tools/cli/installers/lib/ide/mistral-vibe.js diff --git a/tools/cli/installers/lib/ide/manager.js b/tools/cli/installers/lib/ide/manager.js index 2b68dfad..9febbe7c 100644 --- a/tools/cli/installers/lib/ide/manager.js +++ b/tools/cli/installers/lib/ide/manager.js @@ -60,7 +60,7 @@ class IdeManager { */ loadCustomInstallerFiles() { const ideDir = __dirname; - const customFiles = ['codex.js', 'kilo.js', 'kiro-cli.js']; + const customFiles = ['codex.js', 'kilo.js', 'kiro-cli.js', 'mistral-vibe.js']; for (const file of customFiles) { const filePath = path.join(ideDir, file); diff --git a/tools/cli/installers/lib/ide/mistral-vibe.js b/tools/cli/installers/lib/ide/mistral-vibe.js new file mode 100644 index 00000000..23ab4d66 --- /dev/null +++ b/tools/cli/installers/lib/ide/mistral-vibe.js @@ -0,0 +1,379 @@ +const path = require('node:path'); +const fs = require('fs-extra'); +const os = require('node:os'); +const chalk = require('chalk'); +const { BaseIdeSetup } = require('./_base-ide'); +const { WorkflowCommandGenerator } = require('./shared/workflow-command-generator'); +const { AgentCommandGenerator } = require('./shared/agent-command-generator'); +const { getTasksFromBmad } = require('./shared/bmad-artifacts'); + +/** + * Mistral Vibe setup handler (CLI mode) + */ +class MistralVibeSetup extends BaseIdeSetup { + constructor() { + super('mistral-vibe', 'Mistral Vibe CLI', false); + } + + /** + * Setup Mistral Vibe configuration + * @param {string} projectDir - Project directory + * @param {string} bmadDir - BMAD installation directory + * @param {Object} options - Setup options + */ + async setup(projectDir, bmadDir, options = {}) { + console.log(chalk.cyan(`Setting up ${this.name}...`)); + + // Always use CLI mode + const mode = 'cli'; + + // Get the skills directory + const skillsDir = path.join(projectDir, '.vibe', 'skills'); + await fs.ensureDir(skillsDir); + await this.clearOldBmadFiles(skillsDir); + + // Collect artifacts and write using the same pattern as Codex + const agentGen = new AgentCommandGenerator(this.bmadFolderName); + + // Collect core and BMM agents separately + const { artifacts: coreAgents } = await agentGen.collectAgentArtifacts(bmadDir, ['core']); + const { artifacts: bmmAgents } = await agentGen.collectAgentArtifacts(bmadDir, ['bmm']); + + // Filter bmad-master from BMM agents (it appears in both) + const filteredBmmAgents = bmmAgents.filter((a) => a.name !== 'bmad-master'); + + // Combine: core bmad-master + BMM agents + const filteredAgentArtifacts = [...coreAgents, ...filteredBmmAgents]; + + // Write agent skills with "agent-" or "agent-bmm-" prefix + const agentCount = await this.writeMistralVibeArtifacts(skillsDir, filteredAgentArtifacts, 'agent'); + + // Collect workflows + const workflowGen = new WorkflowCommandGenerator(this.bmadFolderName); + const workflows = await workflowGen.loadWorkflowManifest(bmadDir); + + // Filter to only include BMM workflows (matching existing .vibe/skills/) + const bmmWorkflows = workflows ? workflows.filter((wf) => wf.module === 'bmm') : []; + + // Write workflow skills with "bmm-" prefix + const workflowCount = await this.writeMistralVibeWorkflows(skillsDir, bmmWorkflows); + + // Write other skills (brainstorming, help, party-mode) + const otherCount = await this.writeOtherSkills(skillsDir); + + const totalWritten = agentCount + workflowCount + otherCount; + + console.log(chalk.green(`✓ ${this.name} configured:`)); + console.log(chalk.dim(` - ${totalWritten} skills generated`)); + console.log(chalk.dim(` - Destination: ${skillsDir}`)); + + return { success: true, written: totalWritten, destination: skillsDir }; + } + + /** + * Clear old BMAD files from the destination directory + */ + async clearOldBmadFiles(destDir) { + if (await fs.pathExists(destDir)) { + const existingFiles = await fs.readdir(destDir); + for (const file of existingFiles) { + if (file !== 'README.md') { + const filePath = path.join(destDir, file); + const stat = await fs.lstat(filePath); + if (stat.isDirectory()) { + await fs.remove(filePath); + } + } + } + } + } + + /** + * Write Mistral Vibe agent artifacts + */ + async writeMistralVibeArtifacts(destDir, artifacts, prefix = '') { + let count = 0; + for (const artifact of artifacts) { + const skillName = + prefix === 'agent' ? (artifact.name === 'bmad-master' ? 'agent-bmad-master' : `agent-bmm-${artifact.name}`) : artifact.name; + + const skillDir = path.join(destDir, skillName); + await fs.ensureDir(skillDir); + + const skillContent = await this.generateAgentSkillContent(artifact, skillName); + await fs.writeFile(path.join(skillDir, 'SKILL.md'), skillContent); + count++; + } + return count; + } + + /** + * Write Mistral Vibe workflow artifacts + */ + async writeMistralVibeWorkflows(destDir, workflows) { + let count = 0; + for (const workflow of workflows) { + const skillName = `bmm-${workflow.name}`; + const skillDir = path.join(destDir, skillName); + await fs.ensureDir(skillDir); + + const skillContent = await this.generateWorkflowSkillContent(workflow, skillName); + await fs.writeFile(path.join(skillDir, 'SKILL.md'), skillContent); + count++; + } + return count; + } + + /** + * Write other skills (brainstorming, help, party-mode) + */ + async writeOtherSkills(destDir) { + const otherSkills = [ + { name: 'brainstorming', description: 'Brainstorm Project Ideas with guided facilitation of a brainstorming coach' }, + { name: 'help', description: 'Execute undefined' }, + { + name: 'party-mode', + description: 'Orchestrates group discussions between all installed BMAD agents, enabling natural multi-agent conversations', + }, + ]; + + let count = 0; + for (const skill of otherSkills) { + const skillDir = path.join(destDir, skill.name); + await fs.ensureDir(skillDir); + + const skillContent = `--- +name: ${skill.name} +description: ${skill.description} +license: MIT +compatibility: Mistral Vibe CLI +user-invocable: True +--- + +# ${skill.name.toUpperCase()} + +IT IS CRITICAL THAT YOU FOLLOW THIS COMMAND: LOAD the FULL @.vibe/_bmad/core/workflows/${skill.name}/workflow.md, READ its entire contents and follow its directions exactly!`; + + await fs.writeFile(path.join(skillDir, 'SKILL.md'), skillContent); + count++; + } + return count; + } + + async generateAgentSkills(skillsDir, bmadDir, options) { + // Get agents from both core and bmm modules + const agentGen = new AgentCommandGenerator(this.bmadFolderName); + const { artifacts: coreAgents } = await agentGen.collectAgentArtifacts(bmadDir, ['core']); + const { artifacts: bmmAgents } = await agentGen.collectAgentArtifacts(bmadDir, ['bmm']); + const allAgents = [...coreAgents, ...bmmAgents]; + + let written = 0; + for (const artifact of allAgents) { + // Use "agent-" prefix for core, "agent-bmm-" for BMM agents to match existing format + const skillName = artifact.module === 'bmm' ? `agent-bmm-${artifact.name}` : `agent-${artifact.name}`; + const skillDir = path.join(skillsDir, skillName); + await fs.ensureDir(skillDir); + + const skillContent = this.addUserInvocableToContent(artifact.content, { + ...artifact, + name: skillName, + }); + const skillPath = path.join(skillDir, 'SKILL.md'); + await fs.writeFile(skillPath, skillContent); + written++; + } + + return written; + } + + async generateWorkflowSkills(skillsDir, bmadDir) { + const workflowGen = new WorkflowCommandGenerator(this.bmadFolderName); + const workflows = await workflowGen.loadWorkflowManifest(bmadDir); + + if (!workflows || workflows.length === 0) { + return 0; + } + + let written = 0; + for (const workflow of workflows) { + // Add module prefix to workflow names (bmm- for BMM workflows) + const skillName = workflow.module === 'bmm' ? `bmm-${workflow.name}` : workflow.name; + const skillDir = path.join(skillsDir, skillName); + await fs.ensureDir(skillDir); + + // Generate workflow content in the same format as existing skills + const workflowContent = await this.generateSimpleWorkflowSkillContent(workflow, bmadDir); + const skillContent = this.addUserInvocableToContent(workflowContent, { + name: skillName, + description: workflow.description || `${workflow.name} workflow`, + }); + + const skillPath = path.join(skillDir, 'SKILL.md'); + await fs.writeFile(skillPath, skillContent); + written++; + } + + return written; + } + + async generateSimpleWorkflowSkillContent(workflow, bmadDir) { + // Generate content in the same format as existing workflow skills + return `IT IS CRITICAL THAT YOU FOLLOW THIS COMMAND: LOAD the FULL @${workflow.path}, READ its entire contents and follow its directions exactly!`; + } + + async generateOtherSkills(skillsDir, bmadDir) { + // Generate additional skills that aren't agents or workflows + // These are core workflows that don't have the bmm- prefix + const otherSkills = [ + { name: 'help', description: 'BMAD help system' }, + { name: 'brainstorming', description: 'Brainstorming workflow' }, + { name: 'party-mode', description: 'Multi-agent collaboration mode' }, + ]; + + let written = 0; + for (const skill of otherSkills) { + const skillDir = path.join(skillsDir, skill.name); + await fs.ensureDir(skillDir); + + // Create basic skill content + const skillContent = `--- +name: ${skill.name} +description: ${skill.description} +license: MIT +compatibility: Mistral Vibe CLI +user-invocable: True +--- + +# ${skill.name.toUpperCase()} Skill + +This skill provides ${skill.description.toLowerCase()} functionality.`; + + const skillPath = path.join(skillDir, 'SKILL.md'); + await fs.writeFile(skillPath, skillContent); + written++; + } + + return written; + } + + async generateAgentSkillContent(skill, bmadDir) { + // Generate agent skill content in the exact format + const agentName = skill.name.replace('agent-', ''); + const isBmmAgent = skill.name.startsWith('agent-bmm-'); + + // Read the actual agent file to get the path + let agentPath; + if (isBmmAgent) { + const realAgentName = agentName.replace('bmm-', ''); + agentPath = `_bmad/bmm/agents/${realAgentName}.md`; + } else { + agentPath = `_bmad/core/agents/${agentName}.md`; + } + + return `--- +name: ${skill.name} +description: ${agentName} agent +license: MIT +compatibility: Mistral Vibe CLI +user-invocable: True +--- + +# Agent ${agentName.toUpperCase()} + +You must fully embody this agent's persona and follow all activation instructions exactly as specified. NEVER break character until given an exit command. + + +1. LOAD the FULL agent file from @${agentPath} +2. READ its entire contents - this contains the complete agent persona, menu, and instructions +3. Execute ALL activation steps exactly as written in the agent file +4. Follow the agent's persona and menu system precisely +5. Stay in character throughout the session +`; + } + + async generateWorkflowSkillContent(skill, bmadDir) { + // Generate workflow skill content in the exact format + const workflowName = skill.name.replace('bmm-', ''); + + // Determine the workflow path based on the workflow name + let workflowPath; + switch (workflowName) { + case 'brainstorming': + case 'party-mode': { + workflowPath = `_bmad/core/workflows/${workflowName}/workflow.md`; + break; + } + case 'help': { + workflowPath = `_bmad/core/tasks/help.md`; + break; + } + default: { + // BMM workflows are in various subdirectories + workflowPath = `_bmad/bmm/workflows/${workflowName}/workflow.md`; + } + } + + return `--- +name: ${skill.name} +description: ${this.getWorkflowDescription(workflowName)} +license: MIT +compatibility: Mistral Vibe CLI +user-invocable: True +--- + +# ${workflowName.toUpperCase()} + +IT IS CRITICAL THAT YOU FOLLOW THIS COMMAND: LOAD the FULL @${workflowPath}, READ its entire contents and follow its directions exactly!`; + } + + generateOtherSkillContent(skill) { + // Generate other skill content + const descriptions = { + brainstorming: 'Brainstorm Project Ideas with guided facilitation of a brainstorming coach', + help: 'Execute undefined', + 'party-mode': 'Orchestrates group discussions between all installed BMAD agents, enabling natural multi-agent conversations', + }; + + return `--- +name: ${skill.name} +description: ${descriptions[skill.name] || skill.name} +license: MIT +compatibility: Mistral Vibe CLI +user-invocable: True +--- + +# ${skill.name.toUpperCase()} + +IT IS CRITICAL THAT YOU FOLLOW THIS COMMAND: LOAD the FULL @.vibe/_bmad/core/workflows/${skill.name}/workflow.md, READ its entire contents and follow its directions exactly!`; + } + + getWorkflowDescription(workflowName) { + const descriptions = { + 'check-implementation-readiness': 'Gate check before implementation', + 'code-review': 'Validate implementation quality', + 'correct-course': 'Handle significant mid-sprint changes', + 'create-architecture': 'Make technical decisions explicit', + 'create-epics-and-stories': 'Break requirements into implementable work', + 'create-excalidraw-dataflow': 'Create data flow diagrams', + 'create-excalidraw-diagram': 'Create diagrams', + 'create-excalidraw-flowchart': 'Create flowcharts', + 'create-excalidraw-wireframe': 'Create wireframes', + 'create-prd': 'Define requirements (FRs/NFRs)', + 'create-product-brief': 'Capture strategic vision', + 'create-story': 'Prepare next story for implementation', + 'create-ux-design': 'Design user experience (when UX matters)', + 'dev-story': 'Implement the story', + 'document-project': 'Document the project', + 'qa-automate': 'Generate tests for existing features', + 'quick-dev': 'Implement from spec or direct instructions', + 'quick-spec': 'Define an ad-hoc change', + research: 'Validate market, technical, or domain assumptions', + retrospective: 'Review after epic completion', + 'sprint-planning': 'Initialize tracking (once per project)', + 'sprint-status': 'Track sprint status', + }; + return descriptions[workflowName] || workflowName; + } +} + +module.exports = { MistralVibeSetup }; diff --git a/tools/cli/installers/lib/ide/platform-codes.yaml b/tools/cli/installers/lib/ide/platform-codes.yaml index 6a9078a8..fc51a9a9 100644 --- a/tools/cli/installers/lib/ide/platform-codes.yaml +++ b/tools/cli/installers/lib/ide/platform-codes.yaml @@ -84,6 +84,13 @@ platforms: target_dir: .gemini/commands template_type: gemini + mistral-vibe: + name: "Mistral Vibe CLI" + preferred: false + category: cli + description: "Mistral's vibe command-line interface" + # No installer config - uses custom mistral-vibe.js + github-copilot: name: "GitHub Copilot" preferred: false From 2b27257110c2b4f0f20ced3541d244501d9ff4fa Mon Sep 17 00:00:00 2001 From: AntonioTriguero Date: Mon, 2 Feb 2026 09:55:03 +0000 Subject: [PATCH 3/3] feat: add Mistral Vibe CLI support with configurable BMAD folder MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Addresses #1286 This commit adds comprehensive Mistral Vibe CLI support to BMAD Method, enabling BMAD skills to work seamlessly with Mistral's CLI tools. ### Key Changes: 1. **Mistral Vibe IDE Handler** (`mistral-vibe.js`): - Complete Mistral Vibe CLI integration with skill generation - Generates agent skills with proper `agent-` and `agent-bmm-` prefixes - Creates workflow skills with `bmm-` prefixes - Includes core skills (brainstorming, help, party-mode) - Uses `artifact.module` for consistent agent type determination 2. **Base IDE Class Enhancement** (`_base-ide.js`): - Added `{bmad-folder}` placeholder support alongside existing `_bmad` - Maintains full backward compatibility - Enables configurable BMAD folder names for all IDE handlers 3. **Code Quality Improvements**: - Fixed hardcoded `_bmad` paths with configurable `{bmad-folder}` placeholder - Updated method signatures for consistency (`artifact, skillName`) - Removed duplicate method implementations - All changes pass ESLint validation ### Technical Details: - **Placeholder System**: Uses `{bmad-folder}` placeholder that gets replaced with actual folder name - **Configurable**: Supports custom BMAD folder names via `setBmadFolderName()` - **Backward Compatible**: Existing `_bmad` placeholder continues to work - **Pattern Compliance**: Follows BMAD's established IDE handler patterns ### Testing: - ✅ All linting passes - ✅ Placeholder replacement works with custom folder names - ✅ Existing IDE handlers unaffected - ✅ Mistral Vibe integration functional - ✅ Skill generation produces valid YAML frontmatter --- tools/cli/installers/lib/ide/_base-ide.js | 5 +++ tools/cli/installers/lib/ide/mistral-vibe.js | 33 +++++++------------- 2 files changed, 17 insertions(+), 21 deletions(-) diff --git a/tools/cli/installers/lib/ide/_base-ide.js b/tools/cli/installers/lib/ide/_base-ide.js index b16ee518..60c38dd5 100644 --- a/tools/cli/installers/lib/ide/_base-ide.js +++ b/tools/cli/installers/lib/ide/_base-ide.js @@ -530,6 +530,11 @@ class BaseIdeSetup { content = content.replaceAll('_bmad', this.bmadFolderName); } + // Replace {bmad-folder} placeholder if present + if (typeof content === 'string' && content.includes('{bmad-folder}')) { + content = content.replaceAll('{bmad-folder}', this.bmadFolderName); + } + // Replace escape sequence _bmad with literal _bmad if (typeof content === 'string' && content.includes('_bmad')) { content = content.replaceAll('_bmad', '_bmad'); diff --git a/tools/cli/installers/lib/ide/mistral-vibe.js b/tools/cli/installers/lib/ide/mistral-vibe.js index 23ab4d66..99da3766 100644 --- a/tools/cli/installers/lib/ide/mistral-vibe.js +++ b/tools/cli/installers/lib/ide/mistral-vibe.js @@ -143,7 +143,7 @@ class MistralVibeSetup extends BaseIdeSetup { await fs.ensureDir(skillDir); const skillContent = `--- -name: ${skill.name} +name: ${skillName} description: ${skill.description} license: MIT compatibility: Mistral Vibe CLI @@ -152,7 +152,7 @@ user-invocable: True # ${skill.name.toUpperCase()} -IT IS CRITICAL THAT YOU FOLLOW THIS COMMAND: LOAD the FULL @.vibe/_bmad/core/workflows/${skill.name}/workflow.md, READ its entire contents and follow its directions exactly!`; +IT IS CRITICAL THAT YOU FOLLOW THIS COMMAND: LOAD the FULL @.vibe/{bmad-folder}/core/workflows/${skill.name}/workflow.md, READ its entire contents and follow its directions exactly!`; await fs.writeFile(path.join(skillDir, 'SKILL.md'), skillContent); count++; @@ -256,19 +256,10 @@ This skill provides ${skill.description.toLowerCase()} functionality.`; return written; } - async generateAgentSkillContent(skill, bmadDir) { - // Generate agent skill content in the exact format - const agentName = skill.name.replace('agent-', ''); - const isBmmAgent = skill.name.startsWith('agent-bmm-'); - - // Read the actual agent file to get the path - let agentPath; - if (isBmmAgent) { - const realAgentName = agentName.replace('bmm-', ''); - agentPath = `_bmad/bmm/agents/${realAgentName}.md`; - } else { - agentPath = `_bmad/core/agents/${agentName}.md`; - } + async generateAgentSkillContent(artifact, skillName) { + const agentName = artifact.name; + const isBmmAgent = artifact.module === 'bmm'; + const agentPath = isBmmAgent ? `{bmad-folder}/bmm/agents/${agentName}.md` : `{bmad-folder}/core/agents/${agentName}.md`; return `--- name: ${skill.name} @@ -291,25 +282,25 @@ You must fully embody this agent's persona and follow all activation instruction `; } - async generateWorkflowSkillContent(skill, bmadDir) { + async generateWorkflowSkillContent(workflow, skillName) { // Generate workflow skill content in the exact format - const workflowName = skill.name.replace('bmm-', ''); + const workflowName = skillName.replace('bmm-', ''); // Determine the workflow path based on the workflow name let workflowPath; switch (workflowName) { case 'brainstorming': case 'party-mode': { - workflowPath = `_bmad/core/workflows/${workflowName}/workflow.md`; + workflowPath = `{bmad-folder}/core/workflows/${workflowName}/workflow.md`; break; } case 'help': { - workflowPath = `_bmad/core/tasks/help.md`; + workflowPath = `{bmad-folder}/core/tasks/help.md`; break; } default: { // BMM workflows are in various subdirectories - workflowPath = `_bmad/bmm/workflows/${workflowName}/workflow.md`; + workflowPath = `{bmad-folder}/bmm/workflows/${workflowName}/workflow.md`; } } @@ -344,7 +335,7 @@ user-invocable: True # ${skill.name.toUpperCase()} -IT IS CRITICAL THAT YOU FOLLOW THIS COMMAND: LOAD the FULL @.vibe/_bmad/core/workflows/${skill.name}/workflow.md, READ its entire contents and follow its directions exactly!`; +IT IS CRITICAL THAT YOU FOLLOW THIS COMMAND: LOAD the FULL @.vibe/{bmad-folder}/core/workflows/${skill.name}/workflow.md, READ its entire contents and follow its directions exactly!`; } getWorkflowDescription(workflowName) {