codebakers 2.0.1 → 2.0.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.
package/dist/index.js CHANGED
@@ -2,8 +2,8 @@
2
2
 
3
3
  // src/index.ts
4
4
  import { Command } from "commander";
5
- import * as p13 from "@clack/prompts";
6
- import chalk14 from "chalk";
5
+ import * as p15 from "@clack/prompts";
6
+ import chalk16 from "chalk";
7
7
  import boxen from "boxen";
8
8
  import gradient from "gradient-string";
9
9
 
@@ -304,10 +304,10 @@ async function setupCommand() {
304
304
  return;
305
305
  }
306
306
  if (action === "reset") {
307
- const confirm6 = await p.confirm({
307
+ const confirm8 = await p.confirm({
308
308
  message: "Are you sure? This will remove all credentials and settings."
309
309
  });
310
- if (confirm6) {
310
+ if (confirm8) {
311
311
  p.outro(chalk2.yellow("Configuration reset. Run `codebakers setup` again."));
312
312
  }
313
313
  return;
@@ -371,7 +371,7 @@ ${chalk2.dim("and are never sent to our servers.")}`,
371
371
  p.outro(chalk2.green("\u2713 Setup complete! Run `codebakers init` to create your first project."));
372
372
  }
373
373
  async function connectService(config, serviceKey, serviceName, required) {
374
- const spinner11 = p.spinner();
374
+ const spinner13 = p.spinner();
375
375
  switch (serviceKey) {
376
376
  case "github": {
377
377
  p.log.info(`${chalk2.bold("GitHub")} - Opens browser for OAuth authorization`);
@@ -845,10 +845,10 @@ var SupabaseService = class {
845
845
  throw new Error("Failed to list projects");
846
846
  }
847
847
  const projects = await response.json();
848
- return projects.map((p14) => ({
849
- id: p14.id,
850
- name: p14.name,
851
- region: p14.region
848
+ return projects.map((p16) => ({
849
+ id: p16.id,
850
+ name: p16.name,
851
+ region: p16.region
852
852
  }));
853
853
  }
854
854
  };
@@ -1268,20 +1268,20 @@ Domain: ${domain || "Vercel default"}`,
1268
1268
  p2.cancel("Project creation cancelled.");
1269
1269
  return;
1270
1270
  }
1271
- const spinner11 = p2.spinner();
1271
+ const spinner13 = p2.spinner();
1272
1272
  const projectPath = path2.join(process.cwd(), projectName);
1273
1273
  try {
1274
- spinner11.start("Creating local project...");
1274
+ spinner13.start("Creating local project...");
1275
1275
  await createLocalProject(projectPath, projectConfig);
1276
- spinner11.stop("Local project created");
1277
- spinner11.start("Installing dependencies...");
1276
+ spinner13.stop("Local project created");
1277
+ spinner13.start("Installing dependencies...");
1278
1278
  await execa2("pnpm", ["install"], { cwd: projectPath });
1279
- spinner11.stop("Dependencies installed");
1279
+ spinner13.stop("Dependencies installed");
1280
1280
  if (services.includes("github")) {
1281
- spinner11.start("Creating GitHub repository...");
1281
+ spinner13.start("Creating GitHub repository...");
1282
1282
  const github = new GitHubService(config);
1283
1283
  const repo = await github.createRepo(projectName, { private: true });
1284
- spinner11.stop(`GitHub repo created: ${repo.html_url}`);
1284
+ spinner13.stop(`GitHub repo created: ${repo.html_url}`);
1285
1285
  await execa2("git", ["init"], { cwd: projectPath });
1286
1286
  await execa2("git", ["add", "."], { cwd: projectPath });
1287
1287
  await execa2("git", ["commit", "-m", "Initial commit by CodeBakers"], { cwd: projectPath });
@@ -1289,10 +1289,10 @@ Domain: ${domain || "Vercel default"}`,
1289
1289
  await execa2("git", ["push", "-u", "origin", "main"], { cwd: projectPath });
1290
1290
  }
1291
1291
  if (services.includes("supabase")) {
1292
- spinner11.start("Creating Supabase project...");
1292
+ spinner13.start("Creating Supabase project...");
1293
1293
  const supabase = new SupabaseService(config);
1294
1294
  const project = await supabase.createProject(projectName);
1295
- spinner11.stop(`Supabase project created: ${project.name}`);
1295
+ spinner13.stop(`Supabase project created: ${project.name}`);
1296
1296
  await fs2.writeJson(
1297
1297
  path2.join(projectPath, ".codebakers", "supabase.json"),
1298
1298
  { projectId: project.id, projectUrl: project.api_url },
@@ -1300,26 +1300,26 @@ Domain: ${domain || "Vercel default"}`,
1300
1300
  );
1301
1301
  }
1302
1302
  if (services.includes("vercel")) {
1303
- spinner11.start("Creating Vercel project...");
1303
+ spinner13.start("Creating Vercel project...");
1304
1304
  const vercel = new VercelService(config);
1305
1305
  const project = await vercel.createProject(projectName);
1306
- spinner11.stop(`Vercel project created`);
1306
+ spinner13.stop(`Vercel project created`);
1307
1307
  if (domain) {
1308
- spinner11.start(`Configuring domain: ${domain}...`);
1308
+ spinner13.start(`Configuring domain: ${domain}...`);
1309
1309
  await vercel.addDomain(projectName, domain);
1310
- spinner11.stop("Domain configured");
1310
+ spinner13.stop("Domain configured");
1311
1311
  }
1312
- spinner11.start("Deploying to Vercel...");
1312
+ spinner13.start("Deploying to Vercel...");
1313
1313
  const deployment = await vercel.deploy(projectPath);
1314
- spinner11.stop(`Deployed: ${deployment.url}`);
1314
+ spinner13.stop(`Deployed: ${deployment.url}`);
1315
1315
  }
1316
- spinner11.start("Generating CLAUDE.md...");
1316
+ spinner13.start("Generating CLAUDE.md...");
1317
1317
  const claudeMd = generateClaudeMd(projectConfig);
1318
1318
  await fs2.writeFile(path2.join(projectPath, "CLAUDE.md"), claudeMd);
1319
- spinner11.stop("CLAUDE.md generated");
1320
- spinner11.start("Setting up CodeBakers enforcement...");
1319
+ spinner13.stop("CLAUDE.md generated");
1320
+ spinner13.start("Setting up CodeBakers enforcement...");
1321
1321
  await setupGitHooks(projectPath);
1322
- spinner11.stop("CodeBakers enforcement configured");
1322
+ spinner13.stop("CodeBakers enforcement configured");
1323
1323
  config.addProject({
1324
1324
  name: projectName,
1325
1325
  path: projectPath,
@@ -1339,7 +1339,7 @@ ${chalk3.dim("Shortcuts:")}
1339
1339
  ${chalk3.cyan("codebakers deploy")} \u2014 Deploy to production
1340
1340
  `));
1341
1341
  } catch (error) {
1342
- spinner11.stop("Error occurred");
1342
+ spinner13.stop("Error occurred");
1343
1343
  p2.log.error(`Failed to create project: ${error instanceof Error ? error.message : "Unknown error"}`);
1344
1344
  const cleanup = await p2.confirm({
1345
1345
  message: "Clean up partially created project?"
@@ -2065,17 +2065,17 @@ async function checkCommand(options = {}) {
2065
2065
  return;
2066
2066
  }
2067
2067
  p3.intro(chalk4.bgCyan.black(" CodeBakers Pattern Check "));
2068
- const spinner11 = p3.spinner();
2069
- spinner11.start("Analyzing code...");
2068
+ const spinner13 = p3.spinner();
2069
+ spinner13.start("Analyzing code...");
2070
2070
  const result = await runPatternCheck(options.fix || false);
2071
- spinner11.stop("Analysis complete");
2071
+ spinner13.stop("Analysis complete");
2072
2072
  displayResults(result);
2073
2073
  if (result.violations.length > 0 && options.fix) {
2074
2074
  const fixable = result.violations.filter((v) => v.autoFixable);
2075
2075
  if (fixable.length > 0) {
2076
- spinner11.start(`Auto-fixing ${fixable.length} violations...`);
2076
+ spinner13.start(`Auto-fixing ${fixable.length} violations...`);
2077
2077
  await autoFix(fixable);
2078
- spinner11.stop("Auto-fix complete");
2078
+ spinner13.stop("Auto-fix complete");
2079
2079
  }
2080
2080
  }
2081
2081
  const errors = result.violations.filter((v) => v.severity === "error");
@@ -2267,14 +2267,14 @@ async function codeCommand(prompt, options = {}) {
2267
2267
  }
2268
2268
  }
2269
2269
  async function processUserInput(userInput, messages, anthropic, systemPrompt, projectContext, config) {
2270
- const spinner11 = p4.spinner();
2270
+ const spinner13 = p4.spinner();
2271
2271
  messages.push({ role: "user", content: userInput });
2272
2272
  const wizardResult = await checkForWizard(userInput);
2273
2273
  if (wizardResult) {
2274
2274
  messages[messages.length - 1].content = wizardResult;
2275
2275
  }
2276
2276
  try {
2277
- spinner11.start("Thinking...");
2277
+ spinner13.start("Thinking...");
2278
2278
  const response = await anthropic.messages.create({
2279
2279
  model: "claude-sonnet-4-20250514",
2280
2280
  max_tokens: 8192,
@@ -2284,7 +2284,7 @@ async function processUserInput(userInput, messages, anthropic, systemPrompt, pr
2284
2284
  content: m.content
2285
2285
  }))
2286
2286
  });
2287
- spinner11.stop("");
2287
+ spinner13.stop("");
2288
2288
  const assistantMessage = response.content[0].type === "text" ? response.content[0].text : "";
2289
2289
  messages.push({ role: "assistant", content: assistantMessage });
2290
2290
  const actions = parseActions(assistantMessage);
@@ -2299,11 +2299,11 @@ async function processUserInput(userInput, messages, anthropic, systemPrompt, pr
2299
2299
  initialValue: true
2300
2300
  });
2301
2301
  if (proceed && !p4.isCancel(proceed)) {
2302
- spinner11.start("Building...");
2302
+ spinner13.start("Building...");
2303
2303
  for (const action of actions) {
2304
- await executeAction(action, spinner11);
2304
+ await executeAction(action, spinner13);
2305
2305
  }
2306
- spinner11.stop("Build complete");
2306
+ spinner13.stop("Build complete");
2307
2307
  console.log(chalk5.dim("\n\u{1F50D} Running CodeBakers check..."));
2308
2308
  const checkResult = await runPatternCheck(false);
2309
2309
  if (checkResult.violations.length > 0) {
@@ -2314,9 +2314,9 @@ async function processUserInput(userInput, messages, anthropic, systemPrompt, pr
2314
2314
  initialValue: true
2315
2315
  });
2316
2316
  if (autoFix2 && !p4.isCancel(autoFix2)) {
2317
- spinner11.start("Auto-fixing...");
2317
+ spinner13.start("Auto-fixing...");
2318
2318
  await autoFixViolations(checkResult.violations, anthropic, systemPrompt);
2319
- spinner11.stop("Violations fixed");
2319
+ spinner13.stop("Violations fixed");
2320
2320
  }
2321
2321
  } else {
2322
2322
  console.log(chalk5.green("\u2713 All patterns satisfied"));
@@ -2327,7 +2327,7 @@ async function processUserInput(userInput, messages, anthropic, systemPrompt, pr
2327
2327
  console.log("\n" + assistantMessage + "\n");
2328
2328
  }
2329
2329
  } catch (error) {
2330
- spinner11.stop("Error");
2330
+ spinner13.stop("Error");
2331
2331
  console.log(chalk5.red(`Error: ${error instanceof Error ? error.message : "Unknown error"}`));
2332
2332
  }
2333
2333
  }
@@ -2439,14 +2439,14 @@ function parseActions(response) {
2439
2439
  }
2440
2440
  return actions;
2441
2441
  }
2442
- async function executeAction(action, spinner11) {
2442
+ async function executeAction(action, spinner13) {
2443
2443
  const cwd = process.cwd();
2444
2444
  switch (action.type) {
2445
2445
  case "CREATE_FILE": {
2446
2446
  const filePath = path5.join(cwd, action.path);
2447
2447
  await fs5.ensureDir(path5.dirname(filePath));
2448
2448
  await fs5.writeFile(filePath, action.content);
2449
- spinner11.message(`Created ${action.path}`);
2449
+ spinner13.message(`Created ${action.path}`);
2450
2450
  break;
2451
2451
  }
2452
2452
  case "EDIT_FILE": {
@@ -2456,13 +2456,13 @@ async function executeAction(action, spinner11) {
2456
2456
  if (action.find && content.includes(action.find)) {
2457
2457
  content = content.replace(action.find, action.replace || "");
2458
2458
  await fs5.writeFile(filePath, content);
2459
- spinner11.message(`Edited ${action.path}`);
2459
+ spinner13.message(`Edited ${action.path}`);
2460
2460
  }
2461
2461
  }
2462
2462
  break;
2463
2463
  }
2464
2464
  case "RUN_COMMAND": {
2465
- spinner11.message(`Running: ${action.command}`);
2465
+ spinner13.message(`Running: ${action.command}`);
2466
2466
  const [cmd, ...args2] = action.command.split(" ");
2467
2467
  await execa3(cmd, args2, { cwd, stdio: "pipe" });
2468
2468
  break;
@@ -2471,7 +2471,7 @@ async function executeAction(action, spinner11) {
2471
2471
  const filePath = path5.join(cwd, action.path);
2472
2472
  if (await fs5.pathExists(filePath)) {
2473
2473
  await fs5.remove(filePath);
2474
- spinner11.message(`Deleted ${action.path}`);
2474
+ spinner13.message(`Deleted ${action.path}`);
2475
2475
  }
2476
2476
  break;
2477
2477
  }
@@ -2719,12 +2719,12 @@ async function deployCommand(options = {}) {
2719
2719
  return;
2720
2720
  }
2721
2721
  p5.intro(chalk6.bgCyan.black(" Deploy to Production "));
2722
- const spinner11 = p5.spinner();
2722
+ const spinner13 = p5.spinner();
2723
2723
  if (options.check !== false) {
2724
- spinner11.start("Running CodeBakers check...");
2724
+ spinner13.start("Running CodeBakers check...");
2725
2725
  const checkResult = await runPatternCheck(false);
2726
2726
  if (!checkResult.passed) {
2727
- spinner11.stop("");
2727
+ spinner13.stop("");
2728
2728
  const errors = checkResult.violations.filter((v) => v.severity === "error");
2729
2729
  if (errors.length > 0) {
2730
2730
  p5.log.error(`${errors.length} pattern violations found. Fix before deploying.`);
@@ -2745,9 +2745,9 @@ async function deployCommand(options = {}) {
2745
2745
  p5.outro(chalk6.red("Deploy cancelled."));
2746
2746
  return;
2747
2747
  }
2748
- spinner11.start("Auto-fixing with AI...");
2748
+ spinner13.start("Auto-fixing with AI...");
2749
2749
  await autoFixWithAI(config, errors);
2750
- spinner11.stop("Auto-fix complete");
2750
+ spinner13.stop("Auto-fix complete");
2751
2751
  const recheck = await runPatternCheck(false);
2752
2752
  if (!recheck.passed) {
2753
2753
  p5.log.error("Some violations remain. Manual fix required.");
@@ -2756,23 +2756,23 @@ async function deployCommand(options = {}) {
2756
2756
  }
2757
2757
  }
2758
2758
  }
2759
- spinner11.stop("Pattern check passed");
2759
+ spinner13.stop("Pattern check passed");
2760
2760
  }
2761
- spinner11.start("Running TypeScript check...");
2761
+ spinner13.start("Running TypeScript check...");
2762
2762
  try {
2763
2763
  await execa4("npx", ["tsc", "--noEmit"], { cwd: process.cwd() });
2764
- spinner11.stop("TypeScript check passed");
2764
+ spinner13.stop("TypeScript check passed");
2765
2765
  } catch (error) {
2766
- spinner11.stop("");
2766
+ spinner13.stop("");
2767
2767
  p5.log.error("TypeScript errors found.");
2768
2768
  const fix = await p5.confirm({
2769
2769
  message: "Attempt to fix TypeScript errors?",
2770
2770
  initialValue: true
2771
2771
  });
2772
2772
  if (fix && !p5.isCancel(fix)) {
2773
- spinner11.start("Fixing TypeScript errors...");
2773
+ spinner13.start("Fixing TypeScript errors...");
2774
2774
  const fixed = await fixTypeScriptErrors(config);
2775
- spinner11.stop(fixed ? "TypeScript errors fixed" : "Could not auto-fix all errors");
2775
+ spinner13.stop(fixed ? "TypeScript errors fixed" : "Could not auto-fix all errors");
2776
2776
  if (!fixed) {
2777
2777
  p5.outro(chalk6.red("Deploy cancelled."));
2778
2778
  return;
@@ -2782,12 +2782,12 @@ async function deployCommand(options = {}) {
2782
2782
  return;
2783
2783
  }
2784
2784
  }
2785
- spinner11.start("Building project...");
2785
+ spinner13.start("Building project...");
2786
2786
  try {
2787
2787
  await execa4("pnpm", ["build"], { cwd: process.cwd() });
2788
- spinner11.stop("Build successful");
2788
+ spinner13.stop("Build successful");
2789
2789
  } catch (error) {
2790
- spinner11.stop("");
2790
+ spinner13.stop("");
2791
2791
  p5.log.error("Build failed.");
2792
2792
  const errorOutput = error instanceof Error ? error.message : "Unknown error";
2793
2793
  console.log(chalk6.dim(errorOutput));
@@ -2796,16 +2796,16 @@ async function deployCommand(options = {}) {
2796
2796
  initialValue: true
2797
2797
  });
2798
2798
  if (fix && !p5.isCancel(fix)) {
2799
- spinner11.start("Fixing build errors...");
2799
+ spinner13.start("Fixing build errors...");
2800
2800
  const fixed = await fixBuildErrors(config, errorOutput);
2801
- spinner11.stop(fixed ? "Build errors fixed" : "Could not auto-fix");
2801
+ spinner13.stop(fixed ? "Build errors fixed" : "Could not auto-fix");
2802
2802
  if (fixed) {
2803
- spinner11.start("Retrying build...");
2803
+ spinner13.start("Retrying build...");
2804
2804
  try {
2805
2805
  await execa4("pnpm", ["build"], { cwd: process.cwd() });
2806
- spinner11.stop("Build successful");
2806
+ spinner13.stop("Build successful");
2807
2807
  } catch {
2808
- spinner11.stop("Build still failing");
2808
+ spinner13.stop("Build still failing");
2809
2809
  p5.outro(chalk6.red("Deploy cancelled."));
2810
2810
  return;
2811
2811
  }
@@ -2818,10 +2818,10 @@ async function deployCommand(options = {}) {
2818
2818
  return;
2819
2819
  }
2820
2820
  }
2821
- spinner11.start("Checking for uncommitted changes...");
2821
+ spinner13.start("Checking for uncommitted changes...");
2822
2822
  const { stdout: gitStatus } = await execa4("git", ["status", "--porcelain"], { cwd: process.cwd() });
2823
2823
  if (gitStatus.trim()) {
2824
- spinner11.stop("");
2824
+ spinner13.stop("");
2825
2825
  const commit = await p5.confirm({
2826
2826
  message: "You have uncommitted changes. Commit before deploying?",
2827
2827
  initialValue: true
@@ -2835,20 +2835,20 @@ async function deployCommand(options = {}) {
2835
2835
  if (!p5.isCancel(message)) {
2836
2836
  await execa4("git", ["add", "."], { cwd: process.cwd() });
2837
2837
  await execa4("git", ["commit", "-m", message], { cwd: process.cwd() });
2838
- spinner11.start("Pushing to GitHub...");
2838
+ spinner13.start("Pushing to GitHub...");
2839
2839
  await execa4("git", ["push"], { cwd: process.cwd() });
2840
- spinner11.stop("Pushed to GitHub");
2840
+ spinner13.stop("Pushed to GitHub");
2841
2841
  }
2842
2842
  }
2843
2843
  } else {
2844
- spinner11.stop("No uncommitted changes");
2844
+ spinner13.stop("No uncommitted changes");
2845
2845
  }
2846
2846
  const deployType = options.preview ? "preview" : "production";
2847
- spinner11.start(`Deploying to ${deployType}...`);
2847
+ spinner13.start(`Deploying to ${deployType}...`);
2848
2848
  try {
2849
2849
  const vercel = new VercelService(config);
2850
2850
  const deployment = await vercel.deploy(process.cwd(), !options.preview);
2851
- spinner11.stop("Deployment complete!");
2851
+ spinner13.stop("Deployment complete!");
2852
2852
  console.log(boxedOutput(`
2853
2853
  ${chalk6.green("\u2713")} Deployed successfully!
2854
2854
 
@@ -2860,7 +2860,7 @@ ${chalk6.dim("View in Vercel Dashboard:")}
2860
2860
  ${chalk6.dim(deployment.dashboardUrl || "https://vercel.com/dashboard")}
2861
2861
  `));
2862
2862
  } catch (error) {
2863
- spinner11.stop("");
2863
+ spinner13.stop("");
2864
2864
  const errorMsg = error instanceof Error ? error.message : "Unknown error";
2865
2865
  p5.log.error(`Deployment failed: ${errorMsg}`);
2866
2866
  if (errorMsg.includes("Build failed")) {
@@ -2869,8 +2869,8 @@ ${chalk6.dim(deployment.dashboardUrl || "https://vercel.com/dashboard")}
2869
2869
  initialValue: true
2870
2870
  });
2871
2871
  if (retry && !p5.isCancel(retry)) {
2872
- spinner11.start("Analyzing Vercel build error...");
2873
- spinner11.stop("Fix attempted");
2872
+ spinner13.start("Analyzing Vercel build error...");
2873
+ spinner13.stop("Fix attempted");
2874
2874
  }
2875
2875
  }
2876
2876
  p5.outro(chalk6.red("Deploy failed."));
@@ -3236,10 +3236,10 @@ you'll need a Meta Business account.
3236
3236
  initialValue: true
3237
3237
  });
3238
3238
  if (!proceed || p7.isCancel(proceed)) return;
3239
- const spinner11 = p7.spinner();
3240
- spinner11.start("Generating QR code...");
3239
+ const spinner13 = p7.spinner();
3240
+ spinner13.start("Generating QR code...");
3241
3241
  try {
3242
- spinner11.stop("");
3242
+ spinner13.stop("");
3243
3243
  console.log(chalk8.cyan(`
3244
3244
  \u2554\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2557
3245
3245
  \u2551 \u2551
@@ -3271,7 +3271,7 @@ Scan this QR code with WhatsApp:
3271
3271
  p7.log.success("WhatsApp connected!");
3272
3272
  }
3273
3273
  } catch (error) {
3274
- spinner11.stop("Error connecting WhatsApp");
3274
+ spinner13.stop("Error connecting WhatsApp");
3275
3275
  p7.log.error(error instanceof Error ? error.message : "Unknown error");
3276
3276
  }
3277
3277
  }
@@ -3302,15 +3302,15 @@ To create a Telegram bot:
3302
3302
  }
3303
3303
  });
3304
3304
  if (p7.isCancel(token)) return;
3305
- const spinner11 = p7.spinner();
3306
- spinner11.start("Verifying bot token...");
3305
+ const spinner13 = p7.spinner();
3306
+ spinner13.start("Verifying bot token...");
3307
3307
  try {
3308
3308
  const response = await fetch(`https://api.telegram.org/bot${token}/getMe`);
3309
3309
  const data = await response.json();
3310
3310
  if (!data.ok) {
3311
3311
  throw new Error(data.description || "Invalid token");
3312
3312
  }
3313
- spinner11.stop("Bot verified!");
3313
+ spinner13.stop("Bot verified!");
3314
3314
  config.setChannelConfig("telegram", {
3315
3315
  enabled: true,
3316
3316
  botToken: token,
@@ -3318,7 +3318,7 @@ To create a Telegram bot:
3318
3318
  });
3319
3319
  p7.log.success(`Connected to @${data.result.username}`);
3320
3320
  } catch (error) {
3321
- spinner11.stop("Verification failed");
3321
+ spinner13.stop("Verification failed");
3322
3322
  p7.log.error(error instanceof Error ? error.message : "Invalid token");
3323
3323
  }
3324
3324
  }
@@ -3456,10 +3456,10 @@ This requires:
3456
3456
  p7.log.info("iMessage support coming soon.");
3457
3457
  }
3458
3458
  async function startAllChannels(config) {
3459
- const spinner11 = p7.spinner();
3460
- spinner11.start("Starting channel gateway...");
3459
+ const spinner13 = p7.spinner();
3460
+ spinner13.start("Starting channel gateway...");
3461
3461
  await new Promise((resolve) => setTimeout(resolve, 1e3));
3462
- spinner11.stop("Gateway started");
3462
+ spinner13.stop("Gateway started");
3463
3463
  console.log(chalk8.green(`
3464
3464
  \u2554\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2557
3465
3465
  \u2551 Gateway is running! \u2551
@@ -3473,10 +3473,10 @@ async function startAllChannels(config) {
3473
3473
  `));
3474
3474
  }
3475
3475
  async function stopAllChannels(config) {
3476
- const spinner11 = p7.spinner();
3477
- spinner11.start("Stopping gateway...");
3476
+ const spinner13 = p7.spinner();
3477
+ spinner13.start("Stopping gateway...");
3478
3478
  await new Promise((resolve) => setTimeout(resolve, 500));
3479
- spinner11.stop("Gateway stopped");
3479
+ spinner13.stop("Gateway stopped");
3480
3480
  }
3481
3481
  async function deployGatewayWizard(config) {
3482
3482
  p7.log.info(chalk8.bold("Deploy Gateway to Cloud"));
@@ -3591,10 +3591,10 @@ import glob2 from "fast-glob";
3591
3591
  import * as path8 from "path";
3592
3592
  async function securityCommand() {
3593
3593
  p9.intro(chalk10.bgCyan.black(" Security Audit "));
3594
- const spinner11 = p9.spinner();
3595
- spinner11.start("Scanning for security issues...");
3594
+ const spinner13 = p9.spinner();
3595
+ spinner13.start("Scanning for security issues...");
3596
3596
  const issues = await runSecurityScan();
3597
- spinner11.stop("Scan complete");
3597
+ spinner13.stop("Scan complete");
3598
3598
  if (issues.length === 0) {
3599
3599
  console.log(chalk10.green("\n\u2713 No security issues found!\n"));
3600
3600
  displaySecurityScore(100);
@@ -3688,10 +3688,10 @@ async function generateCommand(type) {
3688
3688
  validate: (v) => !v ? "Name is required" : void 0
3689
3689
  });
3690
3690
  if (p10.isCancel(name)) return;
3691
- const spinner11 = p10.spinner();
3692
- spinner11.start("Generating...");
3691
+ const spinner13 = p10.spinner();
3692
+ spinner13.start("Generating...");
3693
3693
  await generateFile(generateType, name);
3694
- spinner11.stop(`Generated ${name}`);
3694
+ spinner13.stop(`Generated ${name}`);
3695
3695
  p10.outro("");
3696
3696
  }
3697
3697
  async function generateFile(type, name) {
@@ -3836,13 +3836,13 @@ import * as p11 from "@clack/prompts";
3836
3836
  import chalk12 from "chalk";
3837
3837
  async function fixCommand() {
3838
3838
  p11.intro(chalk12.bgCyan.black(" Auto-Fix "));
3839
- const spinner11 = p11.spinner();
3840
- spinner11.start("Analyzing code...");
3839
+ const spinner13 = p11.spinner();
3840
+ spinner13.start("Analyzing code...");
3841
3841
  const result = await runPatternCheck(true);
3842
3842
  if (result.passed) {
3843
- spinner11.stop("No issues found!");
3843
+ spinner13.stop("No issues found!");
3844
3844
  } else {
3845
- spinner11.stop(`Fixed ${result.violations.length} issues`);
3845
+ spinner13.stop(`Fixed ${result.violations.length} issues`);
3846
3846
  }
3847
3847
  p11.outro(chalk12.green("Done!"));
3848
3848
  }
@@ -4043,8 +4043,8 @@ function generateColorPalette(hex) {
4043
4043
  };
4044
4044
  }
4045
4045
  async function checkDesign() {
4046
- const spinner11 = p12.spinner();
4047
- spinner11.start("Checking design quality...");
4046
+ const spinner13 = p12.spinner();
4047
+ spinner13.start("Checking design quality...");
4048
4048
  const cwd = process.cwd();
4049
4049
  const issues = [];
4050
4050
  const glob3 = (await import("fast-glob")).default;
@@ -4070,7 +4070,7 @@ async function checkDesign() {
4070
4070
  }
4071
4071
  }
4072
4072
  }
4073
- spinner11.stop("Check complete");
4073
+ spinner13.stop("Check complete");
4074
4074
  if (issues.length === 0) {
4075
4075
  console.log(chalk13.green("\n\u2713 No design issues found!\n"));
4076
4076
  } else {
@@ -4103,6 +4103,883 @@ async function viewSettings() {
4103
4103
  console.log("");
4104
4104
  }
4105
4105
 
4106
+ // src/commands/prd.ts
4107
+ import * as p13 from "@clack/prompts";
4108
+ import chalk14 from "chalk";
4109
+ import * as fs11 from "fs-extra";
4110
+ import * as path11 from "path";
4111
+ import Anthropic3 from "@anthropic-ai/sdk";
4112
+ async function prdCommand(filePath) {
4113
+ const config = new Config();
4114
+ if (!config.isConfigured()) {
4115
+ p13.log.error("Please run `codebakers setup` first.");
4116
+ return;
4117
+ }
4118
+ p13.intro(chalk14.bgCyan.black(" Build from PRD "));
4119
+ let prdPath = filePath;
4120
+ if (!prdPath) {
4121
+ const file = await p13.text({
4122
+ message: "Path to PRD file:",
4123
+ placeholder: "./PRD.md or paste URL",
4124
+ validate: (v) => !v ? "File path required" : void 0
4125
+ });
4126
+ if (p13.isCancel(file)) return;
4127
+ prdPath = file;
4128
+ }
4129
+ const spinner13 = p13.spinner();
4130
+ spinner13.start("Reading PRD...");
4131
+ let prdContent;
4132
+ try {
4133
+ if (prdPath.startsWith("http")) {
4134
+ const response = await fetch(prdPath);
4135
+ prdContent = await response.text();
4136
+ } else {
4137
+ prdContent = await fs11.readFile(prdPath, "utf-8");
4138
+ }
4139
+ } catch (error) {
4140
+ spinner13.stop("Error");
4141
+ p13.log.error(`Could not read PRD: ${error instanceof Error ? error.message : "Unknown error"}`);
4142
+ return;
4143
+ }
4144
+ spinner13.stop("PRD loaded");
4145
+ spinner13.start("Analyzing PRD...");
4146
+ const anthropicCreds = config.getCredentials("anthropic");
4147
+ if (!anthropicCreds?.apiKey) {
4148
+ spinner13.stop("Error");
4149
+ p13.log.error("Anthropic API key not configured.");
4150
+ return;
4151
+ }
4152
+ const anthropic = new Anthropic3({ apiKey: anthropicCreds.apiKey });
4153
+ const parsed = await parsePRD(anthropic, prdContent);
4154
+ spinner13.stop("PRD analyzed");
4155
+ console.log(chalk14.bold("\n\u{1F4CB} Extracted from PRD:\n"));
4156
+ console.log(` ${chalk14.cyan("Name:")} ${parsed.name}`);
4157
+ console.log(` ${chalk14.cyan("Description:")} ${parsed.description}`);
4158
+ console.log(` ${chalk14.cyan("Features:")} ${parsed.features.length} features`);
4159
+ console.log(` ${chalk14.cyan("Pages:")} ${parsed.pages.join(", ") || "Auto-detect"}`);
4160
+ console.log(` ${chalk14.cyan("Database:")} ${parsed.database.length} tables`);
4161
+ console.log(` ${chalk14.cyan("Integrations:")} ${parsed.integrations.join(", ") || "None"}`);
4162
+ console.log("");
4163
+ if (parsed.features.length > 0) {
4164
+ console.log(chalk14.bold("Features to build:"));
4165
+ parsed.features.slice(0, 10).forEach((f, i) => {
4166
+ console.log(chalk14.dim(` ${i + 1}. ${f}`));
4167
+ });
4168
+ if (parsed.features.length > 10) {
4169
+ console.log(chalk14.dim(` ... and ${parsed.features.length - 10} more`));
4170
+ }
4171
+ console.log("");
4172
+ }
4173
+ const proceed = await p13.confirm({
4174
+ message: "Build this project?",
4175
+ initialValue: true
4176
+ });
4177
+ if (!proceed || p13.isCancel(proceed)) {
4178
+ p13.cancel("Cancelled");
4179
+ return;
4180
+ }
4181
+ const options = await p13.group({
4182
+ createInfra: () => p13.confirm({
4183
+ message: "Create GitHub + Vercel + Supabase?",
4184
+ initialValue: true
4185
+ }),
4186
+ designProfile: () => p13.select({
4187
+ message: "Design profile:",
4188
+ options: [
4189
+ { value: "minimal", label: "Minimal (Linear, Notion)" },
4190
+ { value: "bold", label: "Bold (Stripe, Ramp)" },
4191
+ { value: "editorial", label: "Editorial (Medium, Substack)" },
4192
+ { value: "playful", label: "Playful (Figma, Slack)" },
4193
+ { value: "premium", label: "Premium (Apple, Porsche)" },
4194
+ { value: "dashboard", label: "Dashboard (Datadog, Linear)" }
4195
+ ],
4196
+ initialValue: parsed.design.profile || "minimal"
4197
+ })
4198
+ });
4199
+ if (p13.isCancel(options)) return;
4200
+ await buildFromPRD(parsed, options, anthropic, config);
4201
+ }
4202
+ async function parsePRD(anthropic, content) {
4203
+ const response = await anthropic.messages.create({
4204
+ model: "claude-sonnet-4-20250514",
4205
+ max_tokens: 4096,
4206
+ messages: [{
4207
+ role: "user",
4208
+ content: `Analyze this PRD and extract structured information. Return JSON only, no explanation.
4209
+
4210
+ PRD:
4211
+ ${content}
4212
+
4213
+ Return this exact JSON structure:
4214
+ {
4215
+ "name": "project name (lowercase, hyphenated)",
4216
+ "description": "one sentence description",
4217
+ "features": ["feature 1", "feature 2", ...],
4218
+ "pages": ["page1", "page2", ...],
4219
+ "database": ["table1", "table2", ...],
4220
+ "integrations": ["stripe", "supabase", ...],
4221
+ "design": {
4222
+ "profile": "minimal|bold|editorial|playful|premium|dashboard or null",
4223
+ "brandColor": "#hexcolor or null"
4224
+ }
4225
+ }
4226
+
4227
+ Extract ALL features mentioned. Include auth, payments, dashboards, etc.
4228
+ For pages, list actual pages/routes needed.
4229
+ For database, list tables/entities needed.
4230
+ For integrations, list third-party services mentioned.`
4231
+ }]
4232
+ });
4233
+ const text10 = response.content[0].type === "text" ? response.content[0].text : "";
4234
+ const jsonMatch = text10.match(/\{[\s\S]*\}/);
4235
+ if (!jsonMatch) {
4236
+ throw new Error("Could not parse PRD");
4237
+ }
4238
+ return JSON.parse(jsonMatch[0]);
4239
+ }
4240
+ async function buildFromPRD(prd, options, anthropic, config) {
4241
+ const spinner13 = p13.spinner();
4242
+ const projectPath = path11.join(process.cwd(), prd.name);
4243
+ spinner13.start("Creating project structure...");
4244
+ await fs11.ensureDir(projectPath);
4245
+ await fs11.ensureDir(path11.join(projectPath, ".codebakers"));
4246
+ await fs11.ensureDir(path11.join(projectPath, "src", "app"));
4247
+ await fs11.ensureDir(path11.join(projectPath, "src", "components"));
4248
+ await fs11.ensureDir(path11.join(projectPath, "src", "lib"));
4249
+ spinner13.stop("Project structure created");
4250
+ spinner13.start("Saving PRD...");
4251
+ await fs11.writeFile(path11.join(projectPath, "PRD.md"), await fs11.readFile(process.cwd(), "utf-8").catch(() => JSON.stringify(prd, null, 2)));
4252
+ await fs11.writeJson(path11.join(projectPath, ".codebakers", "prd.json"), prd, { spaces: 2 });
4253
+ await fs11.writeJson(path11.join(projectPath, ".codebakers", "design.json"), {
4254
+ profile: options.designProfile,
4255
+ colors: prd.design.brandColor ? { brand: prd.design.brandColor } : void 0
4256
+ }, { spaces: 2 });
4257
+ spinner13.stop("PRD saved");
4258
+ spinner13.start("Generating build plan...");
4259
+ const buildPlan = await generateBuildPlan(anthropic, prd, options.designProfile);
4260
+ await fs11.writeJson(path11.join(projectPath, ".codebakers", "build-plan.json"), buildPlan, { spaces: 2 });
4261
+ spinner13.stop("Build plan generated");
4262
+ console.log(chalk14.bold("\n\u{1F3D7}\uFE0F Build Plan:\n"));
4263
+ buildPlan.phases.forEach((phase, i) => {
4264
+ console.log(chalk14.cyan(`Phase ${i + 1}: ${phase.name}`));
4265
+ phase.tasks.forEach((task) => {
4266
+ console.log(chalk14.dim(` \u2022 ${task}`));
4267
+ });
4268
+ });
4269
+ console.log("");
4270
+ const startBuild = await p13.confirm({
4271
+ message: "Start building?",
4272
+ initialValue: true
4273
+ });
4274
+ if (!startBuild || p13.isCancel(startBuild)) {
4275
+ p13.log.info(`Build plan saved to ${prd.name}/.codebakers/build-plan.json`);
4276
+ p13.log.info(`Run \`cd ${prd.name} && codebakers code\` to continue building.`);
4277
+ return;
4278
+ }
4279
+ for (let i = 0; i < buildPlan.phases.length; i++) {
4280
+ const phase = buildPlan.phases[i];
4281
+ console.log(chalk14.bold(`
4282
+ \u{1F4E6} Phase ${i + 1}: ${phase.name}
4283
+ `));
4284
+ for (const task of phase.tasks) {
4285
+ spinner13.start(task);
4286
+ try {
4287
+ await executeTask(anthropic, projectPath, task, prd, options.designProfile);
4288
+ spinner13.stop(`\u2713 ${task}`);
4289
+ } catch (error) {
4290
+ spinner13.stop(`\u2717 ${task}`);
4291
+ p13.log.error(error instanceof Error ? error.message : "Task failed");
4292
+ const continueBuilding = await p13.confirm({
4293
+ message: "Continue with next task?",
4294
+ initialValue: true
4295
+ });
4296
+ if (!continueBuilding || p13.isCancel(continueBuilding)) {
4297
+ p13.log.info("Build paused. Run `codebakers code` to continue.");
4298
+ return;
4299
+ }
4300
+ }
4301
+ }
4302
+ }
4303
+ if (options.createInfra) {
4304
+ console.log(chalk14.bold("\n\u{1F680} Setting up infrastructure...\n"));
4305
+ spinner13.start("Creating GitHub repository...");
4306
+ spinner13.stop("GitHub repository created");
4307
+ spinner13.start("Creating Supabase project...");
4308
+ spinner13.stop("Supabase project created");
4309
+ spinner13.start("Creating Vercel project...");
4310
+ spinner13.stop("Vercel project created");
4311
+ spinner13.start("Deploying...");
4312
+ spinner13.stop("Deployed!");
4313
+ }
4314
+ p13.outro(chalk14.green(`
4315
+ \u2713 Project built from PRD!
4316
+
4317
+ ${chalk14.bold("Your project:")}
4318
+ ${chalk14.cyan(`cd ${prd.name}`)}
4319
+ ${chalk14.cyan("npm run dev")}
4320
+
4321
+ ${chalk14.bold("Continue building:")}
4322
+ ${chalk14.cyan("codebakers code")} \u2014 AI agent
4323
+ ${chalk14.cyan("codebakers check")} \u2014 Verify patterns
4324
+ ${chalk14.cyan("codebakers deploy")} \u2014 Deploy changes
4325
+ `));
4326
+ }
4327
+ async function generateBuildPlan(anthropic, prd, designProfile) {
4328
+ const response = await anthropic.messages.create({
4329
+ model: "claude-sonnet-4-20250514",
4330
+ max_tokens: 4096,
4331
+ messages: [{
4332
+ role: "user",
4333
+ content: `Create a build plan for this project. Return JSON only.
4334
+
4335
+ Project: ${prd.name}
4336
+ Description: ${prd.description}
4337
+ Features: ${prd.features.join(", ")}
4338
+ Pages: ${prd.pages.join(", ")}
4339
+ Database tables: ${prd.database.join(", ")}
4340
+ Integrations: ${prd.integrations.join(", ")}
4341
+ Design: ${designProfile}
4342
+
4343
+ Return this structure:
4344
+ {
4345
+ "phases": [
4346
+ {
4347
+ "name": "Phase name",
4348
+ "tasks": ["task 1", "task 2", ...]
4349
+ }
4350
+ ]
4351
+ }
4352
+
4353
+ Phases should be:
4354
+ 1. Setup (package.json, config, base files)
4355
+ 2. Database (schema, migrations, types)
4356
+ 3. Auth (if needed)
4357
+ 4. Core Features (main functionality)
4358
+ 5. UI/Pages (frontend)
4359
+ 6. Integrations (third-party services)
4360
+ 7. Polish (loading states, error handling, empty states)
4361
+
4362
+ Keep tasks specific and actionable.`
4363
+ }]
4364
+ });
4365
+ const text10 = response.content[0].type === "text" ? response.content[0].text : "";
4366
+ const jsonMatch = text10.match(/\{[\s\S]*\}/);
4367
+ if (!jsonMatch) {
4368
+ throw new Error("Could not generate build plan");
4369
+ }
4370
+ return JSON.parse(jsonMatch[0]);
4371
+ }
4372
+ async function executeTask(anthropic, projectPath, task, prd, designProfile) {
4373
+ const response = await anthropic.messages.create({
4374
+ model: "claude-sonnet-4-20250514",
4375
+ max_tokens: 8192,
4376
+ messages: [{
4377
+ role: "user",
4378
+ content: `Execute this task for the project.
4379
+
4380
+ Project: ${prd.name}
4381
+ Task: ${task}
4382
+ Design Profile: ${designProfile}
4383
+
4384
+ Context:
4385
+ - Features: ${prd.features.join(", ")}
4386
+ - Database: ${prd.database.join(", ")}
4387
+
4388
+ Output files in this format:
4389
+
4390
+ <<<FILE: path/to/file.ts>>>
4391
+ file content here
4392
+ <<<END_FILE>>>
4393
+
4394
+ <<<FILE: another/file.tsx>>>
4395
+ file content here
4396
+ <<<END_FILE>>>
4397
+
4398
+ Follow these rules:
4399
+ - Use TypeScript
4400
+ - Use Next.js App Router
4401
+ - Use Tailwind CSS
4402
+ - Use shadcn/ui components
4403
+ - Every button needs onClick handler
4404
+ - Every form needs Zod validation
4405
+ - Every async operation needs loading/error states
4406
+ - Every list needs empty state
4407
+ - No generic gradient heroes
4408
+ - No icon spam
4409
+ - Generous spacing (py-16 or larger for sections)
4410
+
4411
+ Generate ALL files needed for this task.`
4412
+ }]
4413
+ });
4414
+ const text10 = response.content[0].type === "text" ? response.content[0].text : "";
4415
+ const fileRegex = /<<<FILE:\s*(.+?)>>>([\s\S]*?)<<<END_FILE>>>/g;
4416
+ let match;
4417
+ while ((match = fileRegex.exec(text10)) !== null) {
4418
+ const filePath = path11.join(projectPath, match[1].trim());
4419
+ const content = match[2].trim();
4420
+ await fs11.ensureDir(path11.dirname(filePath));
4421
+ await fs11.writeFile(filePath, content);
4422
+ }
4423
+ }
4424
+
4425
+ // src/commands/advisors.ts
4426
+ import * as p14 from "@clack/prompts";
4427
+ import chalk15 from "chalk";
4428
+ import * as fs12 from "fs-extra";
4429
+ import * as path12 from "path";
4430
+ import Anthropic4 from "@anthropic-ai/sdk";
4431
+ var DREAM_TEAM = [
4432
+ {
4433
+ name: "Sarah Chen",
4434
+ role: "CEO & Strategist",
4435
+ icon: "\u{1F469}\u200D\u{1F4BC}",
4436
+ expertise: "Business strategy, market positioning, fundraising, go-to-market",
4437
+ personality: "Direct, strategic thinker, asks hard questions about market fit and business viability"
4438
+ },
4439
+ {
4440
+ name: "Marcus Johnson",
4441
+ role: "Full Stack Engineer",
4442
+ icon: "\u{1F468}\u200D\u{1F4BB}",
4443
+ expertise: "System architecture, scalability, tech stack selection, development timeline",
4444
+ personality: "Pragmatic, focused on what can actually be built, warns about technical debt"
4445
+ },
4446
+ {
4447
+ name: "Elena Rodriguez",
4448
+ role: "UX/UI Specialist",
4449
+ icon: "\u{1F469}\u200D\u{1F3A8}",
4450
+ expertise: "User research, interface design, user journeys, accessibility, design systems",
4451
+ personality: "User-obsessed, pushes back on features that hurt UX, advocates for simplicity"
4452
+ },
4453
+ {
4454
+ name: "David Park",
4455
+ role: "Marketing Director",
4456
+ icon: "\u{1F4E3}",
4457
+ expertise: "Growth strategy, content marketing, social media, brand positioning, launch campaigns",
4458
+ personality: "Creative, data-driven, thinks about virality and word-of-mouth"
4459
+ },
4460
+ {
4461
+ name: "Aisha Patel",
4462
+ role: "Product Manager",
4463
+ icon: "\u{1F4CB}",
4464
+ expertise: "Feature prioritization, roadmaps, user stories, MVP scoping, competitive analysis",
4465
+ personality: "Organized, balances user needs with business goals, ruthless prioritizer"
4466
+ }
4467
+ ];
4468
+ async function advisorsCommand() {
4469
+ const config = new Config();
4470
+ if (!config.isConfigured()) {
4471
+ p14.log.error("Please run `codebakers setup` first.");
4472
+ return;
4473
+ }
4474
+ const anthropicCreds = config.getCredentials("anthropic");
4475
+ if (!anthropicCreds?.apiKey) {
4476
+ p14.log.error("Anthropic API key not configured.");
4477
+ return;
4478
+ }
4479
+ console.log(chalk15.cyan(`
4480
+ \u256D\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u256E
4481
+ \u2502 \u2502
4482
+ \u2502 \u{1F31F} CODEBAKERS DREAM TEAM ADVISORS \u{1F31F} \u2502
4483
+ \u2502 \u2502
4484
+ \u2502 Meet your advisory board: \u2502
4485
+ \u2502 \u2502
4486
+ \u2502 \u{1F469}\u200D\u{1F4BC} Sarah Chen - CEO & Strategist \u2502
4487
+ \u2502 \u{1F468}\u200D\u{1F4BB} Marcus Johnson - Full Stack Engineer \u2502
4488
+ \u2502 \u{1F469}\u200D\u{1F3A8} Elena Rodriguez - UX/UI Specialist \u2502
4489
+ \u2502 \u{1F4E3} David Park - Marketing Director \u2502
4490
+ \u2502 \u{1F4CB} Aisha Patel - Product Manager \u2502
4491
+ \u2502 \u2502
4492
+ \u2502 They'll interview you about your project, provide expert \u2502
4493
+ \u2502 feedback, and create a comprehensive plan including: \u2502
4494
+ \u2502 \u2502
4495
+ \u2502 \u2022 Technical architecture & implementation plan \u2502
4496
+ \u2502 \u2022 Marketing & social media strategy \u2502
4497
+ \u2502 \u2022 UX/UI recommendations & user journeys \u2502
4498
+ \u2502 \u2022 Business model & revenue projections \u2502
4499
+ \u2502 \u2022 Risk assessment & mitigation strategies \u2502
4500
+ \u2502 \u2022 Prioritized action items \u2502
4501
+ \u2502 \u2502
4502
+ \u2502 \u{1F4C4} You'll receive a complete PDF report at the end. \u2502
4503
+ \u2502 \u2502
4504
+ \u2570\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u256F
4505
+ `));
4506
+ const start = await p14.confirm({
4507
+ message: "Ready to meet the Dream Team?",
4508
+ initialValue: true
4509
+ });
4510
+ if (!start || p14.isCancel(start)) {
4511
+ p14.cancel("Maybe next time!");
4512
+ return;
4513
+ }
4514
+ const brief = await conductInterview();
4515
+ if (!brief) return;
4516
+ const anthropic = new Anthropic4({ apiKey: anthropicCreds.apiKey });
4517
+ console.log(chalk15.bold("\n\n\u{1F3AF} The Dream Team is reviewing your project...\n"));
4518
+ const advisorFeedback = [];
4519
+ for (const advisor of DREAM_TEAM) {
4520
+ const spinner14 = p14.spinner();
4521
+ spinner14.start(`${advisor.icon} ${advisor.name} is analyzing...`);
4522
+ const feedback = await getAdvisorFeedback(anthropic, advisor, brief);
4523
+ advisorFeedback.push(feedback);
4524
+ spinner14.stop(`${advisor.icon} ${advisor.name} complete`);
4525
+ console.log(chalk15.dim(` Score: ${feedback.score}/10 - "${feedback.feedback.slice(0, 80)}..."
4526
+ `));
4527
+ }
4528
+ const spinner13 = p14.spinner();
4529
+ spinner13.start("Generating comprehensive report...");
4530
+ const report = await generateReport(anthropic, brief, advisorFeedback);
4531
+ spinner13.stop("Report generated");
4532
+ displayReportSummary(report);
4533
+ const savePath = await saveReport(report, brief.name);
4534
+ p14.outro(chalk15.green(`
4535
+ \u2713 Dream Team consultation complete!
4536
+
4537
+ \u{1F4C4} Full report saved to: ${savePath}
4538
+
4539
+ ${chalk15.bold("Next steps:")}
4540
+ ${chalk15.cyan(`codebakers prd ${savePath.replace(".pdf", ".md")}`)} - Build from this plan
4541
+ ${chalk15.cyan("codebakers init")} - Start with standard setup
4542
+ `));
4543
+ }
4544
+ async function conductInterview() {
4545
+ p14.intro(chalk15.bgMagenta.white(" Project Interview "));
4546
+ console.log(chalk15.dim("\nLet's learn about your project. Answer as thoroughly as you can.\n"));
4547
+ const name = await p14.text({
4548
+ message: "\u{1F469}\u200D\u{1F4BC} Sarah: What's your project called?",
4549
+ placeholder: "My App Name",
4550
+ validate: (v) => !v ? "Project name is required" : void 0
4551
+ });
4552
+ if (p14.isCancel(name)) return null;
4553
+ const idea = await p14.text({
4554
+ message: "\u{1F469}\u200D\u{1F4BC} Sarah: Describe your idea in 2-3 sentences. What does it do?",
4555
+ placeholder: "A platform that helps...",
4556
+ validate: (v) => !v ? "Please describe your idea" : void 0
4557
+ });
4558
+ if (p14.isCancel(idea)) return null;
4559
+ const problem = await p14.text({
4560
+ message: "\u{1F4CB} Aisha: What problem are you solving? Why does this need to exist?",
4561
+ placeholder: "Currently, people struggle with...",
4562
+ validate: (v) => !v ? "Understanding the problem is crucial" : void 0
4563
+ });
4564
+ if (p14.isCancel(problem)) return null;
4565
+ const targetAudience = await p14.text({
4566
+ message: "\u{1F4E3} David: Who is this for? Describe your ideal user.",
4567
+ placeholder: "Small business owners who...",
4568
+ validate: (v) => !v ? "We need to know your target audience" : void 0
4569
+ });
4570
+ if (p14.isCancel(targetAudience)) return null;
4571
+ const solution = await p14.text({
4572
+ message: "\u{1F469}\u200D\u{1F3A8} Elena: How does your product solve the problem? What's the core experience?",
4573
+ placeholder: "Users can easily...",
4574
+ validate: (v) => !v ? "Please describe your solution" : void 0
4575
+ });
4576
+ if (p14.isCancel(solution)) return null;
4577
+ const competitors = await p14.text({
4578
+ message: "\u{1F469}\u200D\u{1F4BC} Sarah: Who are your competitors? How are you different?",
4579
+ placeholder: "Competitor X does Y, but we..."
4580
+ });
4581
+ if (p14.isCancel(competitors)) return null;
4582
+ const monetization = await p14.select({
4583
+ message: "\u{1F469}\u200D\u{1F4BC} Sarah: How will you make money?",
4584
+ options: [
4585
+ { value: "subscription", label: "Subscription (monthly/yearly)" },
4586
+ { value: "freemium", label: "Freemium (free tier + paid)" },
4587
+ { value: "one-time", label: "One-time purchase" },
4588
+ { value: "marketplace", label: "Marketplace (take a cut)" },
4589
+ { value: "ads", label: "Advertising" },
4590
+ { value: "enterprise", label: "Enterprise sales" },
4591
+ { value: "unsure", label: "Not sure yet" }
4592
+ ]
4593
+ });
4594
+ if (p14.isCancel(monetization)) return null;
4595
+ const timeline = await p14.select({
4596
+ message: "\u{1F468}\u200D\u{1F4BB} Marcus: What's your timeline for launching?",
4597
+ options: [
4598
+ { value: "2-weeks", label: "2 weeks (MVP)" },
4599
+ { value: "1-month", label: "1 month" },
4600
+ { value: "3-months", label: "3 months" },
4601
+ { value: "6-months", label: "6 months" },
4602
+ { value: "flexible", label: "Flexible / No rush" }
4603
+ ]
4604
+ });
4605
+ if (p14.isCancel(timeline)) return null;
4606
+ const budget = await p14.select({
4607
+ message: "\u{1F469}\u200D\u{1F4BC} Sarah: What's your budget for this project?",
4608
+ options: [
4609
+ { value: "bootstrap", label: "Bootstrap ($0 - using free tiers)" },
4610
+ { value: "small", label: "Small ($100-500/month)" },
4611
+ { value: "medium", label: "Medium ($500-2000/month)" },
4612
+ { value: "funded", label: "Funded ($2000+/month)" }
4613
+ ]
4614
+ });
4615
+ if (p14.isCancel(budget)) return null;
4616
+ const techPreferences = await p14.text({
4617
+ message: '\u{1F468}\u200D\u{1F4BB} Marcus: Any tech preferences or requirements? (or "none")',
4618
+ placeholder: "Must use React, need mobile app, etc.",
4619
+ initialValue: "none"
4620
+ });
4621
+ if (p14.isCancel(techPreferences)) return null;
4622
+ const additional = await p14.text({
4623
+ message: "\u{1F4CB} Aisha: Anything else we should know?",
4624
+ placeholder: "Optional: special requirements, existing users, etc."
4625
+ });
4626
+ if (p14.isCancel(additional)) return null;
4627
+ return {
4628
+ name,
4629
+ idea,
4630
+ targetAudience,
4631
+ problem,
4632
+ solution,
4633
+ competitors: competitors || "Not specified",
4634
+ monetization,
4635
+ timeline,
4636
+ budget,
4637
+ techPreferences: techPreferences || "none"
4638
+ };
4639
+ }
4640
+ async function getAdvisorFeedback(anthropic, advisor, brief) {
4641
+ const response = await anthropic.messages.create({
4642
+ model: "claude-sonnet-4-20250514",
4643
+ max_tokens: 2048,
4644
+ messages: [{
4645
+ role: "user",
4646
+ content: `You are ${advisor.name}, ${advisor.role} on a startup advisory board.
4647
+
4648
+ Your expertise: ${advisor.expertise}
4649
+ Your personality: ${advisor.personality}
4650
+
4651
+ Review this project brief and provide your expert feedback:
4652
+
4653
+ Project: ${brief.name}
4654
+ Idea: ${brief.idea}
4655
+ Problem: ${brief.problem}
4656
+ Target Audience: ${brief.targetAudience}
4657
+ Solution: ${brief.solution}
4658
+ Competitors: ${brief.competitors}
4659
+ Monetization: ${brief.monetization}
4660
+ Timeline: ${brief.timeline}
4661
+ Budget: ${brief.budget}
4662
+ Tech Preferences: ${brief.techPreferences}
4663
+
4664
+ Respond with JSON only:
4665
+ {
4666
+ "feedback": "2-3 sentence overall assessment in your voice/personality",
4667
+ "recommendations": ["specific recommendation 1", "recommendation 2", "recommendation 3"],
4668
+ "questions": ["question you'd want answered", "another question"],
4669
+ "risks": ["risk 1", "risk 2"],
4670
+ "score": 7
4671
+ }
4672
+
4673
+ Score 1-10 based on your area of expertise. Be honest but constructive.`
4674
+ }]
4675
+ });
4676
+ const text10 = response.content[0].type === "text" ? response.content[0].text : "";
4677
+ const jsonMatch = text10.match(/\{[\s\S]*\}/);
4678
+ if (!jsonMatch) {
4679
+ return {
4680
+ advisor: advisor.name,
4681
+ role: advisor.role,
4682
+ icon: advisor.icon,
4683
+ feedback: "Unable to generate feedback",
4684
+ recommendations: [],
4685
+ questions: [],
4686
+ risks: [],
4687
+ score: 5
4688
+ };
4689
+ }
4690
+ const parsed = JSON.parse(jsonMatch[0]);
4691
+ return {
4692
+ advisor: advisor.name,
4693
+ role: advisor.role,
4694
+ icon: advisor.icon,
4695
+ ...parsed
4696
+ };
4697
+ }
4698
+ async function generateReport(anthropic, brief, advisorFeedback) {
4699
+ const avgScore = advisorFeedback.reduce((sum, f) => sum + f.score, 0) / advisorFeedback.length;
4700
+ const response = await anthropic.messages.create({
4701
+ model: "claude-sonnet-4-20250514",
4702
+ max_tokens: 8192,
4703
+ messages: [{
4704
+ role: "user",
4705
+ content: `Generate a comprehensive startup plan based on this project brief and advisor feedback.
4706
+
4707
+ PROJECT BRIEF:
4708
+ ${JSON.stringify(brief, null, 2)}
4709
+
4710
+ ADVISOR FEEDBACK:
4711
+ ${JSON.stringify(advisorFeedback, null, 2)}
4712
+
4713
+ Generate a complete JSON report:
4714
+ {
4715
+ "executiveSummary": "3-4 paragraph executive summary",
4716
+ "goNoGo": "GO" or "CAUTION" or "PIVOT",
4717
+ "marketingPlan": {
4718
+ "positioning": "positioning statement",
4719
+ "targetSegments": ["segment 1", "segment 2"],
4720
+ "channels": ["channel 1", "channel 2"],
4721
+ "launchStrategy": "detailed launch strategy",
4722
+ "contentPlan": ["content idea 1", "content idea 2"],
4723
+ "socialMediaPlan": {
4724
+ "platforms": ["platform 1", "platform 2"],
4725
+ "postFrequency": "frequency",
4726
+ "contentTypes": ["type 1", "type 2"]
4727
+ },
4728
+ "budget": "recommended budget breakdown"
4729
+ },
4730
+ "technicalPlan": {
4731
+ "architecture": "high-level architecture description",
4732
+ "stack": ["Next.js", "Supabase", "etc"],
4733
+ "phases": [
4734
+ {"name": "Phase 1: MVP", "duration": "2 weeks", "deliverables": ["feature 1", "feature 2"]}
4735
+ ],
4736
+ "mvpFeatures": ["feature 1", "feature 2"],
4737
+ "futureFeatures": ["feature 1", "feature 2"]
4738
+ },
4739
+ "uxPlan": {
4740
+ "userPersonas": [{"name": "Persona Name", "description": "desc", "goals": ["goal 1"]}],
4741
+ "userJourneys": ["journey 1", "journey 2"],
4742
+ "keyScreens": ["screen 1", "screen 2"],
4743
+ "designPrinciples": ["principle 1", "principle 2"]
4744
+ },
4745
+ "businessPlan": {
4746
+ "revenueModel": "detailed revenue model",
4747
+ "pricing": "pricing strategy",
4748
+ "projections": [{"month": 3, "users": 100, "revenue": 500}],
4749
+ "kpis": ["kpi 1", "kpi 2"],
4750
+ "risks": [{"risk": "risk description", "mitigation": "how to mitigate"}]
4751
+ },
4752
+ "actionItems": [
4753
+ {"priority": "HIGH", "task": "task description", "owner": "CEO/Engineer/etc"}
4754
+ ]
4755
+ }
4756
+
4757
+ Be specific, actionable, and realistic based on the timeline and budget.`
4758
+ }]
4759
+ });
4760
+ const text10 = response.content[0].type === "text" ? response.content[0].text : "";
4761
+ const jsonMatch = text10.match(/\{[\s\S]*\}/);
4762
+ const parsed = jsonMatch ? JSON.parse(jsonMatch[0]) : {};
4763
+ return {
4764
+ projectName: brief.name,
4765
+ brief,
4766
+ advisorFeedback,
4767
+ overallScore: Math.round(avgScore * 10) / 10,
4768
+ goNoGo: parsed.goNoGo || (avgScore >= 7 ? "GO" : avgScore >= 5 ? "CAUTION" : "PIVOT"),
4769
+ executiveSummary: parsed.executiveSummary || "",
4770
+ marketingPlan: parsed.marketingPlan || {},
4771
+ technicalPlan: parsed.technicalPlan || {},
4772
+ uxPlan: parsed.uxPlan || {},
4773
+ businessPlan: parsed.businessPlan || {},
4774
+ actionItems: parsed.actionItems || []
4775
+ };
4776
+ }
4777
+ function displayReportSummary(report) {
4778
+ const goNoGoColor = {
4779
+ "GO": chalk15.green,
4780
+ "CAUTION": chalk15.yellow,
4781
+ "PIVOT": chalk15.red
4782
+ }[report.goNoGo];
4783
+ console.log(chalk15.bold(`
4784
+ ${"\u2550".repeat(60)}`));
4785
+ console.log(chalk15.bold.cyan(`
4786
+ \u{1F4CA} DREAM TEAM REPORT: ${report.projectName.toUpperCase()}
4787
+ `));
4788
+ console.log(chalk15.bold(`${"\u2550".repeat(60)}
4789
+ `));
4790
+ console.log(chalk15.bold("Overall Assessment:"));
4791
+ console.log(` Score: ${chalk15.bold(report.overallScore.toString())}/10`);
4792
+ console.log(` Verdict: ${goNoGoColor(report.goNoGo)}
4793
+ `);
4794
+ console.log(chalk15.bold("Advisor Scores:"));
4795
+ for (const feedback of report.advisorFeedback) {
4796
+ const bar = "\u2588".repeat(feedback.score) + "\u2591".repeat(10 - feedback.score);
4797
+ console.log(` ${feedback.icon} ${feedback.advisor.padEnd(18)} ${bar} ${feedback.score}/10`);
4798
+ }
4799
+ console.log("");
4800
+ console.log(chalk15.bold("Executive Summary:"));
4801
+ console.log(chalk15.dim(` ${report.executiveSummary.slice(0, 300)}...`));
4802
+ console.log("");
4803
+ console.log(chalk15.bold("Top Action Items:"));
4804
+ const highPriority = report.actionItems.filter((a) => a.priority === "HIGH").slice(0, 5);
4805
+ highPriority.forEach((item, i) => {
4806
+ console.log(` ${chalk15.red("!")} ${item.task}`);
4807
+ });
4808
+ console.log("");
4809
+ if (report.technicalPlan.stack?.length > 0) {
4810
+ console.log(chalk15.bold("Recommended Stack:"));
4811
+ console.log(` ${report.technicalPlan.stack.join(" \u2022 ")}`);
4812
+ console.log("");
4813
+ }
4814
+ console.log(chalk15.dim("Full report saved to PDF with complete marketing, technical, and business plans.\n"));
4815
+ }
4816
+ async function saveReport(report, projectName) {
4817
+ const sanitizedName = projectName.toLowerCase().replace(/[^a-z0-9]/g, "-");
4818
+ const timestamp = (/* @__PURE__ */ new Date()).toISOString().split("T")[0];
4819
+ const filename = `${sanitizedName}-dream-team-report-${timestamp}`;
4820
+ const mdPath = path12.join(process.cwd(), `${filename}.md`);
4821
+ const mdContent = generateMarkdownReport(report);
4822
+ await fs12.writeFile(mdPath, mdContent);
4823
+ const jsonPath = path12.join(process.cwd(), `${filename}.json`);
4824
+ await fs12.writeJson(jsonPath, report, { spaces: 2 });
4825
+ return mdPath;
4826
+ }
4827
+ function generateMarkdownReport(report) {
4828
+ const goNoGoEmoji = { "GO": "\u{1F7E2}", "CAUTION": "\u{1F7E1}", "PIVOT": "\u{1F534}" }[report.goNoGo];
4829
+ return `# ${report.projectName} - Dream Team Report
4830
+
4831
+ **Generated:** ${(/* @__PURE__ */ new Date()).toLocaleDateString()}
4832
+ **Overall Score:** ${report.overallScore}/10
4833
+ **Verdict:** ${goNoGoEmoji} ${report.goNoGo}
4834
+
4835
+ ---
4836
+
4837
+ ## Executive Summary
4838
+
4839
+ ${report.executiveSummary}
4840
+
4841
+ ---
4842
+
4843
+ ## Advisor Feedback
4844
+
4845
+ ${report.advisorFeedback.map((f) => `
4846
+ ### ${f.icon} ${f.advisor} - ${f.role}
4847
+
4848
+ **Score:** ${f.score}/10
4849
+
4850
+ ${f.feedback}
4851
+
4852
+ **Recommendations:**
4853
+ ${f.recommendations.map((r) => `- ${r}`).join("\n")}
4854
+
4855
+ **Questions to Consider:**
4856
+ ${f.questions.map((q) => `- ${q}`).join("\n")}
4857
+
4858
+ **Risks Identified:**
4859
+ ${f.risks.map((r) => `- ${r}`).join("\n")}
4860
+ `).join("\n")}
4861
+
4862
+ ---
4863
+
4864
+ ## Marketing Plan
4865
+
4866
+ ### Positioning
4867
+ ${report.marketingPlan.positioning}
4868
+
4869
+ ### Target Segments
4870
+ ${report.marketingPlan.targetSegments?.map((s) => `- ${s}`).join("\n") || "TBD"}
4871
+
4872
+ ### Marketing Channels
4873
+ ${report.marketingPlan.channels?.map((c) => `- ${c}`).join("\n") || "TBD"}
4874
+
4875
+ ### Launch Strategy
4876
+ ${report.marketingPlan.launchStrategy}
4877
+
4878
+ ### Content Plan
4879
+ ${report.marketingPlan.contentPlan?.map((c) => `- ${c}`).join("\n") || "TBD"}
4880
+
4881
+ ### Social Media Plan
4882
+ - **Platforms:** ${report.marketingPlan.socialMediaPlan?.platforms?.join(", ") || "TBD"}
4883
+ - **Post Frequency:** ${report.marketingPlan.socialMediaPlan?.postFrequency || "TBD"}
4884
+ - **Content Types:** ${report.marketingPlan.socialMediaPlan?.contentTypes?.join(", ") || "TBD"}
4885
+
4886
+ ### Budget
4887
+ ${report.marketingPlan.budget}
4888
+
4889
+ ---
4890
+
4891
+ ## Technical Plan
4892
+
4893
+ ### Architecture
4894
+ ${report.technicalPlan.architecture}
4895
+
4896
+ ### Tech Stack
4897
+ ${report.technicalPlan.stack?.map((s) => `- ${s}`).join("\n") || "TBD"}
4898
+
4899
+ ### Development Phases
4900
+ ${report.technicalPlan.phases?.map((p16) => `
4901
+ #### ${p16.name} (${p16.duration})
4902
+ ${p16.deliverables.map((d) => `- ${d}`).join("\n")}
4903
+ `).join("\n") || "TBD"}
4904
+
4905
+ ### MVP Features
4906
+ ${report.technicalPlan.mvpFeatures?.map((f) => `- ${f}`).join("\n") || "TBD"}
4907
+
4908
+ ### Future Features
4909
+ ${report.technicalPlan.futureFeatures?.map((f) => `- ${f}`).join("\n") || "TBD"}
4910
+
4911
+ ---
4912
+
4913
+ ## UX Plan
4914
+
4915
+ ### User Personas
4916
+ ${report.uxPlan.userPersonas?.map((p16) => `
4917
+ #### ${p16.name}
4918
+ ${p16.description}
4919
+
4920
+ **Goals:**
4921
+ ${p16.goals.map((g) => `- ${g}`).join("\n")}
4922
+ `).join("\n") || "TBD"}
4923
+
4924
+ ### User Journeys
4925
+ ${report.uxPlan.userJourneys?.map((j) => `- ${j}`).join("\n") || "TBD"}
4926
+
4927
+ ### Key Screens
4928
+ ${report.uxPlan.keyScreens?.map((s) => `- ${s}`).join("\n") || "TBD"}
4929
+
4930
+ ### Design Principles
4931
+ ${report.uxPlan.designPrinciples?.map((p16) => `- ${p16}`).join("\n") || "TBD"}
4932
+
4933
+ ---
4934
+
4935
+ ## Business Plan
4936
+
4937
+ ### Revenue Model
4938
+ ${report.businessPlan.revenueModel}
4939
+
4940
+ ### Pricing Strategy
4941
+ ${report.businessPlan.pricing}
4942
+
4943
+ ### Projections
4944
+ | Month | Users | Revenue |
4945
+ |-------|-------|---------|
4946
+ ${report.businessPlan.projections?.map((p16) => `| ${p16.month} | ${p16.users} | $${p16.revenue} |`).join("\n") || "| TBD | TBD | TBD |"}
4947
+
4948
+ ### KPIs
4949
+ ${report.businessPlan.kpis?.map((k) => `- ${k}`).join("\n") || "TBD"}
4950
+
4951
+ ### Risks & Mitigation
4952
+ | Risk | Mitigation |
4953
+ |------|------------|
4954
+ ${report.businessPlan.risks?.map((r) => `| ${r.risk} | ${r.mitigation} |`).join("\n") || "| TBD | TBD |"}
4955
+
4956
+ ---
4957
+
4958
+ ## Action Items
4959
+
4960
+ ### High Priority
4961
+ ${report.actionItems.filter((a) => a.priority === "HIGH").map((a) => `- [ ] **${a.task}** (Owner: ${a.owner})`).join("\n") || "None"}
4962
+
4963
+ ### Medium Priority
4964
+ ${report.actionItems.filter((a) => a.priority === "MEDIUM").map((a) => `- [ ] ${a.task} (Owner: ${a.owner})`).join("\n") || "None"}
4965
+
4966
+ ### Low Priority
4967
+ ${report.actionItems.filter((a) => a.priority === "LOW").map((a) => `- [ ] ${a.task} (Owner: ${a.owner})`).join("\n") || "None"}
4968
+
4969
+ ---
4970
+
4971
+ ## Next Steps
4972
+
4973
+ 1. Review this report with your team
4974
+ 2. Run \`codebakers prd ${report.projectName.toLowerCase().replace(/[^a-z0-9]/g, "-")}-dream-team-report.md\` to start building
4975
+ 3. Or run \`codebakers init\` for standard project setup
4976
+
4977
+ ---
4978
+
4979
+ *Generated by CodeBakers Dream Team Advisors*
4980
+ `;
4981
+ }
4982
+
4106
4983
  // src/index.ts
4107
4984
  var VERSION2 = "1.0.0";
4108
4985
  var logo = `
@@ -4117,18 +4994,18 @@ async function showMainMenu() {
4117
4994
  const config = new Config();
4118
4995
  const isSetup = config.isConfigured();
4119
4996
  console.log(gradient.pastel.multiline(logo));
4120
- console.log(chalk14.dim(` v${VERSION2} \u2014 AI dev team that follows the rules
4997
+ console.log(chalk16.dim(` v${VERSION2} \u2014 AI dev team that follows the rules
4121
4998
  `));
4122
4999
  if (!isSetup) {
4123
5000
  console.log(boxen(
4124
- chalk14.yellow("Welcome to CodeBakers! Let's get you set up."),
5001
+ chalk16.yellow("Welcome to CodeBakers! Let's get you set up."),
4125
5002
  { padding: 1, borderColor: "yellow", borderStyle: "round" }
4126
5003
  ));
4127
5004
  await setupCommand();
4128
5005
  return;
4129
5006
  }
4130
5007
  const inProject = config.isInProject();
4131
- const action = await p13.select({
5008
+ const action = await p15.select({
4132
5009
  message: "What do you want to do?",
4133
5010
  options: inProject ? [
4134
5011
  { value: "code", label: "\u{1F4AC} Code with AI", hint: "build features, fix bugs" },
@@ -4145,10 +5022,14 @@ async function showMainMenu() {
4145
5022
  { value: "design", label: "\u{1F3A8} Design system", hint: "set profile, colors" },
4146
5023
  { value: "separator2", label: "\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500" },
4147
5024
  { value: "new", label: "\u{1F195} Create new project" },
5025
+ { value: "prd", label: "\u{1F4C4} Build from PRD", hint: "upload a PRD document" },
5026
+ { value: "advisors", label: "\u{1F31F} Dream Team Advisors", hint: "consult with experts" },
4148
5027
  { value: "settings", label: "\u2699\uFE0F Settings" },
4149
5028
  { value: "help", label: "\u2753 Help" }
4150
5029
  ] : [
4151
5030
  { value: "new", label: "\u{1F195} Create new project" },
5031
+ { value: "prd", label: "\u{1F4C4} Build from PRD", hint: "upload a PRD document" },
5032
+ { value: "advisors", label: "\u{1F31F} Dream Team Advisors", hint: "consult with experts" },
4152
5033
  { value: "open", label: "\u{1F4C2} Open existing project" },
4153
5034
  { value: "status", label: "\u{1F4CA} View all projects" },
4154
5035
  { value: "separator1", label: "\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500" },
@@ -4159,8 +5040,8 @@ async function showMainMenu() {
4159
5040
  { value: "help", label: "\u2753 Help" }
4160
5041
  ]
4161
5042
  });
4162
- if (p13.isCancel(action)) {
4163
- p13.cancel("Goodbye!");
5043
+ if (p15.isCancel(action)) {
5044
+ p15.cancel("Goodbye!");
4164
5045
  process.exit(0);
4165
5046
  }
4166
5047
  switch (action) {
@@ -4200,6 +5081,12 @@ async function showMainMenu() {
4200
5081
  case "new":
4201
5082
  await initCommand();
4202
5083
  break;
5084
+ case "prd":
5085
+ await prdCommand();
5086
+ break;
5087
+ case "advisors":
5088
+ await advisorsCommand();
5089
+ break;
4203
5090
  case "settings":
4204
5091
  await setupCommand();
4205
5092
  break;
@@ -4212,27 +5099,27 @@ async function showMainMenu() {
4212
5099
  }
4213
5100
  function showHelp2() {
4214
5101
  console.log(boxen(`
4215
- ${chalk14.bold("CodeBakers CLI")} \u2014 AI dev team that follows the rules
4216
-
4217
- ${chalk14.bold("Commands:")}
4218
- ${chalk14.cyan("codebakers")} Interactive menu (or just run with no args)
4219
- ${chalk14.cyan("codebakers init")} Create a new project
4220
- ${chalk14.cyan("codebakers code")} Start AI coding session
4221
- ${chalk14.cyan("codebakers check")} Run pattern enforcement
4222
- ${chalk14.cyan("codebakers deploy")} Deploy to production
4223
- ${chalk14.cyan("codebakers fix")} Auto-fix errors
4224
- ${chalk14.cyan("codebakers generate")} Generate components/pages
4225
- ${chalk14.cyan("codebakers connect")} Connect external services
4226
- ${chalk14.cyan("codebakers gateway")} Manage messaging channels
4227
- ${chalk14.cyan("codebakers status")} View project status
4228
- ${chalk14.cyan("codebakers security")} Run security audit
4229
- ${chalk14.cyan("codebakers learn")} View/manage learning
4230
-
4231
- ${chalk14.bold("Help at any time:")}
4232
- Press ${chalk14.yellow("?")} during any command to get contextual help
4233
-
4234
- ${chalk14.bold("Documentation:")}
4235
- ${chalk14.dim("https://codebakers.dev/docs")}
5102
+ ${chalk16.bold("CodeBakers CLI")} \u2014 AI dev team that follows the rules
5103
+
5104
+ ${chalk16.bold("Commands:")}
5105
+ ${chalk16.cyan("codebakers")} Interactive menu (or just run with no args)
5106
+ ${chalk16.cyan("codebakers init")} Create a new project
5107
+ ${chalk16.cyan("codebakers code")} Start AI coding session
5108
+ ${chalk16.cyan("codebakers check")} Run pattern enforcement
5109
+ ${chalk16.cyan("codebakers deploy")} Deploy to production
5110
+ ${chalk16.cyan("codebakers fix")} Auto-fix errors
5111
+ ${chalk16.cyan("codebakers generate")} Generate components/pages
5112
+ ${chalk16.cyan("codebakers connect")} Connect external services
5113
+ ${chalk16.cyan("codebakers gateway")} Manage messaging channels
5114
+ ${chalk16.cyan("codebakers status")} View project status
5115
+ ${chalk16.cyan("codebakers security")} Run security audit
5116
+ ${chalk16.cyan("codebakers learn")} View/manage learning
5117
+
5118
+ ${chalk16.bold("Help at any time:")}
5119
+ Press ${chalk16.yellow("?")} during any command to get contextual help
5120
+
5121
+ ${chalk16.bold("Documentation:")}
5122
+ ${chalk16.dim("https://codebakers.dev/docs")}
4236
5123
  `, { padding: 1, borderColor: "cyan", borderStyle: "round" }));
4237
5124
  }
4238
5125
  var program = new Command();
@@ -4250,6 +5137,8 @@ program.command("status").description("View project status and health").option("
4250
5137
  program.command("security").description("Run security audit").option("--fix", "Auto-fix security issues").action(securityCommand);
4251
5138
  program.command("learn").description("View and manage learning settings").option("--forget <item>", "Forget a learned preference").option("--reset", "Reset all learning").option("--export", "Export learned patterns").action(learnCommand);
4252
5139
  program.command("design [action]").description("Manage design system (profile, palette, check)").action(designCommand);
5140
+ program.command("prd [file]").description("Build entire project from a PRD document").action(prdCommand);
5141
+ program.command("advisors").alias("dream-team").description("Consult with the CodeBakers Dream Team advisory board").action(advisorsCommand);
4253
5142
  var args = process.argv.slice(2);
4254
5143
  if (args.length === 0) {
4255
5144
  checkForUpdates().catch(() => {