@codebakers/cli 1.4.1 → 1.4.2

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,246 @@
1
1
  import chalk from 'chalk';
2
2
  import ora from 'ora';
3
3
  import { createInterface } from 'readline';
4
- import { writeFileSync, mkdirSync, existsSync, readdirSync } from 'fs';
4
+ import { writeFileSync, mkdirSync, existsSync, readdirSync, readFileSync } from 'fs';
5
5
  import { join } from 'path';
6
6
  import { execSync } from 'child_process';
7
7
  import * as templates from '../templates/nextjs-supabase.js';
8
+ import { getApiKey, getApiUrl } from '../config.js';
9
+
10
+ // Cursor IDE configuration templates
11
+ const CURSORRULES_TEMPLATE = `# CODEBAKERS CURSOR RULES
12
+ # Zero-friction AI assistance - everything is automatic
13
+
14
+ ## ON EVERY MESSAGE - AUTOMATIC WORKFLOW
15
+
16
+ ### PHASE 1: CONTEXT LOAD (automatic)
17
+ 1. Read CLAUDE.md → Load router
18
+ 2. Read PRD.md → Understand what we're building
19
+ 3. Read PROJECT-CONTEXT.md → Understand codebase
20
+ 4. Read PROJECT-STATE.md → Check what's in progress
21
+ 5. Read DECISIONS.md → Know past decisions
22
+
23
+ ### PHASE 2: PRE-FLIGHT CHECK (before writing code)
24
+ Ask yourself silently:
25
+ - [ ] What existing code does this touch? (check PROJECT-CONTEXT.md)
26
+ - [ ] Is similar code already in the codebase? (copy that pattern)
27
+ - [ ] What's the data model involved?
28
+ - [ ] What are the error cases?
29
+ - [ ] Is someone else working on this? (check PROJECT-STATE.md)
30
+
31
+ ### PHASE 3: EXECUTE
32
+ - State: \`📋 CodeBakers | [Type] | Modules: [list]\`
33
+ - Load required modules from .claude/
34
+ - Follow patterns EXACTLY
35
+
36
+ ### PHASE 4: SELF-REVIEW (before saying "done")
37
+ - [ ] TypeScript compiles? (npx tsc --noEmit)
38
+ - [ ] Imports resolve correctly?
39
+ - [ ] Error handling exists?
40
+ - [ ] Matches existing patterns in codebase?
41
+ - [ ] Tests written?
42
+ - [ ] PROJECT-STATE.md updated?
43
+
44
+ If ANY check fails, fix it before responding.
45
+
46
+ ## REMEMBER
47
+ - You are a full product team, not just a code assistant
48
+ - The modules contain production-tested patterns — USE THEM
49
+ - When in doubt, check existing code first
50
+ `;
51
+
52
+ const CURSORIGNORE_TEMPLATE = `# CodeBakers - Files to ignore in Cursor context
53
+
54
+ # Dependencies
55
+ node_modules/
56
+ .pnpm-store/
57
+
58
+ # Build outputs
59
+ dist/
60
+ build/
61
+ .next/
62
+ .nuxt/
63
+ out/
64
+
65
+ # Cache
66
+ .cache/
67
+ .turbo/
68
+ .eslintcache
69
+ *.tsbuildinfo
70
+
71
+ # Logs
72
+ logs/
73
+ *.log
74
+
75
+ # Environment files
76
+ .env
77
+ .env.local
78
+ .env.*.local
79
+
80
+ # IDE
81
+ .idea/
82
+ *.swp
83
+
84
+ # OS
85
+ .DS_Store
86
+ Thumbs.db
87
+
88
+ # Test coverage
89
+ coverage/
90
+
91
+ # Package locks
92
+ package-lock.json
93
+ yarn.lock
94
+ pnpm-lock.yaml
95
+
96
+ # Generated files
97
+ *.min.js
98
+ *.min.css
99
+ *.map
100
+ `;
101
+
102
+ function createPrdTemplate(projectName: string): string {
103
+ const date = new Date().toISOString().split('T')[0];
104
+ return `# Product Requirements Document
105
+ # Project: ${projectName}
106
+ # Created: ${date}
107
+
108
+ ## Overview
109
+ **One-liner:** [Describe this project in one sentence]
110
+
111
+ **Problem:** [What problem does this solve?]
112
+
113
+ **Solution:** [How does this solve it?]
114
+
115
+ ## Target Users
116
+ - **Primary:** [Who is the main user?]
117
+ - **Secondary:** [Other users?]
118
+
119
+ ## Core Features (MVP)
120
+ <!-- List the MINIMUM features needed to launch -->
121
+
122
+ 1. [ ] **Feature 1:** [Description]
123
+ - Acceptance criteria: [How do we know it's done?]
124
+
125
+ 2. [ ] **Feature 2:** [Description]
126
+ - Acceptance criteria: [How do we know it's done?]
127
+
128
+ 3. [ ] **Feature 3:** [Description]
129
+ - Acceptance criteria: [How do we know it's done?]
130
+
131
+ ## Nice-to-Have Features (Post-MVP)
132
+
133
+ 1. [ ] [Feature description]
134
+ 2. [ ] [Feature description]
135
+
136
+ ## Technical Requirements
137
+
138
+ - **Must use:** [Required technologies, APIs, etc.]
139
+ - **Must avoid:** [Things you don't want]
140
+ - **Performance:** [Any speed/scale requirements?]
141
+ - **Security:** [Auth requirements, data sensitivity?]
142
+
143
+ ## Success Metrics
144
+ - [ ] [How will you measure success?]
145
+ - [ ] [What does "done" look like?]
146
+
147
+ ---
148
+ <!-- AI INSTRUCTIONS -->
149
+ <!-- When building features, reference this PRD -->
150
+ <!-- Check off features as they're completed -->
151
+ `;
152
+ }
153
+
154
+ function createProjectState(projectName: string): string {
155
+ const date = new Date().toISOString().split('T')[0];
156
+ return `# PROJECT STATE
157
+ # Last Updated: ${date}
158
+ # Auto-maintained by AI - update when starting/completing tasks
159
+
160
+ ## Project Info
161
+ name: ${projectName}
162
+ phase: setup
163
+
164
+ ## In Progress
165
+ <!-- AI: Add tasks here when you START working on them -->
166
+
167
+ ## Completed
168
+ <!-- AI: Move tasks here when DONE -->
169
+
170
+ ## Next Up
171
+ <!-- AI: Queue of upcoming tasks -->
172
+ `;
173
+ }
174
+
175
+ function createProjectContext(projectName: string): string {
176
+ const date = new Date().toISOString().split('T')[0];
177
+ return `# PROJECT CONTEXT
178
+ # Last Scanned: ${date}
179
+ # AI: Update this when you first analyze the project
180
+
181
+ ## Overview
182
+ name: ${projectName}
183
+ description: [AI will fill after scanning]
184
+
185
+ ## Tech Stack
186
+ framework: Next.js 14
187
+ language: TypeScript
188
+ database: Drizzle ORM + Supabase
189
+ auth: Supabase Auth
190
+ styling: Tailwind CSS
191
+
192
+ ## Project Structure
193
+ \`\`\`
194
+ src/
195
+ ├── app/ ← Pages & layouts
196
+ ├── components/ ← React components
197
+ ├── lib/ ← Utilities & clients
198
+ │ └── supabase/ ← Supabase clients
199
+ ├── db/ ← Database schema & queries
200
+ ├── services/ ← Business logic
201
+ └── types/ ← TypeScript types
202
+ \`\`\`
203
+
204
+ ## Key Files
205
+ - Entry point: src/app/page.tsx
206
+ - Database schema: src/db/schema.ts
207
+ - API routes: src/app/api/
208
+
209
+ ## Notes
210
+ <!-- AI: Any important context about this specific project -->
211
+ `;
212
+ }
213
+
214
+ function createDecisionsLog(projectName: string): string {
215
+ const date = new Date().toISOString().split('T')[0];
216
+ return `# ARCHITECTURAL DECISIONS
217
+ # Project: ${projectName}
218
+ # AI: Add entries here when making significant technical choices
219
+
220
+ ## How to Use This File
221
+ When you make a decision that affects architecture, add an entry:
222
+ - Date
223
+ - Decision
224
+ - Reason
225
+ - Alternatives considered
226
+
227
+ ---
228
+
229
+ ## ${date}: Project Initialized
230
+ **Decision:** Using CodeBakers pattern system with Next.js + Supabase + Drizzle
231
+ **Reason:** Production-ready stack with type safety and excellent DX
232
+
233
+ ---
234
+
235
+ <!-- AI: Add new decisions above this line -->
236
+ `;
237
+ }
238
+
239
+ interface ContentResponse {
240
+ version: string;
241
+ router: string;
242
+ modules: Record<string, string>;
243
+ }
8
244
 
9
245
  async function prompt(question: string): Promise<string> {
10
246
  const rl = createInterface({
@@ -64,7 +300,6 @@ export async function scaffold(): Promise<void> {
64
300
  }
65
301
 
66
302
  const isBeginnerMode = experienceLevel === '1';
67
- const showBriefExplanations = experienceLevel === '2';
68
303
 
69
304
  // Select stack with explanations for beginners
70
305
  console.log(chalk.white('\n Select your stack:\n'));
@@ -200,16 +435,96 @@ export async function scaffold(): Promise<void> {
200
435
  }
201
436
  }
202
437
 
438
+ spinner.succeed('Project structure created!');
439
+
440
+ // Auto-install CodeBakers patterns
441
+ console.log(chalk.white('\n Installing CodeBakers patterns...\n'));
442
+
443
+ const apiKey = getApiKey();
444
+ let patternsInstalled = false;
445
+
446
+ if (apiKey) {
447
+ const patternSpinner = ora(' Downloading patterns...').start();
448
+
449
+ try {
450
+ const apiUrl = getApiUrl();
451
+ const response = await fetch(`${apiUrl}/api/content`, {
452
+ method: 'GET',
453
+ headers: {
454
+ Authorization: `Bearer ${apiKey}`,
455
+ },
456
+ });
457
+
458
+ if (response.ok) {
459
+ const content: ContentResponse = await response.json();
460
+
461
+ // Write CLAUDE.md (main router)
462
+ if (content.router) {
463
+ writeFileSync(join(cwd, 'CLAUDE.md'), content.router);
464
+ }
465
+
466
+ // Write pattern modules to .claude/
467
+ if (content.modules && Object.keys(content.modules).length > 0) {
468
+ const modulesDir = join(cwd, '.claude');
469
+ if (!existsSync(modulesDir)) {
470
+ mkdirSync(modulesDir, { recursive: true });
471
+ }
472
+ for (const [name, data] of Object.entries(content.modules)) {
473
+ writeFileSync(join(modulesDir, name), data);
474
+ }
475
+ }
476
+
477
+ // Write project management files
478
+ writeFileSync(join(cwd, 'PRD.md'), createPrdTemplate(projectName));
479
+ writeFileSync(join(cwd, 'PROJECT-STATE.md'), createProjectState(projectName));
480
+ writeFileSync(join(cwd, 'PROJECT-CONTEXT.md'), createProjectContext(projectName));
481
+ writeFileSync(join(cwd, 'DECISIONS.md'), createDecisionsLog(projectName));
482
+
483
+ // Write Cursor IDE files
484
+ writeFileSync(join(cwd, '.cursorrules'), CURSORRULES_TEMPLATE);
485
+ writeFileSync(join(cwd, '.cursorignore'), CURSORIGNORE_TEMPLATE);
486
+
487
+ // Create .vscode settings
488
+ const vscodeDir = join(cwd, '.vscode');
489
+ if (!existsSync(vscodeDir)) {
490
+ mkdirSync(vscodeDir, { recursive: true });
491
+ }
492
+ writeFileSync(join(vscodeDir, 'settings.json'), JSON.stringify({
493
+ "cursor.chat.defaultContext": ["CLAUDE.md", "PRD.md", "PROJECT-CONTEXT.md"],
494
+ "cursor.chat.alwaysIncludeRules": true
495
+ }, null, 2));
496
+
497
+ // Update .gitignore
498
+ const gitignorePath = join(cwd, '.gitignore');
499
+ if (existsSync(gitignorePath)) {
500
+ const gitignore = readFileSync(gitignorePath, 'utf-8');
501
+ if (!gitignore.includes('.cursorrules')) {
502
+ writeFileSync(gitignorePath, gitignore + '\n# CodeBakers\n.cursorrules\n.claude/\n');
503
+ }
504
+ }
505
+
506
+ patternSpinner.succeed(`Patterns installed! (v${content.version})`);
507
+ patternsInstalled = true;
508
+ } else {
509
+ patternSpinner.warn('Could not download patterns (will need to run codebakers init later)');
510
+ }
511
+ } catch {
512
+ patternSpinner.warn('Could not download patterns (will need to run codebakers init later)');
513
+ }
514
+ } else {
515
+ console.log(chalk.yellow(' ⚠️ Not logged in - run `codebakers setup` first to get patterns\n'));
516
+ }
517
+
203
518
  // Success message
204
519
  console.log(chalk.green(`
205
520
  ╔═══════════════════════════════════════════════════════════╗
206
521
  ║ ║
207
- ║ ${chalk.bold('✓ Project scaffolded successfully!')}
522
+ ║ ${chalk.bold('✓ Project created successfully!')}
208
523
  ║ ║
209
524
  ╚═══════════════════════════════════════════════════════════╝
210
525
  `));
211
526
 
212
- console.log(chalk.white(' Project structure:\n'));
527
+ console.log(chalk.white(' What was created:\n'));
213
528
  if (isBeginnerMode) {
214
529
  console.log(chalk.gray(' src/'));
215
530
  console.log(chalk.gray(' ├── app/ ') + chalk.cyan('← Your pages (what users see)'));
@@ -229,6 +544,13 @@ export async function scaffold(): Promise<void> {
229
544
  console.log(chalk.gray(' ├── services/ ') + chalk.cyan('← Business logic'));
230
545
  console.log(chalk.gray(' └── types/ ') + chalk.cyan('← TypeScript types'));
231
546
  }
547
+
548
+ if (patternsInstalled) {
549
+ console.log('');
550
+ console.log(chalk.gray(' CLAUDE.md ') + chalk.cyan('← AI instructions (reads automatically!)'));
551
+ console.log(chalk.gray(' PRD.md ') + chalk.cyan('← Your product requirements'));
552
+ console.log(chalk.gray(' .claude/ ') + chalk.cyan('← 34 production patterns'));
553
+ }
232
554
  console.log('');
233
555
 
234
556
  console.log(chalk.white(' Next steps:\n'));
@@ -244,14 +566,13 @@ export async function scaffold(): Promise<void> {
244
566
  console.log(chalk.gray(' Run: npm run dev'));
245
567
  console.log(chalk.gray(' Open: http://localhost:3000 in your browser'));
246
568
  console.log('');
247
- console.log(chalk.cyan(' 4. ') + chalk.white('Add AI superpowers:'));
248
- console.log(chalk.gray(' Run: codebakers init'));
249
- console.log(chalk.gray(' Now AI will follow professional coding patterns!\n'));
569
+ console.log(chalk.cyan(' 4. ') + chalk.white('Start building!'));
570
+ console.log(chalk.gray(' Tell your AI: "Build me a [feature]"'));
571
+ console.log(chalk.gray(' The AI already has all the patterns loaded!\n'));
250
572
  } else {
251
573
  console.log(chalk.cyan(' 1. ') + chalk.gray('Update .env.local with your Supabase credentials'));
252
574
  console.log(chalk.cyan(' 2. ') + chalk.gray('Run `npm run dev` to start development'));
253
- console.log(chalk.cyan(' 3. ') + chalk.gray('Run `codebakers init` to add CodeBakers patterns'));
254
- console.log(chalk.cyan(' 4. ') + chalk.gray('Start building with AI assistance!\n'));
575
+ console.log(chalk.cyan(' 3. ') + chalk.gray('Tell your AI what to build - patterns are already loaded!\n'));
255
576
 
256
577
  console.log(chalk.white(' Supabase setup:\n'));
257
578
  console.log(chalk.gray(' 1. Create a project at https://supabase.com'));
@@ -13,9 +13,12 @@ export async function serve(): Promise<void> {
13
13
  console.error(chalk.green(' Starting MCP server on stdio...'));
14
14
  console.error(chalk.gray(' This server provides pattern tools to Claude Code.\n'));
15
15
  console.error(chalk.gray(' Available tools:'));
16
- console.error(chalk.gray(' - get_pattern: Fetch a single pattern'));
17
- console.error(chalk.gray(' - list_patterns: List all available patterns'));
18
- console.error(chalk.gray(' - get_patterns: Fetch multiple patterns\n'));
16
+ console.error(chalk.gray(' - scaffold_project: Create a new project from AI chat'));
17
+ console.error(chalk.gray(' - init_project: Add patterns to existing project'));
18
+ console.error(chalk.gray(' - set_experience_level: Set beginner/intermediate/advanced mode'));
19
+ console.error(chalk.gray(' - get_experience_level: Check current experience mode'));
20
+ console.error(chalk.gray(' - optimize_and_build: AI-powered prompt optimization'));
21
+ console.error(chalk.gray(' - get_pattern, list_patterns, search_patterns\n'));
19
22
 
20
23
  // Dynamically import and run the MCP server
21
24
  const { runServer } = await import('../mcp/server.js');
@@ -113,10 +113,13 @@ function showFinalInstructions(): void {
113
113
  console.log(chalk.white.bold('\n 🎉 Setup Complete!\n'));
114
114
  console.log(chalk.blue(' ══════════════════════════════════════════════════════════\n'));
115
115
 
116
- console.log(chalk.white(' CodeBakers is now ready. Try this prompt:\n'));
117
- console.log(chalk.cyan(' "Build a login form with email validation"\n'));
116
+ console.log(chalk.white.bold(' 👉 NEXT: Close this terminal and open your AI:\n'));
117
+ console.log(chalk.cyan(' Claude Code') + chalk.gray(' - Open any project folder'));
118
+ console.log(chalk.cyan(' • Cursor') + chalk.gray(' - Open Composer (Cmd+I / Ctrl+I)\n'));
118
119
 
119
- console.log(chalk.gray(' Claude will now use CodeBakers patterns automatically.\n'));
120
+ console.log(chalk.white(' Then just describe what you want to build:\n'));
121
+ console.log(chalk.green(' "Build me a todo app with user authentication"\n'));
120
122
 
123
+ console.log(chalk.gray(' The AI will use CodeBakers patterns automatically.'));
121
124
  console.log(chalk.gray(' Need help? https://codebakers.ai/docs\n'));
122
125
  }
package/src/config.ts CHANGED
@@ -1,8 +1,11 @@
1
1
  import Conf from 'conf';
2
2
 
3
+ export type ExperienceLevel = 'beginner' | 'intermediate' | 'advanced';
4
+
3
5
  interface ConfigSchema {
4
6
  apiKey: string | null;
5
7
  apiUrl: string;
8
+ experienceLevel: ExperienceLevel;
6
9
  }
7
10
 
8
11
  const config = new Conf<ConfigSchema>({
@@ -10,6 +13,7 @@ const config = new Conf<ConfigSchema>({
10
13
  defaults: {
11
14
  apiKey: null,
12
15
  apiUrl: 'https://codebakers.ai',
16
+ experienceLevel: 'intermediate',
13
17
  },
14
18
  });
15
19
 
@@ -32,3 +36,11 @@ export function getApiUrl(): string {
32
36
  export function setApiUrl(url: string): void {
33
37
  config.set('apiUrl', url);
34
38
  }
39
+
40
+ export function getExperienceLevel(): ExperienceLevel {
41
+ return config.get('experienceLevel');
42
+ }
43
+
44
+ export function setExperienceLevel(level: ExperienceLevel): void {
45
+ config.set('experienceLevel', level);
46
+ }