feat: add Mistral Vibe harness support (#373)

* feat: add Mistral Vibe harness support

Mistral Vibe is Mistral AI's open-source CLI coding assistant that ships an
Agent Skills system at .vibe/skills/{name}/SKILL.md with slash-command
invocation, mapping cleanly onto the existing transformer pipeline. Adds
Vibe as a 14th first-class harness:

- PROVIDER_PLACEHOLDERS entry in scripts/lib/utils.js (model, config_file
  = AGENTS.md, ask_instruction, command_prefix) mirroring the Qoder shape.
- PROVIDERS entry in scripts/lib/transformers/providers.js with configDir
  .vibe and frontmatterFields user-invocable, license, compatibility,
  metadata, allowed-tools (Vibe docs do not document argument-hint).
- transformVibe named export in scripts/lib/transformers/index.js for
  test-spy parity.
- vibe added to FILE_DOWNLOAD_PROVIDER_CONFIG_DIRS so the download
  endpoint accepts /api/download/skill/vibe/* and resolves to
  dist/vibe/.vibe/.
- .vibe added to PROVIDER_DIRS, PROVIDER_ALIASES, PROVIDER_DISPLAY,
  PROVIDER_INPUT_ORDER, GLOBAL_HARNESS_HINTS, and the normalizeForHash
  provider regex in cli/bin/commands/skills.mjs so the CLI detects
  existing Vibe installs.
- docs/HARNESSES.md updated: official docs row, frontmatter support
  column, directory structure row, and Last verified date bumped.
- docs/DEVELOP.md, README.md (install instructions, providers list,
  Supported Tools), .github issue/PR templates, sync-generated-output
  workflow, and AGENTS.md extended with Vibe.

The dynamic providers.test.js loop picks up Vibe automatically; all 160
provider tests pass including the 14 new Mistral Vibe cases. The build
regenerates dist/vibe/.vibe/skills/impeccable/ with correct frontmatter
and .vibe-substituted script paths. Generated harness output is left
unstaged per the source-first policy; the sync-generated-output workflow
(now listing .vibe) will commit it back to main after merge.

Co-Authored-By: Mistral Vibe <noreply@mistral.ai>

* Address review on Vibe harness support

Verified the Vibe claims against the docs and the mistralai/mistral-vibe
source, then tightened what the tables say.

- model placeholder: 'Mistral', not 'the model'. Vibe is Mistral's own
  first-party CLI, so it belongs with gemini -> Gemini and codex -> GPT
  rather than with the provider-agnostic harnesses. SKILL.src.md's one
  use of {{model}} now renders 'Mistral is capable of extraordinary
  work.' instead of a lowercase 'the model'.
- Docs links point at the skills page, not the product overview, matching
  every other row in both tables.
- disable-model-invocation is No, not TBD. The field appears nowhere in
  Vibe's source; unknown frontmatter keys are silently ignored.
- Split the directory row into project and global scopes the way the Pi
  row already does. Vibe reads .vibe/skills/ and .agents/skills/ at the
  project level and ~/.vibe/skills/ and ~/.agents/skills/ globally; the
  global .agents dir was missing, and project .agents/skills/ was sitting
  in the global column. Sources: vibe/core/paths/_local_config_files.py
  and vibe/core/config/harness_files/_paths.py.
- Restored 'Last verified' to 2026-04-28 and dated the Vibe row on its
  own. Only that row was checked, and this file warns against trusting
  stale claims, so a blanket re-date made ten other rows look fresher
  than they are.

AI assistance: written with Claude Code.

Co-Authored-By: Claude <noreply@anthropic.com>

---------

Co-authored-by: Mistral Vibe <noreply@mistral.ai>
Co-authored-by: Paul Bakaus <paul.bakaus@gmail.com>
Co-authored-by: Claude <noreply@anthropic.com>
This commit is contained in:
Alexis Tacnet
2026-07-20 14:50:32 -07:00
committed by GitHub
co-authored by Mistral Vibe Paul Bakaus Claude
parent b906b41462
commit 83c37e453a
12 changed files with 57 additions and 23 deletions
@@ -24,6 +24,7 @@ assignees: ''
- [ ] Kiro
- [ ] OpenCode
- [ ] Qoder
- [ ] Mistral Vibe
- [ ] All providers
## Alternatives considered
+1 -1
View File
@@ -26,7 +26,7 @@ This repo is issue-first for outside contributions. If you are not `pbakaus` or
- [ ] Source files updated in `source/`
- [ ] `bun run build` ran successfully
- [ ] `bun test` passes
- [ ] Tested with at least one provider (Cursor / Claude Code / Gemini CLI / Codex / Copilot / Kiro / OpenCode / Qoder)
- [ ] Tested with at least one provider (Cursor / Claude Code / Gemini CLI / Codex / Copilot / Kiro / OpenCode / Qoder / Mistral Vibe)
- [ ] README / DEVELOP.md updated if needed
- [ ] I reviewed the full diff myself before requesting human review
- [ ] I disclosed any AI assistance in this PR and related commits/comments, or no AI assistance was used
@@ -33,6 +33,7 @@ env:
.rovodev
.trae
.trae-cn
.vibe
plugin
jobs:
+1 -1
View File
@@ -21,7 +21,7 @@ Run `bun run build` after changing anything in `skill/`, transformer code, or us
## Generated Provider Output Policy
The root harness folders (`.agents/skills/`, `.claude/skills/`, `.cursor/skills/`, `.gemini/skills/`, `.github/skills/`, `.kiro/skills/`, `.opencode/skills/`, `.pi/skills/`, `.qoder/skills/`, `.rovodev/skills/`, `.trae*/skills/`) and `plugin/` stay tracked so `main` remains installable for direct GitHub, `npx skills`, and submodule users. They are still generated artifacts.
The root harness folders (`.agents/skills/`, `.claude/skills/`, `.cursor/skills/`, `.gemini/skills/`, `.github/skills/`, `.kiro/skills/`, `.opencode/skills/`, `.pi/skills/`, `.qoder/skills/`, `.rovodev/skills/`, `.trae*/skills/`, `.vibe/skills/`) and `plugin/` stay tracked so `main` remains installable for direct GitHub, `npx skills`, and submodule users. They are still generated artifacts.
Normal development should be source-first: stage changes in `skill/`, `scripts/`, `cli/`, `site/`, `extension/`, `functions/`, and `tests/`; leave generated harness churn unstaged unless the user asked for it. After source changes land on `main`, `.github/workflows/sync-generated-output.yml` runs `bun run build:release` and commits generated provider output directly back to `main`. Treat generated harness diffs as release artifacts and keep them out of feature PRs unless they are the point of the PR.
+11 -1
View File
@@ -124,7 +124,7 @@ git add .gitmodules .impeccable .claude .cursor
git commit -m "Add Impeccable skills"
```
Use the providers your project needs, for example `claude`, `cursor`, `gemini`, `codex`, `github`, `opencode`, `pi`, `qoder`, `trae`, `trae-cn`, or `rovo-dev`. The command links individual skill folders from `.impeccable/dist/universal/` and leaves existing real skill directories untouched unless you pass `--force`.
Use the providers your project needs, for example `claude`, `cursor`, `gemini`, `codex`, `github`, `opencode`, `pi`, `qoder`, `trae`, `trae-cn`, `rovo-dev`, or `vibe`. The command links individual skill folders from `.impeccable/dist/universal/` and leaves existing real skill directories untouched unless you pass `--force`.
To update later:
@@ -250,6 +250,15 @@ cp -r dist/qoder/.qoder your-project/
cp -r dist/qoder/.qoder/skills/* ~/.qoder/skills/
```
**Mistral Vibe:**
```bash
# Project-specific
cp -r dist/vibe/.vibe your-project/
# Or global (applies to all projects)
cp -r dist/vibe/.vibe/skills/* ~/.vibe/skills/
```
## Usage
Once installed, every command runs through the single `/impeccable` skill:
@@ -379,6 +388,7 @@ Full detector docs: [impeccable.style/docs/detector](https://impeccable.style/do
- [Trae](https://trae.ai)
- [Rovo Dev](https://www.atlassian.com/software/rovo)
- [Qoder](https://qoder.com)
- [Mistral Vibe](https://docs.mistral.ai/vibe/code/overview)
## Community & Ecosystem
+6 -3
View File
@@ -23,7 +23,7 @@ const __dirname = dirname(fileURLToPath(import.meta.url));
const API_BASE = 'https://impeccable.style';
// Provider folder names in project roots
const PROVIDER_DIRS = ['.claude', '.cursor', '.gemini', '.agents', '.github', '.kiro', '.opencode', '.pi', '.qoder', '.trae', '.trae-cn', '.rovodev'];
const PROVIDER_DIRS = ['.claude', '.cursor', '.gemini', '.agents', '.github', '.kiro', '.opencode', '.pi', '.qoder', '.trae', '.trae-cn', '.rovodev', '.vibe'];
const PROVIDER_ALIASES = {
agents: '.agents',
claude: '.claude',
@@ -41,6 +41,7 @@ const PROVIDER_ALIASES = {
rovodev: '.rovodev',
trae: '.trae',
'trae-cn': '.trae-cn',
vibe: '.vibe',
};
const PROVIDER_DISPLAY = {
@@ -56,8 +57,9 @@ const PROVIDER_DISPLAY = {
'.rovodev': { name: 'Rovo Dev', input: 'rovo-dev' },
'.trae': { name: 'Trae', input: 'trae' },
'.trae-cn': { name: 'Trae CN', input: 'trae-cn' },
'.vibe': { name: 'Mistral Vibe', input: 'vibe' },
};
const PROVIDER_INPUT_ORDER = ['claude', 'codex', 'cursor', 'gemini', 'github', 'kiro', 'opencode', 'pi', 'qoder', 'trae', 'trae-cn', 'rovo-dev'];
const PROVIDER_INPUT_ORDER = ['claude', 'codex', 'cursor', 'gemini', 'github', 'kiro', 'opencode', 'pi', 'qoder', 'trae', 'trae-cn', 'rovo-dev', 'vibe'];
// Providers whose GLOBAL (home) skills dir is not `<provider>/skills`.
// Pi discovers global skills from ~/.pi/agent/skills/; project scope
@@ -79,6 +81,7 @@ const GLOBAL_HARNESS_HINTS = [
{ home: '.pi', provider: '.pi' },
{ home: '.qoder', provider: '.qoder' },
{ home: '.rovodev', provider: '.rovodev' },
{ home: '.vibe', provider: '.vibe' },
];
// Last-resort default when nothing is detected: Claude Code + the universal
@@ -568,7 +571,7 @@ async function copyOrExtractLocalBundle(sourceValue) {
*/
function normalizeForHash(content) {
return content
.replace(/\.(claude|cursor|agents|github|gemini|codex|kiro|opencode|pi|qoder|trae|trae-cn|rovodev)\/skills\//g, '.PROVIDER/skills/');
.replace(/\.(claude|cursor|agents|github|gemini|codex|kiro|opencode|pi|qoder|trae|trae-cn|rovodev|vibe)\/skills\//g, '.PROVIDER/skills/');
}
function hashSkillFile(filePath) {
+1
View File
@@ -9,6 +9,7 @@ export const FILE_DOWNLOAD_PROVIDER_CONFIG_DIRS = Object.freeze({
opencode: '.opencode',
pi: '.pi',
qoder: '.qoder',
vibe: '.vibe',
});
export const FILE_DOWNLOAD_PROVIDERS = Object.freeze(
+1
View File
@@ -165,6 +165,7 @@ The skill-behavior suite runs three providers (claude-haiku-4-5, gpt-5.4-mini, g
- [OpenCode Skills](https://opencode.ai/docs/skills/)
- [Pi Skills](https://github.com/badlogic/pi-mono/blob/main/packages/coding-agent/docs/skills.md)
- [Qoder Skills](https://docs.qoder.com/extensions/skills)
- [Mistral Vibe Skills](https://docs.mistral.ai/vibe/code/cli/skills)
## Repository Structure
+19 -17
View File
@@ -3,7 +3,7 @@
Source of truth for what each AI coding harness supports in terms of agent skills.
Used to inform provider configs in `scripts/lib/transformers/providers.js`.
Last verified: 2026-04-28 (subagent landscape spot-checked 2026-06-28)
Last verified: 2026-04-28 (subagent landscape spot-checked 2026-06-28; Mistral Vibe row verified 2026-07-16)
> This file is point-in-time. Capabilities move fast; verify live before relying
> on any "only X supports Y" claim. Notably, the subagent table below lists
@@ -24,6 +24,7 @@ Last verified: 2026-04-28 (subagent landscape spot-checked 2026-06-28)
| Qoder | https://docs.qoder.com/extensions/skills |
| Trae | TBD (no official skills docs found yet) |
| Rovo Dev | https://support.atlassian.com/rovo/docs/extend-rovo-dev-cli-with-agent-skills |
| Mistral Vibe | https://docs.mistral.ai/vibe/code/cli/skills |
## Spec Compliance
@@ -35,22 +36,22 @@ Provider-specific extensions beyond the spec: `user-invocable`, `argument-hint`,
Fields marked with * are spec-standard. Others are provider extensions.
| Field | Claude Code | Cursor | Gemini | Codex | Copilot | Kiro | OpenCode | Pi | Qoder | Rovo Dev |
|-------|:-----------:|:------:|:------:|:-----:|:-------:|:----:|:--------:|:--:|:-----:|:--------:|
| `name`* | Yes | Yes | Yes | Yes | Yes | Yes | Yes | Yes | Yes | Yes |
| `description`* | Yes | Yes | Yes | Yes | Yes | Yes | Yes | Yes | Yes | Yes |
| `license`* | Yes | Yes | Ignored | No | Yes | Yes | Yes | Yes | Yes | Yes |
| `compatibility`* | Yes | Yes | Ignored | No | Yes | Yes | Yes | Yes | Yes | Yes |
| `metadata`* | Yes | Yes | Ignored | No | Yes | Yes | Yes | Yes | Yes | Yes |
| `allowed-tools`* | Yes | No | Ignored | No | No | No | Yes | Yes | Yes | Yes |
| `user-invocable` | Yes | No | No | No | Yes | No | Yes | No | Yes | Yes |
| `argument-hint` | Yes | No | No | No | Yes | No | Yes | No | Yes | Yes |
| `disable-model-invocation` | Yes | Yes | No | No | Yes | No | Yes | Yes | TBD | TBD |
| `model` | Yes | No | No | No | No | No | Yes | No | No | No |
| `effort` | Yes | No | No | No | No | No | No | No | No | No |
| `context` | Yes | No | No | No | No | No | No | No | No | No |
| `agent` | Yes | No | No | No | No | No | Yes | No | No | No |
| `hooks` | Yes | No | No | Yes | No | No | No | No | No | No |
| Field | Claude Code | Cursor | Gemini | Codex | Copilot | Kiro | OpenCode | Pi | Qoder | Rovo Dev | Mistral Vibe |
|-------|:-----------:|:------:|:------:|:-----:|:-------:|:----:|:--------:|:--:|:-----:|:--------:|:------------:|
| `name`* | Yes | Yes | Yes | Yes | Yes | Yes | Yes | Yes | Yes | Yes | Yes |
| `description`* | Yes | Yes | Yes | Yes | Yes | Yes | Yes | Yes | Yes | Yes | Yes |
| `license`* | Yes | Yes | Ignored | No | Yes | Yes | Yes | Yes | Yes | Yes | Yes |
| `compatibility`* | Yes | Yes | Ignored | No | Yes | Yes | Yes | Yes | Yes | Yes | Yes |
| `metadata`* | Yes | Yes | Ignored | No | Yes | Yes | Yes | Yes | Yes | Yes | Yes |
| `allowed-tools`* | Yes | No | Ignored | No | No | No | Yes | Yes | Yes | Yes | Yes |
| `user-invocable` | Yes | No | No | No | Yes | No | Yes | No | Yes | Yes | Yes |
| `argument-hint` | Yes | No | No | No | Yes | No | Yes | No | Yes | Yes | No |
| `disable-model-invocation` | Yes | Yes | No | No | Yes | No | Yes | Yes | TBD | TBD | No |
| `model` | Yes | No | No | No | No | No | Yes | No | No | No | No |
| `effort` | Yes | No | No | No | No | No | No | No | No | No | No |
| `context` | Yes | No | No | No | No | No | No | No | No | No | No |
| `agent` | Yes | No | No | No | No | No | Yes | No | No | No | No |
| `hooks` | Yes | No | No | Yes | No | No | No | No | No | No | No |
Notes:
- Gemini CLI validates only `name` and `description`; other spec fields are parsed but ignored.
@@ -84,6 +85,7 @@ Notes:
| Trae China | `.trae-cn/skills/` | TBD |
| Trae International | `.trae/skills/` | TBD |
| Rovo Dev | `.rovodev/skills/` | `~/.rovodev/skills/` (user-level) |
| Mistral Vibe | `.vibe/skills/` (project), `~/.vibe/skills/` (global) | `.agents/skills/` (project), `~/.agents/skills/` (global) |
All harnesses support the `{skill-name}/SKILL.md` directory structure with optional `reference/`, `scripts/`, and `assets/` subdirectories.
+1
View File
@@ -15,5 +15,6 @@ export const transformOpenCode = createTransformer(PROVIDERS.opencode);
export const transformPi = createTransformer(PROVIDERS.pi);
export const transformQoder = createTransformer(PROVIDERS.qoder);
export const transformRovoDev = createTransformer(PROVIDERS['rovo-dev']);
export const transformVibe = createTransformer(PROVIDERS.vibe);
export { createTransformer, PROVIDERS };
+7
View File
@@ -122,4 +122,11 @@ export const PROVIDERS = {
displayName: 'Rovo Dev',
frontmatterFields: ['user-invocable', 'argument-hint', 'license', 'compatibility', 'metadata', 'allowed-tools'],
},
vibe: {
provider: 'vibe',
providerTags: ['vibe'],
configDir: '.vibe',
displayName: 'Mistral Vibe',
frontmatterFields: ['user-invocable', 'license', 'compatibility', 'metadata', 'allowed-tools'],
},
};
+7
View File
@@ -627,6 +627,12 @@ export const PROVIDER_PLACEHOLDERS = {
config_file: 'AGENTS.md',
ask_instruction: 'ask the user directly to clarify what you cannot infer.',
command_prefix: '/'
},
'vibe': {
model: 'Mistral',
config_file: 'AGENTS.md',
ask_instruction: 'ask the user directly to clarify what you cannot infer.',
command_prefix: '/'
}
};
@@ -645,6 +651,7 @@ export const PROVIDER_BLOCK_TAGS = new Set([
'rovo-dev',
'trae',
'trae-cn',
'vibe',
]);
/**