@vibecheckai/cli 3.2.5 → 3.3.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.
Files changed (197) hide show
  1. package/bin/.generated +25 -25
  2. package/bin/dev/run-v2-torture.js +30 -30
  3. package/bin/registry.js +192 -5
  4. package/bin/runners/lib/__tests__/entitlements-v2.test.js +295 -295
  5. package/bin/runners/lib/agent-firewall/change-packet/builder.js +280 -6
  6. package/bin/runners/lib/agent-firewall/critic/index.js +151 -0
  7. package/bin/runners/lib/agent-firewall/critic/judge.js +432 -0
  8. package/bin/runners/lib/agent-firewall/critic/prompts.js +305 -0
  9. package/bin/runners/lib/agent-firewall/lawbook/distributor.js +465 -0
  10. package/bin/runners/lib/agent-firewall/lawbook/evaluator.js +604 -0
  11. package/bin/runners/lib/agent-firewall/lawbook/index.js +304 -0
  12. package/bin/runners/lib/agent-firewall/lawbook/registry.js +514 -0
  13. package/bin/runners/lib/agent-firewall/lawbook/schema.js +420 -0
  14. package/bin/runners/lib/agent-firewall/logger.js +141 -0
  15. package/bin/runners/lib/agent-firewall/policy/loader.js +312 -4
  16. package/bin/runners/lib/agent-firewall/policy/rules/ghost-env.js +113 -1
  17. package/bin/runners/lib/agent-firewall/policy/rules/ghost-route.js +133 -6
  18. package/bin/runners/lib/agent-firewall/proposal/extractor.js +394 -0
  19. package/bin/runners/lib/agent-firewall/proposal/index.js +212 -0
  20. package/bin/runners/lib/agent-firewall/proposal/schema.js +251 -0
  21. package/bin/runners/lib/agent-firewall/proposal/validator.js +386 -0
  22. package/bin/runners/lib/agent-firewall/reality/index.js +332 -0
  23. package/bin/runners/lib/agent-firewall/reality/state.js +625 -0
  24. package/bin/runners/lib/agent-firewall/reality/watcher.js +322 -0
  25. package/bin/runners/lib/agent-firewall/risk/index.js +173 -0
  26. package/bin/runners/lib/agent-firewall/risk/scorer.js +328 -0
  27. package/bin/runners/lib/agent-firewall/risk/thresholds.js +321 -0
  28. package/bin/runners/lib/agent-firewall/risk/vectors.js +421 -0
  29. package/bin/runners/lib/agent-firewall/simulator/diff-simulator.js +472 -0
  30. package/bin/runners/lib/agent-firewall/simulator/import-resolver.js +346 -0
  31. package/bin/runners/lib/agent-firewall/simulator/index.js +181 -0
  32. package/bin/runners/lib/agent-firewall/simulator/route-validator.js +380 -0
  33. package/bin/runners/lib/agent-firewall/time-machine/incident-correlator.js +661 -0
  34. package/bin/runners/lib/agent-firewall/time-machine/index.js +267 -0
  35. package/bin/runners/lib/agent-firewall/time-machine/replay-engine.js +436 -0
  36. package/bin/runners/lib/agent-firewall/time-machine/state-reconstructor.js +490 -0
  37. package/bin/runners/lib/agent-firewall/time-machine/timeline-builder.js +530 -0
  38. package/bin/runners/lib/analyzers.js +81 -18
  39. package/bin/runners/lib/api-client.js +269 -0
  40. package/bin/runners/lib/auth-truth.js +193 -193
  41. package/bin/runners/lib/authority-badge.js +425 -0
  42. package/bin/runners/lib/backup.js +62 -62
  43. package/bin/runners/lib/billing.js +107 -107
  44. package/bin/runners/lib/claims.js +118 -118
  45. package/bin/runners/lib/cli-output.js +7 -1
  46. package/bin/runners/lib/cli-ui.js +540 -540
  47. package/bin/runners/lib/contracts/auth-contract.js +202 -202
  48. package/bin/runners/lib/contracts/env-contract.js +181 -181
  49. package/bin/runners/lib/contracts/external-contract.js +206 -206
  50. package/bin/runners/lib/contracts/guard.js +168 -168
  51. package/bin/runners/lib/contracts/index.js +89 -89
  52. package/bin/runners/lib/contracts/plan-validator.js +311 -311
  53. package/bin/runners/lib/contracts/route-contract.js +199 -199
  54. package/bin/runners/lib/contracts.js +804 -804
  55. package/bin/runners/lib/detect.js +89 -89
  56. package/bin/runners/lib/doctor/autofix.js +254 -254
  57. package/bin/runners/lib/doctor/index.js +37 -37
  58. package/bin/runners/lib/doctor/modules/dependencies.js +325 -325
  59. package/bin/runners/lib/doctor/modules/index.js +46 -46
  60. package/bin/runners/lib/doctor/modules/network.js +250 -250
  61. package/bin/runners/lib/doctor/modules/project.js +312 -312
  62. package/bin/runners/lib/doctor/modules/runtime.js +224 -224
  63. package/bin/runners/lib/doctor/modules/security.js +348 -348
  64. package/bin/runners/lib/doctor/modules/system.js +213 -213
  65. package/bin/runners/lib/doctor/modules/vibecheck.js +394 -394
  66. package/bin/runners/lib/doctor/reporter.js +262 -262
  67. package/bin/runners/lib/doctor/service.js +262 -262
  68. package/bin/runners/lib/doctor/types.js +113 -113
  69. package/bin/runners/lib/doctor/ui.js +263 -263
  70. package/bin/runners/lib/doctor-v2.js +608 -608
  71. package/bin/runners/lib/drift.js +425 -425
  72. package/bin/runners/lib/enforcement.js +72 -72
  73. package/bin/runners/lib/enterprise-detect.js +603 -603
  74. package/bin/runners/lib/enterprise-init.js +942 -942
  75. package/bin/runners/lib/env-resolver.js +417 -417
  76. package/bin/runners/lib/env-template.js +66 -66
  77. package/bin/runners/lib/env.js +189 -189
  78. package/bin/runners/lib/error-handler.js +16 -9
  79. package/bin/runners/lib/exit-codes.js +275 -0
  80. package/bin/runners/lib/extractors/client-calls.js +990 -990
  81. package/bin/runners/lib/extractors/fastify-route-dump.js +573 -573
  82. package/bin/runners/lib/extractors/fastify-routes.js +426 -426
  83. package/bin/runners/lib/extractors/index.js +363 -363
  84. package/bin/runners/lib/extractors/next-routes.js +524 -524
  85. package/bin/runners/lib/extractors/proof-graph.js +431 -431
  86. package/bin/runners/lib/extractors/route-matcher.js +451 -451
  87. package/bin/runners/lib/extractors/truthpack-v2.js +377 -377
  88. package/bin/runners/lib/extractors/ui-bindings.js +547 -547
  89. package/bin/runners/lib/findings-schema.js +281 -281
  90. package/bin/runners/lib/firewall-prompt.js +50 -50
  91. package/bin/runners/lib/global-flags.js +37 -0
  92. package/bin/runners/lib/graph/graph-builder.js +265 -265
  93. package/bin/runners/lib/graph/html-renderer.js +413 -413
  94. package/bin/runners/lib/graph/index.js +32 -32
  95. package/bin/runners/lib/graph/runtime-collector.js +215 -215
  96. package/bin/runners/lib/graph/static-extractor.js +518 -518
  97. package/bin/runners/lib/help-formatter.js +413 -0
  98. package/bin/runners/lib/html-report.js +650 -650
  99. package/bin/runners/lib/llm.js +75 -75
  100. package/bin/runners/lib/logger.js +38 -0
  101. package/bin/runners/lib/meter.js +61 -61
  102. package/bin/runners/lib/missions/evidence.js +126 -126
  103. package/bin/runners/lib/patch.js +40 -40
  104. package/bin/runners/lib/permissions/auth-model.js +213 -213
  105. package/bin/runners/lib/permissions/idor-prover.js +205 -205
  106. package/bin/runners/lib/permissions/index.js +45 -45
  107. package/bin/runners/lib/permissions/matrix-builder.js +198 -198
  108. package/bin/runners/lib/pkgjson.js +28 -28
  109. package/bin/runners/lib/policy.js +295 -295
  110. package/bin/runners/lib/preflight.js +142 -142
  111. package/bin/runners/lib/reality/correlation-detectors.js +359 -359
  112. package/bin/runners/lib/reality/index.js +318 -318
  113. package/bin/runners/lib/reality/request-hashing.js +416 -416
  114. package/bin/runners/lib/reality/request-mapper.js +453 -453
  115. package/bin/runners/lib/reality/safety-rails.js +463 -463
  116. package/bin/runners/lib/reality/semantic-snapshot.js +408 -408
  117. package/bin/runners/lib/reality/toast-detector.js +393 -393
  118. package/bin/runners/lib/reality-findings.js +84 -84
  119. package/bin/runners/lib/receipts.js +179 -179
  120. package/bin/runners/lib/redact.js +29 -29
  121. package/bin/runners/lib/replay/capsule-manager.js +154 -154
  122. package/bin/runners/lib/replay/index.js +263 -263
  123. package/bin/runners/lib/replay/player.js +348 -348
  124. package/bin/runners/lib/replay/recorder.js +331 -331
  125. package/bin/runners/lib/report.js +135 -135
  126. package/bin/runners/lib/route-detection.js +1140 -1140
  127. package/bin/runners/lib/sandbox/index.js +59 -59
  128. package/bin/runners/lib/sandbox/proof-chain.js +399 -399
  129. package/bin/runners/lib/sandbox/sandbox-runner.js +205 -205
  130. package/bin/runners/lib/sandbox/worktree.js +174 -174
  131. package/bin/runners/lib/schema-validator.js +350 -350
  132. package/bin/runners/lib/schemas/contracts.schema.json +160 -160
  133. package/bin/runners/lib/schemas/finding.schema.json +100 -100
  134. package/bin/runners/lib/schemas/mission-pack.schema.json +206 -206
  135. package/bin/runners/lib/schemas/proof-graph.schema.json +176 -176
  136. package/bin/runners/lib/schemas/reality-report.schema.json +162 -162
  137. package/bin/runners/lib/schemas/share-pack.schema.json +180 -180
  138. package/bin/runners/lib/schemas/ship-report.schema.json +117 -117
  139. package/bin/runners/lib/schemas/truthpack-v2.schema.json +303 -303
  140. package/bin/runners/lib/schemas/validator.js +438 -438
  141. package/bin/runners/lib/score-history.js +282 -282
  142. package/bin/runners/lib/share-pack.js +239 -239
  143. package/bin/runners/lib/snippets.js +67 -67
  144. package/bin/runners/lib/unified-cli-output.js +604 -0
  145. package/bin/runners/lib/upsell.js +658 -510
  146. package/bin/runners/lib/usage.js +153 -153
  147. package/bin/runners/lib/validate-patch.js +156 -156
  148. package/bin/runners/lib/verdict-engine.js +628 -628
  149. package/bin/runners/reality/engine.js +917 -917
  150. package/bin/runners/reality/flows.js +122 -122
  151. package/bin/runners/reality/report.js +378 -378
  152. package/bin/runners/reality/session.js +193 -193
  153. package/bin/runners/runAgent.d.ts +5 -0
  154. package/bin/runners/runApprove.js +1200 -0
  155. package/bin/runners/runAuth.js +324 -95
  156. package/bin/runners/runCheckpoint.js +39 -21
  157. package/bin/runners/runClassify.js +859 -0
  158. package/bin/runners/runContext.js +136 -24
  159. package/bin/runners/runDoctor.js +108 -68
  160. package/bin/runners/runFirewall.d.ts +5 -0
  161. package/bin/runners/runFirewallHook.d.ts +5 -0
  162. package/bin/runners/runFix.js +6 -5
  163. package/bin/runners/runGuard.js +262 -168
  164. package/bin/runners/runInit.js +3 -2
  165. package/bin/runners/runMcp.js +130 -52
  166. package/bin/runners/runPolish.js +43 -20
  167. package/bin/runners/runProve.js +1 -2
  168. package/bin/runners/runReport.js +3 -2
  169. package/bin/runners/runScan.js +145 -44
  170. package/bin/runners/runShip.js +3 -4
  171. package/bin/runners/runTruth.d.ts +5 -0
  172. package/bin/runners/runValidate.js +19 -2
  173. package/bin/runners/runWatch.js +104 -53
  174. package/bin/vibecheck.js +106 -19
  175. package/mcp-server/HARDENING_SUMMARY.md +299 -0
  176. package/mcp-server/agent-firewall-interceptor.js +367 -31
  177. package/mcp-server/authority-tools.js +569 -0
  178. package/mcp-server/conductor/conflict-resolver.js +588 -0
  179. package/mcp-server/conductor/execution-planner.js +544 -0
  180. package/mcp-server/conductor/index.js +377 -0
  181. package/mcp-server/conductor/lock-manager.js +615 -0
  182. package/mcp-server/conductor/request-queue.js +550 -0
  183. package/mcp-server/conductor/session-manager.js +500 -0
  184. package/mcp-server/conductor/tools.js +510 -0
  185. package/mcp-server/index.js +1199 -208
  186. package/mcp-server/lib/api-client.cjs +305 -0
  187. package/mcp-server/lib/logger.cjs +30 -0
  188. package/mcp-server/logger.js +173 -0
  189. package/mcp-server/package.json +2 -2
  190. package/mcp-server/premium-tools.js +2 -2
  191. package/mcp-server/tier-auth.js +351 -136
  192. package/mcp-server/tools/index.js +72 -72
  193. package/mcp-server/truth-firewall-tools.js +145 -15
  194. package/mcp-server/vibecheck-tools.js +2 -2
  195. package/package.json +2 -3
  196. package/mcp-server/index.old.js +0 -4137
  197. package/mcp-server/package-lock.json +0 -165
@@ -18,10 +18,9 @@ const {
18
18
  generateRunId,
19
19
  createJsonOutput,
20
20
  writeJsonOutput,
21
- exitCodeToVerdict,
22
- verdictToExitCode,
23
21
  saveArtifact
24
22
  } = require("./lib/cli-output");
23
+ const { EXIT, verdictToExitCode, exitCodeToVerdict } = require("./lib/exit-codes");
25
24
 
26
25
  // Route Truth v1 - Fake endpoint detection
27
26
  const { buildTruthpack, writeTruthpack, detectFastifyEntry } = require("./lib/truth");
@@ -828,7 +827,7 @@ async function runShip(args, context = {}) {
828
827
  } catch (err) {
829
828
  if (err.code === 'LIMIT_EXCEEDED' || err.code === 'FEATURE_NOT_AVAILABLE') {
830
829
  console.error(`\n ${colors.error}${icons.error}${ansi.reset} ${err.upgradePrompt || err.message}\n`);
831
- return EXIT_CODES.WARN;
830
+ return EXIT.TIER_REQUIRED;
832
831
  }
833
832
  throw err;
834
833
  }
@@ -1131,7 +1130,7 @@ async function runShip(args, context = {}) {
1131
1130
  console.error(` ${ansi.dim}${error.stack}${ansi.reset}`);
1132
1131
  }
1133
1132
 
1134
- return EXIT_CODES.ERROR;
1133
+ return EXIT.INTERNAL_ERROR;
1135
1134
  }
1136
1135
  }
1137
1136
 
@@ -0,0 +1,5 @@
1
+ export interface TruthOptions {
2
+ projectRoot?: string;
3
+ verbose?: boolean;
4
+ }
5
+ export function runTruth(options?: TruthOptions): Promise<void>;
@@ -6,6 +6,9 @@ const fs = require("fs");
6
6
  const path = require("path");
7
7
  const { buildTruthpack } = require("./lib/truth");
8
8
  const { routeMatches } = require("./lib/claims");
9
+ const { EXIT } = require("./lib/exit-codes");
10
+ const { formatSoftUpsell, formatWorkflowUpsell, PRICING_URL } = require("./lib/upsell");
11
+ const { getApiKey } = require("./lib/auth");
9
12
 
10
13
  const c = {
11
14
  reset: "\x1b[0m",
@@ -133,12 +136,19 @@ async function runValidate(args) {
133
136
  }
134
137
 
135
138
  // Output results
139
+ const { key } = getApiKey();
140
+ const currentTier = key ? "starter" : "free";
141
+
136
142
  if (opts.json) {
137
143
  console.log(JSON.stringify({ issues, valid: issues.length === 0 }, null, 2));
138
144
  } else {
139
145
  if (issues.length === 0) {
140
146
  console.log(`${c.green}✓${c.reset} No hallucinations detected!\n`);
141
147
  console.log(` ${c.dim}All routes and env vars are properly defined.${c.reset}\n`);
148
+
149
+ // Workflow upsell
150
+ const workflow = formatWorkflowUpsell("validate", currentTier);
151
+ if (workflow) console.log(` ${workflow}\n`);
142
152
  } else {
143
153
  console.log(`${c.yellow}⚠${c.reset} Found ${issues.length} potential issues:\n`);
144
154
 
@@ -148,14 +158,21 @@ async function runValidate(args) {
148
158
  console.log(` ${c.dim}${issue.file}:${issue.line}${c.reset}`);
149
159
  }
150
160
  console.log();
161
+
162
+ // Upsell for auto-fix
163
+ if (currentTier === "free") {
164
+ console.log(` ${c.dim}─────────────────────────────────────────────────────────────${c.reset}`);
165
+ console.log(` ${c.cyan}★ STARTER${c.reset}${c.dim}: auto-fix hallucinations with vibecheck fix${c.reset}`);
166
+ console.log(` ${c.dim} Upgrade → ${PRICING_URL}${c.reset}\n`);
167
+ }
151
168
  }
152
169
  }
153
170
 
154
- return issues.some(i => i.severity === "error") ? 1 : 0;
171
+ return issues.some(i => i.severity === "error") ? EXIT.BLOCKING : EXIT.SUCCESS;
155
172
 
156
173
  } catch (error) {
157
174
  console.error(`${c.red}✗${c.reset} Validation failed: ${error.message}`);
158
- return 1;
175
+ return EXIT.INTERNAL_ERROR;
159
176
  }
160
177
  }
161
178
 
@@ -14,7 +14,8 @@
14
14
 
15
15
  const fs = require("fs");
16
16
  const path = require("path");
17
- const { parseGlobalFlags, shouldShowBanner } = require("./lib/global-flags");
17
+ const { parseGlobalFlags, shouldShowBanner, shouldSuppressOutput } = require("./lib/global-flags");
18
+ const { EXIT } = require("./lib/exit-codes");
18
19
  const { shipCore } = require("./runShip");
19
20
 
20
21
  // ═══════════════════════════════════════════════════════════════════════════════
@@ -331,12 +332,15 @@ function printHelp(opts = {}) {
331
332
  async function runWatch(argsOrOpts = {}) {
332
333
  // Handle array args from CLI
333
334
  let globalOpts = { noBanner: false, json: false, quiet: false, ci: false };
335
+ let rawArgs = [];
336
+
334
337
  if (Array.isArray(argsOrOpts)) {
338
+ rawArgs = argsOrOpts;
335
339
  const { flags } = parseGlobalFlags(argsOrOpts);
336
340
  globalOpts = { ...globalOpts, ...flags };
337
341
  if (globalOpts.help) {
338
342
  printHelp(globalOpts);
339
- return 0;
343
+ return EXIT.SUCCESS;
340
344
  }
341
345
  const getArg = (flags) => {
342
346
  for (const f of flags) {
@@ -346,10 +350,10 @@ async function runWatch(argsOrOpts = {}) {
346
350
  return undefined;
347
351
  };
348
352
  argsOrOpts = {
349
- repoRoot: process.cwd(),
353
+ repoRoot: globalOpts.path || process.cwd(),
350
354
  fastifyEntry: getArg(["--fastify-entry"]),
351
355
  debounceMs: parseInt(getArg(["--debounce"]) || "500", 10),
352
- clearScreen: !argsOrOpts.includes("--no-clear"),
356
+ clearScreen: !rawArgs.includes("--no-clear"),
353
357
  ...globalOpts,
354
358
  };
355
359
  }
@@ -358,70 +362,117 @@ async function runWatch(argsOrOpts = {}) {
358
362
  repoRoot,
359
363
  fastifyEntry,
360
364
  debounceMs = 500,
361
- clearScreen = true
365
+ clearScreen = true,
366
+ quiet,
362
367
  } = argsOrOpts;
363
368
 
364
369
  const root = repoRoot || process.cwd();
370
+ const suppress = shouldSuppressOutput(argsOrOpts);
371
+
372
+ // Validate project path exists
373
+ if (!fs.existsSync(root)) {
374
+ console.error(`${c.red}✗${c.reset} Project path does not exist: ${root}`);
375
+ console.log(` ${c.dim}Verify the path and try again.${c.reset}`);
376
+ return EXIT.NOT_FOUND;
377
+ }
378
+
379
+ // Validate debounce is a valid number
380
+ if (isNaN(debounceMs) || debounceMs < 0) {
381
+ console.error(`${c.red}✗${c.reset} Invalid debounce value: ${debounceMs}`);
382
+ console.log(` ${c.dim}Debounce must be a positive number in milliseconds.${c.reset}`);
383
+ return EXIT.USER_ERROR;
384
+ }
385
+
365
386
  let runCount = 0;
366
387
  let lastFile = null;
388
+ let watcher = null;
389
+ let exitCode = EXIT.SUCCESS;
367
390
 
368
- console.log(`${c.cyan}Starting vibecheck watch...${c.reset}\n`);
369
-
370
- async function runAndDisplay() {
371
- runCount++;
372
-
373
- if (clearScreen) {
374
- process.stdout.write(c.clear);
391
+ try {
392
+ if (!suppress) {
393
+ console.log(`${c.cyan}Starting vibecheck watch...${c.reset}\n`);
375
394
  }
376
395
 
377
- const result = await runShipQuiet(root, fastifyEntry);
396
+ async function runAndDisplay() {
397
+ runCount++;
398
+
399
+ if (clearScreen && !suppress) {
400
+ process.stdout.write(c.clear);
401
+ }
402
+
403
+ try {
404
+ const result = await runShipQuiet(root, fastifyEntry);
378
405
 
379
- if (result.error) {
380
- console.log(`${c.red}Error: ${result.error}${c.reset}`);
381
- return;
406
+ if (result.error) {
407
+ if (!suppress) {
408
+ console.log(`${c.red}Error: ${result.error}${c.reset}`);
409
+ console.log(` ${c.dim}Will retry on next file change.${c.reset}`);
410
+ }
411
+ return;
412
+ }
413
+
414
+ if (!suppress) {
415
+ printStatus({
416
+ verdict: result.verdict,
417
+ findings: result.findings,
418
+ duration: result.duration,
419
+ lastFile,
420
+ runCount
421
+ });
422
+
423
+ printTopFindings(result.findings);
424
+ }
425
+ } catch (e) {
426
+ if (!suppress) {
427
+ console.log(`${c.red}Analysis error: ${e.message}${c.reset}`);
428
+ }
429
+ }
382
430
  }
383
431
 
384
- printStatus({
385
- verdict: result.verdict,
386
- findings: result.findings,
387
- duration: result.duration,
388
- lastFile,
389
- runCount
432
+ // Initial run
433
+ await runAndDisplay();
434
+
435
+ // Watch for changes
436
+ const debouncedRun = debounce(async (filePath) => {
437
+ lastFile = path.relative(root, filePath);
438
+ await runAndDisplay();
439
+ }, debounceMs);
440
+
441
+ watcher = watchDirectory(root, (filePath) => {
442
+ // Only watch source files
443
+ if (!/\.(ts|tsx|js|jsx|json|env|md|yml|yaml)$/.test(filePath)) return;
444
+ if (shouldIgnore(filePath)) return;
445
+ debouncedRun(filePath);
390
446
  });
391
447
 
392
- printTopFindings(result.findings);
393
- }
448
+ // Handle cleanup - store cleanup function for signal handlers
449
+ const cleanup = () => {
450
+ if (watcher) {
451
+ watcher.close();
452
+ watcher = null;
453
+ }
454
+ };
394
455
 
395
- // Initial run
396
- await runAndDisplay();
456
+ process.on("SIGINT", () => {
457
+ if (!suppress) {
458
+ console.log(`\n${c.dim}Watch stopped.${c.reset}`);
459
+ }
460
+ cleanup();
461
+ process.exit(EXIT.SUCCESS);
462
+ });
397
463
 
398
- // Watch for changes
399
- const debouncedRun = debounce(async (filePath) => {
400
- lastFile = path.relative(root, filePath);
401
- await runAndDisplay();
402
- }, debounceMs);
403
-
404
- const watcher = watchDirectory(root, (filePath) => {
405
- // Only watch source files
406
- if (!/\.(ts|tsx|js|jsx|json|env|md|yml|yaml)$/.test(filePath)) return;
407
- if (shouldIgnore(filePath)) return;
408
- debouncedRun(filePath);
409
- });
410
-
411
- // Handle cleanup
412
- process.on("SIGINT", () => {
413
- console.log(`\n${c.dim}Watch stopped.${c.reset}`);
414
- watcher.close();
415
- process.exit(0);
416
- });
417
-
418
- process.on("SIGTERM", () => {
419
- watcher.close();
420
- process.exit(0);
421
- });
422
-
423
- // Keep process alive
424
- await new Promise(() => {});
464
+ process.on("SIGTERM", () => {
465
+ cleanup();
466
+ process.exit(EXIT.SUCCESS);
467
+ });
468
+
469
+ // Keep process alive
470
+ await new Promise(() => {});
471
+ } catch (error) {
472
+ console.error(`${c.red}✗${c.reset} Watch failed: ${error.message}`);
473
+ if (watcher) watcher.close();
474
+ return EXIT.INTERNAL_ERROR;
475
+ }
425
476
  }
426
477
 
427
478
  module.exports = { runWatch };
package/bin/vibecheck.js CHANGED
@@ -795,7 +795,7 @@ ${c.bold}Installation:${c.reset}
795
795
  }
796
796
 
797
797
  // ═══════════════════════════════════════════════════════════════════════════════
798
- // HELP SYSTEM
798
+ // HELP SYSTEM - World-Class CLI Experience
799
799
  // ═══════════════════════════════════════════════════════════════════════════════
800
800
  function printBanner() {
801
801
  const VERSION = getVersion();
@@ -807,6 +807,72 @@ ${c.dim}${sym.boxBottomLeft}${sym.boxHorizontal.repeat(60)}${sym.boxBottomRight}
807
807
  `);
808
808
  }
809
809
 
810
+ /**
811
+ * Print command-specific help with rich examples
812
+ */
813
+ function printCommandHelp(cmd) {
814
+ const registry = getRegistry();
815
+ const def = registry.COMMANDS[cmd];
816
+ if (!def) return false;
817
+
818
+ // Build reverse alias map
819
+ const reverseAliases = {};
820
+ for (const [alias, target] of Object.entries(registry.ALIAS_MAP)) {
821
+ if (!reverseAliases[target]) reverseAliases[target] = [];
822
+ reverseAliases[target].push(alias);
823
+ }
824
+
825
+ const aliases = reverseAliases[cmd] || [];
826
+
827
+ // Tier badge
828
+ const tierBadge = def.tier === "free" ? `${c.green}[FREE]${c.reset}` :
829
+ def.tier === "starter" ? `${c.cyan}[STARTER]${c.reset}` :
830
+ def.tier === "pro" ? `${c.magenta}[PRO]${c.reset}` : "";
831
+
832
+ console.log(`
833
+ ${c.bold}${sym.arrowRight} vibecheck ${cmd}${c.reset} ${tierBadge}
834
+ ${aliases.length > 0 ? `${c.dim}Aliases: ${aliases.join(", ")}${c.reset}` : ""}
835
+
836
+ ${def.longDescription || def.description}
837
+ `);
838
+
839
+ // Examples
840
+ if (def.examples && def.examples.length > 0) {
841
+ console.log(` ${c.bold}${sym.star} EXAMPLES${c.reset}\n`);
842
+ for (const ex of def.examples) {
843
+ const exTier = ex.tier ? (ex.tier === "starter" ? `${c.cyan}[STARTER]${c.reset} ` :
844
+ ex.tier === "pro" ? `${c.magenta}[PRO]${c.reset} ` : "") : "";
845
+ console.log(` ${c.dim}#${c.reset} ${ex.description} ${exTier}`);
846
+ console.log(` ${c.cyan}${ex.command}${c.reset}`);
847
+ console.log();
848
+ }
849
+ }
850
+
851
+ // Related commands
852
+ if (def.related && def.related.length > 0) {
853
+ console.log(` ${c.bold}${sym.arrowRight} RELATED COMMANDS${c.reset}\n`);
854
+ for (const relCmd of def.related) {
855
+ const relDef = registry.COMMANDS[relCmd];
856
+ if (relDef) {
857
+ const relTier = relDef.tier === "starter" ? `${c.cyan}[STARTER]${c.reset} ` :
858
+ relDef.tier === "pro" ? `${c.magenta}[PRO]${c.reset} ` : "";
859
+ console.log(` ${c.cyan}vibecheck ${relCmd}${c.reset} ${relTier}${c.dim}${relDef.description}${c.reset}`);
860
+ }
861
+ }
862
+ console.log();
863
+ }
864
+
865
+ // Documentation link
866
+ if (def.docsUrl) {
867
+ console.log(` ${c.dim}${sym.boxHorizontal.repeat(56)}${c.reset}`);
868
+ console.log(` ${c.dim}Documentation: ${c.underline}${def.docsUrl}${c.reset}`);
869
+ }
870
+
871
+ console.log(` ${c.dim}Run 'vibecheck --help' for all commands.${c.reset}\n`);
872
+
873
+ return true;
874
+ }
875
+
810
876
  function printHelp(showBanner = true) {
811
877
  if (showBanner) printBanner();
812
878
 
@@ -874,35 +940,48 @@ function printHelp(showBanner = true) {
874
940
  console.log(`
875
941
  ${c.dim}${sym.boxHorizontal.repeat(64)}${c.reset}
876
942
 
877
- ${c.green}TIERS${c.reset}
943
+ ${c.green}${sym.star} PRICING TIERS${c.reset}
878
944
 
879
- ${c.green}FREE${c.reset} $0 init --local, scan, ship (static), report (HTML/MD), doctor, polish
880
- ${c.cyan}STARTER${c.reset} $39/mo + init --connect, scan --autofix, report (SARIF/CSV), mcp, PR comments
881
- ${c.magenta}PRO${c.reset} $99/mo + prove, fix --apply, checkpoint (hallucination), reality (advanced)
945
+ ${c.green}FREE${c.reset} ${c.dim}$0${c.reset} Core scanning, shipping verdicts, health checks
946
+ ${c.cyan}STARTER${c.reset} ${c.dim}$39/mo${c.reset} + AI fixes, reports, IDE rules, MCP server
947
+ ${c.magenta}PRO${c.reset} ${c.dim}$99/mo${c.reset} + Reality proof, video evidence, AI testing
882
948
 
883
- ${c.green}QUICK START - The 5-Step Journey${c.reset}
949
+ ${c.green}${sym.rocket} QUICK START${c.reset}
884
950
 
885
- 1. ${c.bold}Setup${c.reset} ${c.cyan}vibecheck init --local${c.reset}
886
- 2. ${c.bold}Scan${c.reset} ${c.cyan}vibecheck scan${c.reset}
887
- 3. ${c.bold}Fix${c.reset} ${c.cyan}vibecheck scan --autofix${c.reset} ${c.cyan}[STARTER]${c.reset}
888
- 4. ${c.bold}Prove${c.reset} ${c.cyan}vibecheck prove${c.reset} ${c.magenta}[PRO]${c.reset}
889
- 5. ${c.bold}Ship${c.reset} ${c.cyan}vibecheck ship${c.reset}
951
+ ${c.bold}1.${c.reset} ${c.cyan}vibecheck init${c.reset} ${c.dim}Set up your project${c.reset}
952
+ ${c.bold}2.${c.reset} ${c.cyan}vibecheck scan${c.reset} ${c.dim}Analyze your codebase${c.reset}
953
+ ${c.bold}3.${c.reset} ${c.cyan}vibecheck ship${c.reset} ${c.dim}Get shipping verdict${c.reset}
954
+
955
+ ${c.green}${sym.lightning} COMMON WORKFLOWS${c.reset}
956
+
957
+ ${c.dim}# Quick health check${c.reset}
958
+ ${c.cyan}vibecheck doctor${c.reset}
959
+
960
+ ${c.dim}# Scan and auto-fix${c.reset}
961
+ ${c.cyan}vibecheck scan --autofix${c.reset}
962
+
963
+ ${c.dim}# Full proof with evidence pack${c.reset}
964
+ ${c.cyan}vibecheck prove --url http://localhost:3000 --bundle${c.reset}
890
965
 
891
966
  ${c.bold}GLOBAL OPTIONS${c.reset}
892
967
 
893
- ${c.cyan}--offline, --local${c.reset} Run in offline mode (no API, unlimited local scans)
894
- ${c.cyan}--json${c.reset} Output as JSON
895
- ${c.cyan}--quiet, -q${c.reset} Suppress output
896
- ${c.cyan}--verbose${c.reset} Show detailed output
968
+ ${c.cyan}--help, -h${c.reset} Show help for any command
969
+ ${c.cyan}--json${c.reset} Machine-readable JSON output
970
+ ${c.cyan}--quiet, -q${c.reset} Suppress non-essential output
971
+ ${c.cyan}--verbose${c.reset} Detailed output for debugging
972
+ ${c.cyan}--ci${c.reset} CI mode (quiet + no-banner)
973
+ ${c.cyan}--offline${c.reset} Run without API connection
897
974
  ${c.cyan}--path, -p <dir>${c.reset} Run in specified directory
898
975
 
899
976
  ${c.bold}SHELL COMPLETIONS${c.reset}
900
977
 
901
- ${c.cyan}vibecheck completion bash${c.reset} ${c.dim}# Add to ~/.bashrc${c.reset}
902
- ${c.cyan}vibecheck completion zsh${c.reset} ${c.dim}# Add to ~/.zshrc${c.reset}
903
- ${c.cyan}vibecheck completion fish${c.reset} ${c.dim}# Save to completions dir${c.reset}
978
+ ${c.cyan}vibecheck completion bash${c.reset} ${c.dim}# Bash (add to ~/.bashrc)${c.reset}
979
+ ${c.cyan}vibecheck completion zsh${c.reset} ${c.dim}# Zsh (add to ~/.zshrc)${c.reset}
980
+ ${c.cyan}vibecheck completion fish${c.reset} ${c.dim}# Fish (save to completions)${c.reset}
904
981
 
905
- ${c.dim}Run 'vibecheck <command> --help' for command-specific help.${c.reset}
982
+ ${c.dim}${sym.boxHorizontal.repeat(64)}${c.reset}
983
+ ${c.dim}Run 'vibecheck <command> --help' for detailed command help.${c.reset}
984
+ ${c.dim}Documentation: https://docs.vibecheckai.dev${c.reset}
906
985
  ${c.dim}Pricing: https://vibecheckai.dev/pricing${c.reset}
907
986
  `);
908
987
  }
@@ -1074,6 +1153,14 @@ async function main() {
1074
1153
  }
1075
1154
  let cmdArgs = cleanArgs.slice(1);
1076
1155
 
1156
+ // Handle command-specific help (vibecheck <cmd> --help)
1157
+ if (globalFlags.help && cmd && COMMANDS[cmd]) {
1158
+ // Try our rich help first, then fall back to runner's --help
1159
+ if (printCommandHelp(cmd)) {
1160
+ process.exit(0);
1161
+ }
1162
+ }
1163
+
1077
1164
  // Pass --help to runner if specified with command
1078
1165
  if (globalFlags.help) cmdArgs = ["--help", ...cmdArgs];
1079
1166