From d8a4f84b527ff9dec96229fd0bfd7356196f8dda Mon Sep 17 00:00:00 2001 From: Copilot <198982749+Copilot@users.noreply.github.com> Date: Wed, 11 Mar 2026 13:39:31 +0100 Subject: [PATCH] feat: add Mistral Vibe CLI platform support (#1) * Initial plan * feat: add Mistral Vibe CLI platform support Co-authored-by: welcoMattic <773875+welcoMattic@users.noreply.github.com> * docs: add Mistral Vibe to installation documentation Co-authored-by: welcoMattic <773875+welcoMattic@users.noreply.github.com> * Fix directory name for Mistral Vibe skills in docs * Update Mistral Vibe target directory in tests * Change target directory for Mistral's CLI installer --------- Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com> Co-authored-by: welcoMattic <773875+welcoMattic@users.noreply.github.com> Co-authored-by: Mathieu Santostefano --- docs/how-to/install-bmad.md | 6 +- docs/how-to/non-interactive-installation.md | 2 + test/test-installation-components.js | 98 ++++++++++++++++++- .../installers/lib/ide/platform-codes.yaml | 10 ++ 4 files changed, 111 insertions(+), 5 deletions(-) diff --git a/docs/how-to/install-bmad.md b/docs/how-to/install-bmad.md index 3c0ca61d1..b5bdee101 100644 --- a/docs/how-to/install-bmad.md +++ b/docs/how-to/install-bmad.md @@ -49,6 +49,7 @@ Pick which AI tools you use: - Claude Code - Cursor +- Mistral Vibe - Others Each tool has its own way of integrating skills. The installer creates tiny prompt files to activate workflows and agents — it just puts them where your tool expects to find them. @@ -80,7 +81,10 @@ your-project/ │ ├── bmad-help/ │ ├── bmad-persona/ │ └── ... -└── .cursor/ # Cursor skills (if using Cursor) +├── .cursor/ # Cursor skills (if using Cursor) +│ └── skills/ +│ └── ... +└── .vibe/ # Mistral Vibe skills (if using Mistral Vibe) └── skills/ └── ... ``` diff --git a/docs/how-to/non-interactive-installation.md b/docs/how-to/non-interactive-installation.md index fa7a1e7b1..f3cf8161b 100644 --- a/docs/how-to/non-interactive-installation.md +++ b/docs/how-to/non-interactive-installation.md @@ -61,6 +61,8 @@ Available tool IDs for the `--tools` flag: **Preferred:** `claude-code`, `cursor` +**Other CLIs:** `mistral`, `gemini`, `codex`, `auggie`, `pi` + Run `npx bmad-method install` interactively once to see the full current list of supported tools, or check the [platform codes configuration](https://github.com/bmad-code-org/BMAD-METHOD/blob/main/tools/cli/installers/lib/ide/platform-codes.yaml). ## Installation Modes diff --git a/test/test-installation-components.js b/test/test-installation-components.js index 1654bc110..d59f10242 100644 --- a/test/test-installation-components.js +++ b/test/test-installation-components.js @@ -1591,9 +1591,99 @@ async function runTests() { console.log(''); // ============================================================ - // Suite 29: Unified Skill Scanner — collectSkills + // Suite 29: Mistral Vibe CLI Native Skills // ============================================================ - console.log(`${colors.yellow}Test Suite 29: Unified Skill Scanner${colors.reset}\n`); + console.log(`${colors.yellow}Test Suite 29: Mistral Vibe CLI Native Skills${colors.reset}\n`); + + let tempProjectDir29; + let installedBmadDir29; + try { + clearCache(); + const platformCodes29 = await loadPlatformCodes(); + const mistralInstaller = platformCodes29.platforms.mistral?.installer; + + assert(mistralInstaller?.target_dir === '.vibe/skills', 'Mistral Vibe target_dir uses native skills path'); + assert(mistralInstaller?.skill_format === true, 'Mistral Vibe installer enables native skill output'); + assert(mistralInstaller?.template_type === 'default', 'Mistral Vibe installer uses default skill template'); + + tempProjectDir29 = await fs.mkdtemp(path.join(os.tmpdir(), 'bmad-mistral-test-')); + installedBmadDir29 = await createTestBmadFixture(); + + const ideManager29 = new IdeManager(); + await ideManager29.ensureInitialized(); + + // Verify Mistral Vibe is selectable in available IDEs list + const availableIdes29 = ideManager29.getAvailableIdes(); + assert( + availableIdes29.some((ide) => ide.value === 'mistral'), + 'Mistral Vibe appears in available IDEs list', + ); + + // Verify Mistral Vibe is NOT detected before install + const detectedBefore29 = await ideManager29.detectInstalledIdes(tempProjectDir29); + assert(!detectedBefore29.includes('mistral'), 'Mistral Vibe is not detected before install'); + + const result29 = await ideManager29.setup('mistral', tempProjectDir29, installedBmadDir29, { + silent: true, + selectedModules: ['bmm'], + }); + + assert(result29.success === true, 'Mistral Vibe setup succeeds against temp project'); + + // Verify Mistral Vibe IS detected after install + const detectedAfter29 = await ideManager29.detectInstalledIdes(tempProjectDir29); + assert(detectedAfter29.includes('mistral'), 'Mistral Vibe is detected after install'); + + const skillFile29 = path.join(tempProjectDir29, '.vibe', 'skills', 'bmad-master', 'SKILL.md'); + assert(await fs.pathExists(skillFile29), 'Mistral Vibe install writes SKILL.md directory output'); + + // Parse YAML frontmatter between --- markers + const skillContent29 = await fs.readFile(skillFile29, 'utf8'); + const fmMatch29 = skillContent29.match(/^---\n([\s\S]*?)\n---\n?([\s\S]*)$/); + assert(fmMatch29, 'Mistral Vibe SKILL.md contains valid frontmatter delimiters'); + + const frontmatter29 = fmMatch29[1]; + const body29 = fmMatch29[2]; + + // Verify name in frontmatter matches directory name + const fmName29 = frontmatter29.match(/^name:\s*(.+)$/m); + assert(fmName29 && fmName29[1].trim() === 'bmad-master', 'Mistral Vibe skill name frontmatter matches directory name exactly'); + + // Verify description exists and is non-empty + const fmDesc29 = frontmatter29.match(/^description:\s*(.+)$/m); + assert(fmDesc29 && fmDesc29[1].trim().length > 0, 'Mistral Vibe skill description frontmatter is present and non-empty'); + + // Verify frontmatter contains only name and description keys + const fmKeys29 = [...frontmatter29.matchAll(/^([a-zA-Z0-9_-]+):/gm)].map((m) => m[1]); + assert( + fmKeys29.length === 2 && fmKeys29.includes('name') && fmKeys29.includes('description'), + 'Mistral Vibe skill frontmatter contains only name and description keys', + ); + + // Verify body content is non-empty and contains expected activation instructions + assert(body29.trim().length > 0, 'Mistral Vibe skill body content is non-empty'); + assert(body29.includes('agent-activation'), 'Mistral Vibe skill body contains expected agent activation instructions'); + + // Reinstall/upgrade: run setup again over existing output + const result29b = await ideManager29.setup('mistral', tempProjectDir29, installedBmadDir29, { + silent: true, + selectedModules: ['bmm'], + }); + assert(result29b.success === true, 'Mistral Vibe reinstall/upgrade succeeds over existing skills'); + assert(await fs.pathExists(skillFile29), 'Mistral Vibe reinstall preserves SKILL.md output'); + } catch (error) { + assert(false, 'Mistral Vibe native skills test succeeds', error.message); + } finally { + if (tempProjectDir29) await fs.remove(tempProjectDir29).catch(() => {}); + if (installedBmadDir29) await fs.remove(installedBmadDir29).catch(() => {}); + } + + console.log(''); + + // ============================================================ + // Suite 30: Unified Skill Scanner — collectSkills + // ============================================================ + console.log(`${colors.yellow}Test Suite 30: Unified Skill Scanner${colors.reset}\n`); let tempFixture29; try { @@ -1704,9 +1794,9 @@ async function runTests() { console.log(''); // ============================================================ - // Suite 30: parseSkillMd validation (negative cases) + // Suite 31: parseSkillMd validation (negative cases) // ============================================================ - console.log(`${colors.yellow}Test Suite 30: parseSkillMd Validation${colors.reset}\n`); + console.log(`${colors.yellow}Test Suite 31: parseSkillMd Validation${colors.reset}\n`); let tempFixture30; try { diff --git a/tools/cli/installers/lib/ide/platform-codes.yaml b/tools/cli/installers/lib/ide/platform-codes.yaml index 9d5f171f1..bee4a1591 100644 --- a/tools/cli/installers/lib/ide/platform-codes.yaml +++ b/tools/cli/installers/lib/ide/platform-codes.yaml @@ -176,6 +176,16 @@ platforms: template_type: kiro skill_format: true + mistral: + name: "Mistral Vibe" + preferred: false + category: cli + description: "Mistral's AI coding CLI" + installer: + target_dir: .vibe/skills + template_type: default + skill_format: true + opencode: name: "OpenCode" preferred: false