vibecodingmachine-cli 2025.12.25-1541 → 2026.1.3-2209

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.
@@ -46,7 +46,10 @@ const streamPipeline = promisify(pipeline);
46
46
  const packageJson = require('../package.json');
47
47
 
48
48
  // Import localization
49
- const { t, detectLocale, setLocale } = require('vibecodingmachine-core');
49
+ const { t, detectLocale, setLocale, errorReporter } = require('vibecodingmachine-core');
50
+
51
+ // Import prompt helper
52
+ const { promptWithDefaultsOnce } = require('../src/utils/prompt-helper');
50
53
 
51
54
  // Initialize locale detection
52
55
  const detectedLocale = detectLocale();
@@ -56,6 +59,7 @@ setLocale(detectedLocale);
56
59
  const repoCommands = require('../src/commands/repo');
57
60
  const autoCommands = require('../src/commands/auto');
58
61
  const reqCommands = require('../src/commands/requirements');
62
+ const featureCommands = require('../src/commands/feature');
59
63
  const ideCommands = require('../src/commands/ide');
60
64
  const statusCommands = require('../src/commands/status');
61
65
 
@@ -140,6 +144,9 @@ program
140
144
  .command('req:list')
141
145
  .description(t('cli.req.list'))
142
146
  .option('-s, --status <status>', 'Filter by status (pending, in-progress, completed)')
147
+ .option('-c, --computer <hostname>', 'Filter by computer hostname')
148
+ .option('-f, --focus <area>', 'Filter by focus area')
149
+ .option('-a, --all-computers', 'Show requirements from all computers with computer tags')
143
150
  .action(reqCommands.list);
144
151
 
145
152
  program
@@ -172,6 +179,33 @@ program
172
179
  .description(t('cli.req.rename'))
173
180
  .action((oldTitle, newTitle, description) => reqCommands.rename(oldTitle, newTitle, description));
174
181
 
182
+ program
183
+ .command('req:number-all')
184
+ .description('Number all existing requirements with R1, R2, R3, etc.')
185
+ .action(reqCommands.numberAll);
186
+
187
+ // Feature branch management commands
188
+ program
189
+ .command('feature:start <requirement-title>')
190
+ .description('Create and checkout feature branch for requirement (e.g., "R1: Email System")')
191
+ .action(featureCommands.start);
192
+
193
+ program
194
+ .command('feature:finish <requirement-title>')
195
+ .description('Merge feature branch back to parent and delete branch')
196
+ .option('-p, --parent <branch>', 'Parent branch to merge into', 'main')
197
+ .action(featureCommands.finish);
198
+
199
+ program
200
+ .command('feature:remove <requirement-title>')
201
+ .description('Remove a feature by reverting its merge commit')
202
+ .action(featureCommands.remove);
203
+
204
+ program
205
+ .command('feature:list')
206
+ .description('List all requirement feature branches')
207
+ .action(featureCommands.list);
208
+
175
209
  // IDE integration commands
176
210
  program
177
211
  .command('ide:list')
@@ -314,19 +348,21 @@ program
314
348
  });
315
349
 
316
350
  // Error handling
317
- process.on('uncaughtException', (error) => {
351
+ process.on('uncaughtException', async (error) => {
318
352
  console.error(chalk.red(`${t('cli.error')}:`), error.message);
319
353
  if (process.env.DEBUG) {
320
354
  console.error(chalk.gray('Stack:'), error.stack);
321
355
  }
356
+ await errorReporter.reportError(error, { type: 'uncaughtException' });
322
357
  process.exit(1);
323
358
  });
324
359
 
325
- process.on('unhandledRejection', (error) => {
360
+ process.on('unhandledRejection', async (error) => {
326
361
  console.error(chalk.red(`${t('cli.error')}:`), error.message);
327
362
  if (process.env.DEBUG) {
328
363
  console.error(chalk.gray('Stack:'), error.stack);
329
364
  }
365
+ await errorReporter.reportError(error, { type: 'unhandledRejection' });
330
366
  process.exit(1);
331
367
  });
332
368
 
@@ -336,15 +372,29 @@ async function checkForUpdates() {
336
372
  if (process.env.VCM_SKIP_UPDATE_CHECK === '1' || process.env.VCM_SKIP_UPDATE_CHECK === 'true') {
337
373
  return;
338
374
  }
339
- const { checkForCLIUpdates } = require('vibecodingmachine-core');
340
375
  // If running inside the repository (local development), skip update checks entirely
341
376
  const isDevWorkspace = fs.existsSync(path.join(rootDir, '.git'));
342
377
  if (isDevWorkspace) {
343
378
  console.log(chalk.yellow('\nDetected local development workspace; skipping update check.'));
344
379
  return;
345
380
  }
381
+ // Additional check: if we're in a workspace with package.json containing vibecodingmachine-cli
382
+ const packageJsonPath = path.join(rootDir, 'package.json');
383
+ if (fs.existsSync(packageJsonPath)) {
384
+ try {
385
+ const pkg = JSON.parse(fs.readFileSync(packageJsonPath, 'utf8'));
386
+ if (pkg.name === 'vibecodingmachine' || (pkg.workspaces && pkg.workspaces.length > 0)) {
387
+ console.log(chalk.yellow('\nDetected local development workspace; skipping update check.'));
388
+ return;
389
+ }
390
+ } catch (e) {
391
+ // Ignore JSON parse errors
392
+ }
393
+ }
346
394
  console.log(chalk.gray(`\n🔍 Checking for updates... (current: v${packageJson.version})`));
347
- const updateInfo = await checkForCLIUpdates(packageJson.version);
395
+ // Check npm registry for CLI updates (not S3 manifest which is for Electron)
396
+ const { checkForUpdates: checkNpmUpdates } = require('vibecodingmachine-core');
397
+ const updateInfo = await checkNpmUpdates('vibecodingmachine-cli', packageJson.version);
348
398
  console.log(chalk.gray(` Update check result: ${JSON.stringify(updateInfo)}\n`));
349
399
 
350
400
  if (updateInfo.hasUpdate) {
@@ -356,7 +406,7 @@ async function checkForUpdates() {
356
406
  console.log(chalk.gray(` Published: ${updateInfo.publishedDate}`));
357
407
 
358
408
  // Prompt user to update
359
- const answer = await inquirer.prompt([
409
+ const answer = await promptWithDefaultsOnce([
360
410
  {
361
411
  type: 'confirm',
362
412
  name: 'shouldUpdate',
@@ -376,127 +426,19 @@ async function checkForUpdates() {
376
426
  // Do not attempt global install during development to avoid confusing local dev flow
377
427
  return;
378
428
  }
379
- const spinner = ora('Fetching package metadata...').start();
380
-
381
- // Get latest package metadata from npm registry
382
- const registryUrl = 'https://registry.npmjs.org/vibecodingmachine-cli/latest';
383
- const meta = await new Promise((resolve, reject) => {
384
- https.get(registryUrl, (res) => {
385
- let data = '';
386
- res.on('data', (chunk) => data += chunk);
387
- res.on('end', () => {
388
- try {
389
- resolve(JSON.parse(data));
390
- } catch (err) {
391
- reject(err);
392
- }
393
- });
394
- }).on('error', reject);
395
- });
396
-
397
- const tarball = meta && meta.dist && meta.dist.tarball;
398
- if (!tarball) {
399
- spinner.fail('Could not determine tarball URL for update');
400
- console.log(chalk.yellow(' You can manually update with: ') + chalk.bold.white('npm install -g vibecodingmachine-cli@latest\n'));
401
- return;
402
- }
403
-
404
- spinner.text = 'Resolving tarball...';
405
-
406
- // HEAD to get content-length
407
- const totalBytes = await new Promise((resolve) => {
408
- const req = https.request(tarball, { method: 'HEAD' }, (res) => {
409
- const len = parseInt(res.headers['content-length'] || '0', 10);
410
- resolve(Number.isFinite(len) ? len : 0);
411
- });
412
- req.on('error', () => resolve(0));
413
- req.end();
414
- });
415
-
416
- const tmpFile = path.join(os.tmpdir(), `vcm-update-${Date.now()}.tgz`);
417
-
418
- // Download tarball with progress
419
- spinner.text = 'Downloading update...';
420
- // Stop the spinner so we can write a single-line progress indicator without conflicts
421
- try { spinner.stop(); } catch (e) {}
422
- // Print initial progress line (clear line first)
423
- process.stdout.write('\r\x1b[2KDownloading: 0% — 0.0 MB');
424
- const progressStart = Date.now();
425
- function formatEta(sec) {
426
- if (!isFinite(sec) || sec === null) return '--:--';
427
- const s = Math.max(0, Math.round(sec));
428
- const m = Math.floor(s / 60);
429
- const ss = s % 60;
430
- return `${m}:${ss.toString().padStart(2, '0')}`;
431
- }
432
- await new Promise((resolve, reject) => {
433
- https.get(tarball, (res) => {
434
- const fileStream = fs.createWriteStream(tmpFile);
435
- let downloaded = 0;
436
-
437
- // Print an updating single-line progress indicator (percent + MB)
438
- let lastPercent = -1;
439
- let lastMbReported = -1;
440
- res.on('data', (chunk) => {
441
- downloaded += chunk.length;
442
- const percent = totalBytes ? Math.round((downloaded / totalBytes) * 100) : null;
443
- const mbDownloaded = +(downloaded / (1024 * 1024));
444
- const mbTotal = totalBytes ? (totalBytes / (1024 * 1024)) : null;
445
-
446
- // ETA and speed
447
- const elapsedSec = Math.max(0.001, (Date.now() - progressStart) / 1000);
448
- const speed = downloaded / elapsedSec; // bytes/sec
449
- const remaining = totalBytes ? Math.max(0, totalBytes - downloaded) : null;
450
- const etaSec = remaining && speed > 0 ? remaining / speed : null;
451
-
452
- // Build simple ASCII progress bar
453
- const width = 30;
454
- const fill = percent !== null ? Math.round((percent / 100) * width) : Math.min(width, Math.max(0, Math.round((mbDownloaded / (mbTotal || 1)) * width)));
455
- const bar = '█'.repeat(fill) + '-'.repeat(Math.max(0, width - fill));
456
-
457
- const pctText = percent !== null ? `${percent}%` : '--%';
458
- const mbText = mbTotal ? `${mbDownloaded.toFixed(1)} MB / ${mbTotal.toFixed(1)} MB` : `${mbDownloaded.toFixed(1)} MB`;
459
- const etaText = etaSec ? formatEta(etaSec) : '--:--';
460
-
461
- // Update only when percent changes or every 0.5 MB to reduce noise
462
- const mbReport = Math.floor(mbDownloaded * 2) / 2;
463
- if ((percent !== null && percent !== lastPercent) || (percent === null && mbReport !== lastMbReported) || Math.random() < 0.001) {
464
- lastPercent = percent;
465
- lastMbReported = mbReport;
466
- process.stdout.write(`\r\x1b[2K[${bar}] ${pctText} ${mbText} ETA: ${etaText}`);
467
- }
468
- });
469
-
470
- res.on('end', () => fileStream.end());
471
- res.on('error', (err) => reject(err));
472
-
473
- fileStream.on('finish', () => resolve());
474
- fileStream.on('error', (err) => reject(err));
475
-
476
- res.pipe(fileStream);
477
- }).on('error', reject);
478
- });
479
-
480
- // Ensure progress line ends and move to next line
481
- process.stdout.write('\n');
482
- spinner.start();
483
- spinner.succeed('Downloaded update');
484
-
485
- // Install the downloaded tarball
486
- spinner.start('Installing update...');
429
+
430
+ const spinner = ora('Installing update from npm...').start();
487
431
  try {
488
- execSync(`npm install -g "${tmpFile}"`, { stdio: 'inherit', encoding: 'utf8' });
432
+ // Use npm directly to install the latest version from registry
433
+ execSync('npm install -g vibecodingmachine-cli@latest', { stdio: 'inherit', encoding: 'utf8' });
489
434
  spinner.succeed('Installed update');
490
435
  console.log(chalk.green('\n✅ Successfully updated to v' + updateInfo.latestVersion + '!'));
491
436
  console.log(chalk.gray(' Please restart your command to use the new version.\n'));
492
- // Cleanup
493
- try { fs.unlinkSync(tmpFile); } catch (e) {}
494
437
  process.exit(0);
495
438
  } catch (err) {
496
439
  spinner.fail('Installation failed');
497
440
  console.log(chalk.red('\n❌ Update failed:'), err.message);
498
441
  console.log(chalk.yellow(' You can manually update with: ') + chalk.bold.white('npm install -g vibecodingmachine-cli@latest\n'));
499
- try { fs.unlinkSync(tmpFile); } catch (e) {}
500
442
  }
501
443
  } catch (error) {
502
444
  console.log(chalk.red('\n❌ Update failed:'), error.message);
@@ -533,10 +475,22 @@ if (!process.argv.slice(2).length) {
533
475
  try {
534
476
  await auth.login();
535
477
  console.log(chalk.green(`\n✓ ${t('cli.auth.success')}\n`));
478
+
479
+ // Initialize error reporter with auth token
480
+ const token = await auth.getAuthToken();
481
+ if (token) {
482
+ errorReporter.setAuthToken(token);
483
+ }
536
484
  } catch (error) {
537
485
  console.log(chalk.red(`\n✗ ${t('cli.auth.failed')}:`), error.message);
538
486
  process.exit(1);
539
487
  }
488
+ } else {
489
+ // Initialize error reporter with existing auth token
490
+ const token = await auth.getAuthToken();
491
+ if (token) {
492
+ errorReporter.setAuthToken(token);
493
+ }
540
494
  }
541
495
 
542
496
  // Check compliance after authentication
@@ -574,10 +528,22 @@ if (!process.argv.slice(2).length) {
574
528
  try {
575
529
  await auth.login();
576
530
  console.log(chalk.green(`\n✓ ${t('cli.auth.success')}\n`));
531
+
532
+ // Initialize error reporter with auth token
533
+ const token = await auth.getAuthToken();
534
+ if (token) {
535
+ errorReporter.setAuthToken(token);
536
+ }
577
537
  } catch (error) {
578
538
  console.log(chalk.red(`\n✗ ${t('cli.auth.failed')}:`), error.message);
579
539
  process.exit(1);
580
540
  }
541
+ } else {
542
+ // Initialize error reporter with existing auth token
543
+ const token = await auth.getAuthToken();
544
+ if (token) {
545
+ errorReporter.setAuthToken(token);
546
+ }
581
547
  }
582
548
  }
583
549
 
@@ -0,0 +1 @@
1
+ {"timestamp":"2025-12-28T01:17:10.393Z","type":"auto-mode-stop","reason":"startup","message":"Auto Mode stopped (startup)"}
@@ -0,0 +1,2 @@
1
+ {"timestamp":"2026-01-04T04:29:09.497Z","type":"auto-mode-stop","reason":"startup","message":"Auto Mode stopped (startup)"}
2
+ {"timestamp":"2026-01-04T04:46:49.126Z","type":"auto-mode-stop","reason":"startup","message":"Auto Mode stopped (startup)"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "vibecodingmachine-cli",
3
- "version": "2025.12.25-1541",
3
+ "version": "2026.01.03-2209",
4
4
  "description": "Command-line interface for Vibe Coding Machine - Autonomous development",
5
5
  "main": "src/index.js",
6
6
  "bin": {
@@ -25,7 +25,7 @@
25
25
  "author": "Vibe Coding Machine Team",
26
26
  "license": "MIT",
27
27
  "dependencies": {
28
- "vibecodingmachine-core": "^2025.12.25-1541",
28
+ "vibecodingmachine-core": "^2026.01.03-2209",
29
29
  "@aws-sdk/client-dynamodb": "^3.600.0",
30
30
  "@aws-sdk/lib-dynamodb": "^3.600.0",
31
31
  "boxen": "^5.1.2",
@@ -1,6 +1,6 @@
1
1
  const chalk = require('chalk');
2
2
  const auth = require('../utils/auth');
3
- const { t } = require('vibecodingmachine-core');
3
+ const { t, errorReporter } = require('vibecodingmachine-core');
4
4
 
5
5
  /**
6
6
  * Login command
@@ -28,6 +28,10 @@ async function login(options = {}) {
28
28
  }
29
29
  } catch (error) {
30
30
  console.error(chalk.red(`\n✗ ${t('auth.login.failed')}:`), error.message);
31
+ await errorReporter.reportError(error, {
32
+ command: 'auth:login',
33
+ headless: options.headless
34
+ });
31
35
  process.exit(1);
32
36
  }
33
37
  }