@codebakers/cli 3.5.0 → 3.5.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.
@@ -1,10 +1,15 @@
1
1
  import chalk from 'chalk';
2
- import { existsSync } from 'fs';
2
+ import { existsSync, readFileSync } from 'fs';
3
3
  import { join } from 'path';
4
4
  import { getApiKey } from '../config.js';
5
+ import { getCliVersion } from '../lib/api.js';
5
6
 
6
7
  export async function status(): Promise<void> {
7
- console.log(chalk.blue('\n CodeBakers Status\n'));
8
+ console.log(chalk.blue('\n CodeBakers Status (v6.0)\n'));
9
+
10
+ // Show version
11
+ const version = getCliVersion();
12
+ console.log(chalk.gray(` CLI Version: ${version}\n`));
8
13
 
9
14
  // Check login status
10
15
  const apiKey = getApiKey();
@@ -13,7 +18,7 @@ export async function status(): Promise<void> {
13
18
  console.log(chalk.gray(` Key: ${apiKey.slice(0, 10)}...`));
14
19
  } else {
15
20
  console.log(chalk.red(' ✗ Not logged in'));
16
- console.log(chalk.gray(' Run `codebakers login` to authenticate'));
21
+ console.log(chalk.gray(' Run `codebakers setup` to authenticate'));
17
22
  }
18
23
 
19
24
  console.log('');
@@ -28,20 +33,45 @@ export async function status(): Promise<void> {
28
33
  const hasClaudeMd = existsSync(claudemd);
29
34
  const hasClaudeDir = existsSync(claudeDir);
30
35
 
31
- if (hasCursorRules || hasClaudeMd || hasClaudeDir) {
32
- console.log(chalk.green(' Patterns installed in this directory'));
33
- if (hasCursorRules) {
34
- console.log(chalk.gray(' - .cursorrules (Cursor IDE)'));
35
- }
36
- if (hasClaudeMd) {
37
- console.log(chalk.gray(' - CLAUDE.md (Claude Code)'));
38
- }
39
- if (hasClaudeDir) {
40
- console.log(chalk.gray(' - .claude/ (Pattern modules)'));
36
+ // Check version of installed files
37
+ let isV6 = false;
38
+ if (hasClaudeMd) {
39
+ const content = readFileSync(claudemd, 'utf-8');
40
+ isV6 = content.includes('discover_patterns') || content.includes('v6.0');
41
+ }
42
+
43
+ if (hasCursorRules || hasClaudeMd) {
44
+ if (isV6) {
45
+ console.log(chalk.green(' CodeBakers v6.0 installed'));
46
+ console.log(chalk.gray(' - CLAUDE.md (Claude Code gateway)'));
47
+ console.log(chalk.gray(' - .cursorrules (Cursor IDE gateway)'));
48
+ console.log(chalk.cyan('\n v6.0 Features:'));
49
+ console.log(chalk.gray(' - Server-side patterns (always up-to-date)'));
50
+ console.log(chalk.gray(' - AI calls discover_patterns before coding'));
51
+ console.log(chalk.gray(' - Usage tracking & compliance'));
52
+ } else {
53
+ console.log(chalk.yellow(' ⚠ CodeBakers v5 installed (legacy)'));
54
+ if (hasCursorRules) {
55
+ console.log(chalk.gray(' - .cursorrules'));
56
+ }
57
+ if (hasClaudeMd) {
58
+ console.log(chalk.gray(' - CLAUDE.md'));
59
+ }
60
+ if (hasClaudeDir) {
61
+ console.log(chalk.gray(' - .claude/ (local modules)'));
62
+ }
63
+ console.log(chalk.yellow('\n Upgrade to v6.0:'));
64
+ console.log(chalk.gray(' Run `codebakers go` to upgrade'));
41
65
  }
42
66
  } else {
43
- console.log(chalk.yellow(' ○ Patterns not installed in this directory'));
44
- console.log(chalk.gray(' Run `codebakers install` to install'));
67
+ console.log(chalk.yellow(' ○ CodeBakers not installed in this directory'));
68
+ console.log(chalk.gray(' Run `codebakers go` to install'));
69
+ }
70
+
71
+ // Warn about legacy folder
72
+ if (hasClaudeDir && isV6) {
73
+ console.log(chalk.yellow('\n ⚠ Legacy .claude/ folder found'));
74
+ console.log(chalk.gray(' This can be removed - v6.0 uses server-side patterns'));
45
75
  }
46
76
 
47
77
  console.log('');
package/src/mcp/server.ts CHANGED
@@ -1158,13 +1158,13 @@ class CodeBakersServer {
1158
1158
  {
1159
1159
  name: 'update_patterns',
1160
1160
  description:
1161
- 'Download and update CodeBakers pattern files from the server. Use when user says "upgrade codebakers", "update patterns", "download latest patterns", "sync codebakers", or when patterns are missing or outdated. This tool fetches the latest CLAUDE.md router and all .claude/ module files from the server and writes them to disk.',
1161
+ 'Update to CodeBakers v6.0 server-enforced patterns. Use when user says "upgrade codebakers", "update patterns", or "sync codebakers". In v6.0, patterns are server-side - this tool installs minimal bootstrap files (CLAUDE.md and .cursorrules) and removes old .claude/ folder if present.',
1162
1162
  inputSchema: {
1163
1163
  type: 'object' as const,
1164
1164
  properties: {
1165
1165
  force: {
1166
1166
  type: 'boolean',
1167
- description: 'Force update even if already at latest version (default: false)',
1167
+ description: 'Force reinstall even if already on v6.0 (default: false)',
1168
1168
  },
1169
1169
  },
1170
1170
  },
@@ -2705,41 +2705,71 @@ Or if user declines, call without fullDeploy:
2705
2705
  // Use default
2706
2706
  }
2707
2707
 
2708
- results.push(`# 🎨 Adding CodeBakers to: ${projectName}\n`);
2708
+ results.push(`# 🎨 Adding CodeBakers v6.0 to: ${projectName}\n`);
2709
2709
 
2710
- // Check if already initialized
2711
- if (fs.existsSync(path.join(cwd, 'CLAUDE.md'))) {
2712
- results.push('⚠️ CLAUDE.md already exists. Updating patterns...\n');
2713
- }
2710
+ // v6.0 bootstrap content - minimal files, patterns from server
2711
+ const V6_CLAUDE_MD = `# CodeBakers v6.0
2714
2712
 
2715
- try {
2716
- const response = await fetch(`${this.apiUrl}/api/content`, {
2717
- method: 'GET',
2718
- headers: this.getAuthHeaders(),
2719
- });
2713
+ **MANDATORY: Before writing ANY code, call the \`discover_patterns\` MCP tool.**
2720
2714
 
2721
- if (!response.ok) {
2722
- throw new Error('Failed to fetch patterns from API');
2723
- }
2715
+ \`\`\`
2716
+ Tool: discover_patterns
2717
+ Args: { task: "description of what you're building" }
2718
+ \`\`\`
2719
+
2720
+ The server will return:
2721
+ - All coding patterns and rules you must follow
2722
+ - Test requirements
2723
+ - Validation instructions
2724
+
2725
+ **You cannot write code without calling this tool first. The server tracks compliance.**
2726
+
2727
+ ---
2728
+ *CodeBakers v6.0 - Server-Enforced*
2729
+ `;
2724
2730
 
2725
- const content = await response.json();
2731
+ const V6_CURSORRULES = `# CodeBakers v6.0
2726
2732
 
2727
- // Write CLAUDE.md
2728
- if (content.router) {
2729
- fs.writeFileSync(path.join(cwd, 'CLAUDE.md'), content.router);
2730
- results.push(' Created/Updated CLAUDE.md');
2733
+ MANDATORY: Before writing ANY code, call the discover_patterns MCP tool.
2734
+
2735
+ Tool: discover_patterns
2736
+ Args: { task: "description of what you're building" }
2737
+
2738
+ The server returns all patterns, rules, and test requirements.
2739
+ You cannot write code without calling this tool first.
2740
+ `;
2741
+
2742
+ // Check if already v6
2743
+ const claudeMdPath = path.join(cwd, 'CLAUDE.md');
2744
+ if (fs.existsSync(claudeMdPath)) {
2745
+ const content = fs.readFileSync(claudeMdPath, 'utf-8');
2746
+ if (content.includes('v6.0') && content.includes('discover_patterns')) {
2747
+ results.push('✓ CodeBakers v6.0 already installed\n');
2748
+ results.push('Patterns are server-enforced. Just call `discover_patterns` before coding!');
2749
+ return {
2750
+ content: [{ type: 'text' as const, text: results.join('\n') }],
2751
+ };
2731
2752
  }
2753
+ results.push('⚠️ Upgrading to v6.0 (server-enforced patterns)...\n');
2754
+ }
2732
2755
 
2733
- // Write pattern modules
2734
- if (content.modules && Object.keys(content.modules).length > 0) {
2735
- const modulesDir = path.join(cwd, '.claude');
2736
- if (!fs.existsSync(modulesDir)) {
2737
- fs.mkdirSync(modulesDir, { recursive: true });
2738
- }
2739
- for (const [name, data] of Object.entries(content.modules)) {
2740
- fs.writeFileSync(path.join(modulesDir, name), data as string);
2756
+ try {
2757
+ // Write v6.0 bootstrap files
2758
+ fs.writeFileSync(claudeMdPath, V6_CLAUDE_MD);
2759
+ results.push('✓ Created CLAUDE.md (v6.0 bootstrap)');
2760
+
2761
+ fs.writeFileSync(path.join(cwd, '.cursorrules'), V6_CURSORRULES);
2762
+ results.push('✓ Created .cursorrules (v6.0 bootstrap)');
2763
+
2764
+ // Remove old .claude folder if it exists (v5 → v6 migration)
2765
+ const claudeDir = path.join(cwd, '.claude');
2766
+ if (fs.existsSync(claudeDir)) {
2767
+ try {
2768
+ fs.rmSync(claudeDir, { recursive: true, force: true });
2769
+ results.push('✓ Removed .claude/ folder (patterns now server-side)');
2770
+ } catch {
2771
+ results.push('⚠️ Could not remove .claude/ folder - please delete manually');
2741
2772
  }
2742
- results.push(`✓ Installed ${Object.keys(content.modules).length} pattern modules (v${content.version})`);
2743
2773
  }
2744
2774
 
2745
2775
  // Create PRD if doesn't exist
@@ -2760,41 +2790,29 @@ Or if user declines, call without fullDeploy:
2760
2790
  results.push('✓ Created PRD.md template');
2761
2791
  }
2762
2792
 
2763
- // Create PROJECT-STATE if doesn't exist
2764
- const statePath = path.join(cwd, 'PROJECT-STATE.md');
2765
- if (!fs.existsSync(statePath)) {
2766
- fs.writeFileSync(statePath, `# PROJECT STATE
2767
- # Last Updated: ${date}
2768
-
2769
- ## Project Info
2770
- name: ${projectName}
2771
- phase: development
2772
-
2773
- ## In Progress
2774
- ## Completed
2775
- ## Next Up
2776
- `);
2777
- results.push('✓ Created PROJECT-STATE.md');
2778
- }
2779
-
2780
- // Update .gitignore
2781
- const gitignorePath = path.join(cwd, '.gitignore');
2782
- if (fs.existsSync(gitignorePath)) {
2783
- const gitignore = fs.readFileSync(gitignorePath, 'utf-8');
2784
- if (!gitignore.includes('.claude/')) {
2785
- fs.writeFileSync(gitignorePath, gitignore + '\n# CodeBakers\n.claude/\n');
2786
- results.push('✓ Updated .gitignore');
2793
+ // Update .codebakers.json
2794
+ const stateFile = path.join(cwd, '.codebakers.json');
2795
+ let state: Record<string, unknown> = {};
2796
+ if (fs.existsSync(stateFile)) {
2797
+ try {
2798
+ state = JSON.parse(fs.readFileSync(stateFile, 'utf-8'));
2799
+ } catch {
2800
+ // Ignore errors
2787
2801
  }
2788
2802
  }
2803
+ state.version = '6.0';
2804
+ state.serverEnforced = true;
2805
+ state.updatedAt = new Date().toISOString();
2806
+ fs.writeFileSync(stateFile, JSON.stringify(state, null, 2));
2789
2807
 
2790
2808
  results.push('\n---\n');
2791
- results.push('## ✅ CodeBakers Patterns Installed!\n');
2792
- results.push('The AI now has access to production patterns for:');
2793
- results.push('- Authentication, Database, API design');
2794
- results.push('- Frontend components, Forms, Validation');
2795
- results.push('- Payments, Email, Real-time features');
2796
- results.push('- And 30+ more specialized patterns\n');
2797
- results.push('Just describe what you want to build!');
2809
+ results.push('## ✅ CodeBakers v6.0 Installed!\n');
2810
+ results.push('**How it works now:**');
2811
+ results.push('1. Call `discover_patterns` before writing code');
2812
+ results.push('2. Server returns all patterns and rules');
2813
+ results.push('3. Call `validate_complete` before marking done');
2814
+ results.push('4. Server verifies compliance\n');
2815
+ results.push('No local pattern files needed - everything is server-side!');
2798
2816
 
2799
2817
  } catch (error) {
2800
2818
  const message = error instanceof Error ? error.message : 'Unknown error';
@@ -6242,7 +6260,7 @@ ${handlers.join('\n')}
6242
6260
  }
6243
6261
 
6244
6262
  /**
6245
- * Download and update CodeBakers patterns from server
6263
+ * Update to CodeBakers v6.0 - server-enforced patterns
6246
6264
  * This is the MCP equivalent of the `codebakers upgrade` CLI command
6247
6265
  */
6248
6266
  private async handleUpdatePatterns(args: { force?: boolean }) {
@@ -6250,63 +6268,70 @@ ${handlers.join('\n')}
6250
6268
  const cwd = process.cwd();
6251
6269
  const claudeMdPath = path.join(cwd, 'CLAUDE.md');
6252
6270
  const claudeDir = path.join(cwd, '.claude');
6253
- const versionPath = path.join(claudeDir, '.version.json');
6271
+ const codebakersJson = path.join(cwd, '.codebakers.json');
6272
+
6273
+ let response = `# 🔄 CodeBakers v6.0 Update\n\n`;
6274
+
6275
+ // v6.0 bootstrap content
6276
+ const V6_CLAUDE_MD = `# CodeBakers v6.0
6277
+
6278
+ **MANDATORY: Before writing ANY code, call the \`discover_patterns\` MCP tool.**
6279
+
6280
+ \`\`\`
6281
+ Tool: discover_patterns
6282
+ Args: { task: "description of what you're building" }
6283
+ \`\`\`
6284
+
6285
+ The server will return:
6286
+ - All coding patterns and rules you must follow
6287
+ - Test requirements
6288
+ - Validation instructions
6289
+
6290
+ **You cannot write code without calling this tool first. The server tracks compliance.**
6254
6291
 
6255
- let response = `# 🔄 CodeBakers Pattern Update\n\n`;
6292
+ ---
6293
+ *CodeBakers v6.0 - Server-Enforced*
6294
+ `;
6295
+
6296
+ const V6_CURSORRULES = `# CodeBakers v6.0
6297
+
6298
+ MANDATORY: Before writing ANY code, call the discover_patterns MCP tool.
6299
+
6300
+ Tool: discover_patterns
6301
+ Args: { task: "description of what you're building" }
6302
+
6303
+ The server returns all patterns, rules, and test requirements.
6304
+ You cannot write code without calling this tool first.
6305
+ `;
6256
6306
 
6257
6307
  try {
6258
6308
  // Check current version
6259
6309
  let currentVersion: string | null = null;
6260
- let currentModuleCount = 0;
6310
+ let isV6 = false;
6261
6311
 
6262
- if (fs.existsSync(versionPath)) {
6263
- try {
6264
- const versionInfo = JSON.parse(fs.readFileSync(versionPath, 'utf-8'));
6265
- currentVersion = versionInfo.version;
6266
- currentModuleCount = versionInfo.moduleCount || 0;
6267
- } catch {
6268
- // Ignore parse errors
6269
- }
6312
+ if (fs.existsSync(claudeMdPath)) {
6313
+ const content = fs.readFileSync(claudeMdPath, 'utf-8');
6314
+ isV6 = content.includes('v6.0') && content.includes('discover_patterns');
6270
6315
  }
6271
6316
 
6272
- // Count current modules
6273
- if (fs.existsSync(claudeDir)) {
6317
+ if (fs.existsSync(codebakersJson)) {
6274
6318
  try {
6275
- const files = fs.readdirSync(claudeDir).filter(f => f.endsWith('.md'));
6276
- currentModuleCount = files.length;
6319
+ const state = JSON.parse(fs.readFileSync(codebakersJson, 'utf-8'));
6320
+ currentVersion = state.version || null;
6277
6321
  } catch {
6278
- // Ignore read errors
6322
+ // Ignore parse errors
6279
6323
  }
6280
6324
  }
6281
6325
 
6282
6326
  response += `## Current Status\n`;
6283
6327
  response += `- Version: ${currentVersion || 'Unknown'}\n`;
6284
- response += `- Modules: ${currentModuleCount}\n\n`;
6328
+ response += `- v6.0 (Server-Enforced): ${isV6 ? 'Yes ✓' : 'No'}\n\n`;
6285
6329
 
6286
- // Fetch latest version info first
6287
- const versionResponse = await fetch(`${this.apiUrl}/api/content/version`, {
6288
- headers: this.getAuthHeaders(),
6289
- });
6290
-
6291
- if (!versionResponse.ok) {
6292
- throw new Error('Failed to check version from server');
6293
- }
6294
-
6295
- const latestInfo = await versionResponse.json();
6296
- const latestVersion = latestInfo.version;
6297
- const latestModuleCount = latestInfo.moduleCount || 0;
6298
-
6299
- response += `## Server Status\n`;
6300
- response += `- Latest Version: ${latestVersion}\n`;
6301
- response += `- Available Modules: ${latestModuleCount}\n\n`;
6302
-
6303
- // Check if update needed
6304
- const needsUpdate = force || !currentVersion || currentVersion !== latestVersion || currentModuleCount < latestModuleCount;
6305
-
6306
- if (!needsUpdate) {
6307
- response += `✅ **Already up to date!**\n\n`;
6308
- response += `Your patterns are current (v${latestVersion} with ${latestModuleCount} modules).\n`;
6309
- response += `Use \`force: true\` to re-download anyway.\n`;
6330
+ // Check if already on v6
6331
+ if (isV6 && !force) {
6332
+ response += `✅ **Already on v6.0!**\n\n`;
6333
+ response += `Your patterns are server-enforced. Just use \`discover_patterns\` before coding.\n`;
6334
+ response += `Use \`force: true\` to reinstall bootstrap files.\n`;
6310
6335
  response += this.getUpdateNotice();
6311
6336
 
6312
6337
  return {
@@ -6317,76 +6342,58 @@ ${handlers.join('\n')}
6317
6342
  };
6318
6343
  }
6319
6344
 
6320
- response += `## Downloading Updates...\n\n`;
6345
+ response += `## Upgrading to v6.0...\n\n`;
6321
6346
 
6322
- // Fetch full content
6323
- const contentResponse = await fetch(`${this.apiUrl}/api/content`, {
6324
- headers: this.getAuthHeaders(),
6325
- });
6347
+ // Write v6.0 bootstrap files
6348
+ fs.writeFileSync(claudeMdPath, V6_CLAUDE_MD);
6349
+ response += `✓ Updated CLAUDE.md (v6.0 bootstrap)\n`;
6326
6350
 
6327
- if (!contentResponse.ok) {
6328
- const error = await contentResponse.json().catch(() => ({}));
6329
- throw new Error(error.error || error.message || 'Failed to fetch patterns');
6330
- }
6351
+ fs.writeFileSync(path.join(cwd, '.cursorrules'), V6_CURSORRULES);
6352
+ response += `✓ Updated .cursorrules (v6.0 bootstrap)\n`;
6331
6353
 
6332
- const content = await contentResponse.json();
6333
- const moduleCount = content.modules ? Object.keys(content.modules).length : 0;
6334
-
6335
- // Create .claude directory if needed
6336
- if (!fs.existsSync(claudeDir)) {
6337
- fs.mkdirSync(claudeDir, { recursive: true });
6338
- response += `✓ Created .claude/ directory\n`;
6339
- }
6340
-
6341
- // Update CLAUDE.md router
6342
- if (content.router) {
6343
- fs.writeFileSync(claudeMdPath, content.router);
6344
- response += `✓ Updated CLAUDE.md (router)\n`;
6345
- }
6346
-
6347
- // Update all modules
6348
- if (content.modules && moduleCount > 0) {
6349
- for (const [name, data] of Object.entries(content.modules)) {
6350
- fs.writeFileSync(path.join(claudeDir, name), data as string);
6354
+ // Remove old .claude folder (v5 → v6 migration)
6355
+ if (fs.existsSync(claudeDir)) {
6356
+ try {
6357
+ fs.rmSync(claudeDir, { recursive: true, force: true });
6358
+ response += `✓ Removed .claude/ folder (patterns now server-side)\n`;
6359
+ } catch {
6360
+ response += `⚠️ Could not remove .claude/ folder - please delete manually\n`;
6351
6361
  }
6352
- response += `✓ Updated ${moduleCount} modules in .claude/\n`;
6353
6362
  }
6354
6363
 
6355
- // Save version info
6356
- const newVersionInfo = {
6357
- version: content.version || latestVersion,
6358
- moduleCount,
6359
- installedAt: currentVersion ? undefined : new Date().toISOString(),
6360
- updatedAt: new Date().toISOString(),
6361
- cliVersion: getCliVersion(),
6362
- };
6363
- fs.writeFileSync(versionPath, JSON.stringify(newVersionInfo, null, 2));
6364
- response += `✓ Saved version info\n`;
6365
-
6366
- // Confirm download to server (non-blocking analytics)
6367
- this.confirmDownload(content.version || latestVersion, moduleCount).catch(() => {});
6368
-
6369
- response += `\n## ✅ Update Complete!\n\n`;
6370
- response += `- **From:** v${currentVersion || 'none'} (${currentModuleCount} modules)\n`;
6371
- response += `- **To:** v${content.version || latestVersion} (${moduleCount} modules)\n\n`;
6372
-
6373
- if (moduleCount > currentModuleCount) {
6374
- response += `🆕 **${moduleCount - currentModuleCount} new modules added!**\n\n`;
6364
+ // Update .codebakers.json
6365
+ let state: Record<string, unknown> = {};
6366
+ if (fs.existsSync(codebakersJson)) {
6367
+ try {
6368
+ state = JSON.parse(fs.readFileSync(codebakersJson, 'utf-8'));
6369
+ } catch {
6370
+ // Ignore errors
6371
+ }
6375
6372
  }
6376
-
6377
- response += `Your patterns are now up to date. The new patterns will be used in your next response.\n`;
6373
+ state.version = '6.0';
6374
+ state.serverEnforced = true;
6375
+ state.updatedAt = new Date().toISOString();
6376
+ fs.writeFileSync(codebakersJson, JSON.stringify(state, null, 2));
6377
+ response += `✓ Updated .codebakers.json\n`;
6378
+
6379
+ // Confirm to server (non-blocking analytics)
6380
+ this.confirmDownload('6.0', 0).catch(() => {});
6381
+
6382
+ response += `\n## ✅ Upgrade Complete!\n\n`;
6383
+ response += `**What changed in v6.0:**\n`;
6384
+ response += `- No local pattern files (.claude/ folder removed)\n`;
6385
+ response += `- All patterns fetched from server in real-time\n`;
6386
+ response += `- Server tracks compliance via discover_patterns/validate_complete\n\n`;
6387
+ response += `**How to use:**\n`;
6388
+ response += `1. Call \`discover_patterns\` before writing any code\n`;
6389
+ response += `2. Follow the patterns returned by server\n`;
6390
+ response += `3. Call \`validate_complete\` before marking done\n`;
6378
6391
 
6379
6392
  } catch (error) {
6380
6393
  const message = error instanceof Error ? error.message : 'Unknown error';
6381
6394
  response += `\n## ❌ Update Failed\n\n`;
6382
6395
  response += `Error: ${message}\n\n`;
6383
-
6384
- if (message.includes('401') || message.includes('Invalid') || message.includes('expired')) {
6385
- response += `Your API key may be invalid or expired.\n`;
6386
- response += `Run \`codebakers setup\` in terminal to reconfigure.\n`;
6387
- } else {
6388
- response += `Please try again or run \`codebakers upgrade\` in terminal.\n`;
6389
- }
6396
+ response += `Please try again or run \`codebakers upgrade\` in terminal.\n`;
6390
6397
  }
6391
6398
 
6392
6399
  // Add CLI update notice if available