@codebakers/cli 3.2.0 → 3.3.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
@@ -45,6 +45,8 @@ interface ConfigSchema {
45
45
  trial: TrialState | null;
46
46
  lastUpdateCheck: string | null;
47
47
  latestKnownVersion: string | null;
48
+ lastPatternCheck: string | null;
49
+ latestPatternVersion: string | null;
48
50
  }
49
51
  export declare function getApiKey(): string | null;
50
52
  export declare function setApiKey(key: string): void;
@@ -122,4 +124,19 @@ export declare function setCachedUpdateInfo(latestVersion: string): void;
122
124
  * Get the current CLI version from package.json
123
125
  */
124
126
  export declare function getCliVersion(): string;
127
+ /**
128
+ * Get cached pattern version info if still valid (within 6 hours)
129
+ */
130
+ export declare function getCachedPatternInfo(): {
131
+ latestVersion: string;
132
+ checkedAt: string;
133
+ } | null;
134
+ /**
135
+ * Cache the latest pattern version from server
136
+ */
137
+ export declare function setCachedPatternInfo(latestVersion: string): void;
138
+ /**
139
+ * Clear pattern cache to force a fresh check
140
+ */
141
+ export declare function clearPatternCache(): void;
125
142
  export {};
package/dist/config.js CHANGED
@@ -35,6 +35,9 @@ exports.getAuthMode = getAuthMode;
35
35
  exports.getCachedUpdateInfo = getCachedUpdateInfo;
36
36
  exports.setCachedUpdateInfo = setCachedUpdateInfo;
37
37
  exports.getCliVersion = getCliVersion;
38
+ exports.getCachedPatternInfo = getCachedPatternInfo;
39
+ exports.setCachedPatternInfo = setCachedPatternInfo;
40
+ exports.clearPatternCache = clearPatternCache;
38
41
  const conf_1 = __importDefault(require("conf"));
39
42
  const fs_1 = require("fs");
40
43
  const path_1 = require("path");
@@ -121,7 +124,7 @@ exports.PROVISIONABLE_KEYS = ['github', 'supabase', 'vercel'];
121
124
  const defaultServiceKeys = Object.fromEntries(exports.SERVICE_KEYS.map(key => [key, null]));
122
125
  const config = new conf_1.default({
123
126
  projectName: 'codebakers',
124
- projectVersion: '1.8.0',
127
+ projectVersion: '1.9.0',
125
128
  defaults: {
126
129
  apiKey: null,
127
130
  apiUrl: 'https://codebakers.ai',
@@ -131,6 +134,8 @@ const config = new conf_1.default({
131
134
  trial: null,
132
135
  lastUpdateCheck: null,
133
136
  latestKnownVersion: null,
137
+ lastPatternCheck: null,
138
+ latestPatternVersion: null,
134
139
  },
135
140
  // Migration to add new keys when upgrading from old version
136
141
  migrations: {
@@ -151,6 +156,15 @@ const config = new conf_1.default({
151
156
  store.set('trial', null);
152
157
  }
153
158
  },
159
+ '1.9.0': (store) => {
160
+ // Add pattern auto-update fields if not present
161
+ if (!store.has('lastPatternCheck')) {
162
+ store.set('lastPatternCheck', null);
163
+ }
164
+ if (!store.has('latestPatternVersion')) {
165
+ store.set('latestPatternVersion', null);
166
+ }
167
+ },
154
168
  },
155
169
  });
156
170
  // ============================================================
@@ -444,5 +458,36 @@ function setCachedUpdateInfo(latestVersion) {
444
458
  * Get the current CLI version from package.json
445
459
  */
446
460
  function getCliVersion() {
447
- return '3.2.0'; // Keep in sync with package.json
461
+ return '3.3.0'; // Keep in sync with package.json
462
+ }
463
+ // ============================================
464
+ // Pattern Auto-Update Cache
465
+ // ============================================
466
+ const PATTERN_CHECK_INTERVAL_HOURS = 6; // Check more frequently than CLI
467
+ /**
468
+ * Get cached pattern version info if still valid (within 6 hours)
469
+ */
470
+ function getCachedPatternInfo() {
471
+ const lastCheck = config.get('lastPatternCheck');
472
+ const latestVersion = config.get('latestPatternVersion');
473
+ if (!lastCheck || !latestVersion)
474
+ return null;
475
+ const hoursSinceCheck = (Date.now() - new Date(lastCheck).getTime()) / (1000 * 60 * 60);
476
+ if (hoursSinceCheck > PATTERN_CHECK_INTERVAL_HOURS)
477
+ return null;
478
+ return { latestVersion, checkedAt: lastCheck };
479
+ }
480
+ /**
481
+ * Cache the latest pattern version from server
482
+ */
483
+ function setCachedPatternInfo(latestVersion) {
484
+ config.set('lastPatternCheck', new Date().toISOString());
485
+ config.set('latestPatternVersion', latestVersion);
486
+ }
487
+ /**
488
+ * Clear pattern cache to force a fresh check
489
+ */
490
+ function clearPatternCache() {
491
+ config.set('lastPatternCheck', null);
492
+ config.set('latestPatternVersion', null);
448
493
  }
package/dist/index.js CHANGED
@@ -27,10 +27,12 @@ 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
29
  const config_js_2 = require("./config.js");
30
+ const fs_1 = require("fs");
31
+ const path_1 = require("path");
30
32
  // ============================================
31
33
  // Automatic Update Notification
32
34
  // ============================================
33
- const CURRENT_VERSION = '3.2.0';
35
+ const CURRENT_VERSION = '3.3.0';
34
36
  async function checkForUpdatesInBackground() {
35
37
  // Check if we have a valid cached result first (fast path)
36
38
  const cached = (0, config_js_2.getCachedUpdateInfo)();
@@ -73,6 +75,144 @@ function showUpdateBanner(currentVersion, latestVersion) {
73
75
  ╰─────────────────────────────────────────────────────────╯
74
76
  `));
75
77
  }
78
+ function getLocalPatternVersion() {
79
+ const cwd = process.cwd();
80
+ const versionFile = (0, path_1.join)(cwd, '.claude', '.version.json');
81
+ if (!(0, fs_1.existsSync)(versionFile))
82
+ return null;
83
+ try {
84
+ const content = (0, fs_1.readFileSync)(versionFile, 'utf-8');
85
+ const info = JSON.parse(content);
86
+ return info.version;
87
+ }
88
+ catch {
89
+ return null;
90
+ }
91
+ }
92
+ function isCodeBakersProject() {
93
+ const cwd = process.cwd();
94
+ return (0, fs_1.existsSync)((0, path_1.join)(cwd, 'CLAUDE.md')) || (0, fs_1.existsSync)((0, path_1.join)(cwd, '.claude'));
95
+ }
96
+ async function autoUpdatePatterns() {
97
+ // Only auto-update if this is a CodeBakers project
98
+ if (!isCodeBakersProject())
99
+ return;
100
+ // Only auto-update if user has valid access
101
+ if (!(0, config_js_2.hasValidAccess)())
102
+ return;
103
+ const localVersion = getLocalPatternVersion();
104
+ // Check if we have a valid cached result first (fast path)
105
+ const cached = (0, config_js_2.getCachedPatternInfo)();
106
+ if (cached) {
107
+ // If local matches latest, nothing to do
108
+ if (localVersion === cached.latestVersion)
109
+ return;
110
+ // If we know there's an update but haven't updated yet, do it now
111
+ if (localVersion !== cached.latestVersion) {
112
+ await performPatternUpdate(cached.latestVersion);
113
+ }
114
+ return;
115
+ }
116
+ // Fetch from server to check for updates (with timeout)
117
+ try {
118
+ const controller = new AbortController();
119
+ const timeout = setTimeout(() => controller.abort(), 5000);
120
+ const apiUrl = (0, config_js_2.getApiUrl)();
121
+ const apiKey = (0, config_js_2.getApiKey)();
122
+ const trial = (0, config_js_2.getTrialState)();
123
+ // Build authorization header
124
+ let authHeader = '';
125
+ if (apiKey) {
126
+ authHeader = `Bearer ${apiKey}`;
127
+ }
128
+ else if (trial?.trialId) {
129
+ authHeader = `Trial ${trial.trialId}`;
130
+ }
131
+ if (!authHeader)
132
+ return;
133
+ // First, check the version endpoint (lightweight)
134
+ const versionResponse = await fetch(`${apiUrl}/api/content/version`, {
135
+ method: 'GET',
136
+ headers: {
137
+ 'Authorization': authHeader,
138
+ },
139
+ signal: controller.signal,
140
+ });
141
+ clearTimeout(timeout);
142
+ if (versionResponse.ok) {
143
+ const versionData = await versionResponse.json();
144
+ const serverVersion = versionData.version;
145
+ // Cache the version info
146
+ (0, config_js_2.setCachedPatternInfo)(serverVersion);
147
+ // If local version is different, update
148
+ if (localVersion !== serverVersion) {
149
+ await performPatternUpdate(serverVersion);
150
+ }
151
+ }
152
+ }
153
+ catch {
154
+ // Silently fail - don't block CLI for pattern check
155
+ }
156
+ }
157
+ async function performPatternUpdate(targetVersion) {
158
+ const cwd = process.cwd();
159
+ const claudeMdPath = (0, path_1.join)(cwd, 'CLAUDE.md');
160
+ const claudeDir = (0, path_1.join)(cwd, '.claude');
161
+ try {
162
+ const apiUrl = (0, config_js_2.getApiUrl)();
163
+ const apiKey = (0, config_js_2.getApiKey)();
164
+ const trial = (0, config_js_2.getTrialState)();
165
+ let authHeader = '';
166
+ if (apiKey) {
167
+ authHeader = `Bearer ${apiKey}`;
168
+ }
169
+ else if (trial?.trialId) {
170
+ authHeader = `Trial ${trial.trialId}`;
171
+ }
172
+ if (!authHeader)
173
+ return;
174
+ const controller = new AbortController();
175
+ const timeout = setTimeout(() => controller.abort(), 10000);
176
+ const response = await fetch(`${apiUrl}/api/content`, {
177
+ method: 'GET',
178
+ headers: {
179
+ 'Authorization': authHeader,
180
+ },
181
+ signal: controller.signal,
182
+ });
183
+ clearTimeout(timeout);
184
+ if (!response.ok)
185
+ return;
186
+ const content = await response.json();
187
+ // Update CLAUDE.md
188
+ if (content.router) {
189
+ (0, fs_1.writeFileSync)(claudeMdPath, content.router);
190
+ }
191
+ // Update pattern modules
192
+ if (content.modules && Object.keys(content.modules).length > 0) {
193
+ if (!(0, fs_1.existsSync)(claudeDir)) {
194
+ (0, fs_1.mkdirSync)(claudeDir, { recursive: true });
195
+ }
196
+ for (const [name, data] of Object.entries(content.modules)) {
197
+ (0, fs_1.writeFileSync)((0, path_1.join)(claudeDir, name), data);
198
+ }
199
+ }
200
+ // Write version file
201
+ const moduleCount = Object.keys(content.modules || {}).length;
202
+ const versionInfo = {
203
+ version: content.version,
204
+ moduleCount,
205
+ updatedAt: new Date().toISOString(),
206
+ cliVersion: (0, config_js_2.getCliVersion)(),
207
+ };
208
+ (0, fs_1.writeFileSync)((0, path_1.join)(claudeDir, '.version.json'), JSON.stringify(versionInfo, null, 2));
209
+ // Show subtle notification
210
+ console.log(chalk_1.default.green(` ✓ Patterns auto-updated to v${content.version} (${moduleCount} modules)\n`));
211
+ }
212
+ catch {
213
+ // Silently fail - don't block the user
214
+ }
215
+ }
76
216
  // Show welcome message when no command is provided
77
217
  function showWelcome() {
78
218
  console.log(chalk_1.default.blue(`
@@ -114,7 +254,7 @@ const program = new commander_1.Command();
114
254
  program
115
255
  .name('codebakers')
116
256
  .description('CodeBakers CLI - Production patterns for AI-assisted development')
117
- .version('3.2.0');
257
+ .version('3.3.0');
118
258
  // Zero-friction trial entry (no signup required)
119
259
  program
120
260
  .command('go')
@@ -248,7 +388,11 @@ program
248
388
  .action(mcp_config_js_1.mcpUninstall);
249
389
  // Add update check hook (runs before every command)
250
390
  program.hook('preAction', async () => {
251
- await checkForUpdatesInBackground();
391
+ // Run CLI update check and pattern auto-update in parallel
392
+ await Promise.all([
393
+ checkForUpdatesInBackground(),
394
+ autoUpdatePatterns(),
395
+ ]);
252
396
  });
253
397
  // Show welcome if no command provided
254
398
  if (process.argv.length <= 2) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@codebakers/cli",
3
- "version": "3.2.0",
3
+ "version": "3.3.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,9 +116,12 @@ 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
119
+ // Update notification cache (CLI updates)
120
120
  lastUpdateCheck: string | null; // ISO date of last npm registry check
121
121
  latestKnownVersion: string | null; // Cached latest version from npm
122
+ // Pattern auto-update cache
123
+ lastPatternCheck: string | null; // ISO date of last pattern version check
124
+ latestPatternVersion: string | null; // Cached latest pattern version from server
122
125
  }
123
126
 
124
127
  // Create default service keys object with all keys set to null
@@ -128,7 +131,7 @@ const defaultServiceKeys: ServiceKeys = Object.fromEntries(
128
131
 
129
132
  const config = new Conf<ConfigSchema>({
130
133
  projectName: 'codebakers',
131
- projectVersion: '1.8.0',
134
+ projectVersion: '1.9.0',
132
135
  defaults: {
133
136
  apiKey: null,
134
137
  apiUrl: 'https://codebakers.ai',
@@ -138,6 +141,8 @@ const config = new Conf<ConfigSchema>({
138
141
  trial: null,
139
142
  lastUpdateCheck: null,
140
143
  latestKnownVersion: null,
144
+ lastPatternCheck: null,
145
+ latestPatternVersion: null,
141
146
  },
142
147
  // Migration to add new keys when upgrading from old version
143
148
  migrations: {
@@ -160,6 +165,15 @@ const config = new Conf<ConfigSchema>({
160
165
  store.set('trial', null);
161
166
  }
162
167
  },
168
+ '1.9.0': (store) => {
169
+ // Add pattern auto-update fields if not present
170
+ if (!store.has('lastPatternCheck')) {
171
+ store.set('lastPatternCheck', null);
172
+ }
173
+ if (!store.has('latestPatternVersion')) {
174
+ store.set('latestPatternVersion', null);
175
+ }
176
+ },
163
177
  },
164
178
  });
165
179
 
@@ -528,5 +542,42 @@ export function setCachedUpdateInfo(latestVersion: string): void {
528
542
  * Get the current CLI version from package.json
529
543
  */
530
544
  export function getCliVersion(): string {
531
- return '3.2.0'; // Keep in sync with package.json
545
+ return '3.3.0'; // Keep in sync with package.json
546
+ }
547
+
548
+ // ============================================
549
+ // Pattern Auto-Update Cache
550
+ // ============================================
551
+
552
+ const PATTERN_CHECK_INTERVAL_HOURS = 6; // Check more frequently than CLI
553
+
554
+ /**
555
+ * Get cached pattern version info if still valid (within 6 hours)
556
+ */
557
+ export function getCachedPatternInfo(): { latestVersion: string; checkedAt: string } | null {
558
+ const lastCheck = config.get('lastPatternCheck');
559
+ const latestVersion = config.get('latestPatternVersion');
560
+
561
+ if (!lastCheck || !latestVersion) return null;
562
+
563
+ const hoursSinceCheck = (Date.now() - new Date(lastCheck).getTime()) / (1000 * 60 * 60);
564
+ if (hoursSinceCheck > PATTERN_CHECK_INTERVAL_HOURS) return null;
565
+
566
+ return { latestVersion, checkedAt: lastCheck };
567
+ }
568
+
569
+ /**
570
+ * Cache the latest pattern version from server
571
+ */
572
+ export function setCachedPatternInfo(latestVersion: string): void {
573
+ config.set('lastPatternCheck', new Date().toISOString());
574
+ config.set('latestPatternVersion', latestVersion);
575
+ }
576
+
577
+ /**
578
+ * Clear pattern cache to force a fresh check
579
+ */
580
+ export function clearPatternCache(): void {
581
+ config.set('lastPatternCheck', null);
582
+ config.set('latestPatternVersion', null);
532
583
  }
package/src/index.ts CHANGED
@@ -22,13 +22,15 @@ 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';
25
+ import { getCachedUpdateInfo, setCachedUpdateInfo, getCliVersion, getCachedPatternInfo, setCachedPatternInfo, getApiKey, getApiUrl, getTrialState, hasValidAccess } from './config.js';
26
+ import { existsSync, writeFileSync, readFileSync, mkdirSync } from 'fs';
27
+ import { join } from 'path';
26
28
 
27
29
  // ============================================
28
30
  // Automatic Update Notification
29
31
  // ============================================
30
32
 
31
- const CURRENT_VERSION = '3.2.0';
33
+ const CURRENT_VERSION = '3.3.0';
32
34
 
33
35
  async function checkForUpdatesInBackground(): Promise<void> {
34
36
  // Check if we have a valid cached result first (fast path)
@@ -78,6 +80,181 @@ function showUpdateBanner(currentVersion: string, latestVersion: string): void {
78
80
  `));
79
81
  }
80
82
 
83
+ // ============================================
84
+ // Automatic Pattern Updates
85
+ // ============================================
86
+
87
+ interface PatternVersionInfo {
88
+ version: string;
89
+ moduleCount: number;
90
+ updatedAt: string;
91
+ cliVersion: string;
92
+ }
93
+
94
+ interface ContentResponse {
95
+ version: string;
96
+ router: string;
97
+ modules: Record<string, string>;
98
+ }
99
+
100
+ function getLocalPatternVersion(): string | null {
101
+ const cwd = process.cwd();
102
+ const versionFile = join(cwd, '.claude', '.version.json');
103
+
104
+ if (!existsSync(versionFile)) return null;
105
+
106
+ try {
107
+ const content = readFileSync(versionFile, 'utf-8');
108
+ const info: PatternVersionInfo = JSON.parse(content);
109
+ return info.version;
110
+ } catch {
111
+ return null;
112
+ }
113
+ }
114
+
115
+ function isCodeBakersProject(): boolean {
116
+ const cwd = process.cwd();
117
+ return existsSync(join(cwd, 'CLAUDE.md')) || existsSync(join(cwd, '.claude'));
118
+ }
119
+
120
+ async function autoUpdatePatterns(): Promise<void> {
121
+ // Only auto-update if this is a CodeBakers project
122
+ if (!isCodeBakersProject()) return;
123
+
124
+ // Only auto-update if user has valid access
125
+ if (!hasValidAccess()) return;
126
+
127
+ const localVersion = getLocalPatternVersion();
128
+
129
+ // Check if we have a valid cached result first (fast path)
130
+ const cached = getCachedPatternInfo();
131
+ if (cached) {
132
+ // If local matches latest, nothing to do
133
+ if (localVersion === cached.latestVersion) return;
134
+ // If we know there's an update but haven't updated yet, do it now
135
+ if (localVersion !== cached.latestVersion) {
136
+ await performPatternUpdate(cached.latestVersion);
137
+ }
138
+ return;
139
+ }
140
+
141
+ // Fetch from server to check for updates (with timeout)
142
+ try {
143
+ const controller = new AbortController();
144
+ const timeout = setTimeout(() => controller.abort(), 5000);
145
+
146
+ const apiUrl = getApiUrl();
147
+ const apiKey = getApiKey();
148
+ const trial = getTrialState();
149
+
150
+ // Build authorization header
151
+ let authHeader = '';
152
+ if (apiKey) {
153
+ authHeader = `Bearer ${apiKey}`;
154
+ } else if (trial?.trialId) {
155
+ authHeader = `Trial ${trial.trialId}`;
156
+ }
157
+
158
+ if (!authHeader) return;
159
+
160
+ // First, check the version endpoint (lightweight)
161
+ const versionResponse = await fetch(`${apiUrl}/api/content/version`, {
162
+ method: 'GET',
163
+ headers: {
164
+ 'Authorization': authHeader,
165
+ },
166
+ signal: controller.signal,
167
+ });
168
+
169
+ clearTimeout(timeout);
170
+
171
+ if (versionResponse.ok) {
172
+ const versionData = await versionResponse.json();
173
+ const serverVersion = versionData.version;
174
+
175
+ // Cache the version info
176
+ setCachedPatternInfo(serverVersion);
177
+
178
+ // If local version is different, update
179
+ if (localVersion !== serverVersion) {
180
+ await performPatternUpdate(serverVersion);
181
+ }
182
+ }
183
+ } catch {
184
+ // Silently fail - don't block CLI for pattern check
185
+ }
186
+ }
187
+
188
+ async function performPatternUpdate(targetVersion: string): Promise<void> {
189
+ const cwd = process.cwd();
190
+ const claudeMdPath = join(cwd, 'CLAUDE.md');
191
+ const claudeDir = join(cwd, '.claude');
192
+
193
+ try {
194
+ const apiUrl = getApiUrl();
195
+ const apiKey = getApiKey();
196
+ const trial = getTrialState();
197
+
198
+ let authHeader = '';
199
+ if (apiKey) {
200
+ authHeader = `Bearer ${apiKey}`;
201
+ } else if (trial?.trialId) {
202
+ authHeader = `Trial ${trial.trialId}`;
203
+ }
204
+
205
+ if (!authHeader) return;
206
+
207
+ const controller = new AbortController();
208
+ const timeout = setTimeout(() => controller.abort(), 10000);
209
+
210
+ const response = await fetch(`${apiUrl}/api/content`, {
211
+ method: 'GET',
212
+ headers: {
213
+ 'Authorization': authHeader,
214
+ },
215
+ signal: controller.signal,
216
+ });
217
+
218
+ clearTimeout(timeout);
219
+
220
+ if (!response.ok) return;
221
+
222
+ const content: ContentResponse = await response.json();
223
+
224
+ // Update CLAUDE.md
225
+ if (content.router) {
226
+ writeFileSync(claudeMdPath, content.router);
227
+ }
228
+
229
+ // Update pattern modules
230
+ if (content.modules && Object.keys(content.modules).length > 0) {
231
+ if (!existsSync(claudeDir)) {
232
+ mkdirSync(claudeDir, { recursive: true });
233
+ }
234
+
235
+ for (const [name, data] of Object.entries(content.modules)) {
236
+ writeFileSync(join(claudeDir, name), data);
237
+ }
238
+ }
239
+
240
+ // Write version file
241
+ const moduleCount = Object.keys(content.modules || {}).length;
242
+ const versionInfo: PatternVersionInfo = {
243
+ version: content.version,
244
+ moduleCount,
245
+ updatedAt: new Date().toISOString(),
246
+ cliVersion: getCliVersion(),
247
+ };
248
+ writeFileSync(join(claudeDir, '.version.json'), JSON.stringify(versionInfo, null, 2));
249
+
250
+ // Show subtle notification
251
+ console.log(chalk.green(` ✓ Patterns auto-updated to v${content.version} (${moduleCount} modules)\n`));
252
+
253
+ } catch {
254
+ // Silently fail - don't block the user
255
+ }
256
+ }
257
+
81
258
  // Show welcome message when no command is provided
82
259
  function showWelcome(): void {
83
260
  console.log(chalk.blue(`
@@ -127,7 +304,7 @@ const program = new Command();
127
304
  program
128
305
  .name('codebakers')
129
306
  .description('CodeBakers CLI - Production patterns for AI-assisted development')
130
- .version('3.2.0');
307
+ .version('3.3.0');
131
308
 
132
309
  // Zero-friction trial entry (no signup required)
133
310
  program
@@ -282,7 +459,11 @@ program
282
459
 
283
460
  // Add update check hook (runs before every command)
284
461
  program.hook('preAction', async () => {
285
- await checkForUpdatesInBackground();
462
+ // Run CLI update check and pattern auto-update in parallel
463
+ await Promise.all([
464
+ checkForUpdatesInBackground(),
465
+ autoUpdatePatterns(),
466
+ ]);
286
467
  });
287
468
 
288
469
  // Show welcome if no command provided