@codebakers/cli 3.1.0 → 3.2.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.
package/dist/config.d.ts CHANGED
@@ -43,6 +43,8 @@ interface ConfigSchema {
43
43
  serviceKeys: ServiceKeys;
44
44
  lastKeySync: string | null;
45
45
  trial: TrialState | null;
46
+ lastUpdateCheck: string | null;
47
+ latestKnownVersion: string | null;
46
48
  }
47
49
  export declare function getApiKey(): string | null;
48
50
  export declare function setApiKey(key: string): void;
@@ -105,4 +107,19 @@ export declare function hasValidAccess(): boolean;
105
107
  * Get authentication mode: 'apiKey', 'trial', or 'none'
106
108
  */
107
109
  export declare function getAuthMode(): 'apiKey' | 'trial' | 'none';
110
+ /**
111
+ * Get cached update info if still valid (within 24 hours)
112
+ */
113
+ export declare function getCachedUpdateInfo(): {
114
+ latestVersion: string;
115
+ checkedAt: string;
116
+ } | null;
117
+ /**
118
+ * Cache the latest version from npm registry
119
+ */
120
+ export declare function setCachedUpdateInfo(latestVersion: string): void;
121
+ /**
122
+ * Get the current CLI version from package.json
123
+ */
124
+ export declare function getCliVersion(): string;
108
125
  export {};
package/dist/config.js CHANGED
@@ -32,6 +32,9 @@ exports.isTrialExpired = isTrialExpired;
32
32
  exports.getTrialDaysRemaining = getTrialDaysRemaining;
33
33
  exports.hasValidAccess = hasValidAccess;
34
34
  exports.getAuthMode = getAuthMode;
35
+ exports.getCachedUpdateInfo = getCachedUpdateInfo;
36
+ exports.setCachedUpdateInfo = setCachedUpdateInfo;
37
+ exports.getCliVersion = getCliVersion;
35
38
  const conf_1 = __importDefault(require("conf"));
36
39
  const fs_1 = require("fs");
37
40
  const path_1 = require("path");
@@ -126,6 +129,8 @@ const config = new conf_1.default({
126
129
  serviceKeys: defaultServiceKeys,
127
130
  lastKeySync: null,
128
131
  trial: null,
132
+ lastUpdateCheck: null,
133
+ latestKnownVersion: null,
129
134
  },
130
135
  // Migration to add new keys when upgrading from old version
131
136
  migrations: {
@@ -411,3 +416,33 @@ function getAuthMode() {
411
416
  return 'trial';
412
417
  return 'none';
413
418
  }
419
+ // ============================================
420
+ // Update Notification Cache
421
+ // ============================================
422
+ const UPDATE_CHECK_INTERVAL_HOURS = 24;
423
+ /**
424
+ * Get cached update info if still valid (within 24 hours)
425
+ */
426
+ function getCachedUpdateInfo() {
427
+ const lastCheck = config.get('lastUpdateCheck');
428
+ const latestVersion = config.get('latestKnownVersion');
429
+ if (!lastCheck || !latestVersion)
430
+ return null;
431
+ const hoursSinceCheck = (Date.now() - new Date(lastCheck).getTime()) / (1000 * 60 * 60);
432
+ if (hoursSinceCheck > UPDATE_CHECK_INTERVAL_HOURS)
433
+ return null;
434
+ return { latestVersion, checkedAt: lastCheck };
435
+ }
436
+ /**
437
+ * Cache the latest version from npm registry
438
+ */
439
+ function setCachedUpdateInfo(latestVersion) {
440
+ config.set('lastUpdateCheck', new Date().toISOString());
441
+ config.set('latestKnownVersion', latestVersion);
442
+ }
443
+ /**
444
+ * Get the current CLI version from package.json
445
+ */
446
+ function getCliVersion() {
447
+ return '3.2.0'; // Keep in sync with package.json
448
+ }
package/dist/index.js CHANGED
@@ -26,6 +26,53 @@ const push_patterns_js_1 = require("./commands/push-patterns.js");
26
26
  const go_js_1 = require("./commands/go.js");
27
27
  const extend_js_1 = require("./commands/extend.js");
28
28
  const billing_js_1 = require("./commands/billing.js");
29
+ const config_js_2 = require("./config.js");
30
+ // ============================================
31
+ // Automatic Update Notification
32
+ // ============================================
33
+ const CURRENT_VERSION = '3.2.0';
34
+ async function checkForUpdatesInBackground() {
35
+ // Check if we have a valid cached result first (fast path)
36
+ const cached = (0, config_js_2.getCachedUpdateInfo)();
37
+ if (cached) {
38
+ if (cached.latestVersion !== CURRENT_VERSION) {
39
+ showUpdateBanner(CURRENT_VERSION, cached.latestVersion);
40
+ }
41
+ return;
42
+ }
43
+ // Fetch from npm registry (with timeout to not block CLI)
44
+ try {
45
+ const controller = new AbortController();
46
+ const timeout = setTimeout(() => controller.abort(), 3000);
47
+ const response = await fetch('https://registry.npmjs.org/@codebakers/cli/latest', {
48
+ headers: { 'Accept': 'application/json' },
49
+ signal: controller.signal,
50
+ });
51
+ clearTimeout(timeout);
52
+ if (response.ok) {
53
+ const data = await response.json();
54
+ const latestVersion = data.version;
55
+ (0, config_js_2.setCachedUpdateInfo)(latestVersion);
56
+ if (latestVersion !== CURRENT_VERSION) {
57
+ showUpdateBanner(CURRENT_VERSION, latestVersion);
58
+ }
59
+ }
60
+ }
61
+ catch {
62
+ // Silently fail - don't block CLI for update check
63
+ }
64
+ }
65
+ function showUpdateBanner(currentVersion, latestVersion) {
66
+ console.log(chalk_1.default.yellow(`
67
+ ╭─────────────────────────────────────────────────────────╮
68
+ │ │
69
+ │ ${chalk_1.default.bold('Update available!')} ${chalk_1.default.gray(currentVersion)} → ${chalk_1.default.green(latestVersion)} │
70
+ │ │
71
+ │ Run ${chalk_1.default.cyan('npm i -g @codebakers/cli@latest')} to update │
72
+ │ │
73
+ ╰─────────────────────────────────────────────────────────╯
74
+ `));
75
+ }
29
76
  // Show welcome message when no command is provided
30
77
  function showWelcome() {
31
78
  console.log(chalk_1.default.blue(`
@@ -67,7 +114,7 @@ const program = new commander_1.Command();
67
114
  program
68
115
  .name('codebakers')
69
116
  .description('CodeBakers CLI - Production patterns for AI-assisted development')
70
- .version('3.1.0');
117
+ .version('3.2.0');
71
118
  // Zero-friction trial entry (no signup required)
72
119
  program
73
120
  .command('go')
@@ -199,9 +246,16 @@ program
199
246
  .command('mcp-uninstall')
200
247
  .description('Remove MCP configuration from Claude Code')
201
248
  .action(mcp_config_js_1.mcpUninstall);
249
+ // Add update check hook (runs before every command)
250
+ program.hook('preAction', async () => {
251
+ await checkForUpdatesInBackground();
252
+ });
202
253
  // Show welcome if no command provided
203
254
  if (process.argv.length <= 2) {
204
- showWelcome();
255
+ // Still check for updates when showing welcome
256
+ checkForUpdatesInBackground().then(() => {
257
+ showWelcome();
258
+ });
205
259
  }
206
260
  else {
207
261
  program.parse();
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@codebakers/cli",
3
- "version": "3.1.0",
3
+ "version": "3.2.0",
4
4
  "description": "CodeBakers CLI - Production patterns for AI-assisted development",
5
5
  "main": "dist/index.js",
6
6
  "bin": {
package/src/config.ts CHANGED
@@ -116,6 +116,9 @@ interface ConfigSchema {
116
116
  lastKeySync: string | null; // ISO date of last sync with server
117
117
  // Trial state (for zero-friction onboarding)
118
118
  trial: TrialState | null;
119
+ // Update notification cache
120
+ lastUpdateCheck: string | null; // ISO date of last npm registry check
121
+ latestKnownVersion: string | null; // Cached latest version from npm
119
122
  }
120
123
 
121
124
  // Create default service keys object with all keys set to null
@@ -133,6 +136,8 @@ const config = new Conf<ConfigSchema>({
133
136
  serviceKeys: defaultServiceKeys,
134
137
  lastKeySync: null,
135
138
  trial: null,
139
+ lastUpdateCheck: null,
140
+ latestKnownVersion: null,
136
141
  },
137
142
  // Migration to add new keys when upgrading from old version
138
143
  migrations: {
@@ -489,3 +494,39 @@ export function getAuthMode(): 'apiKey' | 'trial' | 'none' {
489
494
 
490
495
  return 'none';
491
496
  }
497
+
498
+ // ============================================
499
+ // Update Notification Cache
500
+ // ============================================
501
+
502
+ const UPDATE_CHECK_INTERVAL_HOURS = 24;
503
+
504
+ /**
505
+ * Get cached update info if still valid (within 24 hours)
506
+ */
507
+ export function getCachedUpdateInfo(): { latestVersion: string; checkedAt: string } | null {
508
+ const lastCheck = config.get('lastUpdateCheck');
509
+ const latestVersion = config.get('latestKnownVersion');
510
+
511
+ if (!lastCheck || !latestVersion) return null;
512
+
513
+ const hoursSinceCheck = (Date.now() - new Date(lastCheck).getTime()) / (1000 * 60 * 60);
514
+ if (hoursSinceCheck > UPDATE_CHECK_INTERVAL_HOURS) return null;
515
+
516
+ return { latestVersion, checkedAt: lastCheck };
517
+ }
518
+
519
+ /**
520
+ * Cache the latest version from npm registry
521
+ */
522
+ export function setCachedUpdateInfo(latestVersion: string): void {
523
+ config.set('lastUpdateCheck', new Date().toISOString());
524
+ config.set('latestKnownVersion', latestVersion);
525
+ }
526
+
527
+ /**
528
+ * Get the current CLI version from package.json
529
+ */
530
+ export function getCliVersion(): string {
531
+ return '3.2.0'; // Keep in sync with package.json
532
+ }
package/src/index.ts CHANGED
@@ -22,6 +22,61 @@ import { pushPatterns, pushPatternsInteractive } from './commands/push-patterns.
22
22
  import { go } from './commands/go.js';
23
23
  import { extend } from './commands/extend.js';
24
24
  import { billing } from './commands/billing.js';
25
+ import { getCachedUpdateInfo, setCachedUpdateInfo, getCliVersion } from './config.js';
26
+
27
+ // ============================================
28
+ // Automatic Update Notification
29
+ // ============================================
30
+
31
+ const CURRENT_VERSION = '3.2.0';
32
+
33
+ async function checkForUpdatesInBackground(): Promise<void> {
34
+ // Check if we have a valid cached result first (fast path)
35
+ const cached = getCachedUpdateInfo();
36
+ if (cached) {
37
+ if (cached.latestVersion !== CURRENT_VERSION) {
38
+ showUpdateBanner(CURRENT_VERSION, cached.latestVersion);
39
+ }
40
+ return;
41
+ }
42
+
43
+ // Fetch from npm registry (with timeout to not block CLI)
44
+ try {
45
+ const controller = new AbortController();
46
+ const timeout = setTimeout(() => controller.abort(), 3000);
47
+
48
+ const response = await fetch('https://registry.npmjs.org/@codebakers/cli/latest', {
49
+ headers: { 'Accept': 'application/json' },
50
+ signal: controller.signal,
51
+ });
52
+
53
+ clearTimeout(timeout);
54
+
55
+ if (response.ok) {
56
+ const data = await response.json();
57
+ const latestVersion = data.version;
58
+ setCachedUpdateInfo(latestVersion);
59
+
60
+ if (latestVersion !== CURRENT_VERSION) {
61
+ showUpdateBanner(CURRENT_VERSION, latestVersion);
62
+ }
63
+ }
64
+ } catch {
65
+ // Silently fail - don't block CLI for update check
66
+ }
67
+ }
68
+
69
+ function showUpdateBanner(currentVersion: string, latestVersion: string): void {
70
+ console.log(chalk.yellow(`
71
+ ╭─────────────────────────────────────────────────────────╮
72
+ │ │
73
+ │ ${chalk.bold('Update available!')} ${chalk.gray(currentVersion)} → ${chalk.green(latestVersion)} │
74
+ │ │
75
+ │ Run ${chalk.cyan('npm i -g @codebakers/cli@latest')} to update │
76
+ │ │
77
+ ╰─────────────────────────────────────────────────────────╯
78
+ `));
79
+ }
25
80
 
26
81
  // Show welcome message when no command is provided
27
82
  function showWelcome(): void {
@@ -72,7 +127,7 @@ const program = new Command();
72
127
  program
73
128
  .name('codebakers')
74
129
  .description('CodeBakers CLI - Production patterns for AI-assisted development')
75
- .version('3.1.0');
130
+ .version('3.2.0');
76
131
 
77
132
  // Zero-friction trial entry (no signup required)
78
133
  program
@@ -225,9 +280,17 @@ program
225
280
  .description('Remove MCP configuration from Claude Code')
226
281
  .action(mcpUninstall);
227
282
 
283
+ // Add update check hook (runs before every command)
284
+ program.hook('preAction', async () => {
285
+ await checkForUpdatesInBackground();
286
+ });
287
+
228
288
  // Show welcome if no command provided
229
289
  if (process.argv.length <= 2) {
230
- showWelcome();
290
+ // Still check for updates when showing welcome
291
+ checkForUpdatesInBackground().then(() => {
292
+ showWelcome();
293
+ });
231
294
  } else {
232
295
  program.parse();
233
296
  }