@open-product-primer/cli 2.5.1 → 2.6.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -48,7 +48,7 @@ function initCommand() {
48
48
  return new commander_1.Command('init')
49
49
  .description('Initialize oprim in the current repository')
50
50
  .option('--name <name>', 'project name (defaults to directory name)')
51
- .option('--agent <name>', 'AI agent to install skills for (repeatable; supported: claude, cursor, codex, gemini, poolside)', (val, prev) => [...prev, val], [])
51
+ .option('--agent <name>', 'AI agent to install skills for (repeatable; supported: claude, cursor, codex, gemini, poolside, vibe)', (val, prev) => [...prev, val], [])
52
52
  .action(async (opts) => {
53
53
  const projectRoot = process.cwd();
54
54
  const projectName = opts.name ?? path.basename(projectRoot);
@@ -84,6 +84,8 @@ function detectAvailableAgents(projectRoot) {
84
84
  detected.push('gemini');
85
85
  if (fs.existsSync(path.join(projectRoot, '.poolside')))
86
86
  detected.push('poolside');
87
+ if (fs.existsSync(path.join(projectRoot, '.vibe')))
88
+ detected.push('vibe');
87
89
  return detected;
88
90
  }
89
91
  function writeAgentsToConfig(agents, projectRoot) {
@@ -1,4 +1,4 @@
1
- export type Agent = 'claude' | 'cursor' | 'codex' | 'gemini' | 'poolside';
1
+ export type Agent = 'claude' | 'cursor' | 'codex' | 'gemini' | 'poolside' | 'vibe';
2
2
  export declare const SUPPORTED_AGENTS: readonly Agent[];
3
3
  export declare function promptFrameworkSelection(projectRoot: string): Promise<string>;
4
4
  export declare function resolveSpecFramework(projectRoot: string): string;
@@ -10,6 +10,7 @@ export declare const OPRIM_CONTEXT_SKILL_STEP = "## Step 0: Check relevant produ
10
10
  export declare const CLAUDE_SKILLS: Record<string, string>;
11
11
  export declare const CLAUDE_COMMANDS: Record<string, string>;
12
12
  export declare const POOLSIDE_SKILLS: Record<string, string>;
13
+ export declare const VIBE_SKILLS: Record<string, string>;
13
14
  export declare const CURSOR_SKILLS: Record<string, string>;
14
15
  export declare const CURSOR_COMMANDS: Record<string, string>;
15
16
  export declare function specAuthoringSkill(): string;
@@ -17,3 +18,4 @@ export declare function writeAgentInstructionFile(filePath: string, section: str
17
18
  export declare function codexInstructions(): string;
18
19
  export declare function geminiInstructions(): string;
19
20
  export declare function poolsideInstructions(): string;
21
+ export declare function vibeInstructions(): string;
@@ -36,7 +36,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
36
36
  return (mod && mod.__esModule) ? mod : { "default": mod };
37
37
  };
38
38
  Object.defineProperty(exports, "__esModule", { value: true });
39
- exports.CURSOR_COMMANDS = exports.CURSOR_SKILLS = exports.POOLSIDE_SKILLS = exports.CLAUDE_COMMANDS = exports.CLAUDE_SKILLS = exports.OPRIM_CONTEXT_SKILL_STEP = exports.SUPPORTED_AGENTS = void 0;
39
+ exports.CURSOR_COMMANDS = exports.CURSOR_SKILLS = exports.VIBE_SKILLS = exports.POOLSIDE_SKILLS = exports.CLAUDE_COMMANDS = exports.CLAUDE_SKILLS = exports.OPRIM_CONTEXT_SKILL_STEP = exports.SUPPORTED_AGENTS = void 0;
40
40
  exports.promptFrameworkSelection = promptFrameworkSelection;
41
41
  exports.resolveSpecFramework = resolveSpecFramework;
42
42
  exports.promptAgentSelection = promptAgentSelection;
@@ -48,6 +48,7 @@ exports.writeAgentInstructionFile = writeAgentInstructionFile;
48
48
  exports.codexInstructions = codexInstructions;
49
49
  exports.geminiInstructions = geminiInstructions;
50
50
  exports.poolsideInstructions = poolsideInstructions;
51
+ exports.vibeInstructions = vibeInstructions;
51
52
  const path = __importStar(require("path"));
52
53
  const fs = __importStar(require("fs"));
53
54
  const chalk_1 = __importDefault(require("chalk"));
@@ -56,7 +57,7 @@ const detect_1 = require("./detect");
56
57
  const config_merge_1 = require("./config-merge");
57
58
  const workflow_schema_1 = require("./workflow-schema");
58
59
  const workflow_renderer_1 = require("./workflow-renderer");
59
- exports.SUPPORTED_AGENTS = ['claude', 'cursor', 'codex', 'gemini', 'poolside'];
60
+ exports.SUPPORTED_AGENTS = ['claude', 'cursor', 'codex', 'gemini', 'poolside', 'vibe'];
60
61
  // oprim/config.yaml (via integrations.spec_framework) is the source of truth for the
61
62
  // selected speccing framework; .claude/hooks/config.json is checked only as a fallback for
62
63
  // projects that installed before that key existed.
@@ -124,6 +125,7 @@ async function promptAgentSelection(projectRoot) {
124
125
  { name: 'Codex', value: 'codex', checked: detected.includes('codex') },
125
126
  { name: 'Gemini CLI', value: 'gemini', checked: detected.includes('gemini') },
126
127
  { name: 'Poolside', value: 'poolside', checked: detected.includes('poolside') },
128
+ { name: 'Mistral Vibe', value: 'vibe', checked: detected.includes('vibe') },
127
129
  ],
128
130
  });
129
131
  }
@@ -281,6 +283,37 @@ function installAgentSkills(agent, projectRoot, framework = 'openspec', pdrSurfa
281
283
  console.log(chalk_1.default.dim(' .poolside/ created — Poolside will discover these files automatically.'));
282
284
  }
283
285
  }
286
+ else if (agent === 'vibe') {
287
+ const vibeDir = path.join(projectRoot, '.vibe');
288
+ const dirCreated = !fs.existsSync(vibeDir);
289
+ const skillsBase = path.join(vibeDir, 'skills');
290
+ for (const id of POOLSIDE_SKILL_WORKFLOW_IDS) {
291
+ const schema = (0, workflow_schema_1.loadWorkflowSchema)(id, projectRoot);
292
+ if (!schema.vibe.skill || !schema.skillName)
293
+ continue;
294
+ (0, scaffold_1.writeFile)(path.join(skillsBase, schema.skillName, 'SKILL.md'), (0, workflow_renderer_1.renderSkillBody)(id, projectRoot));
295
+ console.log(chalk_1.default.green('✓') + ` .vibe/skills/${schema.skillName}/SKILL.md`);
296
+ }
297
+ const vibeSpecSkillPath = path.join(skillsBase, 'oprim-spec', 'SKILL.md');
298
+ if (framework === 'native') {
299
+ (0, scaffold_1.writeFile)(vibeSpecSkillPath, (0, workflow_renderer_1.renderSkillBody)('spec-authoring', projectRoot));
300
+ console.log(chalk_1.default.green('✓') + ' .vibe/skills/oprim-spec/SKILL.md');
301
+ }
302
+ else if (fs.existsSync(vibeSpecSkillPath)) {
303
+ fs.unlinkSync(vibeSpecSkillPath);
304
+ try {
305
+ fs.rmdirSync(path.dirname(vibeSpecSkillPath));
306
+ }
307
+ catch { /* not empty or already gone */ }
308
+ console.log(chalk_1.default.dim(' removed .vibe/skills/oprim-spec/SKILL.md'));
309
+ }
310
+ const agentsFile = path.join(projectRoot, 'AGENTS.md');
311
+ writeAgentInstructionFile(agentsFile, vibeInstructions());
312
+ console.log(chalk_1.default.green('✓') + ' AGENTS.md (oprim section written)');
313
+ if (dirCreated) {
314
+ console.log(chalk_1.default.dim(' .vibe/ created — Mistral Vibe will discover these files automatically.'));
315
+ }
316
+ }
284
317
  else if (agent === 'codex') {
285
318
  const agentsFile = path.join(projectRoot, 'AGENTS.md');
286
319
  writeAgentInstructionFile(agentsFile, codexInstructions());
@@ -441,6 +474,10 @@ exports.POOLSIDE_SKILLS = Object.fromEntries(POOLSIDE_SKILL_WORKFLOW_IDS.map((id
441
474
  const schema = (0, workflow_schema_1.loadWorkflowSchema)(id);
442
475
  return [schema.skillName, (0, workflow_renderer_1.renderSkillBody)(id)];
443
476
  }));
477
+ exports.VIBE_SKILLS = Object.fromEntries(POOLSIDE_SKILL_WORKFLOW_IDS.map((id) => {
478
+ const schema = (0, workflow_schema_1.loadWorkflowSchema)(id);
479
+ return [schema.skillName, (0, workflow_renderer_1.renderSkillBody)(id)];
480
+ }));
444
481
  exports.CURSOR_SKILLS = Object.fromEntries(CURSOR_SKILL_WORKFLOW_IDS.map((id) => {
445
482
  const schema = (0, workflow_schema_1.loadWorkflowSchema)(id);
446
483
  return [schema.skillName, (0, workflow_renderer_1.renderSkillBody)(id)];
@@ -632,3 +669,6 @@ function geminiInstructions() {
632
669
  function poolsideInstructions() {
633
670
  return (0, workflow_renderer_1.renderAgentInstructions)();
634
671
  }
672
+ function vibeInstructions() {
673
+ return (0, workflow_renderer_1.renderAgentInstructions)();
674
+ }
@@ -13,6 +13,9 @@ export interface WorkflowSchema {
13
13
  poolside: {
14
14
  skill: boolean;
15
15
  };
16
+ vibe: {
17
+ skill: boolean;
18
+ };
16
19
  inline: boolean;
17
20
  variants: string[] | null;
18
21
  }
@@ -68,6 +68,9 @@ function parseSchema(raw, filePath) {
68
68
  const claude = requireField(obj, 'claude', filePath);
69
69
  const cursor = requireField(obj, 'cursor', filePath);
70
70
  const poolside = requireField(obj, 'poolside', filePath);
71
+ // vibe is optional and mirrors poolside by default — see mistral-vibe-agent-support spec.
72
+ // This keeps existing bundled/forked schemas (none declare a `vibe:` key) working unchanged.
73
+ const vibe = obj.vibe ?? poolside;
71
74
  requireField(obj, 'inline', filePath);
72
75
  return {
73
76
  id: obj.id,
@@ -78,6 +81,7 @@ function parseSchema(raw, filePath) {
78
81
  claude: { skill: Boolean(claude.skill), command: claude.command ?? null },
79
82
  cursor: { skill: Boolean(cursor.skill), command: cursor.command ?? null },
80
83
  poolside: { skill: Boolean(poolside.skill) },
84
+ vibe: { skill: Boolean(vibe.skill) },
81
85
  inline: Boolean(obj.inline),
82
86
  variants: obj.variants ?? null,
83
87
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@open-product-primer/cli",
3
- "version": "2.5.1",
3
+ "version": "2.6.0",
4
4
  "description": "Open Product Primer CLI — product decisions, sequencing, and KPI tracking for repositories",
5
5
  "keywords": [
6
6
  "product",