codebakers 2.5.4 → 3.1.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.
Files changed (60) hide show
  1. package/README.md +54 -255
  2. package/dist/chunk-HOWR3YTF.js +146 -0
  3. package/dist/index.d.ts +0 -3
  4. package/dist/index.js +10505 -7997
  5. package/dist/terminal-6ZQVP6R7.js +10 -0
  6. package/package.json +26 -41
  7. package/AUDIT_REPORT.md +0 -138
  8. package/dist/advisors-RWRTSJRR.js +0 -7
  9. package/dist/chunk-ASIJIQYC.js +0 -320
  10. package/dist/chunk-D44U3IEA.js +0 -565
  11. package/dist/chunk-LANM5XQW.js +0 -326
  12. package/dist/prd-RYITSL6Q.js +0 -7
  13. package/install.bat +0 -9
  14. package/installers/CodeBakers-Install.bat +0 -207
  15. package/installers/CodeBakers-Install.command +0 -232
  16. package/installers/README.md +0 -157
  17. package/installers/mac/assets/README.txt +0 -31
  18. package/installers/mac/build-mac-installer.sh +0 -240
  19. package/installers/windows/CodeBakers.iss +0 -256
  20. package/installers/windows/assets/README.txt +0 -16
  21. package/installers/windows/scripts/post-install.bat +0 -15
  22. package/src/channels/discord.ts +0 -5
  23. package/src/channels/slack.ts +0 -5
  24. package/src/channels/sms.ts +0 -4
  25. package/src/channels/telegram.ts +0 -5
  26. package/src/channels/whatsapp.ts +0 -7
  27. package/src/commands/advisors.ts +0 -699
  28. package/src/commands/build.ts +0 -1025
  29. package/src/commands/check.ts +0 -365
  30. package/src/commands/code.ts +0 -806
  31. package/src/commands/connect.ts +0 -12
  32. package/src/commands/deploy.ts +0 -448
  33. package/src/commands/design.ts +0 -298
  34. package/src/commands/fix.ts +0 -20
  35. package/src/commands/gateway.ts +0 -604
  36. package/src/commands/generate.ts +0 -178
  37. package/src/commands/init.ts +0 -634
  38. package/src/commands/integrate.ts +0 -884
  39. package/src/commands/learn.ts +0 -36
  40. package/src/commands/migrate.ts +0 -419
  41. package/src/commands/prd-maker.ts +0 -588
  42. package/src/commands/prd.ts +0 -419
  43. package/src/commands/security.ts +0 -102
  44. package/src/commands/setup.ts +0 -600
  45. package/src/commands/status.ts +0 -56
  46. package/src/commands/website.ts +0 -741
  47. package/src/index.ts +0 -627
  48. package/src/patterns/loader.ts +0 -337
  49. package/src/services/github.ts +0 -61
  50. package/src/services/supabase.ts +0 -147
  51. package/src/services/vercel.ts +0 -61
  52. package/src/utils/claude-md.ts +0 -287
  53. package/src/utils/config.ts +0 -375
  54. package/src/utils/display.ts +0 -338
  55. package/src/utils/files.ts +0 -418
  56. package/src/utils/nlp.ts +0 -312
  57. package/src/utils/ui.ts +0 -441
  58. package/src/utils/updates.ts +0 -8
  59. package/src/utils/voice.ts +0 -323
  60. package/tsconfig.json +0 -26
@@ -1,419 +0,0 @@
1
- import * as p from '@clack/prompts';
2
- import chalk from 'chalk';
3
- import fs from 'fs-extra';
4
- import * as path from 'path';
5
- import Anthropic from '@anthropic-ai/sdk';
6
- import { Config } from '../utils/config.js';
7
-
8
- interface PRDSection {
9
- title: string;
10
- content: string;
11
- }
12
-
13
- interface ParsedPRD {
14
- name: string;
15
- description: string;
16
- features: string[];
17
- pages: string[];
18
- database: string[];
19
- integrations: string[];
20
- design: {
21
- profile?: string;
22
- brandColor?: string;
23
- };
24
- }
25
-
26
- export async function prdCommand(filePath?: string): Promise<void> {
27
- const config = new Config();
28
-
29
- if (!config.isConfigured()) {
30
- p.log.error('Please run `codebakers setup` first.');
31
- return;
32
- }
33
-
34
- p.intro(chalk.bgCyan.black(' Build from PRD '));
35
-
36
- // Get PRD file
37
- let prdPath = filePath;
38
- if (!prdPath) {
39
- const file = await p.text({
40
- message: 'Path to PRD file:',
41
- placeholder: './PRD.md or paste URL',
42
- validate: (v) => !v ? 'File path required' : undefined,
43
- });
44
- if (p.isCancel(file)) return;
45
- prdPath = file as string;
46
- }
47
-
48
- // Read PRD
49
- const spinner = p.spinner();
50
- spinner.start('Reading PRD...');
51
-
52
- let prdContent: string;
53
- try {
54
- if (prdPath.startsWith('http')) {
55
- const response = await fetch(prdPath);
56
- prdContent = await response.text();
57
- } else {
58
- prdContent = await fs.readFile(prdPath, 'utf-8');
59
- }
60
- } catch (error) {
61
- spinner.stop('Error');
62
- p.log.error(`Could not read PRD: ${error instanceof Error ? error.message : 'Unknown error'}`);
63
- return;
64
- }
65
-
66
- spinner.stop('PRD loaded');
67
-
68
- // Parse PRD with AI
69
- spinner.start('Analyzing PRD...');
70
-
71
- const anthropicCreds = config.getCredentials('anthropic');
72
- if (!anthropicCreds?.apiKey) {
73
- spinner.stop('Error');
74
- p.log.error('Anthropic API key not configured.');
75
- return;
76
- }
77
-
78
- const anthropic = new Anthropic({ apiKey: anthropicCreds.apiKey });
79
-
80
- const parsed = await parsePRD(anthropic, prdContent);
81
- spinner.stop('PRD analyzed');
82
-
83
- // Show what was extracted
84
- console.log(chalk.bold('\n📋 Extracted from PRD:\n'));
85
- console.log(` ${chalk.cyan('Name:')} ${parsed.name}`);
86
- console.log(` ${chalk.cyan('Description:')} ${parsed.description}`);
87
- console.log(` ${chalk.cyan('Features:')} ${parsed.features.length} features`);
88
- console.log(` ${chalk.cyan('Pages:')} ${parsed.pages.join(', ') || 'Auto-detect'}`);
89
- console.log(` ${chalk.cyan('Database:')} ${parsed.database.length} tables`);
90
- console.log(` ${chalk.cyan('Integrations:')} ${parsed.integrations.join(', ') || 'None'}`);
91
- console.log('');
92
-
93
- // Show features
94
- if (parsed.features.length > 0) {
95
- console.log(chalk.bold('Features to build:'));
96
- parsed.features.slice(0, 10).forEach((f, i) => {
97
- console.log(chalk.dim(` ${i + 1}. ${f}`));
98
- });
99
- if (parsed.features.length > 10) {
100
- console.log(chalk.dim(` ... and ${parsed.features.length - 10} more`));
101
- }
102
- console.log('');
103
- }
104
-
105
- // Confirm
106
- const proceed = await p.confirm({
107
- message: 'Build this project?',
108
- initialValue: true,
109
- });
110
-
111
- if (!proceed || p.isCancel(proceed)) {
112
- p.cancel('Cancelled');
113
- return;
114
- }
115
-
116
- // Build options
117
- const options = await p.group({
118
- createInfra: () => p.confirm({
119
- message: 'Create GitHub + Vercel + Supabase?',
120
- initialValue: true,
121
- }),
122
- designProfile: () => p.select({
123
- message: 'Design profile:',
124
- options: [
125
- { value: 'minimal', label: 'Minimal (Linear, Notion)' },
126
- { value: 'bold', label: 'Bold (Stripe, Ramp)' },
127
- { value: 'editorial', label: 'Editorial (Medium, Substack)' },
128
- { value: 'playful', label: 'Playful (Figma, Slack)' },
129
- { value: 'premium', label: 'Premium (Apple, Porsche)' },
130
- { value: 'dashboard', label: 'Dashboard (Datadog, Linear)' },
131
- ],
132
- initialValue: parsed.design.profile || 'minimal',
133
- }),
134
- });
135
-
136
- if (p.isCancel(options)) return;
137
-
138
- // Build the project
139
- await buildFromPRD(parsed, options, anthropic, config);
140
- }
141
-
142
- async function parsePRD(anthropic: Anthropic, content: string): Promise<ParsedPRD> {
143
- const response = await anthropic.messages.create({
144
- model: 'claude-sonnet-4-5-20250929',
145
- max_tokens: 4096,
146
- messages: [{
147
- role: 'user',
148
- content: `Analyze this PRD and extract structured information. Return JSON only, no explanation.
149
-
150
- PRD:
151
- ${content}
152
-
153
- Return this exact JSON structure:
154
- {
155
- "name": "project name (lowercase, hyphenated)",
156
- "description": "one sentence description",
157
- "features": ["feature 1", "feature 2", ...],
158
- "pages": ["page1", "page2", ...],
159
- "database": ["table1", "table2", ...],
160
- "integrations": ["stripe", "supabase", ...],
161
- "design": {
162
- "profile": "minimal|bold|editorial|playful|premium|dashboard or null",
163
- "brandColor": "#hexcolor or null"
164
- }
165
- }
166
-
167
- Extract ALL features mentioned. Include auth, payments, dashboards, etc.
168
- For pages, list actual pages/routes needed.
169
- For database, list tables/entities needed.
170
- For integrations, list third-party services mentioned.`
171
- }],
172
- });
173
-
174
- const text = response.content[0].type === 'text' ? response.content[0].text : '';
175
-
176
- // Extract JSON from response
177
- const jsonMatch = text.match(/\{[\s\S]*\}/);
178
- if (!jsonMatch) {
179
- throw new Error('Could not parse PRD');
180
- }
181
-
182
- return JSON.parse(jsonMatch[0]);
183
- }
184
-
185
- async function buildFromPRD(
186
- prd: ParsedPRD,
187
- options: { createInfra: boolean; designProfile: string },
188
- anthropic: Anthropic,
189
- config: Config
190
- ): Promise<void> {
191
- const spinner = p.spinner();
192
- const projectPath = path.join(process.cwd(), prd.name);
193
-
194
- // Step 1: Create project structure
195
- spinner.start('Creating project structure...');
196
- await fs.ensureDir(projectPath);
197
- await fs.ensureDir(path.join(projectPath, '.codebakers'));
198
- await fs.ensureDir(path.join(projectPath, 'src', 'app'));
199
- await fs.ensureDir(path.join(projectPath, 'src', 'components'));
200
- await fs.ensureDir(path.join(projectPath, 'src', 'lib'));
201
- spinner.stop('Project structure created');
202
-
203
- // Step 2: Save PRD to project
204
- spinner.start('Saving PRD...');
205
- await fs.writeFile(path.join(projectPath, 'PRD.md'), await fs.readFile(process.cwd(), 'utf-8').catch(() => JSON.stringify(prd, null, 2)));
206
- await fs.writeJson(path.join(projectPath, '.codebakers', 'prd.json'), prd, { spaces: 2 });
207
- await fs.writeJson(path.join(projectPath, '.codebakers', 'design.json'), {
208
- profile: options.designProfile,
209
- colors: prd.design.brandColor ? { brand: prd.design.brandColor } : undefined,
210
- }, { spaces: 2 });
211
- spinner.stop('PRD saved');
212
-
213
- // Step 3: Generate build plan
214
- spinner.start('Generating build plan...');
215
- const buildPlan = await generateBuildPlan(anthropic, prd, options.designProfile);
216
- await fs.writeJson(path.join(projectPath, '.codebakers', 'build-plan.json'), buildPlan, { spaces: 2 });
217
- spinner.stop('Build plan generated');
218
-
219
- // Show build plan
220
- console.log(chalk.bold('\n🏗️ Build Plan:\n'));
221
- buildPlan.phases.forEach((phase: any, i: number) => {
222
- console.log(chalk.cyan(`Phase ${i + 1}: ${phase.name}`));
223
- phase.tasks.forEach((task: string) => {
224
- console.log(chalk.dim(` • ${task}`));
225
- });
226
- });
227
- console.log('');
228
-
229
- // Step 4: Execute build plan
230
- const startBuild = await p.confirm({
231
- message: 'Start building?',
232
- initialValue: true,
233
- });
234
-
235
- if (!startBuild || p.isCancel(startBuild)) {
236
- p.log.info(`Build plan saved to ${prd.name}/.codebakers/build-plan.json`);
237
- p.log.info(`Run \`cd ${prd.name} && codebakers code\` to continue building.`);
238
- return;
239
- }
240
-
241
- // Execute each phase
242
- for (let i = 0; i < buildPlan.phases.length; i++) {
243
- const phase = buildPlan.phases[i];
244
- console.log(chalk.bold(`\n📦 Phase ${i + 1}: ${phase.name}\n`));
245
-
246
- for (const task of phase.tasks) {
247
- spinner.start(task);
248
-
249
- try {
250
- await executeTask(anthropic, projectPath, task, prd, options.designProfile);
251
- spinner.stop(`✓ ${task}`);
252
- } catch (error) {
253
- spinner.stop(`✗ ${task}`);
254
- p.log.error(error instanceof Error ? error.message : 'Task failed');
255
-
256
- const continueBuilding = await p.confirm({
257
- message: 'Continue with next task?',
258
- initialValue: true,
259
- });
260
-
261
- if (!continueBuilding || p.isCancel(continueBuilding)) {
262
- p.log.info('Build paused. Run `codebakers code` to continue.');
263
- return;
264
- }
265
- }
266
- }
267
- }
268
-
269
- // Step 5: Infrastructure (if selected)
270
- if (options.createInfra) {
271
- console.log(chalk.bold('\n🚀 Setting up infrastructure...\n'));
272
-
273
- spinner.start('Creating GitHub repository...');
274
- // Would call GitHub service
275
- spinner.stop('GitHub repository created');
276
-
277
- spinner.start('Creating Supabase project...');
278
- // Would call Supabase service
279
- spinner.stop('Supabase project created');
280
-
281
- spinner.start('Creating Vercel project...');
282
- // Would call Vercel service
283
- spinner.stop('Vercel project created');
284
-
285
- spinner.start('Deploying...');
286
- // Would deploy
287
- spinner.stop('Deployed!');
288
- }
289
-
290
- // Done!
291
- p.outro(chalk.green(`
292
- ✓ Project built from PRD!
293
-
294
- ${chalk.bold('Your project:')}
295
- ${chalk.cyan(`cd ${prd.name}`)}
296
- ${chalk.cyan('npm run dev')}
297
-
298
- ${chalk.bold('Continue building:')}
299
- ${chalk.cyan('codebakers code')} — AI agent
300
- ${chalk.cyan('codebakers check')} — Verify patterns
301
- ${chalk.cyan('codebakers deploy')} — Deploy changes
302
- `));
303
- }
304
-
305
- async function generateBuildPlan(
306
- anthropic: Anthropic,
307
- prd: ParsedPRD,
308
- designProfile: string
309
- ): Promise<{ phases: Array<{ name: string; tasks: string[] }> }> {
310
- const response = await anthropic.messages.create({
311
- model: 'claude-sonnet-4-5-20250929',
312
- max_tokens: 4096,
313
- messages: [{
314
- role: 'user',
315
- content: `Create a build plan for this project. Return JSON only.
316
-
317
- Project: ${prd.name}
318
- Description: ${prd.description}
319
- Features: ${prd.features.join(', ')}
320
- Pages: ${prd.pages.join(', ')}
321
- Database tables: ${prd.database.join(', ')}
322
- Integrations: ${prd.integrations.join(', ')}
323
- Design: ${designProfile}
324
-
325
- Return this structure:
326
- {
327
- "phases": [
328
- {
329
- "name": "Phase name",
330
- "tasks": ["task 1", "task 2", ...]
331
- }
332
- ]
333
- }
334
-
335
- Phases should be:
336
- 1. Setup (package.json, config, base files)
337
- 2. Database (schema, migrations, types)
338
- 3. Auth (if needed)
339
- 4. Core Features (main functionality)
340
- 5. UI/Pages (frontend)
341
- 6. Integrations (third-party services)
342
- 7. Polish (loading states, error handling, empty states)
343
-
344
- Keep tasks specific and actionable.`
345
- }],
346
- });
347
-
348
- const text = response.content[0].type === 'text' ? response.content[0].text : '';
349
- const jsonMatch = text.match(/\{[\s\S]*\}/);
350
- if (!jsonMatch) {
351
- throw new Error('Could not generate build plan');
352
- }
353
-
354
- return JSON.parse(jsonMatch[0]);
355
- }
356
-
357
- async function executeTask(
358
- anthropic: Anthropic,
359
- projectPath: string,
360
- task: string,
361
- prd: ParsedPRD,
362
- designProfile: string
363
- ): Promise<void> {
364
- const response = await anthropic.messages.create({
365
- model: 'claude-sonnet-4-5-20250929',
366
- max_tokens: 8192,
367
- messages: [{
368
- role: 'user',
369
- content: `Execute this task for the project.
370
-
371
- Project: ${prd.name}
372
- Task: ${task}
373
- Design Profile: ${designProfile}
374
-
375
- Context:
376
- - Features: ${prd.features.join(', ')}
377
- - Database: ${prd.database.join(', ')}
378
-
379
- Output files in this format:
380
-
381
- <<<FILE: path/to/file.ts>>>
382
- file content here
383
- <<<END_FILE>>>
384
-
385
- <<<FILE: another/file.tsx>>>
386
- file content here
387
- <<<END_FILE>>>
388
-
389
- Follow these rules:
390
- - Use TypeScript
391
- - Use Next.js App Router
392
- - Use Tailwind CSS
393
- - Use shadcn/ui components
394
- - Every button needs onClick handler
395
- - Every form needs Zod validation
396
- - Every async operation needs loading/error states
397
- - Every list needs empty state
398
- - No generic gradient heroes
399
- - No icon spam
400
- - Generous spacing (py-16 or larger for sections)
401
-
402
- Generate ALL files needed for this task.`
403
- }],
404
- });
405
-
406
- const text = response.content[0].type === 'text' ? response.content[0].text : '';
407
-
408
- // Parse and write files
409
- const fileRegex = /<<<FILE:\s*(.+?)>>>([\s\S]*?)<<<END_FILE>>>/g;
410
- let match;
411
-
412
- while ((match = fileRegex.exec(text)) !== null) {
413
- const filePath = path.join(projectPath, match[1].trim());
414
- const content = match[2].trim();
415
-
416
- await fs.ensureDir(path.dirname(filePath));
417
- await fs.writeFile(filePath, content);
418
- }
419
- }
@@ -1,102 +0,0 @@
1
- import * as p from '@clack/prompts';
2
- import chalk from 'chalk';
3
- import fs from 'fs-extra';
4
- import glob from 'fast-glob';
5
- import * as path from 'path';
6
-
7
- export async function securityCommand(): Promise<void> {
8
- p.intro(chalk.bgCyan.black(' Security Audit '));
9
-
10
- const spinner = p.spinner();
11
- spinner.start('Scanning for security issues...');
12
-
13
- const issues = await runSecurityScan();
14
-
15
- spinner.stop('Scan complete');
16
-
17
- if (issues.length === 0) {
18
- console.log(chalk.green('\n✓ No security issues found!\n'));
19
- displaySecurityScore(100);
20
- } else {
21
- console.log(chalk.yellow(`\n⚠️ ${issues.length} security issues found:\n`));
22
-
23
- for (const issue of issues) {
24
- const icon = issue.severity === 'critical' ? chalk.red('🔴') :
25
- issue.severity === 'high' ? chalk.red('🟠') :
26
- chalk.yellow('🟡');
27
-
28
- console.log(`${icon} ${chalk.bold(issue.title)}`);
29
- console.log(chalk.dim(` ${issue.file}:${issue.line}`));
30
- console.log(` ${issue.description}\n`);
31
- }
32
-
33
- const score = Math.max(0, 100 -
34
- (issues.filter(i => i.severity === 'critical').length * 30) -
35
- (issues.filter(i => i.severity === 'high').length * 15));
36
- displaySecurityScore(score);
37
- }
38
-
39
- p.outro('');
40
- }
41
-
42
- interface SecurityIssue {
43
- title: string;
44
- description: string;
45
- file: string;
46
- line: number;
47
- severity: 'critical' | 'high' | 'medium';
48
- }
49
-
50
- async function runSecurityScan(): Promise<SecurityIssue[]> {
51
- const cwd = process.cwd();
52
- const issues: SecurityIssue[] = [];
53
-
54
- const files = await glob(['src/**/*.{ts,tsx,js,jsx}'], {
55
- cwd,
56
- ignore: ['**/node_modules/**'],
57
- });
58
-
59
- const patterns = [
60
- {
61
- pattern: /(sk_live_|sk_test_)[a-zA-Z0-9]+/g,
62
- title: 'Hardcoded Stripe key',
63
- severity: 'critical' as const,
64
- description: 'Stripe API key should be in environment variables',
65
- },
66
- {
67
- pattern: /\beval\s*\(/g,
68
- title: 'Use of eval()',
69
- severity: 'critical' as const,
70
- description: 'eval() is a security vulnerability',
71
- },
72
- {
73
- pattern: /dangerouslySetInnerHTML/g,
74
- title: 'dangerouslySetInnerHTML',
75
- severity: 'high' as const,
76
- description: 'Ensure content is sanitized with DOMPurify',
77
- },
78
- ];
79
-
80
- for (const file of files) {
81
- const content = await fs.readFile(path.join(cwd, file), 'utf-8');
82
-
83
- for (const { pattern, title, severity, description } of patterns) {
84
- let match;
85
- const regex = new RegExp(pattern.source, pattern.flags);
86
- while ((match = regex.exec(content)) !== null) {
87
- const line = content.substring(0, match.index).split('\n').length;
88
- issues.push({ title, description, file, line, severity });
89
- }
90
- }
91
- }
92
-
93
- return issues;
94
- }
95
-
96
- function displaySecurityScore(score: number): void {
97
- const color = score >= 80 ? chalk.green : score >= 50 ? chalk.yellow : chalk.red;
98
- const grade = score >= 90 ? 'A' : score >= 80 ? 'B' : score >= 70 ? 'C' : 'F';
99
-
100
- console.log(chalk.bold('Security Score:'));
101
- console.log(color(`\n ${score}/100 Grade: ${grade}\n`));
102
- }