@vibecheckai/cli 3.5.0 → 3.5.2
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/registry.js +214 -237
- package/bin/runners/cli-utils.js +33 -2
- package/bin/runners/context/analyzer.js +52 -1
- package/bin/runners/context/generators/cursor.js +2 -49
- package/bin/runners/context/git-context.js +3 -1
- package/bin/runners/context/team-conventions.js +33 -7
- package/bin/runners/lib/analysis-core.js +25 -5
- package/bin/runners/lib/analyzers.js +431 -481
- package/bin/runners/lib/default-config.js +127 -0
- package/bin/runners/lib/doctor/modules/security.js +3 -1
- package/bin/runners/lib/engine/ast-cache.js +210 -0
- package/bin/runners/lib/engine/auth-extractor.js +211 -0
- package/bin/runners/lib/engine/billing-extractor.js +112 -0
- package/bin/runners/lib/engine/enforcement-extractor.js +100 -0
- package/bin/runners/lib/engine/env-extractor.js +207 -0
- package/bin/runners/lib/engine/express-extractor.js +208 -0
- package/bin/runners/lib/engine/extractors.js +849 -0
- package/bin/runners/lib/engine/index.js +207 -0
- package/bin/runners/lib/engine/repo-index.js +514 -0
- package/bin/runners/lib/engine/types.js +124 -0
- package/bin/runners/lib/engines/accessibility-engine.js +18 -218
- package/bin/runners/lib/engines/api-consistency-engine.js +30 -335
- package/bin/runners/lib/engines/cross-file-analysis-engine.js +27 -292
- package/bin/runners/lib/engines/empty-catch-engine.js +17 -127
- package/bin/runners/lib/engines/mock-data-engine.js +10 -53
- package/bin/runners/lib/engines/performance-issues-engine.js +36 -176
- package/bin/runners/lib/engines/security-vulnerabilities-engine.js +54 -382
- package/bin/runners/lib/engines/type-aware-engine.js +39 -263
- package/bin/runners/lib/engines/vibecheck-engines/index.js +13 -122
- package/bin/runners/lib/engines/vibecheck-engines/lib/ast-cache.js +164 -0
- package/bin/runners/lib/engines/vibecheck-engines/lib/code-quality-engine.js +291 -0
- package/bin/runners/lib/engines/vibecheck-engines/lib/console-logs-engine.js +83 -0
- package/bin/runners/lib/engines/vibecheck-engines/lib/dead-code-engine.js +198 -0
- package/bin/runners/lib/engines/vibecheck-engines/lib/deprecated-api-engine.js +275 -0
- package/bin/runners/lib/engines/vibecheck-engines/lib/empty-catch-engine.js +167 -0
- package/bin/runners/lib/engines/vibecheck-engines/lib/file-filter.js +217 -0
- package/bin/runners/lib/engines/vibecheck-engines/lib/hardcoded-secrets-engine.js +73 -373
- package/bin/runners/lib/engines/vibecheck-engines/lib/mock-data-engine.js +140 -0
- package/bin/runners/lib/engines/vibecheck-engines/lib/parallel-processor.js +164 -0
- package/bin/runners/lib/engines/vibecheck-engines/lib/performance-issues-engine.js +234 -0
- package/bin/runners/lib/engines/vibecheck-engines/lib/type-aware-engine.js +217 -0
- package/bin/runners/lib/engines/vibecheck-engines/lib/unsafe-regex-engine.js +78 -0
- package/bin/runners/lib/entitlements-v2.js +73 -97
- package/bin/runners/lib/error-handler.js +44 -3
- package/bin/runners/lib/error-messages.js +289 -0
- package/bin/runners/lib/evidence-pack.js +7 -1
- package/bin/runners/lib/finding-id.js +69 -0
- package/bin/runners/lib/finding-sorter.js +89 -0
- package/bin/runners/lib/html-proof-report.js +700 -350
- package/bin/runners/lib/missions/plan.js +6 -46
- package/bin/runners/lib/missions/templates.js +0 -232
- package/bin/runners/lib/next-action.js +560 -0
- package/bin/runners/lib/prerequisites.js +149 -0
- package/bin/runners/lib/route-detection.js +137 -68
- package/bin/runners/lib/scan-output.js +91 -76
- package/bin/runners/lib/scan-runner.js +135 -0
- package/bin/runners/lib/schemas/ajv-validator.js +464 -0
- package/bin/runners/lib/schemas/error-envelope.schema.json +105 -0
- package/bin/runners/lib/schemas/finding-v3.schema.json +151 -0
- package/bin/runners/lib/schemas/report-artifact.schema.json +120 -0
- package/bin/runners/lib/schemas/run-request.schema.json +108 -0
- package/bin/runners/lib/schemas/validator.js +27 -0
- package/bin/runners/lib/schemas/verdict.schema.json +140 -0
- package/bin/runners/lib/ship-output-enterprise.js +23 -23
- package/bin/runners/lib/ship-output.js +75 -31
- package/bin/runners/lib/terminal-ui.js +6 -113
- package/bin/runners/lib/truth.js +351 -10
- package/bin/runners/lib/unified-cli-output.js +430 -603
- package/bin/runners/lib/unified-output.js +13 -9
- package/bin/runners/runAIAgent.js +10 -5
- package/bin/runners/runAgent.js +0 -3
- package/bin/runners/runAllowlist.js +389 -0
- package/bin/runners/runApprove.js +0 -33
- package/bin/runners/runAuth.js +73 -45
- package/bin/runners/runCheckpoint.js +51 -11
- package/bin/runners/runClassify.js +85 -21
- package/bin/runners/runContext.js +0 -3
- package/bin/runners/runDoctor.js +41 -28
- package/bin/runners/runEvidencePack.js +362 -0
- package/bin/runners/runFirewall.js +0 -3
- package/bin/runners/runFirewallHook.js +0 -3
- package/bin/runners/runFix.js +66 -76
- package/bin/runners/runGuard.js +18 -411
- package/bin/runners/runInit.js +113 -30
- package/bin/runners/runLabs.js +424 -0
- package/bin/runners/runMcp.js +19 -25
- package/bin/runners/runPolish.js +64 -240
- package/bin/runners/runPromptFirewall.js +12 -5
- package/bin/runners/runProve.js +57 -22
- package/bin/runners/runQuickstart.js +531 -0
- package/bin/runners/runReality.js +59 -68
- package/bin/runners/runReport.js +38 -33
- package/bin/runners/runRuntime.js +8 -5
- package/bin/runners/runScan.js +1413 -190
- package/bin/runners/runShip.js +113 -719
- package/bin/runners/runTruth.js +0 -3
- package/bin/runners/runValidate.js +13 -9
- package/bin/runners/runWatch.js +23 -14
- package/bin/scan.js +6 -1
- package/bin/vibecheck.js +204 -185
- package/mcp-server/deprecation-middleware.js +282 -0
- package/mcp-server/handlers/index.ts +15 -0
- package/mcp-server/handlers/tool-handler.ts +554 -0
- package/mcp-server/index-v1.js +698 -0
- package/mcp-server/index.js +210 -238
- package/mcp-server/lib/cache-wrapper.cjs +383 -0
- package/mcp-server/lib/error-envelope.js +138 -0
- package/mcp-server/lib/executor.ts +499 -0
- package/mcp-server/lib/index.ts +19 -0
- package/mcp-server/lib/rate-limiter.js +166 -0
- package/mcp-server/lib/sandbox.test.ts +519 -0
- package/mcp-server/lib/sandbox.ts +395 -0
- package/mcp-server/lib/types.ts +267 -0
- package/mcp-server/package.json +12 -3
- package/mcp-server/registry/tool-registry.js +794 -0
- package/mcp-server/registry/tools.json +605 -0
- package/mcp-server/registry.test.ts +334 -0
- package/mcp-server/tests/tier-gating.test.js +297 -0
- package/mcp-server/tier-auth.js +378 -45
- package/mcp-server/tools-v3.js +353 -442
- package/mcp-server/tsconfig.json +37 -0
- package/mcp-server/vibecheck-2.0-tools.js +14 -1
- package/package.json +1 -1
- package/bin/runners/lib/agent-firewall/learning/learning-engine.js +0 -849
- package/bin/runners/lib/audit-logger.js +0 -532
- package/bin/runners/lib/authority/authorities/architecture.js +0 -364
- package/bin/runners/lib/authority/authorities/compliance.js +0 -341
- package/bin/runners/lib/authority/authorities/human.js +0 -343
- package/bin/runners/lib/authority/authorities/quality.js +0 -420
- package/bin/runners/lib/authority/authorities/security.js +0 -228
- package/bin/runners/lib/authority/index.js +0 -293
- package/bin/runners/lib/bundle/bundle-intelligence.js +0 -846
- package/bin/runners/lib/cli-charts.js +0 -368
- package/bin/runners/lib/cli-config-display.js +0 -405
- package/bin/runners/lib/cli-demo.js +0 -275
- package/bin/runners/lib/cli-errors.js +0 -438
- package/bin/runners/lib/cli-help-formatter.js +0 -439
- package/bin/runners/lib/cli-interactive-menu.js +0 -509
- package/bin/runners/lib/cli-prompts.js +0 -441
- package/bin/runners/lib/cli-scan-cards.js +0 -362
- package/bin/runners/lib/compliance-reporter.js +0 -710
- package/bin/runners/lib/conductor/index.js +0 -671
- package/bin/runners/lib/easy/README.md +0 -123
- package/bin/runners/lib/easy/index.js +0 -140
- package/bin/runners/lib/easy/interactive-wizard.js +0 -788
- package/bin/runners/lib/easy/one-click-firewall.js +0 -564
- package/bin/runners/lib/easy/zero-config-reality.js +0 -714
- package/bin/runners/lib/engines/async-patterns-engine.js +0 -444
- package/bin/runners/lib/engines/bundle-size-engine.js +0 -433
- package/bin/runners/lib/engines/confidence-scoring.js +0 -276
- package/bin/runners/lib/engines/context-detection.js +0 -264
- package/bin/runners/lib/engines/database-patterns-engine.js +0 -429
- package/bin/runners/lib/engines/duplicate-code-engine.js +0 -354
- package/bin/runners/lib/engines/env-variables-engine.js +0 -458
- package/bin/runners/lib/engines/error-handling-engine.js +0 -437
- package/bin/runners/lib/engines/false-positive-prevention.js +0 -630
- package/bin/runners/lib/engines/framework-adapters/index.js +0 -607
- package/bin/runners/lib/engines/framework-detection.js +0 -508
- package/bin/runners/lib/engines/import-order-engine.js +0 -429
- package/bin/runners/lib/engines/naming-conventions-engine.js +0 -544
- package/bin/runners/lib/engines/noise-reduction-engine.js +0 -452
- package/bin/runners/lib/engines/orchestrator.js +0 -334
- package/bin/runners/lib/engines/react-patterns-engine.js +0 -457
- package/bin/runners/lib/engines/vibecheck-engines/lib/ai-hallucination-engine.js +0 -806
- package/bin/runners/lib/engines/vibecheck-engines/lib/smart-fix-engine.js +0 -577
- package/bin/runners/lib/engines/vibecheck-engines/lib/vibe-score-engine.js +0 -543
- package/bin/runners/lib/engines/vibecheck-engines.js +0 -514
- package/bin/runners/lib/enhanced-features/index.js +0 -305
- package/bin/runners/lib/enhanced-output.js +0 -631
- package/bin/runners/lib/enterprise.js +0 -300
- package/bin/runners/lib/firewall/command-validator.js +0 -351
- package/bin/runners/lib/firewall/config.js +0 -341
- package/bin/runners/lib/firewall/content-validator.js +0 -519
- package/bin/runners/lib/firewall/index.js +0 -101
- package/bin/runners/lib/firewall/path-validator.js +0 -256
- package/bin/runners/lib/intelligence/cross-repo-intelligence.js +0 -817
- package/bin/runners/lib/mcp-utils.js +0 -425
- package/bin/runners/lib/output/index.js +0 -1022
- package/bin/runners/lib/policy-engine.js +0 -652
- package/bin/runners/lib/polish/autofix/accessibility-fixes.js +0 -333
- package/bin/runners/lib/polish/autofix/async-handlers.js +0 -273
- package/bin/runners/lib/polish/autofix/dead-code.js +0 -280
- package/bin/runners/lib/polish/autofix/imports-optimizer.js +0 -344
- package/bin/runners/lib/polish/autofix/index.js +0 -200
- package/bin/runners/lib/polish/autofix/remove-consoles.js +0 -209
- package/bin/runners/lib/polish/autofix/strengthen-types.js +0 -245
- package/bin/runners/lib/polish/backend-checks.js +0 -148
- package/bin/runners/lib/polish/documentation-checks.js +0 -111
- package/bin/runners/lib/polish/frontend-checks.js +0 -168
- package/bin/runners/lib/polish/index.js +0 -71
- package/bin/runners/lib/polish/infrastructure-checks.js +0 -131
- package/bin/runners/lib/polish/library-detection.js +0 -175
- package/bin/runners/lib/polish/performance-checks.js +0 -100
- package/bin/runners/lib/polish/security-checks.js +0 -148
- package/bin/runners/lib/polish/utils.js +0 -203
- package/bin/runners/lib/prompt-builder.js +0 -540
- package/bin/runners/lib/proof-certificate.js +0 -634
- package/bin/runners/lib/reality/accessibility-audit.js +0 -946
- package/bin/runners/lib/reality/api-contract-validator.js +0 -1012
- package/bin/runners/lib/reality/chaos-engineering.js +0 -1084
- package/bin/runners/lib/reality/performance-tracker.js +0 -1077
- package/bin/runners/lib/reality/scenario-generator.js +0 -1404
- package/bin/runners/lib/reality/visual-regression.js +0 -852
- package/bin/runners/lib/reality-profiler.js +0 -717
- package/bin/runners/lib/replay/flight-recorder-viewer.js +0 -1160
- package/bin/runners/lib/review/ai-code-review.js +0 -832
- package/bin/runners/lib/rules/custom-rule-engine.js +0 -985
- package/bin/runners/lib/sbom-generator.js +0 -641
- package/bin/runners/lib/scan-output-enhanced.js +0 -512
- package/bin/runners/lib/security/owasp-scanner.js +0 -939
- package/bin/runners/lib/validators/contract-validator.js +0 -283
- package/bin/runners/lib/validators/dead-export-detector.js +0 -279
- package/bin/runners/lib/validators/dep-audit.js +0 -245
- package/bin/runners/lib/validators/env-validator.js +0 -319
- package/bin/runners/lib/validators/index.js +0 -120
- package/bin/runners/lib/validators/license-checker.js +0 -252
- package/bin/runners/lib/validators/route-validator.js +0 -290
- package/bin/runners/runAuthority.js +0 -528
- package/bin/runners/runConductor.js +0 -772
- package/bin/runners/runContainer.js +0 -366
- package/bin/runners/runEasy.js +0 -410
- package/bin/runners/runIaC.js +0 -372
- package/bin/runners/runVibe.js +0 -791
- package/mcp-server/tools.js +0 -495
package/bin/runners/runTruth.js
CHANGED
|
@@ -11,9 +11,6 @@ const fs = require("fs");
|
|
|
11
11
|
const path = require("path");
|
|
12
12
|
const { buildTruthpackV2 } = require("./lib/extractors/truthpack-v2");
|
|
13
13
|
|
|
14
|
-
// Unified Output System
|
|
15
|
-
const { output } = require("./lib/output/index.js");
|
|
16
|
-
|
|
17
14
|
/**
|
|
18
15
|
* Run truth command
|
|
19
16
|
* @param {object} options - Command options
|
|
@@ -4,17 +4,21 @@
|
|
|
4
4
|
|
|
5
5
|
const fs = require("fs");
|
|
6
6
|
const path = require("path");
|
|
7
|
-
const {
|
|
7
|
+
const { buildTruthpackSmart } = require("./lib/truth");
|
|
8
8
|
const { routeMatches } = require("./lib/claims");
|
|
9
9
|
const { EXIT } = require("./lib/exit-codes");
|
|
10
10
|
const { formatSoftUpsell, formatWorkflowUpsell, PRICING_URL } = require("./lib/upsell");
|
|
11
11
|
const { getApiKey } = require("./lib/auth");
|
|
12
12
|
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
13
|
+
const c = {
|
|
14
|
+
reset: "\x1b[0m",
|
|
15
|
+
bold: "\x1b[1m",
|
|
16
|
+
dim: "\x1b[2m",
|
|
17
|
+
green: "\x1b[32m",
|
|
18
|
+
yellow: "\x1b[33m",
|
|
19
|
+
red: "\x1b[31m",
|
|
20
|
+
cyan: "\x1b[36m",
|
|
21
|
+
};
|
|
18
22
|
|
|
19
23
|
function parseArgs(args) {
|
|
20
24
|
const opts = {
|
|
@@ -87,7 +91,7 @@ async function runValidate(args) {
|
|
|
87
91
|
|
|
88
92
|
try {
|
|
89
93
|
// Build truthpack for validation
|
|
90
|
-
const truthpack = await
|
|
94
|
+
const truthpack = await buildTruthpackSmart({ repoRoot: projectPath });
|
|
91
95
|
|
|
92
96
|
const issues = [];
|
|
93
97
|
|
|
@@ -133,7 +137,7 @@ async function runValidate(args) {
|
|
|
133
137
|
|
|
134
138
|
// Output results
|
|
135
139
|
const { key } = getApiKey();
|
|
136
|
-
const currentTier = key ? "
|
|
140
|
+
const currentTier = key ? "starter" : "free";
|
|
137
141
|
|
|
138
142
|
if (opts.json) {
|
|
139
143
|
console.log(JSON.stringify({ issues, valid: issues.length === 0 }, null, 2));
|
|
@@ -158,7 +162,7 @@ async function runValidate(args) {
|
|
|
158
162
|
// Upsell for auto-fix
|
|
159
163
|
if (currentTier === "free") {
|
|
160
164
|
console.log(` ${c.dim}─────────────────────────────────────────────────────────────${c.reset}`);
|
|
161
|
-
console.log(` ${c.
|
|
165
|
+
console.log(` ${c.cyan}★ STARTER${c.reset}${c.dim}: auto-fix hallucinations with vibecheck fix${c.reset}`);
|
|
162
166
|
console.log(` ${c.dim} Upgrade → ${PRICING_URL}${c.reset}\n`);
|
|
163
167
|
}
|
|
164
168
|
}
|
package/bin/runners/runWatch.js
CHANGED
|
@@ -19,15 +19,32 @@ const { EXIT } = require("./lib/exit-codes");
|
|
|
19
19
|
const { shipCore } = require("./runShip");
|
|
20
20
|
|
|
21
21
|
// ═══════════════════════════════════════════════════════════════════════════════
|
|
22
|
-
// TERMINAL
|
|
22
|
+
// ADVANCED TERMINAL - ANSI CODES & UTILITIES
|
|
23
23
|
// ═══════════════════════════════════════════════════════════════════════════════
|
|
24
24
|
|
|
25
|
-
const
|
|
25
|
+
const c = {
|
|
26
|
+
reset: '\x1b[0m',
|
|
27
|
+
bold: '\x1b[1m',
|
|
28
|
+
dim: '\x1b[2m',
|
|
29
|
+
italic: '\x1b[3m',
|
|
30
|
+
underline: '\x1b[4m',
|
|
31
|
+
red: '\x1b[31m',
|
|
32
|
+
green: '\x1b[32m',
|
|
33
|
+
yellow: '\x1b[33m',
|
|
34
|
+
blue: '\x1b[34m',
|
|
35
|
+
magenta: '\x1b[35m',
|
|
36
|
+
cyan: '\x1b[36m',
|
|
37
|
+
white: '\x1b[37m',
|
|
38
|
+
gray: '\x1b[90m',
|
|
39
|
+
clear: '\x1b[2J\x1b[H',
|
|
40
|
+
clearLine: '\x1b[2K',
|
|
41
|
+
hideCursor: '\x1b[?25l',
|
|
42
|
+
showCursor: '\x1b[?25h',
|
|
43
|
+
};
|
|
26
44
|
|
|
27
|
-
|
|
28
|
-
const
|
|
45
|
+
const rgb = (r, g, b) => `\x1b[38;2;${r};${g};${b}m`;
|
|
46
|
+
const bgRgb = (r, g, b) => `\x1b[48;2;${r};${g};${b}m`;
|
|
29
47
|
|
|
30
|
-
// Extended color palette for watch command
|
|
31
48
|
const colors = {
|
|
32
49
|
gradient1: rgb(150, 100, 255),
|
|
33
50
|
gradient2: rgb(130, 80, 255),
|
|
@@ -206,7 +223,7 @@ function printTopFindings(findings, max = 5) {
|
|
|
206
223
|
const blockers = findings.filter(f => f.severity === "BLOCK").length;
|
|
207
224
|
if (blockers > 0) {
|
|
208
225
|
console.log();
|
|
209
|
-
console.log(` ${colors.cyan}→${c.reset} ${c.dim}Fix these with${c.reset} ${colors.cyan}vibecheck fix${c.reset} ${c.dim}(
|
|
226
|
+
console.log(` ${colors.cyan}→${c.reset} ${c.dim}Fix these with${c.reset} ${colors.cyan}vibecheck fix${c.reset} ${c.dim}(STARTER)${c.reset}`);
|
|
210
227
|
}
|
|
211
228
|
console.log();
|
|
212
229
|
}
|
|
@@ -321,14 +338,6 @@ async function runWatch(argsOrOpts = {}) {
|
|
|
321
338
|
rawArgs = argsOrOpts;
|
|
322
339
|
const { flags } = parseGlobalFlags(argsOrOpts);
|
|
323
340
|
globalOpts = { ...globalOpts, ...flags };
|
|
324
|
-
|
|
325
|
-
// Configure unified output mode
|
|
326
|
-
output.setMode({
|
|
327
|
-
json: globalOpts.json,
|
|
328
|
-
quiet: globalOpts.quiet,
|
|
329
|
-
ci: globalOpts.ci
|
|
330
|
-
});
|
|
331
|
-
|
|
332
341
|
if (globalOpts.help) {
|
|
333
342
|
printHelp(globalOpts);
|
|
334
343
|
return EXIT.SUCCESS;
|
package/bin/scan.js
CHANGED
|
@@ -47,7 +47,12 @@ function getScanHistory(projectPath) {
|
|
|
47
47
|
if (fs.existsSync(historyFile)) {
|
|
48
48
|
return JSON.parse(fs.readFileSync(historyFile, "utf8"));
|
|
49
49
|
}
|
|
50
|
-
} catch (e) {
|
|
50
|
+
} catch (e) {
|
|
51
|
+
// Corrupted or unreadable history file - log in debug mode and reset
|
|
52
|
+
if (process.env.DEBUG) {
|
|
53
|
+
console.warn(`[scan] Could not read scan history: ${e.message}`);
|
|
54
|
+
}
|
|
55
|
+
}
|
|
51
56
|
return { scans: [], lastScore: null };
|
|
52
57
|
}
|
|
53
58
|
|
package/bin/vibecheck.js
CHANGED
|
@@ -800,10 +800,17 @@ ${c.bold}Installation:${c.reset}
|
|
|
800
800
|
function printBanner() {
|
|
801
801
|
const VERSION = getVersion();
|
|
802
802
|
console.log(`
|
|
803
|
-
${c.dim}${sym.boxTopLeft}${sym.boxHorizontal.repeat(
|
|
804
|
-
${c.dim}${sym.boxVertical}${c.reset} ${gradient("VIBECHECK", [[0, 255, 255], [138, 43, 226], [255, 20, 147]])} ${c.dim}v${VERSION}${c.reset}${" ".repeat(
|
|
805
|
-
${c.dim}${sym.boxVertical}${c.reset}
|
|
806
|
-
${c.dim}${sym.
|
|
803
|
+
${c.dim}${sym.boxTopLeft}${sym.boxHorizontal.repeat(64)}${sym.boxTopRight}${c.reset}
|
|
804
|
+
${c.dim}${sym.boxVertical}${c.reset} ${gradient("VIBECHECK", [[0, 255, 255], [138, 43, 226], [255, 20, 147]])} ${c.dim}v${VERSION}${c.reset}${" ".repeat(64 - 13 - VERSION.length - 4)}${c.dim}${sym.boxVertical}${c.reset}
|
|
805
|
+
${c.dim}${sym.boxVertical}${c.reset} ${c.dim}${sym.boxVertical}${c.reset}
|
|
806
|
+
${c.dim}${sym.boxVertical}${c.reset} ${c.bold}Catch AI hallucinations before your users do.${c.reset} ${c.dim}${sym.boxVertical}${c.reset}
|
|
807
|
+
${c.dim}${sym.boxVertical}${c.reset} ${c.dim}${sym.boxVertical}${c.reset}
|
|
808
|
+
${c.dim}${sym.boxVertical}${c.reset} ${c.cyan}${sym.check}${c.reset} Detects routes that look real but don't work ${c.dim}${sym.boxVertical}${c.reset}
|
|
809
|
+
${c.dim}${sym.boxVertical}${c.reset} ${c.cyan}${sym.check}${c.reset} Finds env vars used but never declared ${c.dim}${sym.boxVertical}${c.reset}
|
|
810
|
+
${c.dim}${sym.boxVertical}${c.reset} ${c.cyan}${sym.check}${c.reset} Flags auth endpoints with no protection ${c.dim}${sym.boxVertical}${c.reset}
|
|
811
|
+
${c.dim}${sym.boxVertical}${c.reset} ${c.dim}${sym.boxVertical}${c.reset}
|
|
812
|
+
${c.dim}${sym.boxVertical}${c.reset} ${c.dim}SHIP = proof your code works. Not a vibe check.${c.reset} ${c.dim}${sym.boxVertical}${c.reset}
|
|
813
|
+
${c.dim}${sym.boxBottomLeft}${sym.boxHorizontal.repeat(64)}${sym.boxBottomRight}${c.reset}
|
|
807
814
|
`);
|
|
808
815
|
}
|
|
809
816
|
|
|
@@ -883,74 +890,19 @@ function printHelp(showBanner = true) {
|
|
|
883
890
|
reverseAliases[target].push(alias);
|
|
884
891
|
}
|
|
885
892
|
|
|
886
|
-
//
|
|
887
|
-
console.log(`
|
|
888
|
-
${c.yellow}${sym.star} NEW TO VIBECHECK?${c.reset}
|
|
889
|
-
|
|
890
|
-
Run ${c.cyan}${c.bold}vibecheck${c.reset} with no arguments to open the ${c.bold}interactive menu${c.reset}.
|
|
891
|
-
Or follow the Quick Start guide below.
|
|
892
|
-
|
|
893
|
-
${c.dim}${sym.boxHorizontal.repeat(68)}${c.reset}
|
|
894
|
-
`);
|
|
895
|
-
|
|
896
|
-
// Quick Start section (most important for beginners)
|
|
897
|
-
console.log(`${c.green}${sym.rocket} QUICK START${c.reset} ${c.dim}(Get running in 60 seconds)${c.reset}
|
|
898
|
-
|
|
899
|
-
${c.bold}${c.white}Step 1:${c.reset} ${c.cyan}vibecheck init${c.reset}
|
|
900
|
-
${c.dim}Set up vibecheck for your project${c.reset}
|
|
901
|
-
|
|
902
|
-
${c.bold}${c.white}Step 2:${c.reset} ${c.cyan}vibecheck scan${c.reset}
|
|
903
|
-
${c.dim}Analyze your codebase for issues${c.reset}
|
|
904
|
-
|
|
905
|
-
${c.bold}${c.white}Step 3:${c.reset} ${c.cyan}vibecheck ship${c.reset} ${c.magenta}[PRO]${c.reset}
|
|
906
|
-
${c.dim}Get final SHIP/WARN/BLOCK verdict${c.reset}
|
|
907
|
-
`);
|
|
908
|
-
|
|
909
|
-
// Pricing tiers (simple 2-tier)
|
|
910
|
-
console.log(`${c.dim}${sym.boxHorizontal.repeat(68)}${c.reset}
|
|
911
|
-
|
|
912
|
-
${c.bold}PRICING${c.reset}
|
|
913
|
-
|
|
914
|
-
${c.green}${c.bold}FREE${c.reset} ${c.dim}$0${c.reset} Scan, Report, Context, Doctor
|
|
915
|
-
${c.magenta}${c.bold}PRO${c.reset} ${c.dim}$69/mo${c.reset} Ship verdicts, Auto-fix, Runtime proof, CI gates
|
|
916
|
-
${c.dim}→ ${c.cyan}https://vibecheckai.dev/pricing${c.reset}
|
|
917
|
-
`);
|
|
918
|
-
|
|
919
|
-
// Most-used commands
|
|
920
|
-
console.log(`${c.dim}${sym.boxHorizontal.repeat(68)}${c.reset}
|
|
921
|
-
|
|
922
|
-
${c.bold}MOST USED COMMANDS${c.reset}
|
|
923
|
-
`);
|
|
924
|
-
|
|
925
|
-
const popularCommands = [
|
|
926
|
-
{ cmd: "scan", badge: "FREE", desc: "Analyze codebase for issues (routes, env, auth, mocks)" },
|
|
927
|
-
{ cmd: "ship", badge: "PRO", desc: "Get SHIP/WARN/BLOCK verdict with evidence" },
|
|
928
|
-
{ cmd: "fix", badge: "PRO", desc: "AI-powered auto-fix for detected issues" },
|
|
929
|
-
{ cmd: "doctor", badge: "FREE", desc: "Check environment and config health" },
|
|
930
|
-
{ cmd: "report", badge: "FREE", desc: "Generate HTML/JSON/SARIF reports" },
|
|
931
|
-
{ cmd: "prove", badge: "PRO", desc: "Runtime verification with Playwright" },
|
|
932
|
-
];
|
|
933
|
-
|
|
934
|
-
for (const { cmd, badge, desc } of popularCommands) {
|
|
935
|
-
const badgeStr = badge === "FREE"
|
|
936
|
-
? `${c.green}[FREE]${c.reset}`
|
|
937
|
-
: `${c.magenta}[PRO]${c.reset}`;
|
|
938
|
-
console.log(` ${c.cyan}${cmd.padEnd(10)}${c.reset} ${badgeStr} ${c.dim}${desc}${c.reset}`);
|
|
939
|
-
}
|
|
940
|
-
|
|
941
|
-
// Categories with all commands
|
|
893
|
+
// Categories ordered as specified
|
|
942
894
|
const categoryOrder = ["setup", "analysis", "proof", "quality", "truth", "output", "ci", "automation", "account", "extras"];
|
|
943
895
|
const categories = {
|
|
944
|
-
setup: { name: "SETUP
|
|
896
|
+
setup: { name: "SETUP", color: c.yellow, icon: sym.gear },
|
|
945
897
|
analysis: { name: "ANALYSIS", color: c.cyan, icon: sym.chart },
|
|
946
|
-
proof: { name: "PROOF
|
|
898
|
+
proof: { name: "PROOF LOOP", color: c.green, icon: sym.shield },
|
|
947
899
|
quality: { name: "QUALITY", color: c.brightGreen, icon: sym.star },
|
|
948
|
-
truth: { name: "AI
|
|
949
|
-
output: { name: "OUTPUT
|
|
950
|
-
ci: { name: "CI
|
|
900
|
+
truth: { name: "AI TRUTH", color: c.magenta, icon: sym.lightning },
|
|
901
|
+
output: { name: "OUTPUT", color: c.blue, icon: sym.file },
|
|
902
|
+
ci: { name: "CI & COLLABORATION", color: c.cyan, icon: sym.rocket },
|
|
951
903
|
automation: { name: "AUTOMATION", color: c.brightBlue, icon: sym.fire },
|
|
952
|
-
account: { name: "ACCOUNT", color: c.
|
|
953
|
-
extras: { name: "EXTRAS", color: c.
|
|
904
|
+
account: { name: "ACCOUNT", color: c.dim, icon: sym.key },
|
|
905
|
+
extras: { name: "EXTRAS", color: c.dim, icon: sym.starEmpty },
|
|
954
906
|
};
|
|
955
907
|
|
|
956
908
|
// Group commands
|
|
@@ -961,74 +913,126 @@ ${c.bold}MOST USED COMMANDS${c.reset}
|
|
|
961
913
|
grouped[cat].push({ cmd, ...def });
|
|
962
914
|
}
|
|
963
915
|
|
|
964
|
-
console.log(`
|
|
965
|
-
${c.dim}${sym.boxHorizontal.repeat(68)}${c.reset}
|
|
966
|
-
|
|
967
|
-
${c.bold}ALL COMMANDS${c.reset}
|
|
968
|
-
`);
|
|
969
|
-
|
|
970
916
|
// Print in order
|
|
971
917
|
for (const catKey of categoryOrder) {
|
|
972
918
|
const commands = grouped[catKey];
|
|
973
919
|
if (!commands || commands.length === 0) continue;
|
|
974
920
|
|
|
975
921
|
const cat = categories[catKey];
|
|
976
|
-
console.log(
|
|
922
|
+
console.log(`\n${cat.color}${cat.icon} ${cat.name}${c.reset}\n`);
|
|
977
923
|
|
|
978
|
-
for (const { cmd, description, tier } of commands) {
|
|
924
|
+
for (const { cmd, description, tier, caps } of commands) {
|
|
979
925
|
// Tier badge (2-tier: FREE / PRO)
|
|
980
926
|
let tierBadge = "";
|
|
981
|
-
if (tier === "free") tierBadge = `${c.green}[FREE]${c.reset}`;
|
|
982
|
-
else if (tier === "pro") tierBadge = `${c.magenta}[PRO]${c.reset}`;
|
|
927
|
+
if (tier === "free") tierBadge = `${c.green}[FREE]${c.reset} `;
|
|
928
|
+
else if (tier === "pro") tierBadge = `${c.magenta}[PRO]${c.reset} `;
|
|
983
929
|
|
|
984
|
-
// Aliases
|
|
930
|
+
// Aliases (from reverseAliases map built earlier)
|
|
985
931
|
const aliasList = reverseAliases[cmd] || [];
|
|
986
932
|
const aliasStr = aliasList.length > 0
|
|
987
|
-
? `${c.dim}(${aliasList.slice(0,
|
|
933
|
+
? `${c.dim}(${aliasList.slice(0, 3).join(", ")})${c.reset} `
|
|
988
934
|
: "";
|
|
989
935
|
|
|
990
|
-
|
|
936
|
+
// Caps info
|
|
937
|
+
const capsStr = caps ? `${c.dim}(${caps})${c.reset}` : "";
|
|
938
|
+
|
|
939
|
+
console.log(` ${c.cyan}${cmd.padEnd(12)}${c.reset} ${aliasStr}${tierBadge}${description} ${capsStr}`);
|
|
991
940
|
}
|
|
992
|
-
console.log();
|
|
993
941
|
}
|
|
994
942
|
|
|
995
|
-
|
|
996
|
-
|
|
943
|
+
console.log(`
|
|
944
|
+
${c.dim}${sym.boxHorizontal.repeat(64)}${c.reset}
|
|
945
|
+
|
|
946
|
+
${c.green}${sym.star} PRICING TIERS${c.reset}
|
|
947
|
+
|
|
948
|
+
${c.green}FREE${c.reset} ${c.dim}$0${c.reset} scan, ship, report, context, doctor, polish - full visibility
|
|
949
|
+
${c.magenta}PRO${c.reset} ${c.dim}$69/mo${c.reset} + autofix, prove, reality, mcp, guard, ai-test, PR comments
|
|
950
|
+
|
|
951
|
+
${c.green}${sym.rocket} QUICK START (2 minutes to first proof)${c.reset}
|
|
952
|
+
|
|
953
|
+
${c.bold}Option 1: One command${c.reset}
|
|
954
|
+
${c.cyan}vibecheck quickstart${c.reset} ${c.dim}Runs doctor → ctx → scan → ship → report${c.reset}
|
|
955
|
+
|
|
956
|
+
${c.bold}Option 2: Step by step${c.reset}
|
|
957
|
+
${c.bold}1.${c.reset} ${c.cyan}vibecheck init${c.reset} ${c.dim}Set up your project${c.reset}
|
|
958
|
+
${c.bold}2.${c.reset} ${c.cyan}vibecheck scan${c.reset} ${c.dim}Analyze your codebase${c.reset}
|
|
959
|
+
${c.bold}3.${c.reset} ${c.cyan}vibecheck ship${c.reset} ${c.dim}Get shipping verdict${c.reset}
|
|
960
|
+
|
|
961
|
+
${c.green}${sym.lightning} COMMON WORKFLOWS${c.reset}
|
|
962
|
+
|
|
963
|
+
${c.dim}# Quick health check${c.reset}
|
|
964
|
+
${c.cyan}vibecheck doctor${c.reset}
|
|
965
|
+
|
|
966
|
+
${c.dim}# Scan and auto-fix${c.reset}
|
|
967
|
+
${c.cyan}vibecheck scan --autofix${c.reset}
|
|
968
|
+
|
|
969
|
+
${c.dim}# Full proof with evidence pack${c.reset}
|
|
970
|
+
${c.cyan}vibecheck prove --url http://localhost:3000 --bundle${c.reset}
|
|
971
|
+
|
|
972
|
+
${c.bold}GLOBAL OPTIONS${c.reset}
|
|
997
973
|
|
|
998
974
|
${c.cyan}--help, -h${c.reset} Show help for any command
|
|
999
975
|
${c.cyan}--json${c.reset} Machine-readable JSON output
|
|
1000
976
|
${c.cyan}--quiet, -q${c.reset} Suppress non-essential output
|
|
1001
977
|
${c.cyan}--verbose${c.reset} Detailed output for debugging
|
|
1002
978
|
${c.cyan}--ci${c.reset} CI mode (quiet + no-banner)
|
|
979
|
+
${c.cyan}--offline${c.reset} Run without API connection
|
|
1003
980
|
${c.cyan}--path, -p <dir>${c.reset} Run in specified directory
|
|
1004
|
-
`);
|
|
1005
|
-
|
|
1006
|
-
// Common workflows
|
|
1007
|
-
console.log(`${c.bold}COMMON WORKFLOWS${c.reset}
|
|
1008
|
-
|
|
1009
|
-
${c.dim}# First-time setup${c.reset}
|
|
1010
|
-
${c.cyan}vibecheck init${c.reset}
|
|
1011
981
|
|
|
1012
|
-
|
|
1013
|
-
${c.cyan}vibecheck scan${c.reset}
|
|
982
|
+
${c.bold}SHELL COMPLETIONS${c.reset}
|
|
1014
983
|
|
|
1015
|
-
${c.dim}#
|
|
1016
|
-
${c.cyan}vibecheck
|
|
984
|
+
${c.cyan}vibecheck completion bash${c.reset} ${c.dim}# Bash (add to ~/.bashrc)${c.reset}
|
|
985
|
+
${c.cyan}vibecheck completion zsh${c.reset} ${c.dim}# Zsh (add to ~/.zshrc)${c.reset}
|
|
986
|
+
${c.cyan}vibecheck completion fish${c.reset} ${c.dim}# Fish (save to completions)${c.reset}
|
|
1017
987
|
|
|
1018
|
-
|
|
1019
|
-
|
|
1020
|
-
|
|
1021
|
-
|
|
1022
|
-
${c.cyan}vibecheck gate --strict${c.reset}
|
|
988
|
+
${c.dim}${sym.boxHorizontal.repeat(64)}${c.reset}
|
|
989
|
+
${c.dim}Run 'vibecheck <command> --help' for detailed command help.${c.reset}
|
|
990
|
+
${c.dim}Documentation: https://docs.vibecheckai.dev${c.reset}
|
|
991
|
+
${c.dim}Pricing: https://vibecheckai.dev/pricing${c.reset}
|
|
1023
992
|
`);
|
|
993
|
+
}
|
|
1024
994
|
|
|
1025
|
-
|
|
1026
|
-
|
|
1027
|
-
|
|
1028
|
-
|
|
1029
|
-
|
|
1030
|
-
|
|
1031
|
-
|
|
995
|
+
// ═══════════════════════════════════════════════════════════════════════════════
|
|
996
|
+
// HELP VALIDATION
|
|
997
|
+
// ═══════════════════════════════════════════════════════════════════════════════
|
|
998
|
+
|
|
999
|
+
/**
|
|
1000
|
+
* Self-test function to verify help output matches actual commands
|
|
1001
|
+
* Run with: node bin/vibecheck.js --self-test
|
|
1002
|
+
*/
|
|
1003
|
+
function validateHelpOutput() {
|
|
1004
|
+
const registry = getRegistry();
|
|
1005
|
+
const { COMMANDS, ALIAS_MAP } = registry;
|
|
1006
|
+
|
|
1007
|
+
// Extract commands from help text (simplified - just check registry)
|
|
1008
|
+
const actualCommands = Object.keys(COMMANDS);
|
|
1009
|
+
const actualAliases = Object.keys(ALIAS_MAP);
|
|
1010
|
+
const allActualCommands = [...actualCommands, ...actualAliases];
|
|
1011
|
+
|
|
1012
|
+
// Check for obvious issues
|
|
1013
|
+
const issues = [];
|
|
1014
|
+
|
|
1015
|
+
// Check that all commands have runners
|
|
1016
|
+
for (const [cmd, def] of Object.entries(COMMANDS)) {
|
|
1017
|
+
if (!def.runner) {
|
|
1018
|
+
issues.push(`Command '${cmd}' missing runner`);
|
|
1019
|
+
}
|
|
1020
|
+
}
|
|
1021
|
+
|
|
1022
|
+
// Check that aliases point to valid commands
|
|
1023
|
+
for (const [alias, target] of Object.entries(ALIAS_MAP)) {
|
|
1024
|
+
if (!COMMANDS[target]) {
|
|
1025
|
+
issues.push(`Alias '${alias}' points to non-existent command '${target}'`);
|
|
1026
|
+
}
|
|
1027
|
+
}
|
|
1028
|
+
|
|
1029
|
+
if (issues.length > 0) {
|
|
1030
|
+
console.error('Help output validation failed:');
|
|
1031
|
+
issues.forEach(issue => console.error(` - ${issue}`));
|
|
1032
|
+
return false;
|
|
1033
|
+
}
|
|
1034
|
+
|
|
1035
|
+
return true;
|
|
1032
1036
|
}
|
|
1033
1037
|
|
|
1034
1038
|
// ═══════════════════════════════════════════════════════════════════════════════
|
|
@@ -1057,6 +1061,50 @@ function formatError(error, config) {
|
|
|
1057
1061
|
return lines.join("\n");
|
|
1058
1062
|
}
|
|
1059
1063
|
|
|
1064
|
+
/**
|
|
1065
|
+
* Map error to standardized exit code
|
|
1066
|
+
* @param {Error} error - Error object
|
|
1067
|
+
* @param {boolean} json - Whether JSON output is requested
|
|
1068
|
+
* @returns {number} Exit code
|
|
1069
|
+
*/
|
|
1070
|
+
function mapErrorToExitCode(error, json = false) {
|
|
1071
|
+
const EXIT_CODES = {
|
|
1072
|
+
'AUTH_REQUIRED': 5,
|
|
1073
|
+
'AUTH_FAILED': 6,
|
|
1074
|
+
'TIER_REQUIRED': 7,
|
|
1075
|
+
'RATE_LIMITED': 8,
|
|
1076
|
+
'NOT_FOUND': 4,
|
|
1077
|
+
'VALIDATION_ERROR': 3,
|
|
1078
|
+
'USER_ERROR': 3,
|
|
1079
|
+
'NETWORK_ERROR': 9,
|
|
1080
|
+
};
|
|
1081
|
+
|
|
1082
|
+
// Check error.code first
|
|
1083
|
+
if (error.code && EXIT_CODES[error.code]) {
|
|
1084
|
+
return EXIT_CODES[error.code];
|
|
1085
|
+
}
|
|
1086
|
+
|
|
1087
|
+
// Check error.exitCode
|
|
1088
|
+
if (error.exitCode !== undefined) {
|
|
1089
|
+
return error.exitCode;
|
|
1090
|
+
}
|
|
1091
|
+
|
|
1092
|
+
// Check error message for common patterns
|
|
1093
|
+
const message = error.message?.toLowerCase() || '';
|
|
1094
|
+
if (message.includes('not found') || message.includes('not exist')) {
|
|
1095
|
+
return 4; // NOT_FOUND
|
|
1096
|
+
}
|
|
1097
|
+
if (message.includes('auth') || message.includes('login')) {
|
|
1098
|
+
return 5; // AUTH_REQUIRED
|
|
1099
|
+
}
|
|
1100
|
+
if (message.includes('network') || message.includes('connection')) {
|
|
1101
|
+
return 9; // NETWORK_ERROR
|
|
1102
|
+
}
|
|
1103
|
+
|
|
1104
|
+
// Default to internal error
|
|
1105
|
+
return 10; // INTERNAL_ERROR
|
|
1106
|
+
}
|
|
1107
|
+
|
|
1060
1108
|
// ═══════════════════════════════════════════════════════════════════════════════
|
|
1061
1109
|
// FLAG PARSING
|
|
1062
1110
|
// ═══════════════════════════════════════════════════════════════════════════════
|
|
@@ -1156,6 +1204,16 @@ async function main() {
|
|
|
1156
1204
|
process.exit(0);
|
|
1157
1205
|
}
|
|
1158
1206
|
|
|
1207
|
+
// Handle self-test flag (for CI validation)
|
|
1208
|
+
if (cleanArgs.includes('--self-test')) {
|
|
1209
|
+
const registry = getRegistry();
|
|
1210
|
+
if (!validateHelpOutput()) {
|
|
1211
|
+
process.exit(1);
|
|
1212
|
+
}
|
|
1213
|
+
console.log('Self-test passed: Help output matches command registry');
|
|
1214
|
+
process.exit(0);
|
|
1215
|
+
}
|
|
1216
|
+
|
|
1159
1217
|
// Load config and state
|
|
1160
1218
|
const config = loadConfig();
|
|
1161
1219
|
const state = loadState();
|
|
@@ -1170,57 +1228,10 @@ async function main() {
|
|
|
1170
1228
|
config.noBanner = true;
|
|
1171
1229
|
}
|
|
1172
1230
|
|
|
1173
|
-
//
|
|
1174
|
-
// EASY MODE - Super simple commands for non-technical users
|
|
1175
|
-
// ═══════════════════════════════════════════════════════════════════════════
|
|
1176
|
-
const easyModeCommands = ['test', 'protect', 'status'];
|
|
1177
|
-
const firstArg = cleanArgs[0]?.toLowerCase();
|
|
1178
|
-
|
|
1179
|
-
// Check if this is an easy mode command or URL
|
|
1180
|
-
const isEasyCommand = easyModeCommands.includes(firstArg);
|
|
1181
|
-
const isDirectUrl = firstArg && (firstArg.startsWith('http') || firstArg.includes('localhost'));
|
|
1182
|
-
|
|
1183
|
-
if (isEasyCommand || isDirectUrl) {
|
|
1184
|
-
try {
|
|
1185
|
-
const { main: runEasy } = require("./runners/runEasy");
|
|
1186
|
-
await runEasy();
|
|
1187
|
-
return;
|
|
1188
|
-
} catch (err) {
|
|
1189
|
-
if (config.debug) console.error(`Easy mode error: ${err.message}`);
|
|
1190
|
-
// Fall through to normal handling
|
|
1191
|
-
}
|
|
1192
|
-
}
|
|
1193
|
-
|
|
1194
|
-
// Handle no command - show EASY wizard for beginners (much friendlier)
|
|
1231
|
+
// Handle no command
|
|
1195
1232
|
if (!cleanArgs[0]) {
|
|
1196
|
-
|
|
1197
|
-
|
|
1198
|
-
try {
|
|
1199
|
-
// Try easy wizard first (friendlier for new users)
|
|
1200
|
-
const { Wizard } = require("./runners/lib/easy/interactive-wizard");
|
|
1201
|
-
const wizard = new Wizard();
|
|
1202
|
-
await wizard.start();
|
|
1203
|
-
return;
|
|
1204
|
-
} catch {
|
|
1205
|
-
// Fall back to original interactive menu
|
|
1206
|
-
try {
|
|
1207
|
-
const { runInteractiveMenu } = require("./runners/lib/cli-interactive-menu");
|
|
1208
|
-
runInteractiveMenu().then(() => process.exit(0)).catch(() => {
|
|
1209
|
-
printHelp(!config.noBanner);
|
|
1210
|
-
process.exit(0);
|
|
1211
|
-
});
|
|
1212
|
-
return; // Let async menu run
|
|
1213
|
-
} catch {
|
|
1214
|
-
// Fall back to help if menu module not available
|
|
1215
|
-
printHelp(!config.noBanner);
|
|
1216
|
-
process.exit(0);
|
|
1217
|
-
}
|
|
1218
|
-
}
|
|
1219
|
-
} else {
|
|
1220
|
-
// Non-TTY or quiet mode: show help
|
|
1221
|
-
printHelp(!config.noBanner);
|
|
1222
|
-
process.exit(0);
|
|
1223
|
-
}
|
|
1233
|
+
printHelp(!config.noBanner);
|
|
1234
|
+
process.exit(0);
|
|
1224
1235
|
}
|
|
1225
1236
|
|
|
1226
1237
|
// Handle global help
|
|
@@ -1228,28 +1239,6 @@ async function main() {
|
|
|
1228
1239
|
printHelp(!config.noBanner);
|
|
1229
1240
|
process.exit(0);
|
|
1230
1241
|
}
|
|
1231
|
-
|
|
1232
|
-
// Handle explicit menu command
|
|
1233
|
-
if (cleanArgs[0] === "menu") {
|
|
1234
|
-
if (process.stdout.isTTY) {
|
|
1235
|
-
try {
|
|
1236
|
-
const { runInteractiveMenu } = require("./runners/lib/cli-interactive-menu");
|
|
1237
|
-
runInteractiveMenu().then(() => process.exit(0)).catch((err) => {
|
|
1238
|
-
console.error(`Menu error: ${err.message}`);
|
|
1239
|
-
process.exit(1);
|
|
1240
|
-
});
|
|
1241
|
-
return;
|
|
1242
|
-
} catch (err) {
|
|
1243
|
-
console.error(`${c.red}Error:${c.reset} Interactive menu not available: ${err.message}`);
|
|
1244
|
-
console.log(`${c.dim}Use 'vibecheck --help' to see available commands.${c.reset}`);
|
|
1245
|
-
process.exit(1);
|
|
1246
|
-
}
|
|
1247
|
-
} else {
|
|
1248
|
-
console.error(`${c.yellow}Warning:${c.reset} Interactive menu requires a terminal.`);
|
|
1249
|
-
console.log(`${c.dim}Use 'vibecheck --help' to see available commands.${c.reset}`);
|
|
1250
|
-
process.exit(1);
|
|
1251
|
-
}
|
|
1252
|
-
}
|
|
1253
1242
|
|
|
1254
1243
|
// Handle completion command (special - doesn't need registry loaded normally)
|
|
1255
1244
|
if (cleanArgs[0] === "completion") {
|
|
@@ -1318,10 +1307,16 @@ async function main() {
|
|
|
1318
1307
|
const cmdDef = COMMANDS[cmd];
|
|
1319
1308
|
let authInfo = { key: null };
|
|
1320
1309
|
|
|
1321
|
-
// Check for offline mode (via flag or env var)
|
|
1310
|
+
// Check for offline/dev mode (via flag or env var)
|
|
1311
|
+
// SECURITY: VIBECHECK_DEV_PRO only works in non-production to prevent auth bypass
|
|
1312
|
+
const isDevProAllowed = process.env.NODE_ENV !== 'production' &&
|
|
1313
|
+
process.env.CI !== 'true' &&
|
|
1314
|
+
process.env.CI !== '1' &&
|
|
1315
|
+
process.env.VIBECHECK_DEV_PRO === '1';
|
|
1322
1316
|
const isOffline = globalFlags.offline ||
|
|
1323
1317
|
process.env.VIBECHECK_OFFLINE === '1' ||
|
|
1324
|
-
process.env.VIBECHECK_LOCAL === '1'
|
|
1318
|
+
process.env.VIBECHECK_LOCAL === '1' ||
|
|
1319
|
+
isDevProAllowed;
|
|
1325
1320
|
|
|
1326
1321
|
// Auth check (unless skipAuth or offline mode)
|
|
1327
1322
|
// Only allow login, logout, whoami, and help without auth
|
|
@@ -1383,7 +1378,9 @@ async function main() {
|
|
|
1383
1378
|
authInfo.access = access;
|
|
1384
1379
|
} else if (isOffline) {
|
|
1385
1380
|
// Offline mode - provide basic access info
|
|
1386
|
-
if (
|
|
1381
|
+
// Suppress message if JSON/SARIF output is requested (check both global flags and command args)
|
|
1382
|
+
const hasJsonOutput = globalFlags.json || cmdArgs.includes('--json') || cmdArgs.includes('--sarif');
|
|
1383
|
+
if (!config.quiet && !config.noBanner && !hasJsonOutput) {
|
|
1387
1384
|
console.log(`${c.cyan}${sym.arrowRight} OFFLINE${c.reset} ${c.dim}mode - local scanning without API${c.reset}`);
|
|
1388
1385
|
}
|
|
1389
1386
|
authInfo.access = {
|
|
@@ -1412,7 +1409,7 @@ async function main() {
|
|
|
1412
1409
|
const runner = getRunner(cmd);
|
|
1413
1410
|
if (!runner) {
|
|
1414
1411
|
console.error(`${c.red}${sym.error}${c.reset} Failed to load runner for: ${cmd}`);
|
|
1415
|
-
process.exit(
|
|
1412
|
+
process.exit(4); // NOT_FOUND
|
|
1416
1413
|
}
|
|
1417
1414
|
|
|
1418
1415
|
const context = {
|
|
@@ -1427,10 +1424,32 @@ async function main() {
|
|
|
1427
1424
|
};
|
|
1428
1425
|
|
|
1429
1426
|
// Execute command - all commands use consistent runner signature
|
|
1430
|
-
|
|
1427
|
+
const result = await runner(cmdArgs, context);
|
|
1428
|
+
|
|
1429
|
+
// Ensure result has standardized exit code
|
|
1430
|
+
if (typeof result === 'object' && result.exitCode !== undefined) {
|
|
1431
|
+
exitCode = result.exitCode;
|
|
1432
|
+
} else if (typeof result === 'number') {
|
|
1433
|
+
exitCode = result;
|
|
1434
|
+
} else {
|
|
1435
|
+
exitCode = 0; // SUCCESS
|
|
1436
|
+
}
|
|
1431
1437
|
} catch (error) {
|
|
1432
|
-
|
|
1433
|
-
exitCode =
|
|
1438
|
+
// Map errors to exit codes
|
|
1439
|
+
exitCode = mapErrorToExitCode(error, globalFlags.json);
|
|
1440
|
+
|
|
1441
|
+
if (globalFlags.json) {
|
|
1442
|
+
console.log(JSON.stringify({
|
|
1443
|
+
success: false,
|
|
1444
|
+
error: {
|
|
1445
|
+
code: error.code || 'INTERNAL_ERROR',
|
|
1446
|
+
message: error.message,
|
|
1447
|
+
},
|
|
1448
|
+
exitCode,
|
|
1449
|
+
}, null, 2));
|
|
1450
|
+
} else {
|
|
1451
|
+
console.error(formatError(error, config));
|
|
1452
|
+
}
|
|
1434
1453
|
}
|
|
1435
1454
|
|
|
1436
1455
|
// Create receipt for paid commands
|