@codebakers/cli 3.0.0 → 3.0.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.
- package/dist/commands/go.js +159 -4
- package/dist/mcp/server.js +1270 -0
- package/package.json +1 -1
- package/src/commands/go.ts +194 -5
- package/src/mcp/server.ts +1464 -0
package/package.json
CHANGED
package/src/commands/go.ts
CHANGED
|
@@ -1,6 +1,9 @@
|
|
|
1
1
|
import chalk from 'chalk';
|
|
2
2
|
import ora from 'ora';
|
|
3
|
-
import { execSync } from 'child_process';
|
|
3
|
+
import { execSync, spawn } from 'child_process';
|
|
4
|
+
import { writeFileSync, mkdirSync, existsSync } from 'fs';
|
|
5
|
+
import { join } from 'path';
|
|
6
|
+
import { createInterface } from 'readline';
|
|
4
7
|
import {
|
|
5
8
|
getTrialState,
|
|
6
9
|
setTrialState,
|
|
@@ -12,6 +15,26 @@ import {
|
|
|
12
15
|
} from '../config.js';
|
|
13
16
|
import { getDeviceFingerprint } from '../lib/fingerprint.js';
|
|
14
17
|
|
|
18
|
+
function prompt(question: string): Promise<string> {
|
|
19
|
+
const rl = createInterface({
|
|
20
|
+
input: process.stdin,
|
|
21
|
+
output: process.stdout,
|
|
22
|
+
});
|
|
23
|
+
|
|
24
|
+
return new Promise((resolve) => {
|
|
25
|
+
rl.question(question, (answer) => {
|
|
26
|
+
rl.close();
|
|
27
|
+
resolve(answer.trim().toLowerCase());
|
|
28
|
+
});
|
|
29
|
+
});
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
interface ContentResponse {
|
|
33
|
+
version: string;
|
|
34
|
+
router: string;
|
|
35
|
+
modules: Record<string, string>;
|
|
36
|
+
}
|
|
37
|
+
|
|
15
38
|
/**
|
|
16
39
|
* Zero-friction entry point - start using CodeBakers instantly
|
|
17
40
|
*/
|
|
@@ -28,7 +51,10 @@ export async function go(): Promise<void> {
|
|
|
28
51
|
const apiKey = getApiKey();
|
|
29
52
|
if (apiKey) {
|
|
30
53
|
console.log(chalk.green(' ✓ You\'re already logged in with an API key!\n'));
|
|
31
|
-
|
|
54
|
+
|
|
55
|
+
// Still install patterns if not already installed
|
|
56
|
+
await installPatternsWithApiKey(apiKey);
|
|
57
|
+
await configureMCP();
|
|
32
58
|
return;
|
|
33
59
|
}
|
|
34
60
|
|
|
@@ -44,6 +70,9 @@ export async function go(): Promise<void> {
|
|
|
44
70
|
console.log(chalk.cyan(' codebakers extend\n'));
|
|
45
71
|
}
|
|
46
72
|
|
|
73
|
+
// Install patterns if not already installed
|
|
74
|
+
await installPatterns(existingTrial.trialId);
|
|
75
|
+
|
|
47
76
|
await configureMCP();
|
|
48
77
|
return;
|
|
49
78
|
}
|
|
@@ -132,6 +161,9 @@ export async function go(): Promise<void> {
|
|
|
132
161
|
spinner.succeed(`Trial started (${data.daysRemaining} days free)`);
|
|
133
162
|
console.log('');
|
|
134
163
|
|
|
164
|
+
// Install patterns (CLAUDE.md and .claude/)
|
|
165
|
+
await installPatterns(data.trialId);
|
|
166
|
+
|
|
135
167
|
// Configure MCP
|
|
136
168
|
await configureMCP();
|
|
137
169
|
|
|
@@ -189,9 +221,166 @@ async function configureMCP(): Promise<void> {
|
|
|
189
221
|
}
|
|
190
222
|
|
|
191
223
|
async function attemptAutoRestart(): Promise<void> {
|
|
224
|
+
const cwd = process.cwd();
|
|
225
|
+
|
|
192
226
|
console.log(chalk.yellow('\n ⚠️ RESTART REQUIRED\n'));
|
|
193
|
-
console.log(chalk.gray('
|
|
227
|
+
console.log(chalk.gray(' Claude Code needs to restart to load CodeBakers.\n'));
|
|
228
|
+
|
|
229
|
+
const answer = await prompt(chalk.cyan(' Restart Claude Code now? (Y/n): '));
|
|
230
|
+
|
|
231
|
+
if (answer === 'n' || answer === 'no') {
|
|
232
|
+
console.log(chalk.gray('\n No problem! Just restart Claude Code manually when ready.\n'));
|
|
233
|
+
return;
|
|
234
|
+
}
|
|
235
|
+
|
|
236
|
+
// Attempt to restart Claude Code
|
|
237
|
+
console.log(chalk.gray('\n Restarting Claude Code...\n'));
|
|
238
|
+
|
|
239
|
+
try {
|
|
240
|
+
const isWindows = process.platform === 'win32';
|
|
241
|
+
|
|
242
|
+
if (isWindows) {
|
|
243
|
+
// On Windows, spawn a new Claude process detached and exit
|
|
244
|
+
spawn('cmd', ['/c', 'start', 'claude'], {
|
|
245
|
+
cwd,
|
|
246
|
+
detached: true,
|
|
247
|
+
stdio: 'ignore',
|
|
248
|
+
shell: true,
|
|
249
|
+
}).unref();
|
|
250
|
+
} else {
|
|
251
|
+
// On Mac/Linux, spawn claude in new terminal
|
|
252
|
+
spawn('claude', [], {
|
|
253
|
+
cwd,
|
|
254
|
+
detached: true,
|
|
255
|
+
stdio: 'ignore',
|
|
256
|
+
shell: true,
|
|
257
|
+
}).unref();
|
|
258
|
+
}
|
|
259
|
+
|
|
260
|
+
console.log(chalk.green(' ✓ Claude Code is restarting...\n'));
|
|
261
|
+
console.log(chalk.gray(' This terminal will close. Claude Code will open in a new window.\n'));
|
|
262
|
+
|
|
263
|
+
// Give the spawn a moment to start
|
|
264
|
+
await new Promise(resolve => setTimeout(resolve, 1000));
|
|
265
|
+
|
|
266
|
+
// Exit this process
|
|
267
|
+
process.exit(0);
|
|
268
|
+
|
|
269
|
+
} catch (error) {
|
|
270
|
+
console.log(chalk.yellow(' Could not auto-restart. Please restart Claude Code manually.\n'));
|
|
271
|
+
}
|
|
272
|
+
}
|
|
273
|
+
|
|
274
|
+
/**
|
|
275
|
+
* Install pattern files for API key users (paid users)
|
|
276
|
+
*/
|
|
277
|
+
async function installPatternsWithApiKey(apiKey: string): Promise<void> {
|
|
278
|
+
const spinner = ora('Installing CodeBakers patterns...').start();
|
|
279
|
+
const cwd = process.cwd();
|
|
280
|
+
const apiUrl = getApiUrl();
|
|
281
|
+
|
|
282
|
+
try {
|
|
283
|
+
const response = await fetch(`${apiUrl}/api/content`, {
|
|
284
|
+
method: 'GET',
|
|
285
|
+
headers: {
|
|
286
|
+
'Authorization': `Bearer ${apiKey}`,
|
|
287
|
+
},
|
|
288
|
+
});
|
|
289
|
+
|
|
290
|
+
if (!response.ok) {
|
|
291
|
+
spinner.warn('Could not download patterns');
|
|
292
|
+
return;
|
|
293
|
+
}
|
|
294
|
+
|
|
295
|
+
const content: ContentResponse = await response.json();
|
|
296
|
+
await writePatternFiles(cwd, content, spinner);
|
|
297
|
+
|
|
298
|
+
} catch (error) {
|
|
299
|
+
spinner.warn('Could not install patterns');
|
|
300
|
+
console.log(chalk.gray(' Check your internet connection.\n'));
|
|
301
|
+
}
|
|
302
|
+
}
|
|
303
|
+
|
|
304
|
+
/**
|
|
305
|
+
* Install pattern files (CLAUDE.md and .claude/) for trial users
|
|
306
|
+
*/
|
|
307
|
+
async function installPatterns(trialId: string): Promise<void> {
|
|
308
|
+
const spinner = ora('Installing CodeBakers patterns...').start();
|
|
309
|
+
const cwd = process.cwd();
|
|
310
|
+
const apiUrl = getApiUrl();
|
|
311
|
+
|
|
312
|
+
try {
|
|
313
|
+
// Fetch patterns using trial ID
|
|
314
|
+
const response = await fetch(`${apiUrl}/api/content`, {
|
|
315
|
+
method: 'GET',
|
|
316
|
+
headers: {
|
|
317
|
+
'X-Trial-ID': trialId,
|
|
318
|
+
},
|
|
319
|
+
});
|
|
320
|
+
|
|
321
|
+
if (!response.ok) {
|
|
322
|
+
// Try without auth - some patterns may be available for trial
|
|
323
|
+
const publicResponse = await fetch(`${apiUrl}/api/content/trial`, {
|
|
324
|
+
method: 'GET',
|
|
325
|
+
headers: {
|
|
326
|
+
'X-Trial-ID': trialId,
|
|
327
|
+
},
|
|
328
|
+
});
|
|
329
|
+
|
|
330
|
+
if (!publicResponse.ok) {
|
|
331
|
+
spinner.warn('Could not download patterns (will use MCP tools)');
|
|
332
|
+
return;
|
|
333
|
+
}
|
|
334
|
+
|
|
335
|
+
const content: ContentResponse = await publicResponse.json();
|
|
336
|
+
await writePatternFiles(cwd, content, spinner);
|
|
337
|
+
return;
|
|
338
|
+
}
|
|
339
|
+
|
|
340
|
+
const content: ContentResponse = await response.json();
|
|
341
|
+
await writePatternFiles(cwd, content, spinner);
|
|
342
|
+
|
|
343
|
+
} catch (error) {
|
|
344
|
+
spinner.warn('Could not install patterns (will use MCP tools)');
|
|
345
|
+
console.log(chalk.gray(' Patterns will be available via MCP tools.\n'));
|
|
346
|
+
}
|
|
347
|
+
}
|
|
348
|
+
|
|
349
|
+
async function writePatternFiles(cwd: string, content: ContentResponse, spinner: ReturnType<typeof ora>): Promise<void> {
|
|
350
|
+
// Check if patterns already exist
|
|
351
|
+
const claudeMdPath = join(cwd, 'CLAUDE.md');
|
|
352
|
+
if (existsSync(claudeMdPath)) {
|
|
353
|
+
spinner.succeed('CodeBakers patterns already installed');
|
|
354
|
+
return;
|
|
355
|
+
}
|
|
356
|
+
|
|
357
|
+
// Write CLAUDE.md (router file)
|
|
358
|
+
if (content.router) {
|
|
359
|
+
writeFileSync(claudeMdPath, content.router);
|
|
360
|
+
}
|
|
361
|
+
|
|
362
|
+
// Write pattern modules to .claude/
|
|
363
|
+
if (content.modules && Object.keys(content.modules).length > 0) {
|
|
364
|
+
const modulesDir = join(cwd, '.claude');
|
|
365
|
+
if (!existsSync(modulesDir)) {
|
|
366
|
+
mkdirSync(modulesDir, { recursive: true });
|
|
367
|
+
}
|
|
368
|
+
|
|
369
|
+
for (const [name, data] of Object.entries(content.modules)) {
|
|
370
|
+
writeFileSync(join(modulesDir, name), data);
|
|
371
|
+
}
|
|
372
|
+
}
|
|
373
|
+
|
|
374
|
+
// Update .gitignore to exclude encoded patterns
|
|
375
|
+
const gitignorePath = join(cwd, '.gitignore');
|
|
376
|
+
if (existsSync(gitignorePath)) {
|
|
377
|
+
const { readFileSync } = await import('fs');
|
|
378
|
+
const gitignore = readFileSync(gitignorePath, 'utf-8');
|
|
379
|
+
if (!gitignore.includes('.claude/')) {
|
|
380
|
+
writeFileSync(gitignorePath, gitignore + '\n# CodeBakers patterns\n.claude/\n');
|
|
381
|
+
}
|
|
382
|
+
}
|
|
194
383
|
|
|
195
|
-
|
|
196
|
-
|
|
384
|
+
spinner.succeed(`CodeBakers patterns installed (v${content.version})`);
|
|
385
|
+
console.log(chalk.gray(` ${Object.keys(content.modules || {}).length} pattern modules ready\n`));
|
|
197
386
|
}
|