@vibecheckai/cli 3.0.9 → 3.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,4 +1,11 @@
1
- // bin/runners/runInstall.js
1
+ /**
2
+ * vibecheck install - Zero-friction Onboarding
3
+ *
4
+ * ═══════════════════════════════════════════════════════════════════════════════
5
+ * ENTERPRISE EDITION - World-Class Terminal Experience
6
+ * ═══════════════════════════════════════════════════════════════════════════════
7
+ */
8
+
2
9
  const fs = require("fs");
3
10
  const path = require("path");
4
11
  const { buildTruthpack, writeTruthpack } = require("./lib/truth");
@@ -6,34 +13,159 @@ const { detectPackageManager, detectNext, detectFastify, detectFastifyEntry } =
6
13
  const { readPkg, writePkg, upsertScripts } = require("./lib/pkgjson");
7
14
  const { writeEnvTemplateFromTruthpack } = require("./lib/env-template");
8
15
 
16
+ // ═══════════════════════════════════════════════════════════════════════════════
17
+ // ADVANCED TERMINAL - ANSI CODES & UTILITIES
18
+ // ═══════════════════════════════════════════════════════════════════════════════
19
+
20
+ const c = {
21
+ reset: '\x1b[0m',
22
+ bold: '\x1b[1m',
23
+ dim: '\x1b[2m',
24
+ italic: '\x1b[3m',
25
+ red: '\x1b[31m',
26
+ green: '\x1b[32m',
27
+ yellow: '\x1b[33m',
28
+ blue: '\x1b[34m',
29
+ magenta: '\x1b[35m',
30
+ cyan: '\x1b[36m',
31
+ white: '\x1b[37m',
32
+ gray: '\x1b[90m',
33
+ clearLine: '\x1b[2K',
34
+ hideCursor: '\x1b[?25l',
35
+ showCursor: '\x1b[?25h',
36
+ };
37
+
38
+ const rgb = (r, g, b) => `\x1b[38;2;${r};${g};${b}m`;
39
+
40
+ const colors = {
41
+ gradient1: rgb(255, 200, 100),
42
+ gradient2: rgb(255, 180, 80),
43
+ gradient3: rgb(255, 160, 60),
44
+ shipGreen: rgb(0, 255, 150),
45
+ warnAmber: rgb(255, 200, 0),
46
+ blockRed: rgb(255, 80, 80),
47
+ accent: rgb(255, 200, 100),
48
+ muted: rgb(120, 120, 140),
49
+ next: rgb(100, 200, 255),
50
+ fastify: rgb(255, 150, 200),
51
+ };
52
+
53
+ // ═══════════════════════════════════════════════════════════════════════════════
54
+ // PREMIUM BANNER
55
+ // ═══════════════════════════════════════════════════════════════════════════════
56
+
57
+ const INSTALL_BANNER = `
58
+ ${rgb(255, 200, 100)} ██╗███╗ ██╗███████╗████████╗ █████╗ ██╗ ██╗ ${c.reset}
59
+ ${rgb(255, 180, 80)} ██║████╗ ██║██╔════╝╚══██╔══╝██╔══██╗██║ ██║ ${c.reset}
60
+ ${rgb(255, 160, 60)} ██║██╔██╗ ██║███████╗ ██║ ███████║██║ ██║ ${c.reset}
61
+ ${rgb(255, 140, 40)} ██║██║╚██╗██║╚════██║ ██║ ██╔══██║██║ ██║ ${c.reset}
62
+ ${rgb(255, 120, 20)} ██║██║ ╚████║███████║ ██║ ██║ ██║███████╗███████╗${c.reset}
63
+ ${rgb(255, 100, 0)} ╚═╝╚═╝ ╚═══╝╚══════╝ ╚═╝ ╚═╝ ╚═╝╚══════╝╚══════╝${c.reset}
64
+ `;
65
+
66
+ const BANNER_FULL = `
67
+ ${rgb(255, 200, 100)} ██╗ ██╗██╗██████╗ ███████╗ ██████╗██╗ ██╗███████╗ ██████╗██╗ ██╗${c.reset}
68
+ ${rgb(255, 190, 90)} ██║ ██║██║██╔══██╗██╔════╝██╔════╝██║ ██║██╔════╝██╔════╝██║ ██╔╝${c.reset}
69
+ ${rgb(255, 180, 80)} ██║ ██║██║██████╔╝█████╗ ██║ ███████║█████╗ ██║ █████╔╝ ${c.reset}
70
+ ${rgb(255, 160, 60)} ╚██╗ ██╔╝██║██╔══██╗██╔══╝ ██║ ██╔══██║██╔══╝ ██║ ██╔═██╗ ${c.reset}
71
+ ${rgb(255, 140, 40)} ╚████╔╝ ██║██████╔╝███████╗╚██████╗██║ ██║███████╗╚██████╗██║ ██╗${c.reset}
72
+ ${rgb(255, 120, 20)} ╚═══╝ ╚═╝╚═════╝ ╚══════╝ ╚═════╝╚═╝ ╚═╝╚══════╝ ╚═════╝╚═╝ ╚═╝${c.reset}
73
+
74
+ ${c.dim} ┌─────────────────────────────────────────────────────────────────────┐${c.reset}
75
+ ${c.dim} │${c.reset} ${rgb(255, 200, 100)}📥${c.reset} ${c.bold}INSTALL${c.reset} ${c.dim}•${c.reset} ${rgb(200, 200, 200)}Zero-Friction${c.reset} ${c.dim}•${c.reset} ${rgb(150, 150, 150)}Auto-Detect${c.reset} ${c.dim}•${c.reset} ${rgb(100, 100, 100)}Onboarding${c.reset} ${c.dim}│${c.reset}
76
+ ${c.dim} └─────────────────────────────────────────────────────────────────────┘${c.reset}
77
+ `;
78
+
79
+ const ICONS = {
80
+ install: '📥',
81
+ package: '📦',
82
+ file: '📄',
83
+ check: '✓',
84
+ cross: '✗',
85
+ warning: '⚠',
86
+ arrow: '→',
87
+ bullet: '•',
88
+ sparkle: '✨',
89
+ folder: '📁',
90
+ next: '▲',
91
+ fastify: '⚡',
92
+ npm: '📦',
93
+ gear: '⚙️',
94
+ };
95
+
96
+ const SPINNER_DOTS = ['⣾', '⣽', '⣻', '⢿', '⡿', '⣟', '⣯', '⣷'];
97
+ let spinnerIndex = 0;
98
+ let spinnerInterval = null;
99
+ let spinnerStartTime = null;
100
+
101
+ function formatDuration(ms) {
102
+ if (ms < 1000) return `${ms}ms`;
103
+ return `${(ms / 1000).toFixed(1)}s`;
104
+ }
105
+
106
+ function startSpinner(message) {
107
+ spinnerStartTime = Date.now();
108
+ process.stdout.write(c.hideCursor);
109
+ spinnerInterval = setInterval(() => {
110
+ const elapsed = formatDuration(Date.now() - spinnerStartTime);
111
+ process.stdout.write(`\r${c.clearLine} ${colors.accent}${SPINNER_DOTS[spinnerIndex]}${c.reset} ${message} ${c.dim}${elapsed}${c.reset}`);
112
+ spinnerIndex = (spinnerIndex + 1) % SPINNER_DOTS.length;
113
+ }, 80);
114
+ }
115
+
116
+ function stopSpinner(message, success = true) {
117
+ if (spinnerInterval) {
118
+ clearInterval(spinnerInterval);
119
+ spinnerInterval = null;
120
+ }
121
+ const elapsed = spinnerStartTime ? formatDuration(Date.now() - spinnerStartTime) : '';
122
+ const icon = success ? `${colors.shipGreen}${ICONS.check}${c.reset}` : `${colors.blockRed}${ICONS.cross}${c.reset}`;
123
+ process.stdout.write(`\r${c.clearLine} ${icon} ${message} ${c.dim}${elapsed}${c.reset}\n`);
124
+ process.stdout.write(c.showCursor);
125
+ spinnerStartTime = null;
126
+ }
127
+
128
+ function printDivider(char = '─', width = 69, color = c.dim) {
129
+ console.log(`${color} ${char.repeat(width)}${c.reset}`);
130
+ }
131
+
132
+ function printSection(title, icon = '◆') {
133
+ console.log();
134
+ console.log(` ${colors.accent}${icon}${c.reset} ${c.bold}${title}${c.reset}`);
135
+ printDivider();
136
+ }
137
+
9
138
  function printHelp() {
139
+ console.log(BANNER_FULL);
10
140
  console.log(`
11
- vibecheck install - Zero-friction onboarding
12
-
13
- USAGE
14
- vibecheck install [options]
15
-
16
- OPTIONS
17
- --path, -p <dir> Project path (default: current directory)
18
- --help, -h Show this help
19
-
20
- WHAT IT DOES
21
- 1. Detects package manager (npm, yarn, pnpm)
22
- 2. Detects frameworks (Next.js, Fastify)
23
- 3. Builds initial truthpack
24
- 4. Creates .vibecheck/config.json
25
- 5. Generates env template from truthpack
26
- 6. Adds vibecheck scripts to package.json
27
-
28
- CREATED FILES
29
- .vibecheck/config.json - Local configuration
30
- .vibecheck/truthpack.json - Ground truth for AI agents
31
- .env.template - Env vars from truthpack
32
-
33
- EXAMPLES
34
- vibecheck install # Install in current directory
35
- vibecheck install --path ./my-app # Install in specific directory
36
- `);
141
+ ${c.bold}Usage:${c.reset} vibecheck install [options]
142
+
143
+ ${c.bold}Zero-Friction Onboarding${c.reset} — Auto-detect and configure your project.
144
+
145
+ ${c.bold}Options:${c.reset}
146
+ ${colors.accent}--path, -p <dir>${c.reset} Project path ${c.dim}(default: current directory)${c.reset}
147
+ ${colors.accent}--help, -h${c.reset} Show this help
148
+
149
+ ${c.bold}What It Does:${c.reset}
150
+ ${colors.shipGreen}1.${c.reset} Detects package manager ${c.dim}(npm, yarn, pnpm)${c.reset}
151
+ ${colors.shipGreen}2.${c.reset} Detects frameworks ${c.dim}(Next.js, Fastify)${c.reset}
152
+ ${colors.shipGreen}3.${c.reset} Builds initial truthpack
153
+ ${colors.shipGreen}4.${c.reset} Creates .vibecheck/config.json
154
+ ${colors.shipGreen}5.${c.reset} Generates env template from truthpack
155
+ ${colors.shipGreen}6.${c.reset} Adds vibecheck scripts to package.json
156
+
157
+ ${c.bold}Created Files:${c.reset}
158
+ ${ICONS.file} ${colors.accent}.vibecheck/config.json${c.reset} ${c.dim}Local configuration${c.reset}
159
+ ${ICONS.file} ${colors.accent}.vibecheck/truthpack.json${c.reset} ${c.dim}Ground truth for AI agents${c.reset}
160
+ ${ICONS.file} ${colors.accent}.env.template${c.reset} ${c.dim}Env vars from truthpack${c.reset}
161
+
162
+ ${c.bold}Examples:${c.reset}
163
+ ${c.dim}# Install in current directory${c.reset}
164
+ vibecheck install
165
+
166
+ ${c.dim}# Install in specific directory${c.reset}
167
+ vibecheck install --path ./my-app
168
+ `);
37
169
  }
38
170
 
39
171
  function ensureDir(p) {
@@ -52,20 +184,32 @@ async function runInstall(argsOrContext = {}) {
52
184
 
53
185
  const { repoRoot } = argsOrContext;
54
186
  const root = repoRoot || process.cwd();
187
+ const projectName = path.basename(root);
188
+
189
+ // Print banner
190
+ console.log(BANNER_FULL);
191
+ console.log(` ${c.dim}Project:${c.reset} ${c.bold}${projectName}${c.reset}`);
192
+ console.log(` ${c.dim}Path:${c.reset} ${root}`);
193
+ console.log();
55
194
 
56
195
  const { path: pkgPath, json: pkg } = readPkg(root);
57
196
 
197
+ // Detect environment
198
+ startSpinner('Detecting environment...');
58
199
  const pm = detectPackageManager(root);
59
200
  const next = detectNext(root, pkg);
60
201
  const fastify = detectFastify(root, pkg);
61
-
62
202
  const fastifyEntry = fastify.enabled ? await detectFastifyEntry(root) : null;
203
+ stopSpinner('Environment detected', true);
63
204
 
64
- // Build truthpack once (this powers env template + ctx baseline)
205
+ // Build truthpack
206
+ startSpinner('Building truthpack...');
65
207
  const truthpack = await buildTruthpack({ repoRoot: root, fastifyEntry: fastifyEntry || undefined });
66
208
  writeTruthpack(root, truthpack);
209
+ stopSpinner('Truthpack built', true);
67
210
 
68
- // Write minimal local config
211
+ // Write config
212
+ startSpinner('Writing configuration...');
69
213
  const cfgDir = path.join(root, ".vibecheck");
70
214
  ensureDir(cfgDir);
71
215
 
@@ -80,37 +224,54 @@ async function runInstall(argsOrContext = {}) {
80
224
  };
81
225
 
82
226
  fs.writeFileSync(path.join(cfgDir, "config.json"), JSON.stringify(cfg, null, 2), "utf8");
227
+ stopSpinner('Configuration written', true);
83
228
 
84
- // Generate/extend env template from reality
229
+ // Generate env template
230
+ startSpinner('Generating env template...');
85
231
  const envRes = writeEnvTemplateFromTruthpack(root, truthpack);
232
+ stopSpinner(envRes.wrote ? `Env template generated (+${envRes.added.length} vars)` : 'Env template up to date', true);
86
233
 
87
- // Add scripts (vibecoder-friendly)
234
+ // Add scripts
235
+ startSpinner('Updating package.json scripts...');
88
236
  const scriptsToAdd = {
89
237
  "vibecheck:ctx": "vibecheck ctx",
90
238
  "vibecheck:ship": "vibecheck ship",
91
239
  "vibecheck:fix": "vibecheck fix --apply",
92
240
  "vibecheck:pr": "vibecheck pr"
93
241
  };
94
-
95
242
  const changedScripts = upsertScripts(pkg, scriptsToAdd);
96
243
  if (changedScripts.length) writePkg(pkgPath, pkg);
244
+ stopSpinner(changedScripts.length ? `Added ${changedScripts.length} scripts` : 'Scripts up to date', true);
97
245
 
98
- // Output (one next command)
99
- console.log(`\n✅ vibecheck install`);
100
- console.log(`Detected package manager: ${pm}`);
101
- console.log(`Detected Next: ${next.enabled ? "yes" : "no"}`);
102
- console.log(`Detected Fastify: ${fastify.enabled ? "yes" : "no"}`);
103
- if (fastifyEntry) console.log(`Fastify entry: ${fastifyEntry}`);
246
+ // Summary
247
+ printSection('DETECTED', ICONS.gear);
248
+ console.log();
249
+ console.log(` ${ICONS.npm} ${c.bold}Package Manager:${c.reset} ${colors.accent}${pm}${c.reset}`);
250
+ console.log(` ${colors.next}${ICONS.next}${c.reset} ${c.bold}Next.js:${c.reset} ${next.enabled ? `${colors.shipGreen}yes${c.reset}` : `${c.dim}no${c.reset}`}`);
251
+ console.log(` ${colors.fastify}${ICONS.fastify}${c.reset} ${c.bold}Fastify:${c.reset} ${fastify.enabled ? `${colors.shipGreen}yes${c.reset}` : `${c.dim}no${c.reset}`}`);
252
+ if (fastifyEntry) {
253
+ console.log(` ${c.dim} Entry:${c.reset} ${colors.accent}${fastifyEntry}${c.reset}`);
254
+ }
104
255
 
105
- console.log(`\nWrote:`);
106
- console.log(`- .vibecheck/config.json`);
107
- console.log(`- .vibecheck/truthpack.json`);
108
- if (envRes.wrote) console.log(`- ${envRes.outRel} (+${envRes.added.length} var(s))`);
109
- if (changedScripts.length) console.log(`- package.json scripts: ${changedScripts.join(", ")}`);
256
+ printSection('CREATED FILES', ICONS.folder);
257
+ console.log();
258
+ console.log(` ${colors.shipGreen}${ICONS.check}${c.reset} ${ICONS.file} ${colors.accent}.vibecheck/config.json${c.reset}`);
259
+ console.log(` ${colors.shipGreen}${ICONS.check}${c.reset} ${ICONS.file} ${colors.accent}.vibecheck/truthpack.json${c.reset}`);
260
+ if (envRes.wrote) {
261
+ console.log(` ${colors.shipGreen}${ICONS.check}${c.reset} ${ICONS.file} ${colors.accent}${envRes.outRel}${c.reset} ${c.dim}(+${envRes.added.length} vars)${c.reset}`);
262
+ }
263
+ if (changedScripts.length) {
264
+ console.log(` ${colors.shipGreen}${ICONS.check}${c.reset} ${ICONS.file} ${colors.accent}package.json${c.reset} ${c.dim}(${changedScripts.join(', ')})${c.reset}`);
265
+ }
110
266
 
267
+ // Next steps
111
268
  const runner = pm === "pnpm" ? "pnpm" : pm === "yarn" ? "yarn" : "npm run";
112
- console.log(`\nNext (do this):`);
113
- console.log(` ${runner} vibecheck:ship`);
269
+ printSection('NEXT STEP', ICONS.arrow);
270
+ console.log();
271
+ console.log(` ${colors.accent}${runner} vibecheck:ship${c.reset}`);
272
+ console.log();
273
+ console.log(` ${colors.shipGreen}${ICONS.sparkle}${c.reset} Installation complete!`);
274
+ console.log();
114
275
  }
115
276
 
116
277
  module.exports = { runInstall };