@vibecheckai/cli 3.1.5 → 3.1.8

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 (38) hide show
  1. package/README.md +27 -32
  2. package/bin/registry.js +216 -341
  3. package/bin/runners/ENHANCEMENT_GUIDE.md +121 -0
  4. package/bin/runners/lib/global-flags.js +213 -0
  5. package/bin/runners/lib/init-wizard.js +566 -273
  6. package/bin/runners/lib/interactive-menu.js +1496 -0
  7. package/bin/runners/runCheckpoint.js +503 -502
  8. package/bin/runners/runContext.js +16 -9
  9. package/bin/runners/runDoctor.js +20 -33
  10. package/bin/runners/runFix.js +19 -11
  11. package/bin/runners/runInit.js +866 -68
  12. package/bin/runners/runInstall.js +14 -6
  13. package/bin/runners/runProve.js +18 -12
  14. package/bin/runners/runReality.js +15 -6
  15. package/bin/runners/runReport.js +31 -18
  16. package/bin/runners/runScan.js +28 -17
  17. package/bin/runners/runShip.js +27 -21
  18. package/bin/runners/runWatch.js +11 -4
  19. package/bin/vibecheck.js +851 -212
  20. package/mcp-server/package.json +1 -1
  21. package/package.json +1 -1
  22. package/bin/runners/runBadge.js +0 -916
  23. package/bin/runners/runContracts.js +0 -105
  24. package/bin/runners/runCtx.js +0 -675
  25. package/bin/runners/runCtxDiff.js +0 -301
  26. package/bin/runners/runCtxGuard.js +0 -176
  27. package/bin/runners/runCtxSync.js +0 -116
  28. package/bin/runners/runExport.js +0 -93
  29. package/bin/runners/runGraph.js +0 -454
  30. package/bin/runners/runLaunch.js +0 -181
  31. package/bin/runners/runPR.js +0 -255
  32. package/bin/runners/runPermissions.js +0 -304
  33. package/bin/runners/runPreflight.js +0 -580
  34. package/bin/runners/runReplay.js +0 -499
  35. package/bin/runners/runSecurity.js +0 -92
  36. package/bin/runners/runShare.js +0 -212
  37. package/bin/runners/runStatus.js +0 -86
  38. package/bin/runners/runVerify.js +0 -272
package/bin/registry.js CHANGED
@@ -1,387 +1,262 @@
1
1
  /**
2
- * Vibecheck CLI Command Registry
3
- *
4
- * Single source of truth for all CLI commands.
5
- * Tiers match entitlements-v2.js EXACTLY.
6
- *
7
- * @module bin/registry
2
+ * Vibecheck CLI Command Registry (LOCKED)
3
+ *
4
+ * Single source of truth for the public CLI surface.
5
+ * If it isn't here, it does not exist.
8
6
  */
9
7
 
10
8
  "use strict";
11
9
 
12
- // ═══════════════════════════════════════════════════════════════════════════════
13
- // COMMAND REGISTRY - The 14-Command Vibecheck CLI
14
- // Tiers match entitlements-v2.js EXACTLY
15
- // ═══════════════════════════════════════════════════════════════════════════════
10
+ // ─────────────────────────────────────────────────────────────
11
+ // CORE 13 + APPROVED EXTRAS (locked surface area)
12
+ // ─────────────────────────────────────────────────────────────
13
+ const ALLOWED_COMMANDS = new Set([
14
+ // Core 13
15
+ "init",
16
+ "doctor",
17
+ "scan",
18
+ "report",
19
+ "fix",
20
+ "watch",
21
+ "checkpoint",
22
+ "polish",
23
+ "ship",
24
+ "prove", // replaces ctx
25
+ "reality", // runtime crawl
26
+ "context",
27
+ "guard",
28
+
29
+ // Approved extras
30
+ "mcp",
31
+ "login",
32
+ "logout",
33
+ "whoami",
34
+ "ai-test",
35
+ "labs",
36
+ ]);
37
+
38
+ function assertAllowedOnly(obj) {
39
+ const extras = Object.keys(obj).filter((k) => !ALLOWED_COMMANDS.has(k));
40
+ if (extras.length) {
41
+ throw new Error(`Registry contains non-allowed commands: ${extras.join(", ")}`);
42
+ }
43
+ }
44
+
45
+ // ─────────────────────────────────────────────────────────────
46
+ // COMMANDS (ALLOWED ONLY)
47
+ // ─────────────────────────────────────────────────────────────
16
48
  const COMMANDS = {
17
- // ═══════════════════════════════════════════════════════════════════════════════
18
- // SETUP COMMANDS (2)
19
- // ═══════════════════════════════════════════════════════════════════════════════
20
-
21
- // 1) init - One-time setup (config + contracts + scripts)
22
- init: {
23
- description: "One-time setup (config + contracts + scripts)",
24
- tier: "free",
25
- category: "setup",
26
- aliases: ["setup", "configure"],
27
- runner: () => require("./runners/runInit").runInit
28
- },
29
-
30
- // 2) doctor - Environment + dependency + config health check
31
- doctor: {
32
- description: "Environment + dependency + config health check",
33
- tier: "free",
34
- category: "setup",
35
- aliases: ["health", "diag"],
36
- runner: () => require("./runners/runDoctor").runDoctor
37
- },
38
-
39
- // ═══════════════════════════════════════════════════════════════════════════════
40
- // AI TRUTH LANE (4) - Context engine, guardrails, MDC
41
- // ═══════════════════════════════════════════════════════════════════════════════
42
-
43
- // 3) ctx - Generate/update truthpack (core truth engine)
44
- ctx: {
45
- description: "Truthpack generation - core truth engine",
46
- tier: "free",
47
- category: "truth",
48
- aliases: ["truthpack", "tp"],
49
- subcommands: ["build", "diff", "sync", "search"],
50
- runner: () => require("./runners/runCtx").runCtx
51
- },
52
-
53
- // 4) context - MDC + IDE rules + memory engine outputs
54
- context: {
55
- description: "Generate IDE rules (.cursorrules, MDC, Windsurf, Copilot)",
56
- tier: "free",
57
- category: "truth",
58
- aliases: ["rules", "ai-rules", "mdc"],
59
- runner: () => require("./runners/runContext").runContext
60
- },
61
-
62
- // 5) guard - AI guardrails (prompt firewall, hallucination checking)
63
- guard: {
64
- description: "AI guardrails - prompt firewall & hallucination checking",
65
- tier: "free",
66
- category: "truth",
67
- aliases: ["ai-guard", "firewall", "validate"],
68
- runner: () => require("./runners/runGuard").runGuard
49
+ // ── SETUP ───────────────────────────────────────────────────
50
+ init: {
51
+ description: "One-time setup (config + contracts + scripts)",
52
+ tier: "free",
53
+ category: "setup",
54
+ aliases: ["setup", "configure"],
55
+ runner: () => require("./runners/runInit").runInit,
69
56
  },
70
-
71
- // 6) contracts - CI gate for contract drift / invariants
72
- contracts: {
73
- description: "CI gate for contract drift / invariants",
74
- tier: "free",
75
- category: "truth",
76
- aliases: ["drift"],
77
- runner: () => require("./runners/runContracts").runContracts
57
+
58
+ doctor: {
59
+ description: "Environment + dependency + config health check",
60
+ tier: "free",
61
+ category: "setup",
62
+ aliases: ["health", "diag"],
63
+ runner: () => require("./runners/runDoctor").runDoctor,
78
64
  },
79
-
80
- // ═══════════════════════════════════════════════════════════════════════════════
81
- // PROOF LOOP (5) - The main verification commands
82
- // ═══════════════════════════════════════════════════════════════════════════════
83
-
84
- // 7) ship - The only verdict command. Static + (optional) runtime merge
85
- ship: {
86
- description: "Verdict engine - SHIP / WARN / BLOCK",
87
- tier: "free",
88
- category: "proof",
89
- aliases: ["verdict"],
90
- caps: "static-only on FREE",
91
- runner: () => require("./runners/runShip").runShip
65
+
66
+ watch: {
67
+ description: "Continuous mode - re-runs on changes",
68
+ tier: "free",
69
+ category: "setup",
70
+ aliases: ["w", "dev"],
71
+ runner: () => require("./runners/runWatch").runWatch,
92
72
  },
93
-
94
- // 8) runtime - Everything Playwright / browser-based
95
- runtime: {
96
- description: "Browser-based runtime verification",
97
- tier: "free",
98
- category: "proof",
99
- aliases: [],
100
- subcommands: ["crawl", "agent", "record", "play"],
101
- caps: "preview mode on FREE (5 pages, no auth)",
102
- runner: () => require("./runners/runRuntime").runRuntime
73
+
74
+ // ── ANALYSIS ────────────────────────────────────────────────
75
+ checkpoint: {
76
+ description: "Compare baseline vs current, hallucination scoring",
77
+ tier: "free",
78
+ category: "analysis",
79
+ aliases: ["cp", "compare", "diff"],
80
+ caps: "basic on FREE, hallucination scoring on PRO",
81
+ runner: () => require("./runners/runCheckpoint").runCheckpoint,
103
82
  },
104
-
105
- // 9) fix - Mission planning + patching
106
- fix: {
107
- description: "AI-powered auto-fix",
108
- tier: "free",
109
- category: "proof",
110
- caps: "--plan-only on FREE",
111
- aliases: ["f", "repair"],
112
- runner: () => require("./runners/runFix").runFix
83
+
84
+ // ── PROOF LOOP ──────────────────────────────────────────────
85
+ scan: {
86
+ description: "Route integrity & code analysis scanner",
87
+ tier: "free",
88
+ category: "proof",
89
+ aliases: ["s", "check"],
90
+ runner: () => require("./runners/runScan").runScan,
113
91
  },
114
-
115
- // 10) prove - The one command users actually run before launch
116
- prove: {
117
- description: "Full proof loop - ctx → runtime → ship → fix",
118
- tier: "pro",
119
- category: "proof",
120
- aliases: ["p", "full", "all"],
121
- runner: () => require("./runners/runProve").runProve
92
+
93
+ report: {
94
+ description: "Generate HTML/MD/SARIF reports",
95
+ tier: "free",
96
+ category: "output",
97
+ caps: "HTML/MD only on FREE",
98
+ aliases: ["html", "artifact"],
99
+ runner: () => require("./runners/runReport").runReport,
122
100
  },
123
-
124
- // 11) security - AuthZ + IDOR + sensitive security proofs
125
- security: {
126
- description: "AuthZ matrix & IDOR detection",
127
- tier: "pro",
128
- category: "proof",
129
- aliases: [],
130
- subcommands: ["model", "matrix", "idor", "prove"],
131
- runner: () => require("./runners/runSecurity").runSecurity
101
+
102
+ fix: {
103
+ description: "AI-powered auto-fix",
104
+ tier: "free",
105
+ category: "proof",
106
+ caps: "--plan-only on FREE",
107
+ aliases: ["f", "repair"],
108
+ runner: () => require("./runners/runFix").runFix,
132
109
  },
133
-
134
- // ═══════════════════════════════════════════════════════════════════════════════
135
- // OUTPUT & AUTOMATION (3)
136
- // ═══════════════════════════════════════════════════════════════════════════════
137
-
138
- // 12) report - Render artifacts (HTML/MD/SARIF/CSV/etc)
139
- report: {
140
- description: "Generate HTML/MD/SARIF reports",
141
- tier: "free",
142
- category: "output",
143
- caps: "HTML/MD only on FREE",
144
- aliases: ["html", "artifact"],
145
- runner: () => require("./runners/runReport").runReport
110
+
111
+ reality: {
112
+ description: "Runtime proof (browser crawl)",
113
+ tier: "free",
114
+ category: "proof",
115
+ caps: "preview mode on FREE (5 pages, no auth)",
116
+ aliases: ["r", "test", "e2e"],
117
+ runner: () => async (args, ctx) => {
118
+ const { runRuntime } = require("./runners/runRuntime");
119
+ return await runRuntime(["crawl", ...args], ctx);
120
+ },
146
121
  },
147
-
148
- // 13) export - Lightweight collab outputs from latest results
149
- export: {
150
- description: "Generate collaboration outputs",
151
- tier: "free",
152
- category: "output",
153
- aliases: [],
154
- subcommands: ["pr", "badge", "bundle"],
155
- runner: () => require("./runners/runExport").runExport
122
+
123
+ ship: {
124
+ description: "Verdict engine - SHIP / WARN / BLOCK",
125
+ tier: "free",
126
+ category: "proof",
127
+ aliases: ["verdict", "go"],
128
+ caps: "static-only on FREE",
129
+ runner: () => require("./runners/runShip").runShip,
156
130
  },
157
-
158
- // 14) mcp - Start MCP server for AI IDEs
159
- mcp: {
160
- description: "Start MCP server for AI IDEs",
161
- tier: "starter",
162
- category: "automation",
163
- aliases: [],
164
- runner: () => require("./runners/runMcp").runMcp
131
+
132
+ prove: {
133
+ description: "Full proof loop - truth → reality → ship → fix",
134
+ tier: "pro",
135
+ category: "proof",
136
+ aliases: ["p", "full", "all"],
137
+ runner: () => require("./runners/runProve").runProve,
165
138
  },
166
-
167
- // ═══════════════════════════════════════════════════════════════════════════════
168
- // BACKWARD COMPATIBILITY ALIASES (old commands still work)
169
- // ═══════════════════════════════════════════════════════════════════════════════
170
-
171
- // install → init --quick
172
- install: {
173
- description: "Zero-friction onboarding (alias: init --quick)",
174
- tier: "free",
175
- category: "setup",
176
- aliases: ["i", "bootstrap"],
177
- runner: () => async (args) => {
178
- const { runInit } = require("./runners/runInit");
179
- return await runInit(["--quick", ...args]);
180
- }
139
+
140
+ // ── QUALITY ────────────────────────────────────────────────
141
+ polish: {
142
+ description: "Production polish analyzer - finds missing essentials",
143
+ tier: "free",
144
+ category: "quality",
145
+ aliases: ["quality", "finalize", "ready"],
146
+ runner: () => require("./runners/runPolish").runPolish,
181
147
  },
182
-
183
- // scan - Enhanced route integrity scanner with terminal UI
184
- scan: {
185
- description: "Route integrity & code analysis scanner",
186
- tier: "free",
187
- category: "proof",
188
- aliases: ["s", "check"],
189
- runner: () => require("./runners/runScan").runScan
148
+
149
+ // ── AI TRUTH ───────────────────────────────────────────────
150
+ context: {
151
+ description: "Generate IDE rules (.cursorrules, MDC, Windsurf, Copilot)",
152
+ tier: "free",
153
+ category: "truth",
154
+ aliases: ["rules", "ai-rules", "mdc"],
155
+ runner: () => require("./runners/runContext").runContext,
190
156
  },
191
-
192
- // gate → ship --ci
193
- gate: {
194
- description: "CI/CD gate (alias: ship --ci)",
195
- tier: "starter",
196
- category: "ci",
197
- aliases: ["ci", "block"],
198
- runner: () => async (args) => {
199
- const { runShip } = require("./runners/runShip");
200
- return await runShip(["--ci", ...args]);
201
- }
157
+
158
+ guard: {
159
+ description: "AI guardrails - prompt firewall & hallucination checking",
160
+ tier: "free",
161
+ category: "truth",
162
+ aliases: ["ai-guard", "firewall", "validate"],
163
+ runner: () => require("./runners/runGuard").runGuard,
202
164
  },
203
-
204
- // reality runtime crawl
205
- reality: {
206
- description: "Runtime proof (alias: runtime crawl)",
207
- tier: "free",
208
- category: "proof",
209
- aliases: ["r", "test", "e2e"],
210
- caps: "preview mode on FREE (5 pages, no auth)",
211
- runner: () => async (args) => {
212
- const { runRuntime } = require("./runners/runRuntime");
213
- return await runRuntime(["crawl", ...args]);
214
- }
165
+
166
+ // ── AUTOMATION ─────────────────────────────────────────────
167
+ mcp: {
168
+ description: "Start MCP server for AI IDEs",
169
+ tier: "starter",
170
+ category: "automation",
171
+ aliases: [],
172
+ runner: () => require("./runners/runMcp").runMcp,
215
173
  },
216
-
217
- // ai-test → runtime agent
218
- "ai-test": {
219
- description: "AI autonomous test (alias: runtime agent)",
220
- tier: "pro",
221
- category: "automation",
222
- aliases: ["ai", "agent"],
223
- runner: () => async (args) => {
174
+
175
+ "ai-test": {
176
+ description: "AI autonomous test (alias: runtime agent)",
177
+ tier: "pro",
178
+ category: "automation",
179
+ aliases: ["ai", "agent"],
180
+ runner: () => async (args, ctx) => {
224
181
  const { runRuntime } = require("./runners/runRuntime");
225
- return await runRuntime(["agent", ...args]);
226
- }
227
- },
228
-
229
- // replay → runtime record/play
230
- replay: {
231
- description: "Record/replay sessions (alias: runtime record/play)",
232
- tier: "pro",
233
- category: "proof",
234
- aliases: ["record", "playback"],
235
- runner: () => async (args) => {
236
- // If first arg is record or play, delegate to runtime
237
- if (args[0] === "record" || args[0] === "play") {
238
- const { runRuntime } = require("./runners/runRuntime");
239
- return await runRuntime(args);
240
- }
241
- // Otherwise delegate to original replay handler
242
- try {
243
- const { runReplay } = require("./runners/runReplay");
244
- return await runReplay(args);
245
- } catch (e) {
246
- if (args && (args.includes("--help") || args.includes("-h") || args.length === 0)) {
247
- console.log("\n vibecheck replay - Record and replay user sessions\n\n Subcommands:\n record <url> Record a user session\n play <capsule> Replay a recorded session\n list List available replay capsules\n show <id> Show details of a replay capsule\n delete <id> Delete a replay capsule\n export <id> Export a replay capsule\n import <file> Import a replay capsule\n\n Note: Requires 'chalk' and 'playwright' dependencies.\n Install: npm install chalk playwright\n");
248
- return 0;
249
- }
250
- console.error("Replay runner error:", e.message);
251
- return 1;
252
- }
253
- }
182
+ return await runRuntime(["agent", ...args], ctx);
183
+ },
254
184
  },
255
-
256
- // pr export pr
257
- pr: {
258
- description: "Generate PR comment (alias: export pr)",
259
- tier: "starter",
260
- category: "ci",
261
- aliases: ["pull-request"],
262
- runner: () => async (args) => {
263
- const { runExport } = require("./runners/runExport");
264
- return await runExport(["pr", ...args]);
265
- }
266
- },
267
-
268
- // badge → export badge
269
- badge: {
270
- description: "Generate ship badge (alias: export badge)",
271
- tier: "starter",
272
- category: "ci",
273
- aliases: ["b"],
274
- runner: () => async (args) => {
275
- const { runExport } = require("./runners/runExport");
276
- return await runExport(["badge", ...args]);
277
- }
278
- },
279
-
280
- // share → export bundle
281
- share: {
282
- description: "Generate share pack (alias: export bundle)",
283
- tier: "pro",
284
- category: "automation",
285
- aliases: [],
286
- runner: () => async (args) => {
287
- const { runExport } = require("./runners/runExport");
288
- return await runExport(["bundle", ...args]);
289
- }
185
+
186
+ // ── ACCOUNT (skipAuth) ────────────────────────────────────
187
+ login: {
188
+ description: "Authenticate with API key",
189
+ tier: "free",
190
+ category: "account",
191
+ aliases: ["auth", "signin"],
192
+ runner: () => require("./runners/runAuth").runLogin,
193
+ skipAuth: true,
290
194
  },
291
-
292
- // permissions → security model
293
- permissions: {
294
- description: "AuthZ & IDOR (alias: security model)",
295
- tier: "pro",
296
- category: "proof",
297
- aliases: ["authz", "idor"],
298
- runner: () => async (args) => {
299
- const { runSecurity } = require("./runners/runSecurity");
300
- // If no subcommand, default to "model"
301
- if (!args[0] || args[0].startsWith("--")) {
302
- return await runSecurity(["model", ...args]);
303
- }
304
- return await runSecurity(args);
305
- }
195
+
196
+ logout: {
197
+ description: "Remove stored credentials",
198
+ tier: "free",
199
+ category: "account",
200
+ aliases: ["signout"],
201
+ runner: () => require("./runners/runAuth").runLogout,
202
+ skipAuth: true,
306
203
  },
307
-
308
- // ═══════════════════════════════════════════════════════════════════════════════
309
- // QUALITY & CHECKPOINT COMMANDS
310
- // ═══════════════════════════════════════════════════════════════════════════════
311
-
312
- // 15) polish - Production polish analyzer
313
- polish: {
314
- description: "Production polish analyzer - finds missing essentials",
315
- tier: "free",
316
- category: "quality",
317
- aliases: ["quality", "finalize", "ready"],
318
- runner: () => require("./runners/runPolish").runPolish
204
+
205
+ whoami: {
206
+ description: "Show current user and plan",
207
+ tier: "free",
208
+ category: "account",
209
+ aliases: ["me", "user"],
210
+ runner: () => require("./runners/runAuth").runWhoami,
211
+ skipAuth: true,
319
212
  },
320
-
321
- // 16) checkpoint - Compare baseline vs current
322
- checkpoint: {
323
- description: "Compare baseline vs current, hallucination scoring",
213
+
214
+ // ── EXTRAS ────────────────────────────────────────────────
215
+ labs: {
216
+ description: "Experimental features",
324
217
  tier: "free",
325
- category: "analysis",
326
- aliases: ["cp", "compare", "diff"],
327
- caps: "basic on FREE, hallucination scoring on PRO",
328
- runner: () => require("./runners/runCheckpoint").runCheckpoint
218
+ category: "extras",
219
+ aliases: ["experimental", "beta"],
220
+ runner: () => require("./runners/runLabs").runLabs,
329
221
  },
330
-
331
- status: { description: "Project health dashboard", tier: "free", category: "setup", aliases: ["st"], runner: () => require("./runners/runStatus").runStatus },
332
- watch: { description: "Continuous mode - re-runs on changes", tier: "free", category: "setup", aliases: ["w", "dev"], runner: () => require("./runners/runWatch").runWatch },
333
- launch: { description: "Pre-launch checklist wizard", tier: "starter", category: "setup", aliases: ["checklist"], runner: () => require("./runners/runLaunch").runLaunch },
334
- preflight: { description: "Deployment validation checks", tier: "free", category: "setup", aliases: ["deploy-check"], runner: () => require("./runners/runPreflight").runPreflight },
335
- verify: { description: "Verify AI-generated code output", tier: "free", category: "truth", aliases: ["v", "check-output"], runner: () => require("./runners/runVerify").main },
336
- graph: { description: "Reality proof graph visualization", tier: "pro", category: "proof", aliases: ["graphviz", "causal"], runner: () => require("./runners/runGraph").runGraph },
337
-
338
- // ACCOUNT (always free)
339
- login: { description: "Authenticate with API key", tier: "free", category: "account", aliases: ["auth", "signin"], runner: () => require("./runners/runAuth").runLogin, skipAuth: true },
340
- logout: { description: "Remove stored credentials", tier: "free", category: "account", aliases: ["signout"], runner: () => require("./runners/runAuth").runLogout, skipAuth: true },
341
- whoami: { description: "Show current user and plan", tier: "free", category: "account", aliases: ["me", "user"], runner: () => require("./runners/runAuth").runWhoami, skipAuth: true },
342
-
343
- // EXTRAS
344
- labs: { description: "Experimental features", tier: "free", category: "extras", aliases: ["experimental", "beta"], runner: () => require("./runners/runLabs").runLabs },
345
222
  };
346
223
 
347
- // ═══════════════════════════════════════════════════════════════════════════════
348
- // DERIVED DATA STRUCTURES
349
- // ═══════════════════════════════════════════════════════════════════════════════
224
+ assertAllowedOnly(COMMANDS);
225
+
226
+ // ─────────────────────────────────────────────────────────────
227
+ // DERIVED MAPS
228
+ // ─────────────────────────────────────────────────────────────
350
229
  const ALIAS_MAP = {};
351
- for (const [cmd, def] of Object.entries(COMMANDS)) {
352
- for (const alias of def.aliases || []) ALIAS_MAP[alias] = cmd;
230
+ for (const [cmd, def] of Object.entries(COMMANDS)) {
231
+ for (const alias of def.aliases || []) ALIAS_MAP[alias] = cmd;
353
232
  }
354
233
 
355
- const ALL_COMMANDS = [...Object.keys(COMMANDS), ...Object.values(COMMANDS).flatMap(c => c.aliases || [])];
234
+ const ALL_COMMANDS = [
235
+ ...Object.keys(COMMANDS),
236
+ ...Object.values(COMMANDS).flatMap((c) => c.aliases || []),
237
+ ];
356
238
 
357
- // ═══════════════════════════════════════════════════════════════════════════════
239
+ // ─────────────────────────────────────────────────────────────
358
240
  // RUNNER LOADER
359
- // ═══════════════════════════════════════════════════════════════════════════════
360
- /**
361
- * Get runner function for a command
362
- * @param {string} cmd - Command name
363
- * @param {object} styles - Optional styling object with { red, reset, errorSymbol }
364
- * @returns {Function|null} Runner function or null if not found
365
- */
241
+ // ─────────────────────────────────────────────────────────────
366
242
  function getRunner(cmd, styles = {}) {
367
243
  const def = COMMANDS[cmd];
368
244
  if (!def) return null;
245
+
369
246
  const red = styles.red || "";
370
247
  const reset = styles.reset || "";
371
248
  const errorSym = styles.errorSymbol || "✗";
372
- try {
373
- return def.runner();
374
- } catch (e) {
375
- return async () => {
376
- console.error(`${red}${errorSym}${reset} Failed to load ${cmd}: ${e.message}`);
377
- return 1;
378
- };
249
+
250
+ try {
251
+ return def.runner();
252
+ } catch (e) {
253
+ return async () => {
254
+ console.error(`${red}${errorSym}${reset} Failed to load ${cmd}: ${e.message}`);
255
+ return 1;
256
+ };
379
257
  }
380
258
  }
381
259
 
382
- // ═══════════════════════════════════════════════════════════════════════════════
383
- // EXPORTS
384
- // ═══════════════════════════════════════════════════════════════════════════════
385
260
  module.exports = {
386
261
  COMMANDS,
387
262
  ALIAS_MAP,