@codebakers/cli 3.4.0 → 3.5.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/commands/go.d.ts +1 -0
- package/dist/commands/go.js +222 -140
- package/package.json +1 -1
- package/src/commands/go.ts +243 -168
package/dist/commands/go.d.ts
CHANGED
package/dist/commands/go.js
CHANGED
|
@@ -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 -
|
|
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
|
|
86
|
-
if (
|
|
87
|
-
log(`Found API key: ${
|
|
88
|
-
console.log(chalk_1.default.green(' ✓ You\'re already logged in
|
|
89
|
-
//
|
|
90
|
-
await installPatternsWithApiKey(
|
|
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
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
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.
|
|
120
|
-
|
|
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
|
|
@@ -179,22 +194,12 @@ async function go(options = {}) {
|
|
|
179
194
|
(0, config_js_1.setTrialState)(trialState);
|
|
180
195
|
spinner.succeed(`Trial started (${data.daysRemaining} days free)`);
|
|
181
196
|
console.log('');
|
|
182
|
-
// Install
|
|
197
|
+
// Install v6.0 bootstrap files (CLAUDE.md and .cursorrules only)
|
|
183
198
|
await installPatterns(data.trialId, options);
|
|
184
199
|
// Configure MCP
|
|
185
200
|
await configureMCP(options);
|
|
186
|
-
// Show success
|
|
187
|
-
|
|
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
|
-
|
|
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.
|
|
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,135 +312,173 @@ 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
|
|
318
|
+
catch {
|
|
277
319
|
console.log(chalk_1.default.yellow(' Could not auto-restart. Please restart Claude Code manually.\n'));
|
|
278
320
|
}
|
|
279
321
|
}
|
|
322
|
+
// v6.0 Bootstrap content - minimal files that point to MCP tools
|
|
323
|
+
const V6_CLAUDE_MD = `# CodeBakers v6.0 - Server-Enforced Patterns
|
|
324
|
+
|
|
325
|
+
**All patterns are server-side. No local pattern files needed.**
|
|
326
|
+
|
|
327
|
+
## Required MCP Tools
|
|
328
|
+
|
|
329
|
+
Before writing ANY code, you MUST use these CodeBakers MCP tools:
|
|
330
|
+
|
|
331
|
+
### 1. discover_patterns (MANDATORY - START GATE)
|
|
332
|
+
Call this BEFORE writing any code:
|
|
333
|
+
\`\`\`
|
|
334
|
+
Tool: discover_patterns
|
|
335
|
+
Args: { task: "what you're about to do", files: ["files to modify"], keywords: ["relevant terms"] }
|
|
336
|
+
\`\`\`
|
|
337
|
+
This returns:
|
|
338
|
+
- Relevant patterns from the server
|
|
339
|
+
- A session token (required for validation)
|
|
340
|
+
- Code examples to follow
|
|
341
|
+
|
|
342
|
+
### 2. validate_complete (MANDATORY - END GATE)
|
|
343
|
+
Call this BEFORE saying "done" or "complete":
|
|
344
|
+
\`\`\`
|
|
345
|
+
Tool: validate_complete
|
|
346
|
+
Args: { feature: "what you built", files: ["files modified"] }
|
|
347
|
+
\`\`\`
|
|
348
|
+
This checks:
|
|
349
|
+
- You called discover_patterns first (server verifies)
|
|
350
|
+
- Tests exist and pass
|
|
351
|
+
- TypeScript compiles
|
|
352
|
+
- Returns pass/fail from server
|
|
353
|
+
|
|
354
|
+
## Rules
|
|
355
|
+
|
|
356
|
+
1. **You CANNOT skip discover_patterns** - Server tracks compliance
|
|
357
|
+
2. **You CANNOT say "done" without validate_complete** - Server must approve
|
|
358
|
+
3. **Follow patterns returned by server** - They are mandatory
|
|
359
|
+
4. **Write tests** - Validation will fail without them
|
|
360
|
+
5. **Fix TypeScript errors** - Validation will fail with errors
|
|
361
|
+
|
|
362
|
+
## If Server is Unreachable
|
|
363
|
+
|
|
364
|
+
The tools will show "OFFLINE MODE" if the server can't be reached. In this case:
|
|
365
|
+
- Enforcement is limited to local checks only
|
|
366
|
+
- You should still follow best practices
|
|
367
|
+
- Try again when connection is restored
|
|
368
|
+
|
|
369
|
+
## Getting Help
|
|
370
|
+
|
|
371
|
+
- Run \`codebakers doctor\` to diagnose issues
|
|
372
|
+
- Run \`codebakers upgrade\` to update patterns
|
|
373
|
+
- Visit https://codebakers.ai/support for help
|
|
374
|
+
|
|
375
|
+
---
|
|
376
|
+
*CodeBakers v6.0 - Server-Enforced Patterns*
|
|
377
|
+
`;
|
|
378
|
+
const V6_CURSORRULES = `# CodeBakers v6.0 - Server-Enforced Patterns
|
|
379
|
+
|
|
380
|
+
All patterns are server-side. No local pattern files needed.
|
|
381
|
+
|
|
382
|
+
## Required MCP Tools
|
|
383
|
+
|
|
384
|
+
Before writing ANY code, you MUST use these CodeBakers MCP tools:
|
|
385
|
+
|
|
386
|
+
### 1. discover_patterns (MANDATORY - START GATE)
|
|
387
|
+
Call this BEFORE writing any code:
|
|
388
|
+
- Tool: discover_patterns
|
|
389
|
+
- Args: { task: "what you're about to do", files: ["files to modify"], keywords: ["relevant terms"] }
|
|
390
|
+
|
|
391
|
+
Returns:
|
|
392
|
+
- Relevant patterns from the server
|
|
393
|
+
- A session token (required for validation)
|
|
394
|
+
- Code examples to follow
|
|
395
|
+
|
|
396
|
+
### 2. validate_complete (MANDATORY - END GATE)
|
|
397
|
+
Call this BEFORE saying "done" or "complete":
|
|
398
|
+
- Tool: validate_complete
|
|
399
|
+
- Args: { feature: "what you built", files: ["files modified"] }
|
|
400
|
+
|
|
401
|
+
Checks:
|
|
402
|
+
- You called discover_patterns first (server verifies)
|
|
403
|
+
- Tests exist and pass
|
|
404
|
+
- TypeScript compiles
|
|
405
|
+
- Returns pass/fail from server
|
|
406
|
+
|
|
407
|
+
## Rules
|
|
408
|
+
|
|
409
|
+
1. You CANNOT skip discover_patterns - Server tracks compliance
|
|
410
|
+
2. You CANNOT say "done" without validate_complete - Server must approve
|
|
411
|
+
3. Follow patterns returned by server - They are mandatory
|
|
412
|
+
4. Write tests - Validation will fail without them
|
|
413
|
+
5. Fix TypeScript errors - Validation will fail with errors
|
|
414
|
+
|
|
415
|
+
## If Server is Unreachable
|
|
416
|
+
|
|
417
|
+
The tools will show "OFFLINE MODE" if the server can't be reached. In this case:
|
|
418
|
+
- Enforcement is limited to local checks only
|
|
419
|
+
- You should still follow best practices
|
|
420
|
+
- Try again when connection is restored
|
|
421
|
+
|
|
422
|
+
---
|
|
423
|
+
CodeBakers v6.0 - Server-Enforced Patterns
|
|
424
|
+
`;
|
|
280
425
|
/**
|
|
281
|
-
* Install
|
|
426
|
+
* Install v6.0 bootstrap files for API key users (paid users)
|
|
427
|
+
* Only installs minimal CLAUDE.md and .cursorrules - no .claude/ folder
|
|
282
428
|
*/
|
|
283
429
|
async function installPatternsWithApiKey(apiKey, options = {}) {
|
|
284
|
-
log('Installing
|
|
285
|
-
|
|
286
|
-
const cwd = process.cwd();
|
|
287
|
-
const apiUrl = (0, config_js_1.getApiUrl)();
|
|
288
|
-
log(`Fetching from: ${apiUrl}/api/content`, options);
|
|
289
|
-
try {
|
|
290
|
-
const response = await fetch(`${apiUrl}/api/content`, {
|
|
291
|
-
method: 'GET',
|
|
292
|
-
headers: {
|
|
293
|
-
'Authorization': `Bearer ${apiKey}`,
|
|
294
|
-
},
|
|
295
|
-
});
|
|
296
|
-
if (!response.ok) {
|
|
297
|
-
log(`Response not OK: ${response.status} ${response.statusText}`, options);
|
|
298
|
-
spinner.warn('Could not download patterns');
|
|
299
|
-
return;
|
|
300
|
-
}
|
|
301
|
-
log('Response OK, parsing JSON...', options);
|
|
302
|
-
const content = await response.json();
|
|
303
|
-
log(`Received version: ${content.version}, modules: ${Object.keys(content.modules || {}).length}`, options);
|
|
304
|
-
await writePatternFiles(cwd, content, spinner, options, { apiKey });
|
|
305
|
-
}
|
|
306
|
-
catch (error) {
|
|
307
|
-
log(`Error: ${error instanceof Error ? error.message : String(error)}`, options);
|
|
308
|
-
spinner.warn('Could not install patterns');
|
|
309
|
-
console.log(chalk_1.default.gray(' Check your internet connection.\n'));
|
|
310
|
-
}
|
|
430
|
+
log('Installing v6.0 bootstrap files (API key user)...', options);
|
|
431
|
+
await installBootstrapFiles(options, { apiKey });
|
|
311
432
|
}
|
|
312
433
|
/**
|
|
313
|
-
* Install
|
|
434
|
+
* Install v6.0 bootstrap files for trial users
|
|
435
|
+
* Only installs minimal CLAUDE.md and .cursorrules - no .claude/ folder
|
|
314
436
|
*/
|
|
315
437
|
async function installPatterns(trialId, options = {}) {
|
|
316
|
-
log(`Installing
|
|
317
|
-
|
|
438
|
+
log(`Installing v6.0 bootstrap files (trial: ${trialId.substring(0, 8)}...)`, options);
|
|
439
|
+
await installBootstrapFiles(options, { trialId });
|
|
440
|
+
}
|
|
441
|
+
/**
|
|
442
|
+
* Install v6.0 minimal bootstrap files
|
|
443
|
+
* - CLAUDE.md: Instructions for Claude Code
|
|
444
|
+
* - .cursorrules: Instructions for Cursor
|
|
445
|
+
* - NO .claude/ folder - all patterns are server-side
|
|
446
|
+
*/
|
|
447
|
+
async function installBootstrapFiles(options = {}, auth) {
|
|
448
|
+
const spinner = (0, ora_1.default)('Installing CodeBakers v6.0...').start();
|
|
318
449
|
const cwd = process.cwd();
|
|
319
|
-
const apiUrl = (0, config_js_1.getApiUrl)();
|
|
320
450
|
try {
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
});
|
|
329
|
-
if (!response.ok) {
|
|
330
|
-
log(`Primary endpoint failed: ${response.status}, trying trial endpoint...`, options);
|
|
331
|
-
// Try without auth - some patterns may be available for trial
|
|
332
|
-
const publicResponse = await fetch(`${apiUrl}/api/content/trial`, {
|
|
333
|
-
method: 'GET',
|
|
334
|
-
headers: {
|
|
335
|
-
'X-Trial-ID': trialId,
|
|
336
|
-
},
|
|
337
|
-
});
|
|
338
|
-
if (!publicResponse.ok) {
|
|
339
|
-
log(`Trial endpoint also failed: ${publicResponse.status}`, options);
|
|
340
|
-
spinner.warn('Could not download patterns (will use MCP tools)');
|
|
451
|
+
const claudeMdPath = (0, path_1.join)(cwd, 'CLAUDE.md');
|
|
452
|
+
const cursorRulesPath = (0, path_1.join)(cwd, '.cursorrules');
|
|
453
|
+
// Check if already installed with v6
|
|
454
|
+
if ((0, fs_1.existsSync)(claudeMdPath)) {
|
|
455
|
+
const content = (0, fs_1.readFileSync)(claudeMdPath, 'utf-8');
|
|
456
|
+
if (content.includes('v6.0') && content.includes('discover_patterns')) {
|
|
457
|
+
spinner.succeed('CodeBakers v6.0 already installed');
|
|
341
458
|
return;
|
|
342
459
|
}
|
|
343
|
-
|
|
344
|
-
log(
|
|
345
|
-
|
|
346
|
-
|
|
460
|
+
// Upgrade from v5
|
|
461
|
+
log('Upgrading from v5 to v6...', options);
|
|
462
|
+
}
|
|
463
|
+
// Write v6.0 bootstrap files
|
|
464
|
+
(0, fs_1.writeFileSync)(claudeMdPath, V6_CLAUDE_MD);
|
|
465
|
+
(0, fs_1.writeFileSync)(cursorRulesPath, V6_CURSORRULES);
|
|
466
|
+
spinner.succeed('CodeBakers v6.0 installed');
|
|
467
|
+
console.log(chalk_1.default.gray(' Patterns are server-enforced via MCP tools\n'));
|
|
468
|
+
// Confirm install to server (non-blocking)
|
|
469
|
+
if (auth) {
|
|
470
|
+
const apiUrl = (0, config_js_1.getApiUrl)();
|
|
471
|
+
confirmDownload(apiUrl, auth, {
|
|
472
|
+
version: '6.0',
|
|
473
|
+
moduleCount: 0, // No local modules in v6
|
|
474
|
+
cliVersion: getCliVersion(),
|
|
475
|
+
command: 'go',
|
|
476
|
+
}).catch(() => { }); // Silently ignore
|
|
347
477
|
}
|
|
348
|
-
const content = await response.json();
|
|
349
|
-
log(`Received version: ${content.version}, modules: ${Object.keys(content.modules || {}).length}`, options);
|
|
350
|
-
await writePatternFiles(cwd, content, spinner, options, { trialId });
|
|
351
478
|
}
|
|
352
479
|
catch (error) {
|
|
353
480
|
log(`Error: ${error instanceof Error ? error.message : String(error)}`, options);
|
|
354
|
-
spinner.warn('Could not install
|
|
355
|
-
console.log(chalk_1.default.gray('
|
|
356
|
-
}
|
|
357
|
-
}
|
|
358
|
-
async function writePatternFiles(cwd, content, spinner, options = {}, auth) {
|
|
359
|
-
log(`Writing pattern files to ${cwd}...`, options);
|
|
360
|
-
// Check if patterns already exist
|
|
361
|
-
const claudeMdPath = (0, path_1.join)(cwd, 'CLAUDE.md');
|
|
362
|
-
if ((0, fs_1.existsSync)(claudeMdPath)) {
|
|
363
|
-
spinner.succeed('CodeBakers patterns already installed');
|
|
364
|
-
return;
|
|
365
|
-
}
|
|
366
|
-
// Write CLAUDE.md (router file)
|
|
367
|
-
if (content.router) {
|
|
368
|
-
(0, fs_1.writeFileSync)(claudeMdPath, content.router);
|
|
369
|
-
}
|
|
370
|
-
// Write pattern modules to .claude/
|
|
371
|
-
const moduleCount = Object.keys(content.modules || {}).length;
|
|
372
|
-
if (content.modules && moduleCount > 0) {
|
|
373
|
-
const modulesDir = (0, path_1.join)(cwd, '.claude');
|
|
374
|
-
if (!(0, fs_1.existsSync)(modulesDir)) {
|
|
375
|
-
(0, fs_1.mkdirSync)(modulesDir, { recursive: true });
|
|
376
|
-
}
|
|
377
|
-
for (const [name, data] of Object.entries(content.modules)) {
|
|
378
|
-
(0, fs_1.writeFileSync)((0, path_1.join)(modulesDir, name), data);
|
|
379
|
-
}
|
|
380
|
-
}
|
|
381
|
-
// Update .gitignore to exclude encoded patterns
|
|
382
|
-
const gitignorePath = (0, path_1.join)(cwd, '.gitignore');
|
|
383
|
-
if ((0, fs_1.existsSync)(gitignorePath)) {
|
|
384
|
-
const { readFileSync } = await import('fs');
|
|
385
|
-
const gitignore = readFileSync(gitignorePath, 'utf-8');
|
|
386
|
-
if (!gitignore.includes('.claude/')) {
|
|
387
|
-
(0, fs_1.writeFileSync)(gitignorePath, gitignore + '\n# CodeBakers patterns\n.claude/\n');
|
|
388
|
-
}
|
|
389
|
-
}
|
|
390
|
-
spinner.succeed(`CodeBakers patterns installed (v${content.version})`);
|
|
391
|
-
console.log(chalk_1.default.gray(` ${moduleCount} pattern modules ready\n`));
|
|
392
|
-
// Confirm download to server (non-blocking)
|
|
393
|
-
if (auth) {
|
|
394
|
-
const apiUrl = (0, config_js_1.getApiUrl)();
|
|
395
|
-
confirmDownload(apiUrl, auth, {
|
|
396
|
-
version: content.version,
|
|
397
|
-
moduleCount,
|
|
398
|
-
cliVersion: getCliVersion(),
|
|
399
|
-
command: 'go',
|
|
400
|
-
}).catch(() => { }); // Silently ignore
|
|
481
|
+
spinner.warn('Could not install bootstrap files');
|
|
482
|
+
console.log(chalk_1.default.gray(' MCP tools will still work without local files.\n'));
|
|
401
483
|
}
|
|
402
484
|
}
|
package/package.json
CHANGED
package/src/commands/go.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import chalk from 'chalk';
|
|
2
2
|
import ora from 'ora';
|
|
3
3
|
import { execSync, spawn } from 'child_process';
|
|
4
|
-
import { writeFileSync,
|
|
4
|
+
import { writeFileSync, existsSync, readFileSync } from 'fs';
|
|
5
5
|
import { join } from 'path';
|
|
6
6
|
import { createInterface } from 'readline';
|
|
7
7
|
import {
|
|
@@ -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> {
|
|
@@ -29,12 +31,6 @@ function prompt(question: string): Promise<string> {
|
|
|
29
31
|
});
|
|
30
32
|
}
|
|
31
33
|
|
|
32
|
-
interface ContentResponse {
|
|
33
|
-
version: string;
|
|
34
|
-
router: string;
|
|
35
|
-
modules: Record<string, string>;
|
|
36
|
-
}
|
|
37
|
-
|
|
38
34
|
interface GoOptions {
|
|
39
35
|
verbose?: boolean;
|
|
40
36
|
}
|
|
@@ -98,6 +94,7 @@ function log(message: string, options?: GoOptions): void {
|
|
|
98
94
|
|
|
99
95
|
/**
|
|
100
96
|
* Zero-friction entry point - start using CodeBakers instantly
|
|
97
|
+
* Single command for both trial and paid users
|
|
101
98
|
*/
|
|
102
99
|
export async function go(options: GoOptions = {}): Promise<void> {
|
|
103
100
|
log('Starting go command...', options);
|
|
@@ -107,21 +104,22 @@ export async function go(options: GoOptions = {}): Promise<void> {
|
|
|
107
104
|
console.log(chalk.blue(`
|
|
108
105
|
╔═══════════════════════════════════════════════════════════╗
|
|
109
106
|
║ ║
|
|
110
|
-
║ ${chalk.bold.white('CodeBakers -
|
|
107
|
+
║ ${chalk.bold.white('CodeBakers - Get Started')} ║
|
|
111
108
|
║ ║
|
|
112
109
|
╚═══════════════════════════════════════════════════════════╝
|
|
113
110
|
`));
|
|
114
111
|
|
|
115
112
|
// Check if user already has an API key (paid user)
|
|
116
113
|
log('Checking for existing API key...', options);
|
|
117
|
-
const
|
|
118
|
-
if (
|
|
119
|
-
log(`Found API key: ${
|
|
120
|
-
console.log(chalk.green(' ✓ You\'re already logged in
|
|
114
|
+
const existingApiKey = getApiKey();
|
|
115
|
+
if (existingApiKey) {
|
|
116
|
+
log(`Found API key: ${existingApiKey.substring(0, 8)}...`, options);
|
|
117
|
+
console.log(chalk.green(' ✓ You\'re already logged in!\n'));
|
|
121
118
|
|
|
122
|
-
//
|
|
123
|
-
await installPatternsWithApiKey(
|
|
119
|
+
// Install patterns if not already installed
|
|
120
|
+
await installPatternsWithApiKey(existingApiKey, options);
|
|
124
121
|
await configureMCP(options);
|
|
122
|
+
await showSuccessAndRestart();
|
|
125
123
|
return;
|
|
126
124
|
}
|
|
127
125
|
log('No API key found, checking trial state...', options);
|
|
@@ -140,8 +138,8 @@ export async function go(options: GoOptions = {}): Promise<void> {
|
|
|
140
138
|
|
|
141
139
|
// Install patterns if not already installed
|
|
142
140
|
await installPatterns(existingTrial.trialId, options);
|
|
143
|
-
|
|
144
141
|
await configureMCP(options);
|
|
142
|
+
await showSuccessAndRestart();
|
|
145
143
|
return;
|
|
146
144
|
}
|
|
147
145
|
|
|
@@ -149,15 +147,31 @@ export async function go(options: GoOptions = {}): Promise<void> {
|
|
|
149
147
|
if (existingTrial && isTrialExpired()) {
|
|
150
148
|
console.log(chalk.yellow(' ⚠️ Your trial has expired.\n'));
|
|
151
149
|
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
150
|
+
// Offer to login with API key or extend
|
|
151
|
+
console.log(chalk.white(' Options:\n'));
|
|
152
|
+
console.log(chalk.cyan(' [1] Login with API key') + chalk.gray(' (I have an account)'));
|
|
153
|
+
console.log(chalk.cyan(' [2] Extend trial') + chalk.gray(' (7 more days with GitHub)\n'));
|
|
154
|
+
|
|
155
|
+
const choice = await prompt(chalk.gray(' Enter 1 or 2: '));
|
|
156
|
+
|
|
157
|
+
if (choice === '1') {
|
|
158
|
+
await handleApiKeyLogin(options);
|
|
159
|
+
return;
|
|
157
160
|
} else {
|
|
158
|
-
console.log(chalk.
|
|
159
|
-
|
|
161
|
+
console.log(chalk.cyan('\n Run: codebakers extend\n'));
|
|
162
|
+
return;
|
|
160
163
|
}
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
// New user - ask how they want to proceed
|
|
167
|
+
console.log(chalk.white(' How would you like to get started?\n'));
|
|
168
|
+
console.log(chalk.cyan(' [1] Start free 7-day trial') + chalk.gray(' (no signup required)'));
|
|
169
|
+
console.log(chalk.cyan(' [2] Login with API key') + chalk.gray(' (I have an account)\n'));
|
|
170
|
+
|
|
171
|
+
const choice = await prompt(chalk.gray(' Enter 1 or 2: '));
|
|
172
|
+
|
|
173
|
+
if (choice === '2') {
|
|
174
|
+
await handleApiKeyLogin(options);
|
|
161
175
|
return;
|
|
162
176
|
}
|
|
163
177
|
|
|
@@ -229,25 +243,14 @@ export async function go(options: GoOptions = {}): Promise<void> {
|
|
|
229
243
|
spinner.succeed(`Trial started (${data.daysRemaining} days free)`);
|
|
230
244
|
console.log('');
|
|
231
245
|
|
|
232
|
-
// Install
|
|
246
|
+
// Install v6.0 bootstrap files (CLAUDE.md and .cursorrules only)
|
|
233
247
|
await installPatterns(data.trialId, options);
|
|
234
248
|
|
|
235
249
|
// Configure MCP
|
|
236
250
|
await configureMCP(options);
|
|
237
251
|
|
|
238
|
-
// Show success
|
|
239
|
-
|
|
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();
|
|
252
|
+
// Show success and restart
|
|
253
|
+
await showSuccessAndRestart();
|
|
251
254
|
|
|
252
255
|
} catch (error) {
|
|
253
256
|
spinner.fail('Failed to start trial');
|
|
@@ -289,10 +292,61 @@ async function configureMCP(options: GoOptions = {}): Promise<void> {
|
|
|
289
292
|
}
|
|
290
293
|
}
|
|
291
294
|
|
|
292
|
-
|
|
295
|
+
/**
|
|
296
|
+
* Handle API key login flow (for paid users)
|
|
297
|
+
*/
|
|
298
|
+
async function handleApiKeyLogin(options: GoOptions = {}): Promise<void> {
|
|
299
|
+
console.log(chalk.white('\n Enter your API key\n'));
|
|
300
|
+
console.log(chalk.gray(' Find it at: https://codebakers.ai/dashboard\n'));
|
|
301
|
+
|
|
302
|
+
const apiKey = await prompt(chalk.cyan(' API Key: '));
|
|
303
|
+
|
|
304
|
+
if (!apiKey) {
|
|
305
|
+
console.log(chalk.red('\n API key is required.\n'));
|
|
306
|
+
return;
|
|
307
|
+
}
|
|
308
|
+
|
|
309
|
+
const spinner = ora('Validating API key...').start();
|
|
310
|
+
|
|
311
|
+
try {
|
|
312
|
+
await validateApiKey(apiKey);
|
|
313
|
+
spinner.succeed('API key validated');
|
|
314
|
+
|
|
315
|
+
// Save API key
|
|
316
|
+
setApiKey(apiKey);
|
|
317
|
+
console.log(chalk.green(' ✓ Logged in successfully!\n'));
|
|
318
|
+
|
|
319
|
+
// Install patterns
|
|
320
|
+
await installPatternsWithApiKey(apiKey, options);
|
|
321
|
+
|
|
322
|
+
// Configure MCP
|
|
323
|
+
await configureMCP(options);
|
|
324
|
+
|
|
325
|
+
// Show success
|
|
326
|
+
await showSuccessAndRestart();
|
|
327
|
+
|
|
328
|
+
} catch (error) {
|
|
329
|
+
spinner.fail('Invalid API key');
|
|
330
|
+
console.log(chalk.red('\n Could not validate API key.'));
|
|
331
|
+
console.log(chalk.gray(' Check your key at: https://codebakers.ai/dashboard\n'));
|
|
332
|
+
}
|
|
333
|
+
}
|
|
334
|
+
|
|
335
|
+
/**
|
|
336
|
+
* Show success message and offer to restart
|
|
337
|
+
*/
|
|
338
|
+
async function showSuccessAndRestart(): Promise<void> {
|
|
293
339
|
const cwd = process.cwd();
|
|
294
340
|
|
|
295
|
-
console.log(chalk.
|
|
341
|
+
console.log(chalk.green(`
|
|
342
|
+
╔═══════════════════════════════════════════════════════════╗
|
|
343
|
+
║ ✅ CodeBakers is ready! ║
|
|
344
|
+
║ ║
|
|
345
|
+
║ ${chalk.gray('Try: "Build me a todo app with authentication"')} ║
|
|
346
|
+
╚═══════════════════════════════════════════════════════════╝
|
|
347
|
+
`));
|
|
348
|
+
|
|
349
|
+
console.log(chalk.yellow(' ⚠️ RESTART REQUIRED\n'));
|
|
296
350
|
console.log(chalk.gray(' Claude Code needs to restart to load CodeBakers.\n'));
|
|
297
351
|
|
|
298
352
|
const answer = await prompt(chalk.cyan(' Restart Claude Code now? (Y/n): '));
|
|
@@ -309,7 +363,6 @@ async function attemptAutoRestart(): Promise<void> {
|
|
|
309
363
|
const isWindows = process.platform === 'win32';
|
|
310
364
|
|
|
311
365
|
if (isWindows) {
|
|
312
|
-
// On Windows, spawn a new Claude process detached and exit
|
|
313
366
|
spawn('cmd', ['/c', 'start', 'claude'], {
|
|
314
367
|
cwd,
|
|
315
368
|
detached: true,
|
|
@@ -317,7 +370,6 @@ async function attemptAutoRestart(): Promise<void> {
|
|
|
317
370
|
shell: true,
|
|
318
371
|
}).unref();
|
|
319
372
|
} else {
|
|
320
|
-
// On Mac/Linux, spawn claude in new terminal
|
|
321
373
|
spawn('claude', [], {
|
|
322
374
|
cwd,
|
|
323
375
|
detached: true,
|
|
@@ -329,160 +381,183 @@ async function attemptAutoRestart(): Promise<void> {
|
|
|
329
381
|
console.log(chalk.green(' ✓ Claude Code is restarting...\n'));
|
|
330
382
|
console.log(chalk.gray(' This terminal will close. Claude Code will open in a new window.\n'));
|
|
331
383
|
|
|
332
|
-
// Give the spawn a moment to start
|
|
333
384
|
await new Promise(resolve => setTimeout(resolve, 1000));
|
|
334
|
-
|
|
335
|
-
// Exit this process
|
|
336
385
|
process.exit(0);
|
|
337
386
|
|
|
338
|
-
} catch
|
|
387
|
+
} catch {
|
|
339
388
|
console.log(chalk.yellow(' Could not auto-restart. Please restart Claude Code manually.\n'));
|
|
340
389
|
}
|
|
341
390
|
}
|
|
342
391
|
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
*/
|
|
346
|
-
async function installPatternsWithApiKey(apiKey: string, options: GoOptions = {}): Promise<void> {
|
|
347
|
-
log('Installing patterns with API key...', options);
|
|
348
|
-
const spinner = ora('Installing CodeBakers patterns...').start();
|
|
349
|
-
const cwd = process.cwd();
|
|
350
|
-
const apiUrl = getApiUrl();
|
|
392
|
+
// v6.0 Bootstrap content - minimal files that point to MCP tools
|
|
393
|
+
const V6_CLAUDE_MD = `# CodeBakers v6.0 - Server-Enforced Patterns
|
|
351
394
|
|
|
352
|
-
|
|
395
|
+
**All patterns are server-side. No local pattern files needed.**
|
|
353
396
|
|
|
354
|
-
|
|
355
|
-
const response = await fetch(`${apiUrl}/api/content`, {
|
|
356
|
-
method: 'GET',
|
|
357
|
-
headers: {
|
|
358
|
-
'Authorization': `Bearer ${apiKey}`,
|
|
359
|
-
},
|
|
360
|
-
});
|
|
397
|
+
## Required MCP Tools
|
|
361
398
|
|
|
362
|
-
|
|
363
|
-
log(`Response not OK: ${response.status} ${response.statusText}`, options);
|
|
364
|
-
spinner.warn('Could not download patterns');
|
|
365
|
-
return;
|
|
366
|
-
}
|
|
399
|
+
Before writing ANY code, you MUST use these CodeBakers MCP tools:
|
|
367
400
|
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
401
|
+
### 1. discover_patterns (MANDATORY - START GATE)
|
|
402
|
+
Call this BEFORE writing any code:
|
|
403
|
+
\`\`\`
|
|
404
|
+
Tool: discover_patterns
|
|
405
|
+
Args: { task: "what you're about to do", files: ["files to modify"], keywords: ["relevant terms"] }
|
|
406
|
+
\`\`\`
|
|
407
|
+
This returns:
|
|
408
|
+
- Relevant patterns from the server
|
|
409
|
+
- A session token (required for validation)
|
|
410
|
+
- Code examples to follow
|
|
372
411
|
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
412
|
+
### 2. validate_complete (MANDATORY - END GATE)
|
|
413
|
+
Call this BEFORE saying "done" or "complete":
|
|
414
|
+
\`\`\`
|
|
415
|
+
Tool: validate_complete
|
|
416
|
+
Args: { feature: "what you built", files: ["files modified"] }
|
|
417
|
+
\`\`\`
|
|
418
|
+
This checks:
|
|
419
|
+
- You called discover_patterns first (server verifies)
|
|
420
|
+
- Tests exist and pass
|
|
421
|
+
- TypeScript compiles
|
|
422
|
+
- Returns pass/fail from server
|
|
423
|
+
|
|
424
|
+
## Rules
|
|
425
|
+
|
|
426
|
+
1. **You CANNOT skip discover_patterns** - Server tracks compliance
|
|
427
|
+
2. **You CANNOT say "done" without validate_complete** - Server must approve
|
|
428
|
+
3. **Follow patterns returned by server** - They are mandatory
|
|
429
|
+
4. **Write tests** - Validation will fail without them
|
|
430
|
+
5. **Fix TypeScript errors** - Validation will fail with errors
|
|
431
|
+
|
|
432
|
+
## If Server is Unreachable
|
|
433
|
+
|
|
434
|
+
The tools will show "OFFLINE MODE" if the server can't be reached. In this case:
|
|
435
|
+
- Enforcement is limited to local checks only
|
|
436
|
+
- You should still follow best practices
|
|
437
|
+
- Try again when connection is restored
|
|
438
|
+
|
|
439
|
+
## Getting Help
|
|
440
|
+
|
|
441
|
+
- Run \`codebakers doctor\` to diagnose issues
|
|
442
|
+
- Run \`codebakers upgrade\` to update patterns
|
|
443
|
+
- Visit https://codebakers.ai/support for help
|
|
444
|
+
|
|
445
|
+
---
|
|
446
|
+
*CodeBakers v6.0 - Server-Enforced Patterns*
|
|
447
|
+
`;
|
|
448
|
+
|
|
449
|
+
const V6_CURSORRULES = `# CodeBakers v6.0 - Server-Enforced Patterns
|
|
450
|
+
|
|
451
|
+
All patterns are server-side. No local pattern files needed.
|
|
452
|
+
|
|
453
|
+
## Required MCP Tools
|
|
454
|
+
|
|
455
|
+
Before writing ANY code, you MUST use these CodeBakers MCP tools:
|
|
456
|
+
|
|
457
|
+
### 1. discover_patterns (MANDATORY - START GATE)
|
|
458
|
+
Call this BEFORE writing any code:
|
|
459
|
+
- Tool: discover_patterns
|
|
460
|
+
- Args: { task: "what you're about to do", files: ["files to modify"], keywords: ["relevant terms"] }
|
|
461
|
+
|
|
462
|
+
Returns:
|
|
463
|
+
- Relevant patterns from the server
|
|
464
|
+
- A session token (required for validation)
|
|
465
|
+
- Code examples to follow
|
|
466
|
+
|
|
467
|
+
### 2. validate_complete (MANDATORY - END GATE)
|
|
468
|
+
Call this BEFORE saying "done" or "complete":
|
|
469
|
+
- Tool: validate_complete
|
|
470
|
+
- Args: { feature: "what you built", files: ["files modified"] }
|
|
471
|
+
|
|
472
|
+
Checks:
|
|
473
|
+
- You called discover_patterns first (server verifies)
|
|
474
|
+
- Tests exist and pass
|
|
475
|
+
- TypeScript compiles
|
|
476
|
+
- Returns pass/fail from server
|
|
477
|
+
|
|
478
|
+
## Rules
|
|
479
|
+
|
|
480
|
+
1. You CANNOT skip discover_patterns - Server tracks compliance
|
|
481
|
+
2. You CANNOT say "done" without validate_complete - Server must approve
|
|
482
|
+
3. Follow patterns returned by server - They are mandatory
|
|
483
|
+
4. Write tests - Validation will fail without them
|
|
484
|
+
5. Fix TypeScript errors - Validation will fail with errors
|
|
485
|
+
|
|
486
|
+
## If Server is Unreachable
|
|
487
|
+
|
|
488
|
+
The tools will show "OFFLINE MODE" if the server can't be reached. In this case:
|
|
489
|
+
- Enforcement is limited to local checks only
|
|
490
|
+
- You should still follow best practices
|
|
491
|
+
- Try again when connection is restored
|
|
492
|
+
|
|
493
|
+
---
|
|
494
|
+
CodeBakers v6.0 - Server-Enforced Patterns
|
|
495
|
+
`;
|
|
496
|
+
|
|
497
|
+
/**
|
|
498
|
+
* Install v6.0 bootstrap files for API key users (paid users)
|
|
499
|
+
* Only installs minimal CLAUDE.md and .cursorrules - no .claude/ folder
|
|
500
|
+
*/
|
|
501
|
+
async function installPatternsWithApiKey(apiKey: string, options: GoOptions = {}): Promise<void> {
|
|
502
|
+
log('Installing v6.0 bootstrap files (API key user)...', options);
|
|
503
|
+
await installBootstrapFiles(options, { apiKey });
|
|
378
504
|
}
|
|
379
505
|
|
|
380
506
|
/**
|
|
381
|
-
* Install
|
|
507
|
+
* Install v6.0 bootstrap files for trial users
|
|
508
|
+
* Only installs minimal CLAUDE.md and .cursorrules - no .claude/ folder
|
|
382
509
|
*/
|
|
383
510
|
async function installPatterns(trialId: string, options: GoOptions = {}): Promise<void> {
|
|
384
|
-
log(`Installing
|
|
385
|
-
|
|
511
|
+
log(`Installing v6.0 bootstrap files (trial: ${trialId.substring(0, 8)}...)`, options);
|
|
512
|
+
await installBootstrapFiles(options, { trialId });
|
|
513
|
+
}
|
|
514
|
+
|
|
515
|
+
/**
|
|
516
|
+
* Install v6.0 minimal bootstrap files
|
|
517
|
+
* - CLAUDE.md: Instructions for Claude Code
|
|
518
|
+
* - .cursorrules: Instructions for Cursor
|
|
519
|
+
* - NO .claude/ folder - all patterns are server-side
|
|
520
|
+
*/
|
|
521
|
+
async function installBootstrapFiles(options: GoOptions = {}, auth?: AuthInfo): Promise<void> {
|
|
522
|
+
const spinner = ora('Installing CodeBakers v6.0...').start();
|
|
386
523
|
const cwd = process.cwd();
|
|
387
|
-
const apiUrl = getApiUrl();
|
|
388
524
|
|
|
389
525
|
try {
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
if (!response.ok) {
|
|
400
|
-
log(`Primary endpoint failed: ${response.status}, trying trial endpoint...`, options);
|
|
401
|
-
// Try without auth - some patterns may be available for trial
|
|
402
|
-
const publicResponse = await fetch(`${apiUrl}/api/content/trial`, {
|
|
403
|
-
method: 'GET',
|
|
404
|
-
headers: {
|
|
405
|
-
'X-Trial-ID': trialId,
|
|
406
|
-
},
|
|
407
|
-
});
|
|
408
|
-
|
|
409
|
-
if (!publicResponse.ok) {
|
|
410
|
-
log(`Trial endpoint also failed: ${publicResponse.status}`, options);
|
|
411
|
-
spinner.warn('Could not download patterns (will use MCP tools)');
|
|
526
|
+
const claudeMdPath = join(cwd, 'CLAUDE.md');
|
|
527
|
+
const cursorRulesPath = join(cwd, '.cursorrules');
|
|
528
|
+
|
|
529
|
+
// Check if already installed with v6
|
|
530
|
+
if (existsSync(claudeMdPath)) {
|
|
531
|
+
const content = readFileSync(claudeMdPath, 'utf-8');
|
|
532
|
+
if (content.includes('v6.0') && content.includes('discover_patterns')) {
|
|
533
|
+
spinner.succeed('CodeBakers v6.0 already installed');
|
|
412
534
|
return;
|
|
413
535
|
}
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
log(`Received version: ${content.version}, modules: ${Object.keys(content.modules || {}).length}`, options);
|
|
417
|
-
await writePatternFiles(cwd, content, spinner, options, { trialId });
|
|
418
|
-
return;
|
|
536
|
+
// Upgrade from v5
|
|
537
|
+
log('Upgrading from v5 to v6...', options);
|
|
419
538
|
}
|
|
420
539
|
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
540
|
+
// Write v6.0 bootstrap files
|
|
541
|
+
writeFileSync(claudeMdPath, V6_CLAUDE_MD);
|
|
542
|
+
writeFileSync(cursorRulesPath, V6_CURSORRULES);
|
|
543
|
+
|
|
544
|
+
spinner.succeed('CodeBakers v6.0 installed');
|
|
545
|
+
console.log(chalk.gray(' Patterns are server-enforced via MCP tools\n'));
|
|
546
|
+
|
|
547
|
+
// Confirm install to server (non-blocking)
|
|
548
|
+
if (auth) {
|
|
549
|
+
const apiUrl = getApiUrl();
|
|
550
|
+
confirmDownload(apiUrl, auth, {
|
|
551
|
+
version: '6.0',
|
|
552
|
+
moduleCount: 0, // No local modules in v6
|
|
553
|
+
cliVersion: getCliVersion(),
|
|
554
|
+
command: 'go',
|
|
555
|
+
}).catch(() => {}); // Silently ignore
|
|
556
|
+
}
|
|
424
557
|
|
|
425
558
|
} catch (error) {
|
|
426
559
|
log(`Error: ${error instanceof Error ? error.message : String(error)}`, options);
|
|
427
|
-
spinner.warn('Could not install
|
|
428
|
-
console.log(chalk.gray('
|
|
429
|
-
}
|
|
430
|
-
}
|
|
431
|
-
|
|
432
|
-
async function writePatternFiles(
|
|
433
|
-
cwd: string,
|
|
434
|
-
content: ContentResponse,
|
|
435
|
-
spinner: ReturnType<typeof ora>,
|
|
436
|
-
options: GoOptions = {},
|
|
437
|
-
auth?: AuthInfo
|
|
438
|
-
): Promise<void> {
|
|
439
|
-
log(`Writing pattern files to ${cwd}...`, options);
|
|
440
|
-
// Check if patterns already exist
|
|
441
|
-
const claudeMdPath = join(cwd, 'CLAUDE.md');
|
|
442
|
-
if (existsSync(claudeMdPath)) {
|
|
443
|
-
spinner.succeed('CodeBakers patterns already installed');
|
|
444
|
-
return;
|
|
445
|
-
}
|
|
446
|
-
|
|
447
|
-
// Write CLAUDE.md (router file)
|
|
448
|
-
if (content.router) {
|
|
449
|
-
writeFileSync(claudeMdPath, content.router);
|
|
450
|
-
}
|
|
451
|
-
|
|
452
|
-
// Write pattern modules to .claude/
|
|
453
|
-
const moduleCount = Object.keys(content.modules || {}).length;
|
|
454
|
-
if (content.modules && moduleCount > 0) {
|
|
455
|
-
const modulesDir = join(cwd, '.claude');
|
|
456
|
-
if (!existsSync(modulesDir)) {
|
|
457
|
-
mkdirSync(modulesDir, { recursive: true });
|
|
458
|
-
}
|
|
459
|
-
|
|
460
|
-
for (const [name, data] of Object.entries(content.modules)) {
|
|
461
|
-
writeFileSync(join(modulesDir, name), data);
|
|
462
|
-
}
|
|
463
|
-
}
|
|
464
|
-
|
|
465
|
-
// Update .gitignore to exclude encoded patterns
|
|
466
|
-
const gitignorePath = join(cwd, '.gitignore');
|
|
467
|
-
if (existsSync(gitignorePath)) {
|
|
468
|
-
const { readFileSync } = await import('fs');
|
|
469
|
-
const gitignore = readFileSync(gitignorePath, 'utf-8');
|
|
470
|
-
if (!gitignore.includes('.claude/')) {
|
|
471
|
-
writeFileSync(gitignorePath, gitignore + '\n# CodeBakers patterns\n.claude/\n');
|
|
472
|
-
}
|
|
473
|
-
}
|
|
474
|
-
|
|
475
|
-
spinner.succeed(`CodeBakers patterns installed (v${content.version})`);
|
|
476
|
-
console.log(chalk.gray(` ${moduleCount} pattern modules ready\n`));
|
|
477
|
-
|
|
478
|
-
// Confirm download to server (non-blocking)
|
|
479
|
-
if (auth) {
|
|
480
|
-
const apiUrl = getApiUrl();
|
|
481
|
-
confirmDownload(apiUrl, auth, {
|
|
482
|
-
version: content.version,
|
|
483
|
-
moduleCount,
|
|
484
|
-
cliVersion: getCliVersion(),
|
|
485
|
-
command: 'go',
|
|
486
|
-
}).catch(() => {}); // Silently ignore
|
|
560
|
+
spinner.warn('Could not install bootstrap files');
|
|
561
|
+
console.log(chalk.gray(' MCP tools will still work without local files.\n'));
|
|
487
562
|
}
|
|
488
563
|
}
|