@vibecheckai/cli 3.0.10 → 3.1.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.
- package/bin/.generated +25 -0
- package/bin/registry.js +105 -0
- package/bin/runners/lib/cli-output.js +368 -0
- package/bin/runners/lib/entitlements-v2.js +26 -30
- package/bin/runners/lib/receipts.js +179 -0
- package/bin/runners/lib/upsell.js +510 -0
- package/bin/runners/lib/usage.js +153 -0
- package/bin/runners/runBadge.js +31 -4
- package/bin/runners/runDoctor.js +72 -3
- package/bin/runners/runFix.js +13 -0
- package/bin/runners/runGraph.js +14 -0
- package/bin/runners/runMcp.js +865 -42
- package/bin/runners/runPermissions.js +14 -0
- package/bin/runners/runPreflight.js +553 -0
- package/bin/runners/runProve.js +100 -41
- package/bin/runners/runShip.js +98 -19
- package/bin/runners/runVerify.js +272 -0
- package/bin/vibecheck.js +108 -94
- package/mcp-server/package.json +1 -1
- package/package.json +1 -1
package/bin/vibecheck.js
CHANGED
|
@@ -12,6 +12,7 @@ const path = require("path");
|
|
|
12
12
|
const fs = require("fs");
|
|
13
13
|
const os = require("os");
|
|
14
14
|
const { performance } = require("perf_hooks");
|
|
15
|
+
const crypto = require("crypto");
|
|
15
16
|
|
|
16
17
|
// ═══════════════════════════════════════════════════════════════════════════════
|
|
17
18
|
// PERFORMANCE: Track startup time
|
|
@@ -235,58 +236,28 @@ function findSimilarCommands(input, commands, maxDistance = 3) {
|
|
|
235
236
|
const entitlements = require("./runners/lib/entitlements-v2");
|
|
236
237
|
|
|
237
238
|
// ═══════════════════════════════════════════════════════════════════════════════
|
|
238
|
-
//
|
|
239
|
+
// UPSELL COPY MODULE - Central copy generator for all upgrade messaging
|
|
239
240
|
// ═══════════════════════════════════════════════════════════════════════════════
|
|
240
|
-
const
|
|
241
|
-
// PROOF LOOP
|
|
242
|
-
scan: { description: "Static analysis - routes, secrets, contracts", tier: "free", category: "proof", aliases: ["s", "check"], runner: () => require("./runners/runScan").runScan },
|
|
243
|
-
ship: { description: "Verdict engine - SHIP / WARN / BLOCK", tier: "free", category: "proof", aliases: ["verdict"], caps: "static-only on FREE", runner: () => require("./runners/runShip").runShip },
|
|
244
|
-
reality: { description: "Runtime proof - Playwright clicks every button", tier: "free", category: "proof", aliases: ["r", "test", "e2e"], caps: "preview mode on FREE (5 pages, no auth)", runner: () => { try { return require("./runners/runReality").runReality; } catch (e) { return async () => { console.error("Reality runner unavailable:", e.message); return 1; }; } } },
|
|
245
|
-
prove: { description: "Full proof loop - ctx → reality → ship → fix", tier: "pro", category: "proof", aliases: ["p", "full", "all"], runner: () => require("./runners/runProve").runProve },
|
|
246
|
-
fix: { description: "AI-powered auto-fix", tier: "free", category: "proof", caps: "--plan-only on FREE/STARTER", aliases: ["f", "repair"], runner: () => require("./runners/runFix").runFix },
|
|
247
|
-
report: { description: "Generate HTML/MD/SARIF reports", tier: "free", category: "proof", caps: "HTML/MD only on FREE", aliases: ["html", "artifact"], runner: () => require("./runners/runReport").runReport },
|
|
248
|
-
|
|
249
|
-
// SETUP & DX
|
|
250
|
-
install: { description: "Zero-friction onboarding", tier: "free", category: "setup", aliases: ["i", "bootstrap"], runner: () => require("./runners/runInstall").runInstall },
|
|
251
|
-
init: { description: "Project setup wizard", tier: "free", category: "setup", aliases: ["setup", "configure"], runner: () => require("./runners/runInit").runInit },
|
|
252
|
-
doctor: { description: "Environment diagnostics", tier: "free", category: "setup", aliases: ["health", "diag"], runner: () => require("./runners/runDoctor").runDoctor },
|
|
253
|
-
status: { description: "Project health dashboard", tier: "free", category: "setup", aliases: ["st"], runner: () => require("./runners/runStatus").runStatus },
|
|
254
|
-
watch: { description: "Continuous mode - re-runs on changes", tier: "free", category: "setup", aliases: ["w", "dev"], runner: () => require("./runners/runWatch").runWatch },
|
|
255
|
-
launch: { description: "Pre-launch checklist wizard", tier: "starter", category: "setup", aliases: ["checklist", "preflight"], runner: () => require("./runners/runLaunch").runLaunch },
|
|
256
|
-
|
|
257
|
-
// AI TRUTH
|
|
258
|
-
ctx: { description: "Generate truthpack for AI agents", tier: "free", category: "truth", aliases: ["truthpack", "tp"], subcommands: ["build", "diff", "guard", "sync", "search"], runner: () => require("./runners/runCtx").runCtx },
|
|
259
|
-
guard: { description: "Validate AI claims against truth", tier: "free", category: "truth", aliases: ["validate", "trust"], runner: () => require("./runners/runGuard").runGuard },
|
|
260
|
-
context: { description: "Generate .cursorrules, .windsurf/rules", tier: "free", category: "truth", aliases: ["rules", "ai-rules"], runner: () => require("./runners/runContext").runContext },
|
|
261
|
-
mdc: { description: "Generate MDC specifications", tier: "free", category: "truth", aliases: [], runner: () => require("./runners/runMdc").runMdc },
|
|
262
|
-
|
|
263
|
-
// CI & COLLABORATION (STARTER+)
|
|
264
|
-
gate: { description: "CI/CD gate - blocks deploys on failures", tier: "starter", category: "ci", aliases: ["ci", "block"], runner: () => require("./runners/runGate").runGate },
|
|
265
|
-
pr: { description: "Generate PR comment with findings", tier: "starter", category: "ci", aliases: ["pull-request"], runner: () => require("./runners/runPR").runPR },
|
|
266
|
-
badge: { description: "Generate ship badge for README", tier: "starter", category: "ci", aliases: ["b"], runner: () => require("./runners/runBadge").runBadge },
|
|
267
|
-
|
|
268
|
-
// AUTOMATION (STARTER+/PRO)
|
|
269
|
-
mcp: { description: "Start MCP server for AI IDEs", tier: "starter", category: "automation", aliases: [], runner: () => require("./runners/runMcp").runMcp },
|
|
270
|
-
share: { description: "Generate share pack for PR/docs", tier: "pro", category: "automation", aliases: [], runner: () => require("./runners/runShare").runShare },
|
|
271
|
-
"ai-test": { description: "AI autonomous test generation", tier: "pro", category: "automation", aliases: ["ai", "agent"], runner: () => require("./runners/runAIAgent").runAIAgent },
|
|
272
|
-
|
|
273
|
-
// ACCOUNT (always free)
|
|
274
|
-
login: { description: "Authenticate with API key", tier: "free", category: "account", aliases: ["auth", "signin"], runner: () => require("./runners/runAuth").runLogin, skipAuth: true },
|
|
275
|
-
logout: { description: "Remove stored credentials", tier: "free", category: "account", aliases: ["signout"], runner: () => require("./runners/runAuth").runLogout, skipAuth: true },
|
|
276
|
-
whoami: { description: "Show current user and plan", tier: "free", category: "account", aliases: ["me", "user"], runner: () => require("./runners/runAuth").runWhoami, skipAuth: true },
|
|
277
|
-
|
|
278
|
-
// EXTRAS
|
|
279
|
-
labs: { description: "Experimental features", tier: "free", category: "extras", aliases: ["experimental", "beta"], runner: () => require("./runners/runLabs").runLabs },
|
|
280
|
-
};
|
|
241
|
+
const upsell = require("./runners/lib/upsell");
|
|
281
242
|
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
243
|
+
// ═══════════════════════════════════════════════════════════════════════════════
|
|
244
|
+
// CLI OUTPUT UTILITIES
|
|
245
|
+
// ═══════════════════════════════════════════════════════════════════════════════
|
|
246
|
+
const {
|
|
247
|
+
generateRunId,
|
|
248
|
+
withStandardOutput,
|
|
249
|
+
parseStandardFlags,
|
|
250
|
+
exitCodeToVerdict
|
|
251
|
+
} = require("./runners/lib/cli-output");
|
|
252
|
+
|
|
253
|
+
// ═══════════════════════════════════════════════════════════════════════════════
|
|
254
|
+
// COMMAND REGISTRY - Imported from bin/registry.js (single source of truth)
|
|
255
|
+
// ═══════════════════════════════════════════════════════════════════════════════
|
|
256
|
+
const { COMMANDS, ALIAS_MAP, ALL_COMMANDS, getRunner: _getRunner } = require("./registry");
|
|
285
257
|
|
|
258
|
+
// Wrap getRunner to pass styling
|
|
286
259
|
function getRunner(cmd) {
|
|
287
|
-
|
|
288
|
-
if (!def) return null;
|
|
289
|
-
try { return def.runner(); } catch (e) { return async () => { console.error(`${c.red}${sym.error}${c.reset} Failed to load ${cmd}: ${e.message}`); return 1; }; }
|
|
260
|
+
return _getRunner(cmd, { red: c.red, reset: c.reset, errorSymbol: sym.error });
|
|
290
261
|
}
|
|
291
262
|
|
|
292
263
|
// ═══════════════════════════════════════════════════════════════════════════════
|
|
@@ -331,22 +302,11 @@ async function checkCommandAccess(cmd, args, authInfo) {
|
|
|
331
302
|
}
|
|
332
303
|
|
|
333
304
|
function formatAccessDenied(cmd, requiredTier, currentTier) {
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
let msg = `\n${c.red}${c.bold}⛔ Feature Not Available${c.reset}\n\n`;
|
|
340
|
-
msg += ` ${c.yellow}${cmd}${c.reset} requires ${tierColor}${tierLabel}${c.reset} plan.\n`;
|
|
341
|
-
msg += ` Your current plan: ${c.dim}${currentLabel}${c.reset}\n\n`;
|
|
342
|
-
|
|
343
|
-
if (currentTier === "free") {
|
|
344
|
-
msg += ` ${c.cyan}Get started:${c.reset} vibecheck login\n`;
|
|
345
|
-
}
|
|
346
|
-
msg += ` ${c.cyan}Upgrade at:${c.reset} https://vibecheckai.dev/pricing\n`;
|
|
347
|
-
msg += `\n ${c.dim}Exit code: ${entitlements.EXIT_FEATURE_NOT_ALLOWED}${c.reset}\n`;
|
|
348
|
-
|
|
349
|
-
return msg;
|
|
305
|
+
// Use centralized upsell copy module
|
|
306
|
+
return upsell.formatDenied(cmd, {
|
|
307
|
+
currentTier,
|
|
308
|
+
requiredTier,
|
|
309
|
+
});
|
|
350
310
|
}
|
|
351
311
|
|
|
352
312
|
// ═══════════════════════════════════════════════════════════════════════════════
|
|
@@ -456,52 +416,71 @@ async function main() {
|
|
|
456
416
|
const config = loadConfig();
|
|
457
417
|
const state = loadState();
|
|
458
418
|
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
verbose: rawArgs.includes("--verbose") || rawArgs.includes("-v"),
|
|
462
|
-
quiet: rawArgs.includes("--quiet") || rawArgs.includes("-q"),
|
|
463
|
-
help: rawArgs.includes("--help") || rawArgs.includes("-h"),
|
|
464
|
-
version: rawArgs.includes("--version") || rawArgs.includes("-V"),
|
|
465
|
-
};
|
|
419
|
+
// Parse standard flags
|
|
420
|
+
const { flags: globalFlags, parsed: cleanArgs } = parseStandardFlags(rawArgs);
|
|
466
421
|
|
|
422
|
+
// Update config based on flags
|
|
467
423
|
if (globalFlags.debug) config.debug = true;
|
|
468
424
|
if (globalFlags.verbose) config.verbose = true;
|
|
469
425
|
if (globalFlags.quiet) config.quiet = true;
|
|
426
|
+
if (globalFlags.ci) config.quiet = true; // CI mode implies quiet
|
|
470
427
|
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
if (globalFlags.version || args[0] === "version") {
|
|
428
|
+
// Handle version
|
|
429
|
+
if (globalFlags.version) {
|
|
474
430
|
console.log(`vibecheck v${VERSION}`);
|
|
475
431
|
process.exit(0);
|
|
476
432
|
}
|
|
477
433
|
|
|
478
|
-
|
|
434
|
+
// Handle no command
|
|
435
|
+
if (!cleanArgs[0]) { printHelp(); process.exit(0); }
|
|
479
436
|
|
|
480
437
|
// Handle command-specific help (vibecheck <cmd> --help)
|
|
481
|
-
if (globalFlags.help &&
|
|
438
|
+
if (globalFlags.help && cleanArgs[0] && COMMANDS[cleanArgs[0]]) {
|
|
482
439
|
// Pass --help to the command runner
|
|
483
|
-
} else if (globalFlags.help && !
|
|
440
|
+
} else if (globalFlags.help && !cleanArgs[0]) {
|
|
484
441
|
printHelp(); process.exit(0);
|
|
485
442
|
}
|
|
486
443
|
|
|
487
|
-
let cmd =
|
|
444
|
+
let cmd = cleanArgs[0];
|
|
488
445
|
if (ALIAS_MAP[cmd]) { cmd = ALIAS_MAP[cmd]; }
|
|
489
|
-
let cmdArgs =
|
|
446
|
+
let cmdArgs = cleanArgs.slice(1);
|
|
490
447
|
|
|
491
448
|
// Add --help back to cmdArgs if it was passed with a command
|
|
492
449
|
if (globalFlags.help) cmdArgs = ["--help", ...cmdArgs];
|
|
493
450
|
|
|
451
|
+
// Pass standard flags to runners
|
|
452
|
+
cmdArgs = [...cmdArgs];
|
|
453
|
+
if (globalFlags.json) cmdArgs.push("--json");
|
|
454
|
+
if (globalFlags.ci) cmdArgs.push("--ci");
|
|
455
|
+
if (globalFlags.path && globalFlags.path !== process.cwd()) {
|
|
456
|
+
cmdArgs.push("--path", globalFlags.path);
|
|
457
|
+
}
|
|
458
|
+
if (globalFlags.output) {
|
|
459
|
+
cmdArgs.push("--output", globalFlags.output);
|
|
460
|
+
}
|
|
461
|
+
if (globalFlags.verbose) cmdArgs.push("--verbose");
|
|
462
|
+
if (globalFlags.strict) cmdArgs.push("--strict");
|
|
463
|
+
|
|
494
464
|
if (!COMMANDS[cmd]) {
|
|
495
465
|
const suggestions = findSimilarCommands(cmd, ALL_COMMANDS);
|
|
496
466
|
console.log(`\n${c.red}${sym.error}${c.reset} Unknown command: ${c.yellow}${cmd}${c.reset}`);
|
|
497
|
-
|
|
467
|
+
|
|
468
|
+
// Check for specific common misses
|
|
469
|
+
if (cmd === "replay" || cmd === "record") {
|
|
470
|
+
console.log(`\n${c.dim}replay is a PRO feature for session recording.${c.reset}`);
|
|
471
|
+
console.log(`${c.dim}Free alternative:${c.reset} ${c.cyan}vibecheck reality${c.reset} ${c.dim}(one-time runtime proof)${c.reset}`);
|
|
472
|
+
} else if (suggestions.length > 0) {
|
|
498
473
|
console.log(`\n${c.dim}Did you mean:${c.reset}`);
|
|
499
474
|
suggestions.forEach(s => { const actual = ALIAS_MAP[s] || s; const def = COMMANDS[actual]; console.log(` ${c.cyan}vibecheck ${s}${c.reset} ${c.dim}${def?.description || ""}${c.reset}`); });
|
|
500
475
|
}
|
|
501
476
|
console.log(`\n${c.dim}Run 'vibecheck --help' for available commands.${c.reset}\n`);
|
|
502
|
-
process.exit(
|
|
477
|
+
process.exit(4); // INVALID_INPUT
|
|
503
478
|
}
|
|
504
479
|
|
|
480
|
+
// Generate runId for tracking
|
|
481
|
+
const runId = generateRunId();
|
|
482
|
+
const runStart = new Date().toISOString();
|
|
483
|
+
|
|
505
484
|
const cmdDef = COMMANDS[cmd];
|
|
506
485
|
let authInfo = { key: null };
|
|
507
486
|
|
|
@@ -516,18 +495,22 @@ async function main() {
|
|
|
516
495
|
if (!access.allowed) {
|
|
517
496
|
console.log(access.reason);
|
|
518
497
|
// Use proper exit code: 3 = feature not allowed
|
|
519
|
-
process.exit(access.exitCode ||
|
|
498
|
+
process.exit(access.exitCode || 3);
|
|
520
499
|
}
|
|
521
500
|
|
|
522
|
-
// Show downgrade notice if applicable
|
|
501
|
+
// Show downgrade notice if applicable (single-line at start)
|
|
523
502
|
if (access.downgrade && !config.quiet) {
|
|
524
|
-
console.log(
|
|
503
|
+
console.log(upsell.formatDowngrade(cmd, {
|
|
504
|
+
currentTier: access.tier,
|
|
505
|
+
effectiveMode: access.downgrade,
|
|
506
|
+
caps: access.caps,
|
|
507
|
+
}));
|
|
525
508
|
}
|
|
526
509
|
|
|
527
510
|
// Show tier badge
|
|
528
511
|
if (!config.quiet) {
|
|
529
|
-
if (access.tier === "
|
|
530
|
-
else if (access.tier === "
|
|
512
|
+
if (access.tier === "pro") console.log(`${c.magenta}${sym.arrowRight} PRO${c.reset} ${c.dim}feature${c.reset}`);
|
|
513
|
+
else if (access.tier === "complete") console.log(`${c.yellow}${sym.arrowRight} COMPLETE${c.reset} ${c.dim}feature${c.reset}`);
|
|
531
514
|
}
|
|
532
515
|
|
|
533
516
|
// Attach access info for runners to use
|
|
@@ -543,27 +526,58 @@ async function main() {
|
|
|
543
526
|
const runner = getRunner(cmd);
|
|
544
527
|
if (!runner) { console.error(`${c.red}${sym.error}${c.reset} Failed to load runner for: ${cmd}`); process.exit(1); }
|
|
545
528
|
|
|
546
|
-
const context = {
|
|
529
|
+
const context = {
|
|
530
|
+
repoRoot: process.cwd(),
|
|
531
|
+
config,
|
|
532
|
+
state,
|
|
533
|
+
authInfo,
|
|
534
|
+
version: VERSION,
|
|
535
|
+
isCI: isCI(),
|
|
536
|
+
runId,
|
|
537
|
+
runStart
|
|
538
|
+
};
|
|
547
539
|
|
|
540
|
+
// Pass context to runners that support it
|
|
548
541
|
switch (cmd) {
|
|
549
|
-
case "prove": exitCode = await runner(cmdArgs); break;
|
|
550
|
-
case "reality": exitCode = await runner(cmdArgs); break;
|
|
551
|
-
case "watch": exitCode = await runner(cmdArgs); break;
|
|
542
|
+
case "prove": exitCode = await runner(cmdArgs, context); break;
|
|
543
|
+
case "reality": exitCode = await runner(cmdArgs, context); break;
|
|
544
|
+
case "watch": exitCode = await runner(cmdArgs, context); break;
|
|
545
|
+
case "ship": exitCode = await runner(cmdArgs, context); break;
|
|
552
546
|
case "ctx": case "truthpack":
|
|
553
547
|
if (cmdArgs[0] === "sync") { const { runCtxSync } = require("./runners/runCtxSync"); exitCode = await runCtxSync({ ...context, fastifyEntry: getArgValue(cmdArgs, ["--fastify-entry"]) }); }
|
|
554
548
|
else if (cmdArgs[0] === "guard") { const { runCtxGuard } = require("./runners/runCtxGuard"); exitCode = await runCtxGuard.main(cmdArgs.slice(1)); }
|
|
555
549
|
else if (cmdArgs[0] === "diff") { const { main: ctxDiffMain } = require("./runners/runCtxDiff"); exitCode = await ctxDiffMain(cmdArgs.slice(1)); }
|
|
556
550
|
else if (cmdArgs[0] === "search") { const { runContext } = require("./runners/runContext"); exitCode = await runContext(["--search", ...cmdArgs.slice(1)]); }
|
|
557
|
-
else { exitCode = await runner(cmdArgs); }
|
|
551
|
+
else { exitCode = await runner(cmdArgs, context); }
|
|
558
552
|
break;
|
|
559
|
-
case "install": exitCode = await runner(cmdArgs); break;
|
|
553
|
+
case "install": exitCode = await runner(cmdArgs, context); break;
|
|
560
554
|
case "status": exitCode = await runner({ ...context, json: cmdArgs.includes("--json") }); break;
|
|
561
|
-
case "pr": exitCode = await runner(cmdArgs); break;
|
|
562
|
-
case "share": exitCode = await runner(cmdArgs); break;
|
|
555
|
+
case "pr": exitCode = await runner(cmdArgs, context); break;
|
|
556
|
+
case "share": exitCode = await runner(cmdArgs, context); break;
|
|
563
557
|
default: exitCode = await runner(cmdArgs);
|
|
564
558
|
}
|
|
565
559
|
} catch (error) { console.error(formatError(error, config)); exitCode = 1; }
|
|
566
560
|
|
|
561
|
+
// Create manifest and receipt for paid commands
|
|
562
|
+
if (cmdDef.tier !== "free" && runId) {
|
|
563
|
+
try {
|
|
564
|
+
const { createManifestAndReceipt } = require("./runners/lib/receipts");
|
|
565
|
+
await createManifestAndReceipt({
|
|
566
|
+
runId,
|
|
567
|
+
command: cmd,
|
|
568
|
+
args: cmdArgs,
|
|
569
|
+
tier: authInfo.access?.tier || "free",
|
|
570
|
+
exitCode,
|
|
571
|
+
startTime: runStart,
|
|
572
|
+
endTime: new Date().toISOString(),
|
|
573
|
+
projectPath: process.cwd(),
|
|
574
|
+
});
|
|
575
|
+
} catch (e) {
|
|
576
|
+
// Don't fail the command if receipt creation fails
|
|
577
|
+
if (config.debug) console.error(`Failed to create receipt: ${e.message}`);
|
|
578
|
+
}
|
|
579
|
+
}
|
|
580
|
+
|
|
567
581
|
if (config.debug) console.log(`\n${c.dim}${sym.clock} Total: ${(performance.now() - startTime).toFixed(0)}ms${c.reset}`);
|
|
568
582
|
process.exit(exitCode);
|
|
569
583
|
}
|
package/mcp-server/package.json
CHANGED