@codebakers/cli 3.4.0 → 3.4.1

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.
@@ -3,6 +3,7 @@ interface GoOptions {
3
3
  }
4
4
  /**
5
5
  * Zero-friction entry point - start using CodeBakers instantly
6
+ * Single command for both trial and paid users
6
7
  */
7
8
  export declare function go(options?: GoOptions): Promise<void>;
8
9
  export {};
@@ -11,6 +11,7 @@ const fs_1 = require("fs");
11
11
  const path_1 = require("path");
12
12
  const readline_1 = require("readline");
13
13
  const config_js_1 = require("../config.js");
14
+ const api_js_1 = require("../lib/api.js");
14
15
  const fingerprint_js_1 = require("../lib/fingerprint.js");
15
16
  function prompt(question) {
16
17
  const rl = (0, readline_1.createInterface)({
@@ -68,6 +69,7 @@ function log(message, options) {
68
69
  }
69
70
  /**
70
71
  * Zero-friction entry point - start using CodeBakers instantly
72
+ * Single command for both trial and paid users
71
73
  */
72
74
  async function go(options = {}) {
73
75
  log('Starting go command...', options);
@@ -76,19 +78,20 @@ async function go(options = {}) {
76
78
  console.log(chalk_1.default.blue(`
77
79
  ╔═══════════════════════════════════════════════════════════╗
78
80
  ║ ║
79
- ║ ${chalk_1.default.bold.white('CodeBakers - Zero Setup Required')}
81
+ ║ ${chalk_1.default.bold.white('CodeBakers - Get Started')}
80
82
  ║ ║
81
83
  ╚═══════════════════════════════════════════════════════════╝
82
84
  `));
83
85
  // Check if user already has an API key (paid user)
84
86
  log('Checking for existing API key...', options);
85
- const apiKey = (0, config_js_1.getApiKey)();
86
- if (apiKey) {
87
- log(`Found API key: ${apiKey.substring(0, 8)}...`, options);
88
- console.log(chalk_1.default.green(' ✓ You\'re already logged in with an API key!\n'));
89
- // Still install patterns if not already installed
90
- await installPatternsWithApiKey(apiKey, options);
87
+ const existingApiKey = (0, config_js_1.getApiKey)();
88
+ if (existingApiKey) {
89
+ log(`Found API key: ${existingApiKey.substring(0, 8)}...`, options);
90
+ console.log(chalk_1.default.green(' ✓ You\'re already logged in!\n'));
91
+ // Install patterns if not already installed
92
+ await installPatternsWithApiKey(existingApiKey, options);
91
93
  await configureMCP(options);
94
+ await showSuccessAndRestart();
92
95
  return;
93
96
  }
94
97
  log('No API key found, checking trial state...', options);
@@ -104,21 +107,33 @@ async function go(options = {}) {
104
107
  // Install patterns if not already installed
105
108
  await installPatterns(existingTrial.trialId, options);
106
109
  await configureMCP(options);
110
+ await showSuccessAndRestart();
107
111
  return;
108
112
  }
109
113
  // Check if trial expired
110
114
  if (existingTrial && (0, config_js_1.isTrialExpired)()) {
111
115
  console.log(chalk_1.default.yellow(' ⚠️ Your trial has expired.\n'));
112
- if (existingTrial.stage === 'anonymous') {
113
- console.log(chalk_1.default.white(' Extend your trial for 7 more days with GitHub:\n'));
114
- console.log(chalk_1.default.cyan(' codebakers extend\n'));
115
- console.log(chalk_1.default.gray(' Or upgrade to Pro ($49/month):\n'));
116
- console.log(chalk_1.default.cyan(' codebakers upgrade\n'));
116
+ // Offer to login with API key or extend
117
+ console.log(chalk_1.default.white(' Options:\n'));
118
+ console.log(chalk_1.default.cyan(' [1] Login with API key') + chalk_1.default.gray(' (I have an account)'));
119
+ console.log(chalk_1.default.cyan(' [2] Extend trial') + chalk_1.default.gray(' (7 more days with GitHub)\n'));
120
+ const choice = await prompt(chalk_1.default.gray(' Enter 1 or 2: '));
121
+ if (choice === '1') {
122
+ await handleApiKeyLogin(options);
123
+ return;
117
124
  }
118
125
  else {
119
- console.log(chalk_1.default.white(' Ready to upgrade? $49/month for unlimited access:\n'));
120
- console.log(chalk_1.default.cyan(' codebakers upgrade\n'));
126
+ console.log(chalk_1.default.cyan('\n Run: codebakers extend\n'));
127
+ return;
121
128
  }
129
+ }
130
+ // New user - ask how they want to proceed
131
+ console.log(chalk_1.default.white(' How would you like to get started?\n'));
132
+ console.log(chalk_1.default.cyan(' [1] Start free 7-day trial') + chalk_1.default.gray(' (no signup required)'));
133
+ console.log(chalk_1.default.cyan(' [2] Login with API key') + chalk_1.default.gray(' (I have an account)\n'));
134
+ const choice = await prompt(chalk_1.default.gray(' Enter 1 or 2: '));
135
+ if (choice === '2') {
136
+ await handleApiKeyLogin(options);
122
137
  return;
123
138
  }
124
139
  // Start new trial
@@ -183,18 +198,8 @@ async function go(options = {}) {
183
198
  await installPatterns(data.trialId, options);
184
199
  // Configure MCP
185
200
  await configureMCP(options);
186
- // Show success message
187
- console.log(chalk_1.default.green(`
188
- ╔═══════════════════════════════════════════════════════════╗
189
- ║ ✅ CodeBakers is ready! ║
190
- ║ ║
191
- ║ ${chalk_1.default.white('Your 7-day free trial has started.')} ║
192
- ║ ║
193
- ║ ${chalk_1.default.gray('Try: "Build me a todo app with authentication"')} ║
194
- ╚═══════════════════════════════════════════════════════════╝
195
- `));
196
- // Attempt auto-restart Claude Code
197
- await attemptAutoRestart();
201
+ // Show success and restart
202
+ await showSuccessAndRestart();
198
203
  }
199
204
  catch (error) {
200
205
  spinner.fail('Failed to start trial');
@@ -235,9 +240,50 @@ async function configureMCP(options = {}) {
235
240
  }
236
241
  }
237
242
  }
238
- async function attemptAutoRestart() {
243
+ /**
244
+ * Handle API key login flow (for paid users)
245
+ */
246
+ async function handleApiKeyLogin(options = {}) {
247
+ console.log(chalk_1.default.white('\n Enter your API key\n'));
248
+ console.log(chalk_1.default.gray(' Find it at: https://codebakers.ai/dashboard\n'));
249
+ const apiKey = await prompt(chalk_1.default.cyan(' API Key: '));
250
+ if (!apiKey) {
251
+ console.log(chalk_1.default.red('\n API key is required.\n'));
252
+ return;
253
+ }
254
+ const spinner = (0, ora_1.default)('Validating API key...').start();
255
+ try {
256
+ await (0, api_js_1.validateApiKey)(apiKey);
257
+ spinner.succeed('API key validated');
258
+ // Save API key
259
+ (0, config_js_1.setApiKey)(apiKey);
260
+ console.log(chalk_1.default.green(' ✓ Logged in successfully!\n'));
261
+ // Install patterns
262
+ await installPatternsWithApiKey(apiKey, options);
263
+ // Configure MCP
264
+ await configureMCP(options);
265
+ // Show success
266
+ await showSuccessAndRestart();
267
+ }
268
+ catch (error) {
269
+ spinner.fail('Invalid API key');
270
+ console.log(chalk_1.default.red('\n Could not validate API key.'));
271
+ console.log(chalk_1.default.gray(' Check your key at: https://codebakers.ai/dashboard\n'));
272
+ }
273
+ }
274
+ /**
275
+ * Show success message and offer to restart
276
+ */
277
+ async function showSuccessAndRestart() {
239
278
  const cwd = process.cwd();
240
- console.log(chalk_1.default.yellow('\n ⚠️ RESTART REQUIRED\n'));
279
+ console.log(chalk_1.default.green(`
280
+ ╔═══════════════════════════════════════════════════════════╗
281
+ ║ ✅ CodeBakers is ready! ║
282
+ ║ ║
283
+ ║ ${chalk_1.default.gray('Try: "Build me a todo app with authentication"')} ║
284
+ ╚═══════════════════════════════════════════════════════════╝
285
+ `));
286
+ console.log(chalk_1.default.yellow(' ⚠️ RESTART REQUIRED\n'));
241
287
  console.log(chalk_1.default.gray(' Claude Code needs to restart to load CodeBakers.\n'));
242
288
  const answer = await prompt(chalk_1.default.cyan(' Restart Claude Code now? (Y/n): '));
243
289
  if (answer === 'n' || answer === 'no') {
@@ -249,7 +295,6 @@ async function attemptAutoRestart() {
249
295
  try {
250
296
  const isWindows = process.platform === 'win32';
251
297
  if (isWindows) {
252
- // On Windows, spawn a new Claude process detached and exit
253
298
  (0, child_process_1.spawn)('cmd', ['/c', 'start', 'claude'], {
254
299
  cwd,
255
300
  detached: true,
@@ -258,7 +303,6 @@ async function attemptAutoRestart() {
258
303
  }).unref();
259
304
  }
260
305
  else {
261
- // On Mac/Linux, spawn claude in new terminal
262
306
  (0, child_process_1.spawn)('claude', [], {
263
307
  cwd,
264
308
  detached: true,
@@ -268,12 +312,10 @@ async function attemptAutoRestart() {
268
312
  }
269
313
  console.log(chalk_1.default.green(' ✓ Claude Code is restarting...\n'));
270
314
  console.log(chalk_1.default.gray(' This terminal will close. Claude Code will open in a new window.\n'));
271
- // Give the spawn a moment to start
272
315
  await new Promise(resolve => setTimeout(resolve, 1000));
273
- // Exit this process
274
316
  process.exit(0);
275
317
  }
276
- catch (error) {
318
+ catch {
277
319
  console.log(chalk_1.default.yellow(' Could not auto-restart. Please restart Claude Code manually.\n'));
278
320
  }
279
321
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@codebakers/cli",
3
- "version": "3.4.0",
3
+ "version": "3.4.1",
4
4
  "description": "CodeBakers CLI - Production patterns for AI-assisted development",
5
5
  "main": "dist/index.js",
6
6
  "bin": {
@@ -9,10 +9,12 @@ import {
9
9
  setTrialState,
10
10
  getApiUrl,
11
11
  getApiKey,
12
+ setApiKey,
12
13
  isTrialExpired,
13
14
  getTrialDaysRemaining,
14
15
  type TrialState,
15
16
  } from '../config.js';
17
+ import { validateApiKey } from '../lib/api.js';
16
18
  import { getDeviceFingerprint } from '../lib/fingerprint.js';
17
19
 
18
20
  function prompt(question: string): Promise<string> {
@@ -98,6 +100,7 @@ function log(message: string, options?: GoOptions): void {
98
100
 
99
101
  /**
100
102
  * Zero-friction entry point - start using CodeBakers instantly
103
+ * Single command for both trial and paid users
101
104
  */
102
105
  export async function go(options: GoOptions = {}): Promise<void> {
103
106
  log('Starting go command...', options);
@@ -107,21 +110,22 @@ export async function go(options: GoOptions = {}): Promise<void> {
107
110
  console.log(chalk.blue(`
108
111
  ╔═══════════════════════════════════════════════════════════╗
109
112
  ║ ║
110
- ║ ${chalk.bold.white('CodeBakers - Zero Setup Required')}
113
+ ║ ${chalk.bold.white('CodeBakers - Get Started')}
111
114
  ║ ║
112
115
  ╚═══════════════════════════════════════════════════════════╝
113
116
  `));
114
117
 
115
118
  // Check if user already has an API key (paid user)
116
119
  log('Checking for existing API key...', options);
117
- const apiKey = getApiKey();
118
- if (apiKey) {
119
- log(`Found API key: ${apiKey.substring(0, 8)}...`, options);
120
- console.log(chalk.green(' ✓ You\'re already logged in with an API key!\n'));
120
+ const existingApiKey = getApiKey();
121
+ if (existingApiKey) {
122
+ log(`Found API key: ${existingApiKey.substring(0, 8)}...`, options);
123
+ console.log(chalk.green(' ✓ You\'re already logged in!\n'));
121
124
 
122
- // Still install patterns if not already installed
123
- await installPatternsWithApiKey(apiKey, options);
125
+ // Install patterns if not already installed
126
+ await installPatternsWithApiKey(existingApiKey, options);
124
127
  await configureMCP(options);
128
+ await showSuccessAndRestart();
125
129
  return;
126
130
  }
127
131
  log('No API key found, checking trial state...', options);
@@ -140,8 +144,8 @@ export async function go(options: GoOptions = {}): Promise<void> {
140
144
 
141
145
  // Install patterns if not already installed
142
146
  await installPatterns(existingTrial.trialId, options);
143
-
144
147
  await configureMCP(options);
148
+ await showSuccessAndRestart();
145
149
  return;
146
150
  }
147
151
 
@@ -149,15 +153,31 @@ export async function go(options: GoOptions = {}): Promise<void> {
149
153
  if (existingTrial && isTrialExpired()) {
150
154
  console.log(chalk.yellow(' ⚠️ Your trial has expired.\n'));
151
155
 
152
- if (existingTrial.stage === 'anonymous') {
153
- console.log(chalk.white(' Extend your trial for 7 more days with GitHub:\n'));
154
- console.log(chalk.cyan(' codebakers extend\n'));
155
- console.log(chalk.gray(' Or upgrade to Pro ($49/month):\n'));
156
- console.log(chalk.cyan(' codebakers upgrade\n'));
156
+ // Offer to login with API key or extend
157
+ console.log(chalk.white(' Options:\n'));
158
+ console.log(chalk.cyan(' [1] Login with API key') + chalk.gray(' (I have an account)'));
159
+ console.log(chalk.cyan(' [2] Extend trial') + chalk.gray(' (7 more days with GitHub)\n'));
160
+
161
+ const choice = await prompt(chalk.gray(' Enter 1 or 2: '));
162
+
163
+ if (choice === '1') {
164
+ await handleApiKeyLogin(options);
165
+ return;
157
166
  } else {
158
- console.log(chalk.white(' Ready to upgrade? $49/month for unlimited access:\n'));
159
- console.log(chalk.cyan(' codebakers upgrade\n'));
167
+ console.log(chalk.cyan('\n Run: codebakers extend\n'));
168
+ return;
160
169
  }
170
+ }
171
+
172
+ // New user - ask how they want to proceed
173
+ console.log(chalk.white(' How would you like to get started?\n'));
174
+ console.log(chalk.cyan(' [1] Start free 7-day trial') + chalk.gray(' (no signup required)'));
175
+ console.log(chalk.cyan(' [2] Login with API key') + chalk.gray(' (I have an account)\n'));
176
+
177
+ const choice = await prompt(chalk.gray(' Enter 1 or 2: '));
178
+
179
+ if (choice === '2') {
180
+ await handleApiKeyLogin(options);
161
181
  return;
162
182
  }
163
183
 
@@ -235,19 +255,8 @@ export async function go(options: GoOptions = {}): Promise<void> {
235
255
  // Configure MCP
236
256
  await configureMCP(options);
237
257
 
238
- // Show success message
239
- console.log(chalk.green(`
240
- ╔═══════════════════════════════════════════════════════════╗
241
- ║ ✅ CodeBakers is ready! ║
242
- ║ ║
243
- ║ ${chalk.white('Your 7-day free trial has started.')} ║
244
- ║ ║
245
- ║ ${chalk.gray('Try: "Build me a todo app with authentication"')} ║
246
- ╚═══════════════════════════════════════════════════════════╝
247
- `));
248
-
249
- // Attempt auto-restart Claude Code
250
- await attemptAutoRestart();
258
+ // Show success and restart
259
+ await showSuccessAndRestart();
251
260
 
252
261
  } catch (error) {
253
262
  spinner.fail('Failed to start trial');
@@ -289,10 +298,61 @@ async function configureMCP(options: GoOptions = {}): Promise<void> {
289
298
  }
290
299
  }
291
300
 
292
- async function attemptAutoRestart(): Promise<void> {
301
+ /**
302
+ * Handle API key login flow (for paid users)
303
+ */
304
+ async function handleApiKeyLogin(options: GoOptions = {}): Promise<void> {
305
+ console.log(chalk.white('\n Enter your API key\n'));
306
+ console.log(chalk.gray(' Find it at: https://codebakers.ai/dashboard\n'));
307
+
308
+ const apiKey = await prompt(chalk.cyan(' API Key: '));
309
+
310
+ if (!apiKey) {
311
+ console.log(chalk.red('\n API key is required.\n'));
312
+ return;
313
+ }
314
+
315
+ const spinner = ora('Validating API key...').start();
316
+
317
+ try {
318
+ await validateApiKey(apiKey);
319
+ spinner.succeed('API key validated');
320
+
321
+ // Save API key
322
+ setApiKey(apiKey);
323
+ console.log(chalk.green(' ✓ Logged in successfully!\n'));
324
+
325
+ // Install patterns
326
+ await installPatternsWithApiKey(apiKey, options);
327
+
328
+ // Configure MCP
329
+ await configureMCP(options);
330
+
331
+ // Show success
332
+ await showSuccessAndRestart();
333
+
334
+ } catch (error) {
335
+ spinner.fail('Invalid API key');
336
+ console.log(chalk.red('\n Could not validate API key.'));
337
+ console.log(chalk.gray(' Check your key at: https://codebakers.ai/dashboard\n'));
338
+ }
339
+ }
340
+
341
+ /**
342
+ * Show success message and offer to restart
343
+ */
344
+ async function showSuccessAndRestart(): Promise<void> {
293
345
  const cwd = process.cwd();
294
346
 
295
- console.log(chalk.yellow('\n ⚠️ RESTART REQUIRED\n'));
347
+ console.log(chalk.green(`
348
+ ╔═══════════════════════════════════════════════════════════╗
349
+ ║ ✅ CodeBakers is ready! ║
350
+ ║ ║
351
+ ║ ${chalk.gray('Try: "Build me a todo app with authentication"')} ║
352
+ ╚═══════════════════════════════════════════════════════════╝
353
+ `));
354
+
355
+ console.log(chalk.yellow(' ⚠️ RESTART REQUIRED\n'));
296
356
  console.log(chalk.gray(' Claude Code needs to restart to load CodeBakers.\n'));
297
357
 
298
358
  const answer = await prompt(chalk.cyan(' Restart Claude Code now? (Y/n): '));
@@ -309,7 +369,6 @@ async function attemptAutoRestart(): Promise<void> {
309
369
  const isWindows = process.platform === 'win32';
310
370
 
311
371
  if (isWindows) {
312
- // On Windows, spawn a new Claude process detached and exit
313
372
  spawn('cmd', ['/c', 'start', 'claude'], {
314
373
  cwd,
315
374
  detached: true,
@@ -317,7 +376,6 @@ async function attemptAutoRestart(): Promise<void> {
317
376
  shell: true,
318
377
  }).unref();
319
378
  } else {
320
- // On Mac/Linux, spawn claude in new terminal
321
379
  spawn('claude', [], {
322
380
  cwd,
323
381
  detached: true,
@@ -329,13 +387,10 @@ async function attemptAutoRestart(): Promise<void> {
329
387
  console.log(chalk.green(' ✓ Claude Code is restarting...\n'));
330
388
  console.log(chalk.gray(' This terminal will close. Claude Code will open in a new window.\n'));
331
389
 
332
- // Give the spawn a moment to start
333
390
  await new Promise(resolve => setTimeout(resolve, 1000));
334
-
335
- // Exit this process
336
391
  process.exit(0);
337
392
 
338
- } catch (error) {
393
+ } catch {
339
394
  console.log(chalk.yellow(' Could not auto-restart. Please restart Claude Code manually.\n'));
340
395
  }
341
396
  }