@vibecheckai/cli 3.0.2 → 3.0.3

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.
Files changed (68) hide show
  1. package/package.json +9 -1
  2. package/bin/cli-hygiene.js +0 -241
  3. package/bin/guardrail.js +0 -834
  4. package/bin/runners/cli-utils.js +0 -1070
  5. package/bin/runners/context/ai-task-decomposer.js +0 -337
  6. package/bin/runners/context/analyzer.js +0 -462
  7. package/bin/runners/context/api-contracts.js +0 -427
  8. package/bin/runners/context/context-diff.js +0 -342
  9. package/bin/runners/context/context-pruner.js +0 -291
  10. package/bin/runners/context/dependency-graph.js +0 -414
  11. package/bin/runners/context/generators/claude.js +0 -107
  12. package/bin/runners/context/generators/codex.js +0 -108
  13. package/bin/runners/context/generators/copilot.js +0 -119
  14. package/bin/runners/context/generators/cursor.js +0 -514
  15. package/bin/runners/context/generators/mcp.js +0 -151
  16. package/bin/runners/context/generators/windsurf.js +0 -180
  17. package/bin/runners/context/git-context.js +0 -302
  18. package/bin/runners/context/index.js +0 -1042
  19. package/bin/runners/context/insights.js +0 -173
  20. package/bin/runners/context/mcp-server/generate-rules.js +0 -337
  21. package/bin/runners/context/mcp-server/index.js +0 -1176
  22. package/bin/runners/context/mcp-server/package.json +0 -24
  23. package/bin/runners/context/memory.js +0 -200
  24. package/bin/runners/context/monorepo.js +0 -215
  25. package/bin/runners/context/multi-repo-federation.js +0 -404
  26. package/bin/runners/context/patterns.js +0 -253
  27. package/bin/runners/context/proof-context.js +0 -972
  28. package/bin/runners/context/security-scanner.js +0 -303
  29. package/bin/runners/context/semantic-search.js +0 -350
  30. package/bin/runners/context/shared.js +0 -264
  31. package/bin/runners/context/team-conventions.js +0 -310
  32. package/bin/runners/lib/ai-bridge.js +0 -416
  33. package/bin/runners/lib/analysis-core.js +0 -271
  34. package/bin/runners/lib/analyzers.js +0 -541
  35. package/bin/runners/lib/audit-bridge.js +0 -391
  36. package/bin/runners/lib/auth-truth.js +0 -193
  37. package/bin/runners/lib/auth.js +0 -215
  38. package/bin/runners/lib/backup.js +0 -62
  39. package/bin/runners/lib/billing.js +0 -107
  40. package/bin/runners/lib/claims.js +0 -118
  41. package/bin/runners/lib/cli-ui.js +0 -540
  42. package/bin/runners/lib/compliance-bridge-new.js +0 -0
  43. package/bin/runners/lib/compliance-bridge.js +0 -165
  44. package/bin/runners/lib/contracts/auth-contract.js +0 -194
  45. package/bin/runners/lib/contracts/env-contract.js +0 -178
  46. package/bin/runners/lib/contracts/external-contract.js +0 -198
  47. package/bin/runners/lib/contracts/guard.js +0 -168
  48. package/bin/runners/lib/contracts/index.js +0 -89
  49. package/bin/runners/lib/contracts/plan-validator.js +0 -311
  50. package/bin/runners/lib/contracts/route-contract.js +0 -192
  51. package/bin/runners/lib/detect.js +0 -89
  52. package/bin/runners/lib/doctor/autofix.js +0 -254
  53. package/bin/runners/lib/doctor/index.js +0 -37
  54. package/bin/runners/lib/doctor/modules/dependencies.js +0 -325
  55. package/bin/runners/lib/doctor/modules/index.js +0 -46
  56. package/bin/runners/lib/doctor/modules/network.js +0 -250
  57. package/bin/runners/lib/doctor/modules/project.js +0 -312
  58. package/bin/runners/lib/doctor/modules/runtime.js +0 -224
  59. package/bin/runners/lib/doctor/modules/security.js +0 -348
  60. package/bin/runners/lib/doctor/modules/system.js +0 -213
  61. package/bin/runners/lib/doctor/modules/vibecheck.js +0 -394
  62. package/bin/runners/lib/doctor/reporter.js +0 -262
  63. package/bin/runners/lib/doctor/service.js +0 -262
  64. package/bin/runners/lib/doctor/types.js +0 -113
  65. package/bin/runners/lib/doctor/ui.js +0 -263
  66. package/bin/runners/lib/doctor-enhanced.js +0 -233
  67. package/bin/runners/lib/doctor-v2.js +0 -608
  68. package/bin/runners/lib/enforcement.js +0 -72
package/bin/guardrail.js DELETED
@@ -1,834 +0,0 @@
1
- #!/usr/bin/env node
2
- // bin/vibecheck.js
3
- const readline = require("readline");
4
- const path = require("path");
5
- const fs = require("fs");
6
- const { routeArgv } = require("./_router");
7
- const { warnDeprecationOnce } = require("./_deprecations");
8
- const {
9
- getApiKey,
10
- checkEntitlement,
11
- getEntitlements,
12
- } = require("./runners/lib/auth");
13
-
14
- // Read version from package.json
15
- function getVersion() {
16
- try {
17
- const pkgPath = path.join(__dirname, "..", "package.json");
18
- const pkg = JSON.parse(fs.readFileSync(pkgPath, "utf-8"));
19
- return pkg.version || "0.0.0";
20
- } catch {
21
- return "0.0.0";
22
- }
23
- }
24
-
25
- // Runners
26
- const { runScan } = require("./runners/runScan");
27
- const { runGate } = require("./runners/runGate");
28
- const { runContext } = require("./runners/runContext");
29
- const { runDashboard, runDemo } = require("./runners/runDashboard");
30
- const { runFix } = require("./runners/runFix");
31
- const { runShip } = require("./runners/runShip");
32
- const { runLaunch } = require("./runners/runLaunch");
33
- const { runAutopilot } = require("./runners/runAutopilot");
34
- const { runProof } = require("./runners/runProof");
35
-
36
- // Graceful loading for modules that may have syntax issues
37
- let runReality, runRealitySniff;
38
- try {
39
- runReality = require("./runners/runReality").runReality;
40
- } catch (e) {
41
- runReality = async () => { console.error("Reality runner unavailable:", e.message); return 1; };
42
- }
43
- try {
44
- runRealitySniff = require("./runners/runRealitySniff").runRealitySniff;
45
- } catch (e) {
46
- runRealitySniff = async () => { console.error("RealitySniff runner unavailable:", e.message); return 1; };
47
- }
48
- const { runValidate } = require("./runners/runValidate");
49
- const { runDoctor } = require("./runners/runDoctor");
50
- const { runInit } = require("./runners/runInit");
51
- const { runMcp } = require("./runners/runMcp");
52
- const { runLogin, runLogout, runWhoami } = require("./runners/runAuth");
53
- const {
54
- runNaturalLanguage,
55
- isNaturalLanguageCommand,
56
- } = require("./runners/runNaturalLanguage");
57
- const { runAIAgent } = require("./runners/runAIAgent");
58
- const { runBadge } = require("./runners/runBadge");
59
- const { runUpgrade } = require("./runners/runUpgrade");
60
- const { runCertify } = require("./runners/runCertify");
61
- const { runVerifyAgentOutput } = require("./runners/runVerifyAgentOutput");
62
- const { runFixPacks } = require("./runners/runFixPacks");
63
- const { runAudit } = require("./runners/runAudit");
64
- const { runMdc } = require("./runners/runMdc");
65
- const { runEnhancedShip } = require("./runners/runEnhancedShip");
66
- const { runPromptFirewall } = require("./runners/runPromptFirewall");
67
-
68
- // Route Truth v1 - ctx command
69
- const { runCtx } = require("./runners/runCtx");
70
- // Share command
71
- const { runShare } = require("./runners/runShare");
72
- // PR command
73
- const { runPR } = require("./runners/runPR");
74
- // Init GHA command
75
- const { runInitGha } = require("./runners/runInitGha");
76
- // Install command
77
- const { runInstall } = require("./runners/runInstall");
78
- // Prove command
79
- const { runProve } = require("./runners/runProve");
80
- // Watch command
81
- const { runWatch } = require("./runners/runWatch");
82
- // Status command
83
- const { runStatus } = require("./runners/runStatus");
84
- // Graph command - Reality Proof Graph
85
- const { runGraph } = require("./runners/runGraph");
86
- // Permissions command - AuthZ Matrix & IDOR
87
- const { runPermissions } = require("./runners/runPermissions");
88
- // Replay command - Record and replay user sessions
89
- const { runReplay } = require("./runners/runReplay");
90
- // Context Contracts commands
91
- const { runCtxSync } = require("./runners/runCtxSync");
92
- const { runCtxGuard } = require("./runners/runCtxGuard");
93
-
94
- // Truth Pack v1 - Core truth system
95
- let runTruthpack;
96
- try {
97
- runTruthpack = require("./runners/runTruthpack").runTruthpack;
98
- } catch (e) {
99
- runTruthpack = async () => { console.error("Truthpack runner unavailable:", e.message); return 1; };
100
- }
101
-
102
- const VERSION = getVersion();
103
-
104
- // ANSI colors
105
- const c = {
106
- reset: "\x1b[0m",
107
- dim: "\x1b[2m",
108
- cyan: "\x1b[36m",
109
- green: "\x1b[32m",
110
- yellow: "\x1b[33m",
111
- red: "\x1b[31m",
112
- blue: "\x1b[34m",
113
- magenta: "\x1b[35m",
114
- };
115
-
116
- // Detect CI/CD environment (non-interactive)
117
- function isCI() {
118
- return !!(
119
- process.env.CI ||
120
- process.env.CONTINUOUS_INTEGRATION ||
121
- process.env.RAILWAY_ENVIRONMENT ||
122
- process.env.VERCEL ||
123
- process.env.NETLIFY ||
124
- process.env.GITHUB_ACTIONS ||
125
- process.env.GITLAB_CI ||
126
- process.env.CIRCLECI ||
127
- process.env.TRAVIS ||
128
- process.env.BUILDKITE ||
129
- process.env.RENDER ||
130
- process.env.HEROKU ||
131
- !process.stdin.isTTY
132
- );
133
- }
134
-
135
- // ============================================================================
136
- // TIER-BASED COMMAND ACCESS
137
- // ============================================================================
138
- // FREE ($0) - No API key needed
139
- const FREE_COMMANDS = [
140
- "help",
141
- "version",
142
- "doctor",
143
- "init",
144
- "login",
145
- "logout",
146
- "whoami",
147
- "scan", // Route integrity + security analysis
148
- "validate", // AI code validation
149
- "badge", // Generate badges
150
- "certify", // Certification badges (SEO fuel)
151
- "context", // AI rules generator
152
- "dashboard", // Real-time monitoring
153
- "demo", // Interactive demo
154
- "upgrade", // Subscription management
155
- "verify-agent-output", // Verify AI agent output
156
- "mdc", // MDC documentation generator
157
- "prompt-firewall", // Prompt firewall (free tier with limited features)
158
- "firewall", // Alias for prompt-firewall
159
- "ctx", // Truth Pack generator
160
- "truthpack", // Alias for ctx
161
- "replay", // Record and replay user sessions
162
- "graph", // Reality Proof Graph
163
- "status", // Quick project status
164
- "watch", // Continuous dev mode
165
- "prove", // One command reality proof
166
- "install", // Zero-friction onboarding
167
- "pr", // PR comment generator
168
- "share", // Share bundle generator
169
- "reality", // Runtime UI verification
170
- ];
171
-
172
- // STARTER ($19/mo) - Requires API key with starter+ plan
173
- const STARTER_COMMANDS = {
174
- ship: "ship:audit", // Plain English audit
175
- "enhanced-ship": "enhanced-ship:full", // Enhanced ship decision with all features
176
- gate: "gate:ci", // CI/CD gate
177
- reality: "reality:basic", // Browser testing
178
- launch: "launch:checklist", // Pre-launch wizard
179
- };
180
-
181
- // PRO ($49/mo) - Requires API key with pro+ plan
182
- const PRO_COMMANDS = {
183
- "ai-test": "ai:agent", // AI Agent testing
184
- ai: "ai:agent",
185
- agent: "ai:agent",
186
- // fix: removed - handled specially to allow --plan-only on FREE tier
187
- autopilot: "autopilot:enable", // Continuous protection
188
- };
189
-
190
- // Commands with FREE tier read-only modes
191
- const TIERED_COMMANDS = {
192
- fix: {
193
- freeArgs: ["--plan-only", "--help", "-h"], // Allow these args on FREE
194
- requiredScope: "fix:apply",
195
- tier: "pro",
196
- },
197
- };
198
-
199
- // Special: proof command has sub-modes with different tiers
200
- const PROOF_COMMANDS = {
201
- mocks: "proof:mocks", // Starter+
202
- reality: "proof:reality", // Pro+
203
- };
204
-
205
- // Commands that always work (utilities)
206
- const UTILITY_COMMANDS = ["mcp", "rules", "api", "deps", "sbom", "fixpacks"];
207
-
208
- // Compliance tier commands
209
- const COMPLIANCE_COMMANDS = {
210
- audit: "audit:full", // Full audit trail
211
- };
212
-
213
- async function prompt(question) {
214
- const rl = readline.createInterface({
215
- input: process.stdin,
216
- output: process.stdout,
217
- });
218
- return new Promise((resolve) => {
219
- rl.question(question, (answer) => {
220
- rl.close();
221
- resolve(answer.trim());
222
- });
223
- });
224
- }
225
-
226
- async function showWelcomeAndPromptLogin() {
227
- console.log(`
228
- ${c.cyan}╔════════════════════════════════════════════════════════════╗
229
- ║ ${c.reset}🛡️ VIBECHECK${c.cyan} ║
230
- ╚════════════════════════════════════════════════════════════╝${c.reset}
231
-
232
- ${c.dim}Ship with confidence. Catch fake features before your users do.${c.reset}
233
-
234
- `);
235
-
236
- const { key, source } = getApiKey();
237
-
238
- if (!key) {
239
- // In CI/CD environments, skip interactive prompts
240
- if (isCI()) {
241
- console.log(`${c.yellow}⚠ No API key found${c.reset}`);
242
- console.log(
243
- `${c.dim}Running in CI mode with FREE tier features.${c.reset}`,
244
- );
245
- console.log(
246
- `${c.dim}Set VIBECHECK_API_KEY env var to unlock more features.${c.reset}\n`,
247
- );
248
- return { key: null, entitlements: null };
249
- }
250
-
251
- console.log(`${c.yellow}⚠ No API key found${c.reset}`);
252
- console.log(`
253
- ${c.dim}To unlock all features, you need a vibecheck API key.${c.reset}
254
-
255
- ${c.green}FREE${c.reset} scan, validate, badge, doctor, init
256
- ${c.cyan}STARTER${c.reset} ship, gate, reality, launch, proof mocks ${c.dim}($29/mo)${c.reset}
257
- ${c.magenta}PRO${c.reset} ai-test, fix, autopilot, proof reality ${c.dim}($99/mo)${c.reset}
258
-
259
- ${c.dim}Get your API key at: ${c.cyan}https://vibecheckai.dev/settings/keys${c.reset}
260
- `);
261
-
262
- const answer = await prompt(
263
- `${c.cyan}?${c.reset} Do you have an API key? (y/N) `,
264
- );
265
-
266
- if (answer.toLowerCase() === "y") {
267
- const apiKey = await prompt(`${c.cyan}?${c.reset} Paste your API key: `);
268
- if (apiKey) {
269
- const { saveApiKey } = require("./runners/lib/auth");
270
- console.log(`\n${c.dim}Verifying...${c.reset}`);
271
-
272
- const entitlements = await getEntitlements(apiKey);
273
- if (entitlements) {
274
- saveApiKey(apiKey);
275
- console.log(
276
- `\n${c.green}✓${c.reset} Logged in as ${entitlements.user?.name || "User"}`,
277
- );
278
- console.log(
279
- `${c.dim}Plan: ${entitlements.plan?.toUpperCase() || "FREE"}${c.reset}\n`,
280
- );
281
- return { key: apiKey, entitlements };
282
- } else {
283
- console.log(`\n${c.red}✗${c.reset} Invalid API key\n`);
284
- }
285
- }
286
- }
287
-
288
- console.log(`
289
- ${c.dim}Continuing in FREE mode. Some features will be limited.${c.reset}
290
- ${c.dim}Run ${c.cyan}vibecheck login${c.dim} anytime to upgrade.${c.reset}
291
- `);
292
- return { key: null, entitlements: null };
293
- }
294
-
295
- // User has API key, get entitlements
296
- const entitlements = await getEntitlements(key);
297
- return { key, entitlements };
298
- }
299
-
300
- async function checkCommandAccess(cmd, entitlements, args = []) {
301
- // Free commands always work (no API key needed)
302
- if (FREE_COMMANDS.includes(cmd)) {
303
- return { allowed: true, tier: "free" };
304
- }
305
-
306
- // Utility commands always work
307
- if (UTILITY_COMMANDS.includes(cmd)) {
308
- return { allowed: true, tier: "utility" };
309
- }
310
-
311
- // Tiered commands with FREE read-only modes
312
- if (TIERED_COMMANDS[cmd]) {
313
- const config = TIERED_COMMANDS[cmd];
314
- // Check if using a FREE tier argument
315
- const hasFreeArg = args.some(arg => config.freeArgs.includes(arg));
316
- // Also allow if no fix pack specified (shows help)
317
- const hasNoFixPack = cmd === "fix" && !args.some(arg => !arg.startsWith("-"));
318
-
319
- if (hasFreeArg || hasNoFixPack) {
320
- return { allowed: true, tier: "free" };
321
- }
322
-
323
- // Requires paid tier
324
- if (!entitlements) {
325
- return {
326
- allowed: false,
327
- reason: `${c.yellow}${cmd}${c.reset} requires a ${c.magenta}PRO${c.reset} plan.\n\n Run ${c.cyan}vibecheck login${c.reset} to authenticate.\n Get your API key at: ${c.cyan}https://vibecheckai.dev/settings/keys${c.reset}`,
328
- };
329
- }
330
-
331
- if (
332
- entitlements.scopes?.includes(config.requiredScope) ||
333
- entitlements.scopes?.includes("*")
334
- ) {
335
- return { allowed: true, tier: config.tier };
336
- }
337
-
338
- return {
339
- allowed: false,
340
- reason: `Your ${c.yellow}${entitlements.plan?.toUpperCase()}${c.reset} plan doesn't include this feature.\n\n Required: ${config.requiredScope}\n Upgrade to ${c.magenta}PRO${c.reset} at: ${c.cyan}https://vibecheckai.dev/pricing${c.reset}`,
341
- };
342
- }
343
-
344
- // Special handling for proof command (has sub-modes with different tiers)
345
- if (cmd === "proof") {
346
- const subMode = args[0]; // mocks or reality
347
- if (subMode === "mocks") {
348
- // Starter+ required
349
- if (!entitlements) {
350
- return {
351
- allowed: false,
352
- reason: `${c.yellow}proof mocks${c.reset} requires a ${c.cyan}STARTER${c.reset} plan or higher.\n\n Run ${c.cyan}vibecheck login${c.reset} to authenticate.\n Get your API key at: ${c.cyan}https://vibecheckai.dev/settings/keys${c.reset}`,
353
- };
354
- }
355
- if (
356
- entitlements.scopes?.includes("proof:mocks") ||
357
- entitlements.scopes?.includes("*")
358
- ) {
359
- return { allowed: true, tier: "starter" };
360
- }
361
- return {
362
- allowed: false,
363
- reason: `Your ${c.yellow}${entitlements.plan?.toUpperCase()}${c.reset} plan doesn't include mock detection.\n\n Upgrade to ${c.cyan}STARTER${c.reset} at: ${c.cyan}https://vibecheckai.dev/pricing${c.reset}`,
364
- };
365
- } else if (subMode === "reality") {
366
- // Pro+ required
367
- if (!entitlements) {
368
- return {
369
- allowed: false,
370
- reason: `${c.yellow}proof reality${c.reset} requires a ${c.magenta}PRO${c.reset} plan.\n\n Run ${c.cyan}vibecheck login${c.reset} to authenticate.\n Get your API key at: ${c.cyan}https://vibecheckai.dev/settings/keys${c.reset}`,
371
- };
372
- }
373
- if (
374
- entitlements.scopes?.includes("proof:reality") ||
375
- entitlements.scopes?.includes("*")
376
- ) {
377
- return { allowed: true, tier: "pro" };
378
- }
379
- return {
380
- allowed: false,
381
- reason: `Your ${c.yellow}${entitlements.plan?.toUpperCase()}${c.reset} plan doesn't include runtime verification.\n\n Upgrade to ${c.magenta}PRO${c.reset} at: ${c.cyan}https://vibecheckai.dev/pricing${c.reset}`,
382
- };
383
- }
384
- // No submode - show help
385
- return { allowed: true };
386
- }
387
-
388
- // STARTER tier commands
389
- if (STARTER_COMMANDS[cmd]) {
390
- const requiredScope = STARTER_COMMANDS[cmd];
391
-
392
- if (!entitlements) {
393
- return {
394
- allowed: false,
395
- reason: `${c.yellow}${cmd}${c.reset} requires a ${c.cyan}STARTER${c.reset} plan or higher.\n\n Run ${c.cyan}vibecheck login${c.reset} to authenticate.\n Get your API key at: ${c.cyan}https://vibecheckai.dev/settings/keys${c.reset}`,
396
- };
397
- }
398
-
399
- if (
400
- entitlements.scopes?.includes(requiredScope) ||
401
- entitlements.scopes?.includes("*")
402
- ) {
403
- return { allowed: true, tier: "starter" };
404
- }
405
-
406
- return {
407
- allowed: false,
408
- reason: `Your ${c.yellow}${entitlements.plan?.toUpperCase()}${c.reset} plan doesn't include this feature.\n\n Required: ${requiredScope}\n Upgrade to ${c.cyan}STARTER${c.reset} at: ${c.cyan}https://vibecheckai.dev/pricing${c.reset}`,
409
- };
410
- }
411
-
412
- // PRO tier commands
413
- if (PRO_COMMANDS[cmd]) {
414
- const requiredScope = PRO_COMMANDS[cmd];
415
-
416
- if (!entitlements) {
417
- return {
418
- allowed: false,
419
- reason: `${c.yellow}${cmd}${c.reset} requires a ${c.magenta}PRO${c.reset} plan.\n\n Run ${c.cyan}vibecheck login${c.reset} to authenticate.\n Get your API key at: ${c.cyan}https://vibecheckai.dev/settings/keys${c.reset}`,
420
- };
421
- }
422
-
423
- if (
424
- entitlements.scopes?.includes(requiredScope) ||
425
- entitlements.scopes?.includes("*")
426
- ) {
427
- return { allowed: true, tier: "pro" };
428
- }
429
-
430
- return {
431
- allowed: false,
432
- reason: `Your ${c.yellow}${entitlements.plan?.toUpperCase()}${c.reset} plan doesn't include this feature.\n\n Required: ${requiredScope}\n Upgrade to ${c.magenta}PRO${c.reset} at: ${c.cyan}https://vibecheckai.dev/pricing${c.reset}`,
433
- };
434
- }
435
-
436
- return { allowed: true };
437
- }
438
-
439
- function printHelp() {
440
- console.log(
441
- `
442
- ${c.cyan}━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━${c.reset}
443
- ${c.cyan} VIBECHECK${c.reset} - Ship with confidence
444
- ${c.cyan}━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━${c.reset}
445
-
446
- ${c.green}🚀 QUICK START${c.reset}
447
-
448
- ${c.cyan}ship${c.reset} "Is my app ready?" - Plain English, traffic light score
449
- ${c.cyan}ship --fix${c.reset} Same + auto-fix problems
450
-
451
- ${c.yellow}🧪 TESTING${c.reset} (each does something different!)
452
-
453
- ${c.cyan}scan${c.reset} ${c.dim}Route Integrity${c.reset} - dead links, orphans, coverage, security 🗺️
454
- ${c.cyan}scan --truth${c.reset} ${c.dim}+ Build manifest${c.reset} verification (CI/ship ready)
455
- ${c.cyan}scan --reality${c.reset} ${c.dim}+ Playwright${c.reset} runtime proof (best-in-class)
456
- ${c.cyan}reality${c.reset} ${c.dim}Browser testing${c.reset} - clicks buttons, fills forms, finds broken UI
457
- ${c.cyan}ai-test${c.reset} ${c.dim}AI Agent${c.reset} - autonomous testing + generates fix prompts 🤖
458
-
459
- ${c.magenta}🚦 CI/CD & GATES${c.reset}
460
-
461
- ${c.cyan}gate${c.reset} Block bad deploys - pass/fail for CI pipelines
462
- ${c.cyan}proof mocks${c.reset} Block mock/demo code from reaching production
463
- ${c.cyan}proof reality${c.reset} Runtime GO/NO-GO verification with Playwright
464
-
465
- ${c.blue}🔧 FIX & AUTOMATE${c.reset}
466
-
467
- ${c.cyan}fix${c.reset} Auto-fix detected issues (--plan first, then --apply)
468
- ${c.cyan}autopilot${c.reset} Continuous protection - weekly reports, auto-PRs
469
- ${c.cyan}badge${c.reset} Generate Ship Badge for your README/PR
470
- ${c.cyan}certify${c.reset} Generate vibecheck Certified badge with verification link
471
-
472
- ${c.dim}📦 TRUTH SYSTEM${c.reset}
473
-
474
- ${c.cyan}ctx${c.reset} Generate Truth Pack - ground truth for AI agents
475
- ${c.cyan}ctx --snapshot${c.reset} Save snapshot to .vibecheck/truth/snapshots/
476
- ${c.cyan}graph${c.reset} Build Reality Proof Graph - end-to-end causal chains
477
-
478
- ${c.dim}📦 EXTRAS${c.reset}
479
-
480
- ${c.cyan}audit${c.reset} View/export audit trail (Compliance+ tier)
481
- ${c.cyan}context${c.reset} Generate AI rules files (.cursorrules, .windsurf/rules, etc.)
482
- ${c.cyan}dashboard${c.reset} Real-time monitoring dashboard with live metrics
483
- ${c.cyan}demo${c.reset} Interactive terminal features showcase
484
- ${c.cyan}launch${c.reset} Pre-launch checklist wizard
485
- ${c.cyan}validate${c.reset} Check AI-generated code for hallucinations
486
- ${c.cyan}init${c.reset} Set up vibecheck in your project
487
- ${c.cyan}doctor${c.reset} Debug environment issues
488
- ${c.cyan}mcp${c.reset} Start MCP server for AI editors
489
-
490
- ${c.dim}🔑 ACCOUNT${c.reset}
491
-
492
- ${c.cyan}login${c.reset} Sign in with API key
493
- ${c.cyan}logout${c.reset} Sign out
494
- ${c.cyan}whoami${c.reset} Show current user & plan
495
- ${c.cyan}upgrade${c.reset} Manage subscription & view usage
496
-
497
- ${c.cyan}━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━${c.reset}
498
-
499
- ${c.green}Examples:${c.reset}
500
-
501
- vibecheck ship ${c.dim}# Quick health check${c.reset}
502
- vibecheck scan ${c.dim}# Route integrity + security analysis${c.reset}
503
- vibecheck scan --truth ${c.dim}# + Build manifest verification${c.reset}
504
- vibecheck scan --reality --url http://localhost:3000 ${c.dim}# Full proof${c.reset}
505
- vibecheck reality --url https://... ${c.dim}# Test live app${c.reset}
506
- vibecheck ai-test --url https://... ${c.dim}# AI explores your app${c.reset}
507
- vibecheck gate ${c.dim}# Block bad deploy in CI${c.reset}
508
- vibecheck badge ${c.dim}# Generate ship badge${c.reset}
509
-
510
- ${c.dim}Run 'vibecheck <command> --help' for details.${c.reset}
511
- `.trim(),
512
- );
513
- }
514
-
515
- (async function main() {
516
- const rawArgs = process.argv.slice(2);
517
-
518
- // Check if the first argument looks like a natural language command
519
- // Natural language commands are typically quoted strings or multi-word phrases
520
- const firstArg = rawArgs[0];
521
- if (firstArg && isNaturalLanguageCommand(firstArg)) {
522
- // Join all args as the natural language input
523
- const nlInput = rawArgs.join(" ");
524
- const exitCode = await runNaturalLanguage(nlInput);
525
- process.exit(exitCode);
526
- }
527
-
528
- const { legacyFrom, routed } = routeArgv(process.argv);
529
-
530
- const cmd = routed[0];
531
- const args = routed.slice(1);
532
-
533
- // Commands that skip auth check entirely
534
- const skipAuthCommands = [
535
- "help",
536
- "-h",
537
- "--help",
538
- "version",
539
- "login",
540
- "logout",
541
- "whoami",
542
- "doctor",
543
- ];
544
-
545
- if (!cmd || cmd === "-h" || cmd === "--help" || cmd === "help") {
546
- printHelp();
547
- process.exit(0);
548
- }
549
-
550
- // Check for first run (no API key) - only for non-skip commands
551
- let authInfo = { key: null, entitlements: null };
552
-
553
- if (!skipAuthCommands.includes(cmd)) {
554
- // Check if this is a free command or utility - if so, skip entitlement checks
555
- const isFreeCommand = FREE_COMMANDS.includes(cmd) || UTILITY_COMMANDS.includes(cmd);
556
- const isKnownCommand = isFreeCommand ||
557
- STARTER_COMMANDS[cmd] ||
558
- PRO_COMMANDS[cmd] ||
559
- TIERED_COMMANDS[cmd] ||
560
- PROOF_COMMANDS[cmd] ||
561
- COMPLIANCE_COMMANDS[cmd];
562
-
563
- // For unknown commands, skip auth and let them fail with "Unknown command" message
564
- if (!isKnownCommand) {
565
- // Skip authentication for unknown commands - they'll show help/error message
566
- authInfo = { key: null, entitlements: null };
567
- } else {
568
- const { key } = getApiKey();
569
-
570
- // First run without API key - show welcome and prompt
571
- if (!key && !process.env.VIBECHECK_SKIP_AUTH) {
572
- authInfo = await showWelcomeAndPromptLogin();
573
- } else if (key && !isFreeCommand) {
574
- // Has API key and command requires auth - get entitlements silently
575
- // For free commands, we don't need to check entitlements
576
- try {
577
- const entitlements = await getEntitlements(key);
578
- authInfo = { key, entitlements };
579
- } catch (error) {
580
- // If API is unavailable, allow free commands to proceed
581
- // Paid commands will be blocked in checkCommandAccess
582
- if (isFreeCommand) {
583
- authInfo = { key, entitlements: null };
584
- } else {
585
- throw error;
586
- }
587
- }
588
- } else if (key && isFreeCommand) {
589
- // Free command with key - no need to fetch entitlements
590
- authInfo = { key, entitlements: null };
591
- }
592
- }
593
-
594
- // Check if user has access to this command (only for known commands)
595
- if (isKnownCommand) {
596
- const access = await checkCommandAccess(cmd, authInfo.entitlements, args);
597
-
598
- if (!access.allowed) {
599
- console.log(`\n${c.red}✗ Access Denied${c.reset}\n`);
600
- console.log(access.reason);
601
- console.log("");
602
- process.exit(1);
603
- }
604
-
605
- // Show tier info for paid features
606
- if (access.tier === "starter") {
607
- console.log(`${c.cyan}▸ STARTER${c.reset} ${c.dim}feature${c.reset}\n`);
608
- } else if (access.tier === "pro") {
609
- console.log(`${c.magenta}▸ PRO${c.reset} ${c.dim}feature${c.reset}\n`);
610
- }
611
- }
612
- }
613
-
614
- // Deprecation suggestions
615
- if (legacyFrom) {
616
- const suggestion = routed.slice(0, 2).join(" ");
617
- warnDeprecationOnce(legacyFrom, suggestion, VERSION);
618
- }
619
-
620
- try {
621
- let exitCode = 0;
622
- switch (cmd) {
623
- case "scan":
624
- exitCode = await runScan(args);
625
- break;
626
- case "gate":
627
- exitCode = await runGate(args);
628
- break;
629
- case "ship":
630
- exitCode = await runShip(args);
631
- break;
632
- case "enhanced-ship":
633
- exitCode = await runEnhancedShip(args);
634
- break;
635
- case "prompt-firewall":
636
- case "firewall":
637
- exitCode = await runPromptFirewall(args);
638
- break;
639
- case "launch":
640
- exitCode = await runLaunch(args);
641
- break;
642
- case "autopilot":
643
- exitCode = await runAutopilot(args);
644
- break;
645
- case "fix":
646
- exitCode = await runFix(args);
647
- break;
648
- case "share":
649
- exitCode = await runShare({
650
- repoRoot: process.cwd(),
651
- missionDir: args.find((a, i) => args[i-1] === '--mission-dir'),
652
- outputDir: args.find((a, i) => args[i-1] === '--output-dir'),
653
- prComment: args.includes('--pr-comment')
654
- });
655
- break;
656
- case "pr":
657
- exitCode = await runPR({
658
- repoRoot: process.cwd(),
659
- fastifyEntry: args.find((a, i) => args[i-1] === '--fastify-entry'),
660
- out: args.find((a, i) => args[i-1] === '--out'),
661
- failOnWarn: args.includes('--fail-on-warn'),
662
- maxFindings: Number(args.find((a, i) => args[i-1] === '--max-findings')) || 12
663
- });
664
- break;
665
- case "install":
666
- exitCode = await runInstall({ repoRoot: process.cwd() });
667
- break;
668
- case "prove":
669
- exitCode = await runProve({
670
- repoRoot: process.cwd(),
671
- url: args.find((a, i) => args[i-1] === '--url' || args[i-1] === '-u'),
672
- auth: args.find((a, i) => args[i-1] === '--auth'),
673
- storageState: args.find((a, i) => args[i-1] === '--storage-state'),
674
- fastifyEntry: args.find((a, i) => args[i-1] === '--fastify-entry'),
675
- maxFixRounds: Number(args.find((a, i) => args[i-1] === '--max-fix-rounds')) || 3,
676
- maxMissions: Number(args.find((a, i) => args[i-1] === '--max-missions')) || 8,
677
- maxSteps: Number(args.find((a, i) => args[i-1] === '--max-steps')) || 10,
678
- skipReality: args.includes('--skip-reality'),
679
- skipFix: args.includes('--skip-fix'),
680
- headed: args.includes('--headed'),
681
- danger: args.includes('--danger'),
682
- maxPages: Number(args.find((a, i) => args[i-1] === '--max-pages')) || 18,
683
- maxDepth: Number(args.find((a, i) => args[i-1] === '--max-depth')) || 2,
684
- timeoutMs: Number(args.find((a, i) => args[i-1] === '--timeout-ms')) || 15000
685
- });
686
- break;
687
- case "watch":
688
- exitCode = await runWatch({
689
- repoRoot: process.cwd(),
690
- fastifyEntry: args.find((a, i) => args[i-1] === '--fastify-entry'),
691
- debounceMs: Number(args.find((a, i) => args[i-1] === '--debounce')) || 500,
692
- clearScreen: !args.includes('--no-clear')
693
- });
694
- break;
695
- case "status":
696
- exitCode = await runStatus({
697
- repoRoot: process.cwd(),
698
- json: args.includes('--json')
699
- });
700
- break;
701
- case "proof":
702
- exitCode = await runProof(args);
703
- break;
704
- case "reality":
705
- exitCode = await runReality({
706
- repoRoot: process.cwd(),
707
- url: args.find((a, i) => args[i-1] === '--url' || args[i-1] === '-u'),
708
- auth: args.find((a, i) => args[i-1] === '--auth'),
709
- storageState: args.find((a, i) => args[i-1] === '--storage-state'),
710
- saveStorageState: args.find((a, i) => args[i-1] === '--save-storage-state'),
711
- truthpack: args.find((a, i) => args[i-1] === '--truthpack'),
712
- verifyAuth: args.includes('--verify-auth'),
713
- headed: args.includes('--headed'),
714
- maxPages: Number(args.find((a, i) => args[i-1] === '--max-pages')) || 18,
715
- maxDepth: Number(args.find((a, i) => args[i-1] === '--max-depth')) || 2,
716
- danger: args.includes('--danger'),
717
- timeoutMs: Number(args.find((a, i) => args[i-1] === '--timeout-ms')) || 15000
718
- });
719
- break;
720
- case "reality-sniff":
721
- case "sniff":
722
- exitCode = await runRealitySniff(args);
723
- break;
724
- case "ai-test":
725
- case "ai":
726
- case "agent":
727
- exitCode = await runAIAgent(args);
728
- break;
729
- case "validate":
730
- exitCode = await runValidate(args);
731
- break;
732
- case "doctor":
733
- exitCode = runDoctor(args);
734
- break;
735
- case "init":
736
- // Enterprise init handles all flags including --gha, --gitlab, --compliance, etc.
737
- exitCode = await runInit(args);
738
- break;
739
- case "mcp":
740
- exitCode = runMcp(args);
741
- break;
742
- case "login":
743
- exitCode = await runLogin(args);
744
- break;
745
- case "logout":
746
- exitCode = await runLogout(args);
747
- break;
748
- case "whoami":
749
- exitCode = await runWhoami(args);
750
- break;
751
- case "badge":
752
- exitCode = await runBadge(args);
753
- break;
754
- case "context":
755
- case "rules":
756
- exitCode = await runContext(args);
757
- break;
758
- case "dashboard":
759
- exitCode = await runDashboard(args);
760
- break;
761
- case "demo":
762
- exitCode = await runDemo(args);
763
- break;
764
- case "upgrade":
765
- exitCode = await runUpgrade(args);
766
- break;
767
- case "certify":
768
- exitCode = await runCertify(args, process.cwd());
769
- break;
770
- case "verify-agent-output":
771
- exitCode = await runVerifyAgentOutput(args);
772
- break;
773
- case "fixpacks":
774
- exitCode = await runFixPacks(args);
775
- break;
776
- case "audit":
777
- exitCode = await runAudit(args);
778
- break;
779
- case "mdc":
780
- exitCode = await runMdc(args);
781
- break;
782
- case "graph":
783
- exitCode = await runGraph(args);
784
- break;
785
- case "permissions":
786
- case "authz":
787
- exitCode = await runPermissions(args);
788
- break;
789
- case "ctx":
790
- case "truthpack":
791
- // Check for subcommands
792
- if (args[0] === "sync") {
793
- exitCode = await runCtxSync({
794
- repoRoot: process.cwd(),
795
- fastifyEntry: args.find((a, i) => args[i-1] === '--fastify-entry')
796
- });
797
- break;
798
- }
799
- if (args[0] === "guard") {
800
- exitCode = await runCtxGuard.main(args.slice(1));
801
- break;
802
- }
803
- // Parse args for ctx command - use Route Truth v1
804
- const fastifyEntryIdx = args.indexOf('--fastify-entry');
805
- const fastifyEntry = fastifyEntryIdx !== -1 ? args[fastifyEntryIdx + 1] : undefined;
806
- await runCtx({
807
- repoRoot: process.cwd(),
808
- fastifyEntry,
809
- print: args.includes('--print'),
810
- });
811
- exitCode = 0;
812
- break;
813
- case "version":
814
- console.log(`vibecheck v${VERSION}`);
815
- break;
816
- default:
817
- // Try natural language parsing as fallback for unknown commands
818
- const nlInput = [cmd, ...args].join(" ");
819
- if (isNaturalLanguageCommand(nlInput)) {
820
- exitCode = await runNaturalLanguage(nlInput);
821
- } else {
822
- process.stderr.write(`Unknown command: ${cmd}\n\n`);
823
- printHelp();
824
- exitCode = 1;
825
- }
826
- }
827
- process.exit(exitCode);
828
- } catch (err) {
829
- process.stderr.write(
830
- err && err.stack ? err.stack + "\n" : String(err) + "\n",
831
- );
832
- process.exit(1);
833
- }
834
- })();