Skip to content

Commit fbcc244

Browse files
CopilotwelcoMattic
andcommitted
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 <msantostefano@proton.me>
1 parent bed9052 commit fbcc244

4 files changed

Lines changed: 111 additions & 3 deletions

File tree

docs/how-to/install-bmad.md

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -89,7 +89,10 @@ your-project/
8989
│ ├── bmad-help/
9090
│ ├── bmad-persona/
9191
│ └── ...
92-
└── .cursor/ # Cursor skills (if using Cursor)
92+
├── .cursor/ # Cursor skills (if using Cursor)
93+
│ └── skills/
94+
│ └── ...
95+
└── .vibe/ # Mistral Vibe skills (if using Mistral Vibe)
9396
└── skills/
9497
└── ...
9598
```

docs/how-to/non-interactive-installation.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,8 @@ Available tool IDs for the `--tools` flag:
6161

6262
**Preferred:** `claude-code`, `cursor`
6363

64+
**Other CLIs:** `mistral`, `gemini`, `codex`, `auggie`, `pi`
65+
6466
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).
6567

6668
## Installation Modes

test/test-installation-components.js

Lines changed: 95 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1587,7 +1587,7 @@ async function runTests() {
15871587
// ============================================================
15881588
// Suite 29: Unified Skill Scanner — collectSkills
15891589
// ============================================================
1590-
console.log(`${colors.yellow}Test Suite 29: Unified Skill Scanner${colors.reset}\n`);
1590+
console.log(`${colors.yellow}Test Suite 30: Unified Skill Scanner${colors.reset}\n`);
15911591

15921592
let tempFixture29;
15931593
try {
@@ -1700,7 +1700,7 @@ async function runTests() {
17001700
// ============================================================
17011701
// Suite 30: parseSkillMd validation (negative cases)
17021702
// ============================================================
1703-
console.log(`${colors.yellow}Test Suite 30: parseSkillMd Validation${colors.reset}\n`);
1703+
console.log(`${colors.yellow}Test Suite 31: parseSkillMd Validation${colors.reset}\n`);
17041704

17051705
let tempFixture30;
17061706
try {
@@ -1808,6 +1808,99 @@ async function runTests() {
18081808

18091809
console.log('');
18101810

1811+
// ============================================================
1812+
// Suite 31: Mistral Vibe CLI Native Skills
1813+
// ============================================================
1814+
console.log(`${colors.yellow}Test Suite 31: Mistral Vibe CLI Native Skills${colors.reset}\n`);
1815+
1816+
let tempProjectDirMistral;
1817+
let installedBmadDirMistral;
1818+
try {
1819+
clearCache();
1820+
const platformCodesMistral = await loadPlatformCodes();
1821+
const mistralInstaller = platformCodesMistral.platforms.mistral?.installer;
1822+
1823+
assert(mistralInstaller?.target_dir === '.vibe/skills', 'Mistral Vibe target_dir uses native skills path');
1824+
assert(mistralInstaller?.skill_format === true, 'Mistral Vibe installer enables native skill output');
1825+
assert(mistralInstaller?.template_type === 'default', 'Mistral Vibe installer uses default skill template');
1826+
assert(mistralInstaller?.legacy_targets === undefined, 'Mistral Vibe installer has no legacy_targets');
1827+
1828+
tempProjectDirMistral = await fs.mkdtemp(path.join(os.tmpdir(), 'bmad-mistral-test-'));
1829+
installedBmadDirMistral = await createTestBmadFixture();
1830+
1831+
const ideManagerMistral = new IdeManager();
1832+
await ideManagerMistral.ensureInitialized();
1833+
1834+
// Verify Mistral Vibe is selectable in an available IDEs list
1835+
const availableIdesMistral = ideManagerMistral.getAvailableIdes();
1836+
assert(
1837+
availableIdesMistral.some((ide) => ide.value === 'mistral'),
1838+
'Mistral Vibe appears in available IDEs list',
1839+
);
1840+
1841+
// Verify Mistral Vibe is NOT detected before install
1842+
const detectedBeforeMistral = await ideManagerMistral.detectInstalledIdes(tempProjectDirMistral);
1843+
assert(!detectedBeforeMistral.includes('mistral'), 'Mistral Vibe is not detected before install');
1844+
1845+
const resultMistral = await ideManagerMistral.setup('mistral', tempProjectDirMistral, installedBmadDirMistral, {
1846+
silent: true,
1847+
selectedModules: ['bmm'],
1848+
});
1849+
1850+
assert(resultMistral.success === true, 'Mistral Vibe setup succeeds against temp project');
1851+
1852+
// Verify Mistral Vibe IS detected after install
1853+
const detectedAfterMistral = await ideManagerMistral.detectInstalledIdes(tempProjectDirMistral);
1854+
assert(detectedAfterMistral.includes('mistral'), 'Mistral Vibe is detected after install');
1855+
1856+
const skillFileMistral = path.join(tempProjectDirMistral, '.vibe', 'skills', 'bmad-master', 'SKILL.md');
1857+
assert(await fs.pathExists(skillFileMistral), 'Mistral Vibe install writes SKILL.md directory output');
1858+
1859+
// Parse YAML frontmatter between --- markers
1860+
const skillContentMistral = await fs.readFile(skillFileMistral, 'utf8');
1861+
const fmMatchMistral = skillContentMistral.match(/^---\n([\s\S]*?)\n---\n?([\s\S]*)$/);
1862+
assert(fmMatchMistral, 'Mistral Vibe SKILL.md contains valid frontmatter delimiters');
1863+
1864+
const frontmatterMistral = fmMatchMistral[1];
1865+
const bodyMistral = fmMatchMistral[2];
1866+
1867+
// Verify the name in the frontmatter matches the directory name
1868+
const fmNameMistral = frontmatterMistral.match(/^name:\s*(.+)$/m);
1869+
assert(
1870+
fmNameMistral && fmNameMistral[1].trim() === 'bmad-master',
1871+
'Mistral Vibe skill name frontmatter matches directory name exactly',
1872+
);
1873+
1874+
// Verify description exists and is non-empty
1875+
const fmDescMistral = frontmatterMistral.match(/^description:\s*(.+)$/m);
1876+
assert(fmDescMistral && fmDescMistral[1].trim().length > 0, 'Mistral Vibe skill description frontmatter is present and non-empty');
1877+
1878+
// Verify frontmatter contains only name and description keys
1879+
const fmKeysMistral = [...frontmatterMistral.matchAll(/^([a-zA-Z0-9_-]+):/gm)].map((m) => m[1]);
1880+
assert(
1881+
fmKeysMistral.length === 2 && fmKeysMistral.includes('name') && fmKeysMistral.includes('description'),
1882+
'Mistral Vibe skill frontmatter contains only name and description keys',
1883+
);
1884+
1885+
// Verify body content is non-empty
1886+
assert(bodyMistral.trim().length > 0, 'Mistral Vibe skill body content is non-empty');
1887+
1888+
// Reinstall/upgrade: run setup again over existing output
1889+
const resultMistralb = await ideManagerMistral.setup('mistral', tempProjectDirMistral, installedBmadDirMistral, {
1890+
silent: true,
1891+
selectedModules: ['bmm'],
1892+
});
1893+
assert(resultMistralb.success === true, 'Mistral Vibe reinstall/upgrade succeeds over existing skills');
1894+
assert(await fs.pathExists(skillFileMistral), 'Mistral Vibe reinstall preserves SKILL.md output');
1895+
} catch (error) {
1896+
assert(false, 'Mistral Vibe native skills test succeeds', error.message);
1897+
} finally {
1898+
if (tempProjectDirMistral) await fs.remove(tempProjectDirMistral).catch(() => {});
1899+
if (installedBmadDirMistral) await fs.remove(installedBmadDirMistral).catch(() => {});
1900+
}
1901+
1902+
console.log('');
1903+
18111904
// ============================================================
18121905
// Summary
18131906
// ============================================================

tools/cli/installers/lib/ide/platform-codes.yaml

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -176,6 +176,16 @@ platforms:
176176
template_type: kiro
177177
skill_format: true
178178

179+
mistral:
180+
name: "Mistral Vibe"
181+
preferred: false
182+
category: cli
183+
description: "Mistral's AI coding CLI"
184+
installer:
185+
target_dir: .vibe/skills
186+
template_type: default
187+
skill_format: true
188+
179189
opencode:
180190
name: "OpenCode"
181191
preferred: false

0 commit comments

Comments
 (0)