codebakers 2.3.7 → 2.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.
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  prdCommand
3
- } from "./chunk-ND6T4UDY.js";
3
+ } from "./chunk-WZQNFV7Q.js";
4
4
  import "./chunk-ASIJIQYC.js";
5
5
  export {
6
6
  prdCommand
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "codebakers",
3
- "version": "2.3.7",
3
+ "version": "2.5.0",
4
4
  "description": "AI dev team that follows the rules. Build apps from anywhere with pattern enforcement.",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",
@@ -328,7 +328,7 @@ async function getAdvisorFeedback(
328
328
  brief: ProjectBrief
329
329
  ): Promise<AdvisorFeedback> {
330
330
  const response = await anthropic.messages.create({
331
- model: 'claude-sonnet-4-20250514',
331
+ model: 'claude-sonnet-4-5-20250929',
332
332
  max_tokens: 2048,
333
333
  messages: [{
334
334
  role: 'user',
@@ -397,7 +397,7 @@ async function generateReport(
397
397
  const avgScore = advisorFeedback.reduce((sum, f) => sum + f.score, 0) / advisorFeedback.length;
398
398
 
399
399
  const response = await anthropic.messages.create({
400
- model: 'claude-sonnet-4-20250514',
400
+ model: 'claude-sonnet-4-5-20250929',
401
401
  max_tokens: 8192,
402
402
  messages: [{
403
403
  role: 'user',
@@ -206,8 +206,13 @@ export async function buildCommand(prdPath?: string, options: { sequential?: boo
206
206
 
207
207
  // Step 7: Final setup
208
208
  spinner.start('Installing dependencies...');
209
- await execa('npm', ['install'], { cwd: projectPath, reject: false });
210
- spinner.stop('Dependencies installed');
209
+ try {
210
+ await execa('npm', ['install'], { cwd: projectPath, stdio: 'inherit' });
211
+ spinner.stop('Dependencies installed');
212
+ } catch (error) {
213
+ spinner.stop('Dependencies installation failed');
214
+ console.log(chalk.yellow(' ⚠️ Run "npm install" manually in the project folder'));
215
+ }
211
216
 
212
217
  // Done!
213
218
  const elapsed = Math.round((Date.now() - startTime) / 1000);
@@ -237,7 +242,7 @@ export async function buildCommand(prdPath?: string, options: { sequential?: boo
237
242
 
238
243
  async function analyzePRD(anthropic: Anthropic, prdContent: string): Promise<BuildPlan> {
239
244
  const response = await anthropic.messages.create({
240
- model: 'claude-sonnet-4-20250514',
245
+ model: 'claude-sonnet-4-5-20250929',
241
246
  max_tokens: 4096,
242
247
  messages: [{
243
248
  role: 'user',
@@ -362,7 +367,7 @@ async function runSetupPhase(
362
367
 
363
368
  // Generate shared setup code
364
369
  const setupResponse = await anthropic.messages.create({
365
- model: 'claude-sonnet-4-20250514',
370
+ model: 'claude-sonnet-4-5-20250929',
366
371
  max_tokens: 8192,
367
372
  messages: [{
368
373
  role: 'user',
@@ -648,7 +653,7 @@ Start with the index.ts that exports everything.`
648
653
  iteration++;
649
654
 
650
655
  const response = await anthropic.messages.create({
651
- model: 'claude-sonnet-4-20250514',
656
+ model: 'claude-sonnet-4-5-20250929',
652
657
  max_tokens: 8192,
653
658
  messages,
654
659
  });
@@ -783,7 +788,7 @@ async function healerAgent(
783
788
  plan: BuildPlan
784
789
  ): Promise<HealerSolution> {
785
790
  const response = await anthropic.messages.create({
786
- model: 'claude-sonnet-4-20250514',
791
+ model: 'claude-sonnet-4-5-20250929',
787
792
  max_tokens: 4096,
788
793
  messages: [{
789
794
  role: 'user',
@@ -852,7 +857,7 @@ async function runIntegrationPhase(
852
857
  const features = plan.waves.flatMap(w => w.agents);
853
858
 
854
859
  const response = await anthropic.messages.create({
855
- model: 'claude-sonnet-4-20250514',
860
+ model: 'claude-sonnet-4-5-20250929',
856
861
  max_tokens: 8192,
857
862
  messages: [{
858
863
  role: 'user',
@@ -266,7 +266,7 @@ async function processUserInput(
266
266
 
267
267
  // Call Claude
268
268
  const response = await anthropic.messages.create({
269
- model: 'claude-sonnet-4-20250514',
269
+ model: 'claude-sonnet-4-5-20250929',
270
270
  max_tokens: 8192,
271
271
  system: systemPrompt,
272
272
  messages: messages.map(m => ({
@@ -787,7 +787,7 @@ ${content}
787
787
  Output only the fixed file content, no explanation.`;
788
788
 
789
789
  const response = await anthropic.messages.create({
790
- model: 'claude-sonnet-4-20250514',
790
+ model: 'claude-sonnet-4-5-20250929',
791
791
  max_tokens: 8192,
792
792
  system: systemPrompt,
793
793
  messages: [{ role: 'user', content: fixPrompt }],
@@ -295,7 +295,7 @@ ${content}
295
295
  Output ONLY the corrected file content, no explanations. Keep all existing functionality.`;
296
296
 
297
297
  const response = await anthropic.messages.create({
298
- model: 'claude-sonnet-4-20250514',
298
+ model: 'claude-sonnet-4-5-20250929',
299
299
  max_tokens: 8192,
300
300
  messages: [{ role: 'user', content: prompt }],
301
301
  });
@@ -359,7 +359,7 @@ ${content}
359
359
  Output ONLY the corrected file content, no explanations.`;
360
360
 
361
361
  const response = await anthropic.messages.create({
362
- model: 'claude-sonnet-4-20250514',
362
+ model: 'claude-sonnet-4-5-20250929',
363
363
  max_tokens: 8192,
364
364
  messages: [{ role: 'user', content: prompt }],
365
365
  });
@@ -417,7 +417,7 @@ Output ONLY the corrected file content, no explanations.`;
417
417
 
418
418
  try {
419
419
  const response = await anthropic.messages.create({
420
- model: 'claude-sonnet-4-20250514',
420
+ model: 'claude-sonnet-4-5-20250929',
421
421
  max_tokens: 8192,
422
422
  messages: [{ role: 'user', content: prompt }],
423
423
  });
@@ -190,65 +190,108 @@ Domain: ${domain || 'Vercel default'}`,
190
190
  spinner.start('Installing dependencies...');
191
191
 
192
192
  // Try npm first (most common), fall back to pnpm or yarn
193
+ let installSuccess = false;
193
194
  try {
194
- await execa('npm', ['install'], { cwd: projectPath });
195
+ await execa('npm', ['install'], { cwd: projectPath, stdio: 'inherit' });
196
+ installSuccess = true;
195
197
  } catch {
196
198
  try {
197
- await execa('pnpm', ['install'], { cwd: projectPath });
199
+ await execa('pnpm', ['install'], { cwd: projectPath, stdio: 'inherit' });
200
+ installSuccess = true;
198
201
  } catch {
199
- await execa('yarn', ['install'], { cwd: projectPath });
202
+ try {
203
+ await execa('yarn', ['install'], { cwd: projectPath, stdio: 'inherit' });
204
+ installSuccess = true;
205
+ } catch {
206
+ // All failed
207
+ }
200
208
  }
201
209
  }
202
- spinner.stop('Dependencies installed');
210
+
211
+ if (installSuccess) {
212
+ spinner.stop('Dependencies installed');
213
+ } else {
214
+ spinner.stop('Dependencies installation failed');
215
+ console.log(chalk.yellow(' ⚠️ Run "npm install" manually in the project folder'));
216
+ }
203
217
 
204
218
  // Step 3: GitHub
205
219
  if ((services as string[]).includes('github')) {
206
220
  spinner.start('Creating GitHub repository...');
207
- const github = new GitHubService(config);
208
- const repo = await github.createRepo(projectName, { private: true });
209
- spinner.stop(`GitHub repo created: ${repo.html_url}`);
210
-
211
- // Init git and push
212
- await execa('git', ['init'], { cwd: projectPath });
213
- await execa('git', ['add', '.'], { cwd: projectPath });
214
- await execa('git', ['commit', '-m', 'Initial commit by CodeBakers'], { cwd: projectPath });
215
- await execa('git', ['remote', 'add', 'origin', repo.clone_url], { cwd: projectPath });
216
- await execa('git', ['push', '-u', 'origin', 'main'], { cwd: projectPath });
221
+ try {
222
+ const github = new GitHubService(config);
223
+ const repo = await github.createRepo(projectName, { private: true });
224
+ spinner.stop(`GitHub repo created: ${repo.html_url}`);
225
+
226
+ // Init git and push
227
+ try {
228
+ await execa('git', ['init'], { cwd: projectPath });
229
+ await execa('git', ['add', '.'], { cwd: projectPath });
230
+ await execa('git', ['commit', '-m', 'Initial commit by CodeBakers'], { cwd: projectPath });
231
+ await execa('git', ['remote', 'add', 'origin', repo.clone_url], { cwd: projectPath });
232
+ await execa('git', ['push', '-u', 'origin', 'main'], { cwd: projectPath });
233
+ } catch (gitError) {
234
+ console.log(chalk.yellow(' ⚠️ Git push failed. You can push manually later.'));
235
+ }
236
+ } catch (error) {
237
+ spinner.stop('GitHub setup failed');
238
+ console.log(chalk.yellow(' ⚠️ Could not create GitHub repo. Check your GitHub token.'));
239
+ }
217
240
  }
218
241
 
219
242
  // Step 4: Supabase
220
243
  if ((services as string[]).includes('supabase')) {
221
244
  spinner.start('Creating Supabase project...');
222
- const supabase = new SupabaseService(config);
223
- const project = await supabase.createProject(projectName);
224
- spinner.stop(`Supabase project created: ${project.name}`);
225
-
226
- // Save Supabase config
227
- await fs.writeJson(
228
- path.join(projectPath, '.codebakers', 'supabase.json'),
229
- { projectId: project.id, projectUrl: project.api_url },
230
- { spaces: 2 }
231
- );
245
+ try {
246
+ const supabase = new SupabaseService(config);
247
+ const project = await supabase.createProject(projectName);
248
+ spinner.stop(`Supabase project created: ${project.name}`);
249
+
250
+ // Save Supabase config
251
+ await fs.writeJson(
252
+ path.join(projectPath, '.codebakers', 'supabase.json'),
253
+ { projectId: project.id, projectUrl: project.api_url },
254
+ { spaces: 2 }
255
+ );
256
+ } catch (error) {
257
+ spinner.stop('Supabase setup failed');
258
+ console.log(chalk.yellow(' ⚠️ Could not create Supabase project. Check your Supabase token.'));
259
+ }
232
260
  }
233
261
 
234
262
  // Step 5: Vercel
235
263
  if ((services as string[]).includes('vercel')) {
236
264
  spinner.start('Creating Vercel project...');
237
- const vercel = new VercelService(config);
238
- const project = await vercel.createProject(projectName);
239
- spinner.stop(`Vercel project created`);
240
-
241
- // Configure domain if specified
242
- if (domain) {
243
- spinner.start(`Configuring domain: ${domain}...`);
244
- await vercel.addDomain(projectName, domain);
245
- spinner.stop('Domain configured');
265
+ try {
266
+ const vercel = new VercelService(config);
267
+ const project = await vercel.createProject(projectName);
268
+ spinner.stop(`Vercel project created`);
269
+
270
+ // Configure domain if specified
271
+ if (domain) {
272
+ spinner.start(`Configuring domain: ${domain}...`);
273
+ try {
274
+ await vercel.addDomain(projectName, domain);
275
+ spinner.stop('Domain configured');
276
+ } catch {
277
+ spinner.stop('Domain configuration failed');
278
+ console.log(chalk.yellow(' ⚠️ Could not configure domain. Add it manually in Vercel.'));
279
+ }
280
+ }
281
+
282
+ // Deploy
283
+ spinner.start('Deploying to Vercel...');
284
+ try {
285
+ const deployment = await vercel.deploy(projectPath);
286
+ spinner.stop(`Deployed: ${deployment.url}`);
287
+ } catch {
288
+ spinner.stop('Deployment failed');
289
+ console.log(chalk.yellow(' ⚠️ Could not deploy. Run "vercel" manually later.'));
290
+ }
291
+ } catch (error) {
292
+ spinner.stop('Vercel setup failed');
293
+ console.log(chalk.yellow(' ⚠️ Could not create Vercel project. Check your Vercel token.'));
246
294
  }
247
-
248
- // Deploy
249
- spinner.start('Deploying to Vercel...');
250
- const deployment = await vercel.deploy(projectPath);
251
- spinner.stop(`Deployed: ${deployment.url}`);
252
295
  }
253
296
 
254
297
  // Step 6: Generate CLAUDE.md
@@ -507,7 +507,7 @@ async function recordWithLinux(): Promise<string> {
507
507
 
508
508
  async function generatePRD(anthropic: Anthropic, input: PRDInput): Promise<string> {
509
509
  const response = await anthropic.messages.create({
510
- model: 'claude-sonnet-4-20250514',
510
+ model: 'claude-sonnet-4-5-20250929',
511
511
  max_tokens: 8192,
512
512
  messages: [{
513
513
  role: 'user',
@@ -141,7 +141,7 @@ export async function prdCommand(filePath?: string): Promise<void> {
141
141
 
142
142
  async function parsePRD(anthropic: Anthropic, content: string): Promise<ParsedPRD> {
143
143
  const response = await anthropic.messages.create({
144
- model: 'claude-sonnet-4-20250514',
144
+ model: 'claude-sonnet-4-5-20250929',
145
145
  max_tokens: 4096,
146
146
  messages: [{
147
147
  role: 'user',
@@ -308,7 +308,7 @@ async function generateBuildPlan(
308
308
  designProfile: string
309
309
  ): Promise<{ phases: Array<{ name: string; tasks: string[] }> }> {
310
310
  const response = await anthropic.messages.create({
311
- model: 'claude-sonnet-4-20250514',
311
+ model: 'claude-sonnet-4-5-20250929',
312
312
  max_tokens: 4096,
313
313
  messages: [{
314
314
  role: 'user',
@@ -362,7 +362,7 @@ async function executeTask(
362
362
  designProfile: string
363
363
  ): Promise<void> {
364
364
  const response = await anthropic.messages.create({
365
- model: 'claude-sonnet-4-20250514',
365
+ model: 'claude-sonnet-4-5-20250929',
366
366
  max_tokens: 8192,
367
367
  messages: [{
368
368
  role: 'user',
@@ -6,6 +6,7 @@ import Anthropic from '@anthropic-ai/sdk';
6
6
  import { execa } from 'execa';
7
7
  import { Config } from '../utils/config.js';
8
8
  import { textWithVoice } from '../utils/voice.js';
9
+ import { StepTracker, showError, showSuccess, showFileList, ERRORS } from '../utils/display.js';
9
10
 
10
11
  // ============================================================================
11
12
  // WEBSITE TEMPLATES
@@ -254,7 +255,7 @@ async function describeWebsite(anthropic: Anthropic): Promise<WebsiteSpec | null
254
255
  spinner.start('Understanding your vision...');
255
256
 
256
257
  const response = await anthropic.messages.create({
257
- model: 'claude-sonnet-4-20250514',
258
+ model: 'claude-sonnet-4-5-20250929',
258
259
  max_tokens: 2048,
259
260
  messages: [{
260
261
  role: 'user',
@@ -350,7 +351,7 @@ async function templateWebsite(anthropic: Anthropic): Promise<WebsiteSpec | null
350
351
  spinner.start('Customizing template...');
351
352
 
352
353
  const response = await anthropic.messages.create({
353
- model: 'claude-sonnet-4-20250514',
354
+ model: 'claude-sonnet-4-5-20250929',
354
355
  max_tokens: 2048,
355
356
  messages: [{
356
357
  role: 'user',
@@ -429,7 +430,7 @@ async function cloneDesign(anthropic: Anthropic): Promise<WebsiteSpec | null> {
429
430
  spinner.start('Analyzing design inspiration...');
430
431
 
431
432
  const response = await anthropic.messages.create({
432
- model: 'claude-sonnet-4-20250514',
433
+ model: 'claude-sonnet-4-5-20250929',
433
434
  max_tokens: 2048,
434
435
  messages: [{
435
436
  role: 'user',
@@ -497,48 +498,110 @@ async function buildWebsite(
497
498
  await fs.remove(projectPath);
498
499
  }
499
500
 
500
- console.log(chalk.cyan(`\n 🏗️ Building ${spec.name}...\n`));
501
+ console.log(chalk.cyan(`\n 🏗️ Building ${chalk.bold(spec.name)}\n`));
501
502
 
502
- const spinner = p.spinner();
503
+ // Initialize step tracker
504
+ const steps = new StepTracker([
505
+ 'Create project structure',
506
+ 'Install dependencies',
507
+ 'Set up UI components',
508
+ 'Generate website code',
509
+ 'Create additional pages',
510
+ 'Initialize git repository',
511
+ ]);
512
+
513
+ const createdFiles: string[] = [];
503
514
 
504
515
  // Step 1: Create project
505
- spinner.start('Creating Next.js project...');
516
+ steps.start();
506
517
 
507
- await execa('npx', [
508
- 'create-next-app@latest',
509
- spec.name,
510
- '--typescript',
511
- '--tailwind',
512
- '--eslint',
513
- '--app',
514
- '--src-dir',
515
- '--import-alias', '@/*',
516
- '--no-git',
517
- ], { cwd: process.cwd(), reject: false });
518
-
519
- spinner.stop('Project created');
520
-
521
- // Step 2: Install shadcn
522
- spinner.start('Setting up shadcn/ui...');
518
+ try {
519
+ await execa('npx', [
520
+ 'create-next-app@latest',
521
+ spec.name,
522
+ '--typescript',
523
+ '--tailwind',
524
+ '--eslint',
525
+ '--app',
526
+ '--src-dir',
527
+ '--import-alias', '@/*',
528
+ '--no-git',
529
+ '--yes',
530
+ ], {
531
+ cwd: process.cwd(),
532
+ stdio: 'pipe', // Hide output for cleaner display
533
+ });
534
+ steps.complete();
535
+ } catch (error) {
536
+ steps.error();
537
+ showError({
538
+ title: 'Project creation failed',
539
+ message: 'create-next-app could not complete',
540
+ fixes: [
541
+ 'Make sure Node.js 18+ is installed',
542
+ 'Check your internet connection',
543
+ 'Try running manually: npx create-next-app@latest ' + spec.name,
544
+ ],
545
+ command: 'npx create-next-app@latest ' + spec.name,
546
+ });
547
+ return;
548
+ }
549
+
550
+ // Verify project was created
551
+ if (!(await fs.pathExists(projectPath))) {
552
+ steps.error();
553
+ showError({
554
+ title: 'Project folder not created',
555
+ message: 'The project directory was not found after creation',
556
+ fixes: [
557
+ 'Check if you have write permissions in this folder',
558
+ 'Try creating the project in a different location',
559
+ ],
560
+ });
561
+ return;
562
+ }
563
+
564
+ // Step 2: Install dependencies
565
+ steps.start();
523
566
 
524
- await execa('npx', ['shadcn@latest', 'init', '-y', '-d'], {
525
- cwd: projectPath,
526
- reject: false,
527
- });
567
+ try {
568
+ await execa('npm', ['install', 'lucide-react'], {
569
+ cwd: projectPath,
570
+ stdio: 'pipe',
571
+ });
572
+ steps.complete();
573
+ } catch (error) {
574
+ steps.error();
575
+ showError({
576
+ ...ERRORS.npmFailed,
577
+ command: `cd ${spec.name} && npm install`,
578
+ });
579
+ return;
580
+ }
528
581
 
529
- // Install common components
530
- await execa('npx', ['shadcn@latest', 'add', 'button', 'card', 'input', 'badge', '-y'], {
531
- cwd: projectPath,
532
- reject: false,
533
- });
582
+ // Step 3: Install shadcn
583
+ steps.start();
584
+
585
+ try {
586
+ await execa('npx', ['shadcn@latest', 'init', '-y', '-d'], {
587
+ cwd: projectPath,
588
+ stdio: 'pipe',
589
+ });
534
590
 
535
- spinner.stop('UI components ready');
591
+ await execa('npx', ['shadcn@latest', 'add', 'button', 'card', 'input', 'badge', '-y'], {
592
+ cwd: projectPath,
593
+ stdio: 'pipe',
594
+ });
595
+ steps.complete();
596
+ } catch (error) {
597
+ steps.skip(); // Not critical, continue anyway
598
+ }
536
599
 
537
- // Step 3: Generate pages
538
- spinner.start('Generating website code...');
600
+ // Step 4: Generate pages
601
+ steps.start();
539
602
 
540
603
  const response = await anthropic.messages.create({
541
- model: 'claude-sonnet-4-20250514',
604
+ model: 'claude-sonnet-4-5-20250929',
542
605
  max_tokens: 16000,
543
606
  messages: [{
544
607
  role: 'user',
@@ -596,7 +659,6 @@ Make it production-quality and visually impressive.`
596
659
  // Write files
597
660
  const fileRegex = /<<<FILE:\s*(.+?)>>>([\s\S]*?)<<<END_FILE>>>/g;
598
661
  let match;
599
- let fileCount = 0;
600
662
 
601
663
  while ((match = fileRegex.exec(text)) !== null) {
602
664
  const filePath = path.join(projectPath, match[1].trim());
@@ -604,38 +666,51 @@ Make it production-quality and visually impressive.`
604
666
 
605
667
  await fs.ensureDir(path.dirname(filePath));
606
668
  await fs.writeFile(filePath, content);
607
- fileCount++;
669
+ createdFiles.push(match[1].trim());
608
670
  }
609
671
 
610
- spinner.stop(`Generated ${fileCount} files`);
672
+ steps.complete();
611
673
 
612
- // Step 4: Git init
613
- spinner.start('Initializing git...');
614
- await execa('git', ['init'], { cwd: projectPath, reject: false });
615
- await execa('git', ['add', '.'], { cwd: projectPath, reject: false });
616
- await execa('git', ['commit', '-m', 'Initial website build by CodeBakers'], { cwd: projectPath, reject: false });
617
- spinner.stop('Git initialized');
674
+ // Step 5: Additional pages (placeholder for now)
675
+ steps.start();
676
+ steps.complete();
618
677
 
619
- // Done!
620
- console.log(chalk.green(`
621
- ╔═══════════════════════════════════════════════════════════════╗
622
- Website built successfully! ║
623
- ╠═══════════════════════════════════════════════════════════════╣
624
- ║ ║
625
- ║ ${spec.name.padEnd(55)}║
626
- ║ ${spec.description.substring(0, 55).padEnd(55)}║
627
- ║ ║
628
- ║ Next steps: ║
629
- ║ cd ${spec.name.padEnd(52)}
630
- ║ npm run dev ║
631
- ║ ║
632
- Then open http://localhost:3000 ║
633
- ║ ║
634
- ║ Ready to deploy? ║
635
- ║ codebakers deploy ║
636
- ║ ║
637
- ╚═══════════════════════════════════════════════════════════════╝
638
- `));
678
+ // Step 6: Git init
679
+ steps.start();
680
+
681
+ try {
682
+ await execa('git', ['init'], { cwd: projectPath, stdio: 'pipe' });
683
+ await execa('git', ['add', '.'], { cwd: projectPath, stdio: 'pipe' });
684
+ await execa('git', ['commit', '-m', 'Initial website build by CodeBakers'], { cwd: projectPath, stdio: 'pipe' });
685
+ steps.complete();
686
+ } catch (error) {
687
+ steps.skip();
688
+ }
689
+
690
+ // Show created files
691
+ if (createdFiles.length > 0) {
692
+ showFileList('Files created', createdFiles.slice(0, 10));
693
+ if (createdFiles.length > 10) {
694
+ console.log(chalk.dim(` ... and ${createdFiles.length - 10} more files`));
695
+ }
696
+ }
697
+
698
+ // Success message
699
+ showSuccess({
700
+ title: 'Website built successfully!',
701
+ message: spec.description,
702
+ stats: [
703
+ { label: 'Project', value: spec.name },
704
+ { label: 'Files created', value: createdFiles.length.toString() },
705
+ { label: 'Sections', value: spec.sections.length.toString() },
706
+ { label: 'Build time', value: steps.getElapsedTime() },
707
+ ],
708
+ nextSteps: [
709
+ `cd ${spec.name}`,
710
+ 'npm run dev',
711
+ ],
712
+ command: `cd ${spec.name} && npm run dev`,
713
+ });
639
714
 
640
715
  // Offer to open in browser
641
716
  const openDev = await p.confirm({
package/src/index.ts CHANGED
@@ -30,7 +30,7 @@ import { integrateCommand, INTEGRATIONS } from './commands/integrate.js';
30
30
  import { websiteCommand } from './commands/website.js';
31
31
  import { parseNaturalLanguage } from './utils/nlp.js';
32
32
 
33
- const VERSION = '2.3.6';
33
+ const VERSION = '2.5.0';
34
34
 
35
35
  // ASCII art logo
36
36
  const logo = `