codebakers 2.2.2 → 2.3.4

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
@@ -13,8 +13,9 @@ import {
13
13
  import { Command } from "commander";
14
14
  import * as p21 from "@clack/prompts";
15
15
  import chalk21 from "chalk";
16
- import boxen from "boxen";
16
+ import boxen2 from "boxen";
17
17
  import gradient from "gradient-string";
18
+ import * as path16 from "path";
18
19
 
19
20
  // src/utils/updates.ts
20
21
  import chalk from "chalk";
@@ -42,19 +43,26 @@ async function checkForUpdates() {
42
43
  // src/commands/setup.ts
43
44
  import * as p from "@clack/prompts";
44
45
  import chalk2 from "chalk";
46
+ import boxen from "boxen";
45
47
  import open from "open";
46
48
  var SERVICES = {
47
49
  anthropic: {
48
50
  key: "anthropic",
49
51
  name: "Anthropic (Claude)",
50
52
  description: "Powers the AI coding agent",
51
- whyNeeded: "Without this, CodeBakers cannot generate any code. This is the brain of the system.",
53
+ whyNeeded: "This is REQUIRED. Without it, CodeBakers cannot generate any code.",
52
54
  url: "https://console.anthropic.com/settings/keys",
53
- urlDescription: "Create an API key",
55
+ steps: [
56
+ "Sign up or log in to Anthropic Console",
57
+ 'Click "Create Key"',
58
+ 'Give it a name like "CodeBakers"',
59
+ "Copy the key (starts with sk-ant-)"
60
+ ],
54
61
  fields: [{
55
62
  key: "apiKey",
56
- label: "Anthropic API Key",
63
+ label: "Paste your Anthropic API Key",
57
64
  placeholder: "sk-ant-...",
65
+ hint: "Starts with sk-ant-",
58
66
  validate: (v) => {
59
67
  if (!v) return "API key is required";
60
68
  if (!v.startsWith("sk-ant-")) return "Should start with sk-ant-";
@@ -66,13 +74,19 @@ var SERVICES = {
66
74
  key: "github",
67
75
  name: "GitHub",
68
76
  description: "Create repos and push code",
69
- whyNeeded: "Without this, CodeBakers cannot create repositories or save your code to GitHub.",
77
+ whyNeeded: "Needed to create repositories and save your code. Skip if you'll manage git manually.",
70
78
  url: "https://github.com/settings/tokens/new?scopes=repo,user&description=CodeBakers",
71
- urlDescription: 'Create a token with "repo" and "user" scopes checked',
79
+ steps: [
80
+ "Log in to GitHub",
81
+ 'The "repo" and "user" boxes should already be checked',
82
+ 'Scroll down and click "Generate token"',
83
+ "Copy the token (starts with ghp_)"
84
+ ],
72
85
  fields: [{
73
86
  key: "token",
74
- label: "GitHub Token",
75
- placeholder: "ghp_... or github_pat_...",
87
+ label: "Paste your GitHub Token",
88
+ placeholder: "ghp_...",
89
+ hint: "Starts with ghp_ or github_pat_",
76
90
  validate: (v) => {
77
91
  if (!v) return "Token is required";
78
92
  if (!v.startsWith("ghp_") && !v.startsWith("github_pat_")) {
@@ -86,38 +100,55 @@ var SERVICES = {
86
100
  key: "vercel",
87
101
  name: "Vercel",
88
102
  description: "Deploy your apps to production",
89
- whyNeeded: "Without this, CodeBakers cannot deploy your apps. You'll have to deploy manually.",
103
+ whyNeeded: "Needed to deploy apps automatically. Skip if you'll deploy manually.",
90
104
  url: "https://vercel.com/account/tokens",
91
- urlDescription: 'Click "Create" to generate a new token',
105
+ steps: [
106
+ "Log in to Vercel",
107
+ 'Click "Create" button',
108
+ 'Name it "CodeBakers"',
109
+ 'Click "Create Token"',
110
+ "Copy the token"
111
+ ],
92
112
  fields: [{
93
113
  key: "token",
94
- label: "Vercel Token",
95
- placeholder: "vercel_..."
114
+ label: "Paste your Vercel Token",
115
+ placeholder: "vercel_...",
116
+ hint: "The token you just created"
96
117
  }]
97
118
  },
98
119
  supabase: {
99
120
  key: "supabase",
100
121
  name: "Supabase",
101
122
  description: "Database and authentication",
102
- whyNeeded: "Without this, CodeBakers cannot create databases for your apps. You'll need to set up databases manually.",
123
+ whyNeeded: "Needed for database features. Skip if you'll set up databases manually.",
103
124
  url: "https://supabase.com/dashboard/account/tokens",
104
- urlDescription: "Generate a new access token",
125
+ steps: [
126
+ "Log in to Supabase",
127
+ 'Click "Generate new token"',
128
+ 'Name it "CodeBakers"',
129
+ "Copy the token"
130
+ ],
105
131
  fields: [{
106
132
  key: "accessToken",
107
- label: "Supabase Access Token",
108
- placeholder: "sbp_..."
133
+ label: "Paste your Supabase Token",
134
+ placeholder: "sbp_...",
135
+ hint: "Starts with sbp_"
109
136
  }]
110
137
  },
111
138
  openai: {
112
139
  key: "openai",
113
140
  name: "OpenAI",
114
141
  description: "GPT models, embeddings, DALL-E",
115
- whyNeeded: "Optional. Only needed if you want to use OpenAI models instead of or alongside Claude.",
142
+ whyNeeded: "Optional. Only if you want to use OpenAI alongside Claude.",
116
143
  url: "https://platform.openai.com/api-keys",
117
- urlDescription: "Create a new API key",
144
+ steps: [
145
+ "Log in to OpenAI",
146
+ 'Click "Create new secret key"',
147
+ "Copy the key"
148
+ ],
118
149
  fields: [{
119
150
  key: "apiKey",
120
- label: "OpenAI API Key",
151
+ label: "Paste your OpenAI API Key",
121
152
  placeholder: "sk-..."
122
153
  }]
123
154
  },
@@ -125,12 +156,15 @@ var SERVICES = {
125
156
  key: "stripe",
126
157
  name: "Stripe",
127
158
  description: "Payment processing",
128
- whyNeeded: "Optional. Only needed if your app accepts payments.",
159
+ whyNeeded: "Optional. Only if your app accepts payments.",
129
160
  url: "https://dashboard.stripe.com/apikeys",
130
- urlDescription: "Copy your Secret key (sk_live or sk_test)",
161
+ steps: [
162
+ "Log in to Stripe",
163
+ "Copy your Secret key (starts with sk_)"
164
+ ],
131
165
  fields: [{
132
166
  key: "secretKey",
133
- label: "Stripe Secret Key",
167
+ label: "Paste your Stripe Secret Key",
134
168
  placeholder: "sk_live_... or sk_test_..."
135
169
  }]
136
170
  },
@@ -138,9 +172,13 @@ var SERVICES = {
138
172
  key: "twilio",
139
173
  name: "Twilio",
140
174
  description: "SMS, voice calls, WhatsApp",
141
- whyNeeded: "Optional. Only needed if your app sends SMS or makes calls.",
175
+ whyNeeded: "Optional. Only if your app sends SMS or makes calls.",
142
176
  url: "https://console.twilio.com/",
143
- urlDescription: "Find Account SID and Auth Token on the dashboard",
177
+ steps: [
178
+ "Log in to Twilio",
179
+ "Find Account SID on the dashboard",
180
+ "Find Auth Token on the dashboard"
181
+ ],
144
182
  fields: [
145
183
  {
146
184
  key: "accountSid",
@@ -158,12 +196,16 @@ var SERVICES = {
158
196
  key: "resend",
159
197
  name: "Resend",
160
198
  description: "Email sending",
161
- whyNeeded: "Optional. Only needed if your app sends emails.",
199
+ whyNeeded: "Optional. Only if your app sends emails.",
162
200
  url: "https://resend.com/api-keys",
163
- urlDescription: "Create an API key",
201
+ steps: [
202
+ "Log in to Resend",
203
+ 'Click "Create API Key"',
204
+ "Copy the key"
205
+ ],
164
206
  fields: [{
165
207
  key: "apiKey",
166
- label: "Resend API Key",
208
+ label: "Paste your Resend API Key",
167
209
  placeholder: "re_..."
168
210
  }]
169
211
  },
@@ -171,12 +213,16 @@ var SERVICES = {
171
213
  key: "vapi",
172
214
  name: "VAPI",
173
215
  description: "Voice AI agents",
174
- whyNeeded: "Optional. Only needed if you're building voice agents.",
216
+ whyNeeded: "Optional. Only if you're building voice agents.",
175
217
  url: "https://dashboard.vapi.ai/",
176
- urlDescription: "Copy your API key from the dashboard",
218
+ steps: [
219
+ "Log in to VAPI",
220
+ "Go to Settings > API Keys",
221
+ "Copy your API key"
222
+ ],
177
223
  fields: [{
178
224
  key: "apiKey",
179
- label: "VAPI API Key",
225
+ label: "Paste your VAPI API Key",
180
226
  placeholder: "..."
181
227
  }]
182
228
  },
@@ -184,12 +230,16 @@ var SERVICES = {
184
230
  key: "elevenlabs",
185
231
  name: "ElevenLabs",
186
232
  description: "AI voice generation",
187
- whyNeeded: "Optional. Only needed if you want AI-generated voices.",
233
+ whyNeeded: "Optional. Only if you want AI-generated voices.",
188
234
  url: "https://elevenlabs.io/app/settings/api-keys",
189
- urlDescription: "Create an API key",
235
+ steps: [
236
+ "Log in to ElevenLabs",
237
+ 'Click "Create API Key"',
238
+ "Copy the key"
239
+ ],
190
240
  fields: [{
191
241
  key: "apiKey",
192
- label: "ElevenLabs API Key",
242
+ label: "Paste your ElevenLabs API Key",
193
243
  placeholder: "..."
194
244
  }]
195
245
  }
@@ -198,173 +248,210 @@ var CORE_SERVICES = ["anthropic", "github", "vercel", "supabase"];
198
248
  var OPTIONAL_SERVICES = ["openai", "stripe", "twilio", "resend", "vapi", "elevenlabs"];
199
249
  async function setupCommand() {
200
250
  const config = new Config();
201
- p.intro(chalk2.bgCyan.black(" CodeBakers Setup "));
202
- if (config.isConfigured()) {
203
- const action = await p.select({
204
- message: "CodeBakers is already configured. What do you want to do?",
205
- options: [
206
- { value: "view", label: "\u{1F440} View connected services" },
207
- { value: "add", label: "\u2795 Add another service" },
208
- { value: "update", label: "\u{1F504} Update a service" },
209
- { value: "reset", label: "\u{1F5D1}\uFE0F Reset all configuration" },
210
- { value: "back", label: "\u2190 Back" }
211
- ]
251
+ const hasAnthropic = !!config.getCredentials("anthropic")?.apiKey;
252
+ if (hasAnthropic) {
253
+ await showManagementMenu(config);
254
+ return;
255
+ }
256
+ console.log(boxen(
257
+ chalk2.bold.cyan("Welcome to CodeBakers Setup!\n\n") + chalk2.white("We need to connect a few services to get started.\n\n") + chalk2.dim("Your credentials are stored locally on your computer\n") + chalk2.dim("in ~/.codebakers/ and never sent to our servers.\n\n") + chalk2.yellow("Required: ") + chalk2.white("Anthropic API key (for AI)\n") + chalk2.dim("Optional: GitHub, Vercel, Supabase (for full features)"),
258
+ { padding: 1, borderColor: "cyan", borderStyle: "round" }
259
+ ));
260
+ console.log(chalk2.bold.cyan("\n\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501"));
261
+ console.log(chalk2.bold.cyan(" STEP 1 of 4: Anthropic API Key (Required)"));
262
+ console.log(chalk2.bold.cyan("\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\n"));
263
+ console.log(chalk2.white(" Anthropic (Claude)"));
264
+ console.log(chalk2.dim(" Powers the AI coding agent\n"));
265
+ const hasAccount = await p.select({
266
+ message: "Do you have an Anthropic account?",
267
+ options: [
268
+ { value: "yes", label: "\u2713 Yes, I have an API key ready" },
269
+ { value: "no", label: "\u2717 No, I need to sign up (free)" }
270
+ ]
271
+ });
272
+ if (p.isCancel(hasAccount)) {
273
+ return;
274
+ }
275
+ if (hasAccount === "no") {
276
+ console.log(chalk2.yellow("\n No problem! Let's get you signed up.\n"));
277
+ console.log(chalk2.white(" Steps:"));
278
+ console.log(chalk2.cyan(" 1. ") + 'Click "Sign Up" on the page that opens');
279
+ console.log(chalk2.cyan(" 2. ") + "Create your account (email + password)");
280
+ console.log(chalk2.cyan(" 3. ") + "Once logged in, go to Settings \u2192 API Keys");
281
+ console.log(chalk2.cyan(" 4. ") + 'Click "Create Key"');
282
+ console.log(chalk2.cyan(" 5. ") + "Copy the key and paste it here\n");
283
+ const openSignup = await p.confirm({
284
+ message: "Open Anthropic signup page?",
285
+ initialValue: true
212
286
  });
213
- if (p.isCancel(action) || action === "back") {
214
- return;
287
+ if (openSignup && !p.isCancel(openSignup)) {
288
+ await open("https://console.anthropic.com/");
289
+ console.log(chalk2.dim("\n Take your time - come back when you have your API key.\n"));
215
290
  }
216
- switch (action) {
217
- case "view":
218
- showConnectedServices(config);
219
- return;
220
- case "add":
221
- await addService(config);
222
- return;
223
- case "update":
224
- await updateService(config);
225
- return;
226
- case "reset":
227
- await resetConfig(config);
228
- return;
291
+ } else {
292
+ console.log(chalk2.bold.white("\n Here's what to do:\n"));
293
+ console.log(chalk2.cyan(" 1. ") + "Log in to Anthropic Console");
294
+ console.log(chalk2.cyan(" 2. ") + "Go to Settings \u2192 API Keys");
295
+ console.log(chalk2.cyan(" 3. ") + 'Click "Create Key"');
296
+ console.log(chalk2.cyan(" 4. ") + "Copy the key (starts with sk-ant-)");
297
+ console.log("");
298
+ const openBrowser = await p.confirm({
299
+ message: "Open Anthropic Console?",
300
+ initialValue: true
301
+ });
302
+ if (openBrowser && !p.isCancel(openBrowser)) {
303
+ await open("https://console.anthropic.com/settings/keys");
229
304
  }
230
305
  }
231
- console.log(chalk2.cyan(`
232
- Welcome to CodeBakers! Let's connect your services.
233
-
234
- ${chalk2.dim("Your credentials are stored locally in ~/.codebakers/")}
235
- ${chalk2.dim("and are never sent to our servers.")}
236
-
237
- ${chalk2.bold("Core Services (Recommended):")}
238
- ${chalk2.dim("These power the main CodeBakers features.")}
239
-
240
- `));
241
- let skippedCore = [];
242
- for (const serviceKey of CORE_SERVICES) {
243
- const service = SERVICES[serviceKey];
244
- const connected = await connectService(config, service);
245
- if (!connected) {
246
- skippedCore.push(service.name);
306
+ console.log("");
307
+ const apiKey = await p.text({
308
+ message: "Paste your Anthropic API Key:",
309
+ placeholder: "sk-ant-...",
310
+ validate: (v) => {
311
+ if (!v) return "API key is required";
312
+ if (!v.startsWith("sk-ant-")) return "Should start with sk-ant-";
313
+ return void 0;
247
314
  }
248
- }
249
- if (skippedCore.length > 0) {
250
- console.log(chalk2.yellow(`
251
- \u26A0\uFE0F You skipped: ${skippedCore.join(", ")}
252
-
253
- Some features won't work without these services.
254
- Run ${chalk2.bold("codebakers setup")} anytime to add them.
255
- `));
256
- }
257
- const addOptional = await p.confirm({
258
- message: "Add optional services? (Stripe, Twilio, Resend, etc.)",
259
- initialValue: false
260
315
  });
261
- if (addOptional && !p.isCancel(addOptional)) {
262
- const selected = await p.multiselect({
263
- message: "Select services to add:",
264
- options: OPTIONAL_SERVICES.map((key) => ({
265
- value: key,
266
- label: `${SERVICES[key].name} - ${SERVICES[key].description}`
267
- })),
268
- required: false
269
- });
270
- if (!p.isCancel(selected) && Array.isArray(selected)) {
271
- for (const serviceKey of selected) {
272
- await connectService(config, SERVICES[serviceKey]);
273
- }
274
- }
316
+ if (p.isCancel(apiKey) || !apiKey) {
317
+ console.log(chalk2.red("\n \u274C Anthropic API key is required to use CodeBakers."));
318
+ console.log(chalk2.dim(" Run `codebakers setup` when you're ready to try again.\n"));
319
+ return;
275
320
  }
276
- const connectedCount = [...CORE_SERVICES, ...OPTIONAL_SERVICES].filter(
277
- (key) => config.getCredentials(key)
278
- ).length;
279
- p.outro(chalk2.green(`
280
- \u2713 Setup complete! ${connectedCount} services connected.
281
-
282
- Run ${chalk2.bold("codebakers")} to get started.
321
+ config.setCredentials("anthropic", { apiKey });
322
+ console.log(chalk2.green("\n \u2713 Anthropic connected successfully!\n"));
323
+ console.log(chalk2.bold.cyan("\n\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501"));
324
+ console.log(chalk2.bold.cyan(" STEP 2 of 4: GitHub Token (Recommended)"));
325
+ console.log(chalk2.bold.cyan("\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\n"));
326
+ await connectServiceWithInstructions(config, SERVICES.github, false);
327
+ console.log(chalk2.bold.cyan("\n\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501"));
328
+ console.log(chalk2.bold.cyan(" STEP 3 of 4: Vercel Token (Recommended)"));
329
+ console.log(chalk2.bold.cyan("\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\n"));
330
+ await connectServiceWithInstructions(config, SERVICES.vercel, false);
331
+ console.log(chalk2.bold.cyan("\n\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501"));
332
+ console.log(chalk2.bold.cyan(" STEP 4 of 4: Supabase Token (Optional)"));
333
+ console.log(chalk2.bold.cyan("\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\n"));
334
+ await connectServiceWithInstructions(config, SERVICES.supabase, false);
335
+ const connectedServices = CORE_SERVICES.filter((key) => config.getCredentials(key)).map((key) => SERVICES[key].name);
336
+ console.log(boxen(
337
+ chalk2.bold.green("\u2713 Setup Complete!\n\n") + chalk2.white("Connected: ") + chalk2.cyan(connectedServices.join(", ")) + "\n\n" + chalk2.bold.white("What to do next:\n\n") + chalk2.cyan("1. ") + chalk2.white("Open a terminal and navigate to where you want to build:\n") + chalk2.dim(" cd C:\\dev\\my-project\n") + chalk2.dim(" (or any folder where you want to create your project)\n\n") + chalk2.cyan("2. ") + chalk2.white("Run CodeBakers:\n") + chalk2.dim(" codebakers\n\n") + chalk2.bold.white("Or try these commands directly:\n\n") + chalk2.dim(" codebakers website ") + chalk2.white("Build a website by describing it\n") + chalk2.dim(" codebakers init ") + chalk2.white("Create a new project from scratch\n") + chalk2.dim(" codebakers help ") + chalk2.white("See all available commands"),
338
+ { padding: 1, borderColor: "green", borderStyle: "round" }
339
+ ));
340
+ }
341
+ async function connectServiceWithInstructions(config, service, required) {
342
+ console.log(chalk2.white(` ${service.name}`));
343
+ console.log(chalk2.dim(` ${service.description}
283
344
  `));
284
- }
285
- async function connectService(config, service) {
286
- console.log("");
287
- console.log(chalk2.bold(` ${service.name}`));
288
- console.log(chalk2.dim(` ${service.description}`));
289
- console.log("");
345
+ if (!required) {
346
+ console.log(chalk2.yellow(` ${service.whyNeeded}
347
+ `));
348
+ }
290
349
  const action = await p.select({
291
350
  message: `Connect ${service.name}?`,
292
- options: [
293
- { value: "connect", label: "\u2713 Yes, connect now" },
294
- { value: "skip", label: "\u2192 Skip for now" },
295
- { value: "why", label: "? Why do I need this?" }
351
+ options: required ? [
352
+ { value: "connect", label: "\u2713 Yes, let's connect it" }
353
+ ] : [
354
+ { value: "connect", label: "\u2713 Yes, connect it" },
355
+ { value: "skip", label: "\u2192 Skip for now" }
296
356
  ]
297
357
  });
298
- if (p.isCancel(action)) return false;
299
- if (action === "why") {
300
- console.log(chalk2.yellow(`
301
- ${service.whyNeeded}
358
+ if (p.isCancel(action) || action === "skip") {
359
+ if (!required) {
360
+ console.log(chalk2.dim(`
361
+ Skipped ${service.name}. You can add it later with: codebakers setup
302
362
  `));
303
- const proceed = await p.confirm({
304
- message: `Connect ${service.name}?`,
305
- initialValue: true
306
- });
307
- if (!proceed || p.isCancel(proceed)) {
308
- console.log(chalk2.dim(` Skipped ${service.name}`));
309
- return false;
310
363
  }
311
- } else if (action === "skip") {
312
- console.log(chalk2.dim(` Skipped ${service.name}`));
313
- console.log(chalk2.dim(` ${service.whyNeeded}`));
314
364
  return false;
315
365
  }
366
+ console.log(chalk2.bold.white("\n Here's what to do:\n"));
367
+ service.steps.forEach((step, i) => {
368
+ console.log(chalk2.cyan(` ${i + 1}. `) + chalk2.white(step));
369
+ });
370
+ console.log("");
316
371
  const openBrowser = await p.confirm({
317
- message: "Open browser to get credentials?",
372
+ message: "Open the website in your browser?",
318
373
  initialValue: true
319
374
  });
320
375
  if (openBrowser && !p.isCancel(openBrowser)) {
321
376
  console.log(chalk2.dim(`
322
- Opening: ${service.url}`));
323
- console.log(chalk2.dim(` ${service.urlDescription}
377
+ Opening: ${service.url}
324
378
  `));
325
379
  await open(service.url);
380
+ console.log(chalk2.dim(" Complete the steps above, then paste your key below.\n"));
326
381
  }
327
382
  const credentials = {};
328
383
  for (const field of service.fields) {
329
384
  const value = await p.text({
330
- message: `${field.label}:`,
385
+ message: field.label + (field.hint ? chalk2.dim(` (${field.hint})`) : "") + ":",
331
386
  placeholder: field.placeholder,
332
387
  validate: field.validate
333
388
  });
334
389
  if (p.isCancel(value)) return false;
335
390
  if (!value) {
336
- console.log(chalk2.dim(` Skipped ${service.name} (no ${field.label} provided)`));
391
+ if (required) {
392
+ console.log(chalk2.red(`
393
+ ${field.label} is required.
394
+ `));
395
+ return false;
396
+ }
397
+ console.log(chalk2.dim(`
398
+ Skipped ${service.name}.
399
+ `));
337
400
  return false;
338
401
  }
339
402
  credentials[field.key] = value;
340
403
  }
341
404
  config.setCredentials(service.key, credentials);
342
- console.log(chalk2.green(` \u2713 ${service.name} connected!`));
405
+ console.log(chalk2.green(`
406
+ \u2713 ${service.name} connected successfully!
407
+ `));
343
408
  return true;
344
409
  }
345
- function showConnectedServices(config) {
346
- console.log(chalk2.bold("\n Connected Services:\n"));
410
+ async function showManagementMenu(config) {
411
+ console.log(chalk2.bold.cyan("\n CodeBakers Settings\n"));
347
412
  const allServices = [...CORE_SERVICES, ...OPTIONAL_SERVICES];
348
- let connectedCount = 0;
349
- for (const key of allServices) {
350
- const service = SERVICES[key];
351
- const creds = config.getCredentials(key);
352
- if (creds) {
353
- console.log(chalk2.green(` \u2713 ${service.name}`));
354
- connectedCount++;
355
- } else {
356
- console.log(chalk2.dim(` \u25CB ${service.name} (not connected)`));
357
- }
413
+ const connected = allServices.filter((key) => config.getCredentials(key));
414
+ const notConnected = allServices.filter((key) => !config.getCredentials(key));
415
+ console.log(chalk2.green(" Connected:"));
416
+ connected.forEach((key) => {
417
+ console.log(chalk2.green(` \u2713 ${SERVICES[key].name}`));
418
+ });
419
+ if (notConnected.length > 0) {
420
+ console.log(chalk2.dim("\n Not connected:"));
421
+ notConnected.forEach((key) => {
422
+ console.log(chalk2.dim(` \u25CB ${SERVICES[key].name}`));
423
+ });
424
+ }
425
+ console.log("");
426
+ const action = await p.select({
427
+ message: "What would you like to do?",
428
+ options: [
429
+ { value: "add", label: "\u2795 Add a service" },
430
+ { value: "update", label: "\u{1F504} Update a service" },
431
+ { value: "reset", label: "\u{1F5D1}\uFE0F Reset all settings" },
432
+ { value: "back", label: "\u2190 Back" }
433
+ ]
434
+ });
435
+ if (p.isCancel(action) || action === "back") {
436
+ return;
437
+ }
438
+ switch (action) {
439
+ case "add":
440
+ await addService(config);
441
+ break;
442
+ case "update":
443
+ await updateService(config);
444
+ break;
445
+ case "reset":
446
+ await resetConfig(config);
447
+ break;
358
448
  }
359
- console.log(chalk2.dim(`
360
- ${connectedCount}/${allServices.length} services connected
361
- `));
362
449
  }
363
450
  async function addService(config) {
364
451
  const allServices = [...CORE_SERVICES, ...OPTIONAL_SERVICES];
365
452
  const unconnected = allServices.filter((key) => !config.getCredentials(key));
366
453
  if (unconnected.length === 0) {
367
- p.log.info("All services are already connected!");
454
+ console.log(chalk2.green("\n All services are already connected!\n"));
368
455
  return;
369
456
  }
370
457
  const selected = await p.select({
@@ -375,13 +462,13 @@ async function addService(config) {
375
462
  }))
376
463
  });
377
464
  if (p.isCancel(selected)) return;
378
- await connectService(config, SERVICES[selected]);
465
+ await connectServiceWithInstructions(config, SERVICES[selected], false);
379
466
  }
380
467
  async function updateService(config) {
381
468
  const allServices = [...CORE_SERVICES, ...OPTIONAL_SERVICES];
382
469
  const connected = allServices.filter((key) => config.getCredentials(key));
383
470
  if (connected.length === 0) {
384
- p.log.info("No services connected yet. Run setup first.");
471
+ console.log(chalk2.yellow("\n No services connected yet.\n"));
385
472
  return;
386
473
  }
387
474
  const selected = await p.select({
@@ -392,19 +479,24 @@ async function updateService(config) {
392
479
  }))
393
480
  });
394
481
  if (p.isCancel(selected)) return;
395
- await connectService(config, SERVICES[selected]);
482
+ await connectServiceWithInstructions(config, SERVICES[selected], false);
396
483
  }
397
484
  async function resetConfig(config) {
485
+ console.log(chalk2.yellow("\n \u26A0\uFE0F This will remove ALL your saved API keys.\n"));
398
486
  const confirm13 = await p.confirm({
399
- message: "Are you sure? This will remove ALL credentials.",
487
+ message: "Are you sure?",
400
488
  initialValue: false
401
489
  });
402
- if (!confirm13 || p.isCancel(confirm13)) return;
490
+ if (!confirm13 || p.isCancel(confirm13)) {
491
+ console.log(chalk2.dim("\n Cancelled.\n"));
492
+ return;
493
+ }
403
494
  const allServices = [...CORE_SERVICES, ...OPTIONAL_SERVICES];
404
495
  for (const key of allServices) {
405
496
  config.setCredentials(key, null);
406
497
  }
407
- p.log.success("Configuration reset. Run `codebakers setup` to reconfigure.");
498
+ console.log(chalk2.green("\n \u2713 All settings reset.\n"));
499
+ console.log(chalk2.dim(" Run `codebakers setup` to configure again.\n"));
408
500
  }
409
501
 
410
502
  // src/commands/init.ts
@@ -7538,73 +7630,9 @@ If unclear between multiple commands, use the most likely one with lower confide
7538
7630
  }
7539
7631
  return JSON.parse(jsonMatch[0]);
7540
7632
  }
7541
- async function clarifyCommand(parsed) {
7542
- if (parsed.confidence >= 0.8) {
7543
- return parsed;
7544
- }
7545
- if (parsed.confidence >= 0.5) {
7546
- const confirm13 = await p20.confirm({
7547
- message: `Did you mean: ${parsed.interpretation}?`,
7548
- initialValue: true
7549
- });
7550
- if (confirm13 && !p20.isCancel(confirm13)) {
7551
- return { ...parsed, confidence: 1 };
7552
- }
7553
- }
7554
- const options = [
7555
- { value: "init", label: "\u{1F195} Create new project", description: "Start a fresh project" },
7556
- { value: "build", label: "\u{1F3D7}\uFE0F Build from PRD", description: "Parallel build from document" },
7557
- { value: "code", label: "\u{1F4AC} AI Coding", description: "Get help writing code" },
7558
- { value: "check", label: "\u{1F50D} Check code", description: "Lint and validate" },
7559
- { value: "deploy", label: "\u{1F680} Deploy", description: "Push to production" },
7560
- { value: "fix", label: "\u{1F527} Fix errors", description: "Auto-fix issues" },
7561
- { value: "advisors", label: "\u{1F31F} Dream Team", description: "Get expert advice" },
7562
- { value: "prd-maker", label: "\u{1F4DD} Create PRD", description: "Document your idea" },
7563
- { value: "other", label: "\u2753 Something else", description: "Describe what you need" }
7564
- ];
7565
- const selection = await p20.select({
7566
- message: "What would you like to do?",
7567
- options: options.map((o) => ({ value: o.value, label: o.label, hint: o.description }))
7568
- });
7569
- if (p20.isCancel(selection)) {
7570
- return { ...parsed, command: "cancel", confidence: 1 };
7571
- }
7572
- if (selection === "other") {
7573
- const description = await p20.text({
7574
- message: "Describe what you want to do:",
7575
- placeholder: "I want to..."
7576
- });
7577
- if (p20.isCancel(description)) {
7578
- return { ...parsed, command: "cancel", confidence: 1 };
7579
- }
7580
- return {
7581
- command: "code",
7582
- args: [description],
7583
- confidence: 1,
7584
- interpretation: description
7585
- };
7586
- }
7587
- return {
7588
- command: selection,
7589
- args: parsed.args,
7590
- confidence: 1,
7591
- interpretation: options.find((o) => o.value === selection)?.description || ""
7592
- };
7593
- }
7594
- async function clarifyDeployTarget() {
7595
- const target = await p20.select({
7596
- message: "Where do you want to deploy?",
7597
- options: [
7598
- { value: "preview", label: "\u{1F50D} Preview", hint: "Test URL to review changes" },
7599
- { value: "production", label: "\u{1F680} Production", hint: "Live site for users" }
7600
- ]
7601
- });
7602
- if (p20.isCancel(target)) return null;
7603
- return target;
7604
- }
7605
7633
 
7606
7634
  // src/index.ts
7607
- var VERSION2 = "2.2.2";
7635
+ var VERSION2 = "2.3.4";
7608
7636
  var logo = `
7609
7637
  \u2588\u2588\u2588\u2588\u2588\u2588\u2557 \u2588\u2588\u2588\u2588\u2588\u2588\u2557 \u2588\u2588\u2588\u2588\u2588\u2588\u2557 \u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2557\u2588\u2588\u2588\u2588\u2588\u2588\u2557 \u2588\u2588\u2588\u2588\u2588\u2557 \u2588\u2588\u2557 \u2588\u2588\u2557\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2557\u2588\u2588\u2588\u2588\u2588\u2588\u2557 \u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2557
7610
7638
  \u2588\u2588\u2554\u2550\u2550\u2550\u2550\u255D\u2588\u2588\u2554\u2550\u2550\u2550\u2588\u2588\u2557\u2588\u2588\u2554\u2550\u2550\u2588\u2588\u2557\u2588\u2588\u2554\u2550\u2550\u2550\u2550\u255D\u2588\u2588\u2554\u2550\u2550\u2588\u2588\u2557\u2588\u2588\u2554\u2550\u2550\u2588\u2588\u2557\u2588\u2588\u2551 \u2588\u2588\u2554\u255D\u2588\u2588\u2554\u2550\u2550\u2550\u2550\u255D\u2588\u2588\u2554\u2550\u2550\u2588\u2588\u2557\u2588\u2588\u2554\u2550\u2550\u2550\u2550\u255D
@@ -7615,94 +7643,142 @@ var logo = `
7615
7643
  `;
7616
7644
  async function showMainMenu() {
7617
7645
  const config = new Config();
7618
- const isSetup = config.isConfigured();
7619
7646
  console.log(gradient.pastel.multiline(logo));
7620
7647
  console.log(chalk21.dim(` v${VERSION2} \u2014 AI dev team that follows the rules
7621
7648
  `));
7622
- if (!isSetup) {
7623
- console.log(boxen(
7624
- chalk21.yellow("Welcome to CodeBakers! Let's get you set up."),
7649
+ const hasAnthropic = !!config.getCredentials("anthropic")?.apiKey;
7650
+ if (!hasAnthropic) {
7651
+ console.log(boxen2(
7652
+ chalk21.yellow("Welcome to CodeBakers!\n\n") + chalk21.white("Let's connect your Anthropic API key so the AI can work.\n") + chalk21.dim("(Takes about 1 minute)"),
7625
7653
  { padding: 1, borderColor: "yellow", borderStyle: "round" }
7626
7654
  ));
7627
7655
  await setupCommand();
7656
+ showPostSetupInstructions();
7628
7657
  return;
7629
7658
  }
7630
7659
  const inProject = config.isInProject();
7631
- const menuOptions = [];
7632
- menuOptions.push({ value: "new", label: "\u{1F195} Create new project" });
7633
- menuOptions.push({ value: "website", label: "\u{1F310} Website Builder", hint: "Describe \u2192 AI builds it" });
7634
- menuOptions.push({ value: "build", label: "\u{1F3D7}\uFE0F Parallel Build", hint: "3 agents from PRD" });
7635
- menuOptions.push({ value: "prd", label: "\u{1F4C4} Build from PRD", hint: "sequential build" });
7636
- menuOptions.push({ value: "prd-maker", label: "\u270F\uFE0F Create PRD", hint: "interview \u2192 generate PRD" });
7637
- menuOptions.push({ value: "advisors", label: "\u{1F31F} Dream Team Advisors", hint: "consult with experts" });
7638
- if (inProject) {
7639
- menuOptions.push({ value: "separator1", label: "\u2500\u2500\u2500\u2500\u2500 Current Project \u2500\u2500\u2500\u2500\u2500" });
7640
- menuOptions.push({ value: "code", label: "\u{1F4AC} Code with AI", hint: "build features, fix bugs" });
7641
- menuOptions.push({ value: "check", label: "\u{1F50D} Check code quality", hint: "run pattern enforcement" });
7642
- menuOptions.push({ value: "deploy", label: "\u{1F680} Deploy", hint: "deploy to Vercel" });
7643
- menuOptions.push({ value: "fix", label: "\u{1F527} Fix errors", hint: "auto-fix with AI" });
7644
- menuOptions.push({ value: "generate", label: "\u26A1 Generate", hint: "scaffold components, pages" });
7645
- menuOptions.push({ value: "migrate", label: "\u{1F5C4}\uFE0F Database migrations", hint: "push, generate, status" });
7646
- }
7647
- menuOptions.push({ value: "separator2", label: "\u2500\u2500\u2500\u2500\u2500 Tools & Settings \u2500\u2500\u2500\u2500\u2500" });
7648
- menuOptions.push({ value: "integrate", label: "\u{1F50C} One-Click Integrations", hint: "50+ services" });
7649
- menuOptions.push({ value: "gateway", label: "\u{1F4F1} Channel gateway", hint: "WhatsApp, Telegram, etc." });
7650
- menuOptions.push({ value: "connect", label: "\u{1F517} Connect service", hint: "API keys" });
7651
- menuOptions.push({ value: "settings", label: "\u2699\uFE0F Settings" });
7652
- menuOptions.push({ value: "help", label: "\u2753 Help" });
7653
- const action = await p21.select({
7654
- message: "What do you want to do?",
7655
- options: menuOptions
7656
- });
7657
- if (p21.isCancel(action)) {
7658
- p21.cancel("Goodbye!");
7659
- process.exit(0);
7660
+ const projectConfig = config.getProjectConfig();
7661
+ const cwd = process.cwd();
7662
+ const folderName = path16.basename(cwd);
7663
+ if (inProject && projectConfig) {
7664
+ const framework = projectConfig.framework || "detected";
7665
+ console.log(chalk21.cyan(` \u{1F4C1} Working in: ${chalk21.bold(folderName)}`));
7666
+ console.log(chalk21.dim(` ${framework} project
7667
+ `));
7668
+ await showProjectMenu(config);
7669
+ } else {
7670
+ console.log(chalk21.cyan(` \u{1F4C1} Current folder: ${chalk21.bold(cwd)}`));
7671
+ console.log(chalk21.dim(` Not a project folder
7672
+ `));
7673
+ await showStartMenu(config);
7674
+ }
7675
+ }
7676
+ async function showStartMenu(config) {
7677
+ while (true) {
7678
+ const action = await p21.select({
7679
+ message: "What would you like to do?",
7680
+ options: [
7681
+ { value: "website", label: "\u{1F310} Build a website", hint: "Describe it \u2192 AI builds it" },
7682
+ { value: "new", label: "\u{1F195} Create new project", hint: "Start fresh with Next.js, React, etc." },
7683
+ { value: "prd-maker", label: "\u270F\uFE0F Create a PRD", hint: "Plan your project first" },
7684
+ { value: "build", label: "\u{1F3D7}\uFE0F Build from PRD", hint: "Have a PRD file? Build it now" },
7685
+ { value: "advisors", label: "\u{1F31F} Consult advisors", hint: "Get advice from AI experts" },
7686
+ { value: "divider1", label: chalk21.dim("\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") },
7687
+ { value: "integrate", label: "\u{1F50C} Add integration", hint: "Stripe, Supabase, Twilio, etc." },
7688
+ { value: "settings", label: "\u2699\uFE0F Settings", hint: "API keys & preferences" },
7689
+ { value: "help", label: "\u2753 Help", hint: "Learn how to use CodeBakers" },
7690
+ { value: "divider2", label: chalk21.dim("\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") },
7691
+ { value: "exit", label: "\u{1F6AA} Return to terminal", hint: "Exit CodeBakers" }
7692
+ ]
7693
+ });
7694
+ if (p21.isCancel(action) || action === "exit") {
7695
+ console.log("");
7696
+ console.log(chalk21.cyan(" \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"));
7697
+ console.log(chalk21.white(" You're back in the terminal."));
7698
+ console.log("");
7699
+ console.log(chalk21.dim(" To start CodeBakers again, type:"));
7700
+ console.log(chalk21.green(" codebakers"));
7701
+ console.log("");
7702
+ console.log(chalk21.dim(" Quick commands you can run directly:"));
7703
+ console.log(chalk21.dim(" codebakers website") + chalk21.gray(" - Build a website"));
7704
+ console.log(chalk21.dim(" codebakers code") + chalk21.gray(" - Code with AI"));
7705
+ console.log(chalk21.dim(" codebakers help") + chalk21.gray(" - See all commands"));
7706
+ console.log(chalk21.cyan(" \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"));
7707
+ console.log("");
7708
+ process.exit(0);
7709
+ }
7710
+ if (action === "divider1" || action === "divider2") {
7711
+ continue;
7712
+ }
7713
+ await handleAction(action, config);
7714
+ }
7715
+ }
7716
+ async function showProjectMenu(config) {
7717
+ while (true) {
7718
+ const action = await p21.select({
7719
+ message: "What would you like to do?",
7720
+ options: [
7721
+ { value: "code", label: "\u{1F4AC} Code with AI", hint: "Ask AI to build features or fix bugs" },
7722
+ { value: "deploy", label: "\u{1F680} Deploy", hint: "Push your project live" },
7723
+ { value: "check", label: "\u{1F50D} Check code", hint: "Review quality & patterns" },
7724
+ { value: "fix", label: "\u{1F527} Fix errors", hint: "AI automatically fixes issues" },
7725
+ { value: "integrate", label: "\u{1F50C} Add integration", hint: "Stripe, Supabase, Twilio, etc." },
7726
+ { value: "generate", label: "\u26A1 Generate", hint: "Create components, pages, APIs" },
7727
+ { value: "divider1", label: chalk21.dim("\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") },
7728
+ { value: "new", label: "\u{1F195} Start new project", hint: "Create a different project" },
7729
+ { value: "settings", label: "\u2699\uFE0F Settings", hint: "API keys & preferences" },
7730
+ { value: "help", label: "\u2753 Help", hint: "Learn how to use CodeBakers" },
7731
+ { value: "divider2", label: chalk21.dim("\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") },
7732
+ { value: "exit", label: "\u{1F6AA} Return to terminal", hint: "Exit CodeBakers" }
7733
+ ]
7734
+ });
7735
+ if (p21.isCancel(action) || action === "exit") {
7736
+ console.log("");
7737
+ console.log(chalk21.cyan(" \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"));
7738
+ console.log(chalk21.white(" You're back in the terminal."));
7739
+ console.log("");
7740
+ console.log(chalk21.dim(" To start CodeBakers again, type:"));
7741
+ console.log(chalk21.green(" codebakers"));
7742
+ console.log("");
7743
+ console.log(chalk21.dim(" Quick commands you can run directly:"));
7744
+ console.log(chalk21.dim(" codebakers code") + chalk21.gray(" - Code with AI"));
7745
+ console.log(chalk21.dim(" codebakers deploy") + chalk21.gray(" - Deploy your project"));
7746
+ console.log(chalk21.dim(" codebakers help") + chalk21.gray(" - See all commands"));
7747
+ console.log(chalk21.cyan(" \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"));
7748
+ console.log("");
7749
+ process.exit(0);
7750
+ }
7751
+ if (action === "divider1" || action === "divider2") {
7752
+ continue;
7753
+ }
7754
+ await handleAction(action, config);
7660
7755
  }
7756
+ }
7757
+ async function handleAction(action, config) {
7661
7758
  switch (action) {
7759
+ case "website":
7760
+ await websiteCommand();
7761
+ break;
7762
+ case "new":
7763
+ await initCommand();
7764
+ break;
7662
7765
  case "code":
7663
7766
  await codeCommand();
7664
7767
  break;
7665
- case "integrate":
7666
- await integrateCommand();
7667
- break;
7668
7768
  case "check":
7669
7769
  await checkCommand();
7670
7770
  break;
7671
7771
  case "deploy":
7672
7772
  await deployCommand();
7673
7773
  break;
7674
- case "migrate":
7675
- await migrateCommand();
7676
- break;
7677
7774
  case "fix":
7678
7775
  await fixCommand();
7679
7776
  break;
7680
7777
  case "generate":
7681
7778
  await generateCommand();
7682
7779
  break;
7683
- case "status":
7684
- await statusCommand();
7685
- break;
7686
- case "connect":
7687
- await connectCommand();
7688
- break;
7689
- case "gateway":
7690
- await gatewayCommand();
7691
- break;
7692
- case "learn":
7693
- await learnCommand();
7694
- break;
7695
- case "security":
7696
- await securityCommand();
7697
- break;
7698
- case "design":
7699
- await designCommand();
7700
- break;
7701
- case "new":
7702
- await initCommand();
7703
- break;
7704
- case "website":
7705
- await websiteCommand();
7780
+ case "integrate":
7781
+ await integrateCommand();
7706
7782
  break;
7707
7783
  case "build":
7708
7784
  await buildCommand();
@@ -7716,6 +7792,12 @@ async function showMainMenu() {
7716
7792
  case "advisors":
7717
7793
  await advisorsCommand();
7718
7794
  break;
7795
+ case "gateway":
7796
+ await gatewayCommand();
7797
+ break;
7798
+ case "migrate":
7799
+ await migrateCommand();
7800
+ break;
7719
7801
  case "settings":
7720
7802
  await setupCommand();
7721
7803
  break;
@@ -7723,121 +7805,107 @@ async function showMainMenu() {
7723
7805
  showHelp2();
7724
7806
  break;
7725
7807
  default:
7726
- await showMainMenu();
7808
+ console.log(chalk21.yellow("Coming soon!"));
7727
7809
  }
7728
7810
  }
7811
+ function showPostSetupInstructions() {
7812
+ console.log(boxen2(
7813
+ chalk21.green.bold("\u2713 Setup complete!\n\n") + chalk21.white("What's next?\n\n") + chalk21.cyan("1. ") + "Navigate to where you want to build:\n" + chalk21.dim(" cd C:\\dev\\my-project\n\n") + chalk21.cyan("2. ") + "Run CodeBakers:\n" + chalk21.dim(" codebakers\n\n") + chalk21.white("Or build a website right now:\n") + chalk21.dim(" codebakers website"),
7814
+ { padding: 1, borderColor: "green", borderStyle: "round" }
7815
+ ));
7816
+ }
7817
+ function showPostBuildInstructions(projectName, projectPath) {
7818
+ const displayPath = projectPath || projectName;
7819
+ console.log(boxen2(
7820
+ chalk21.green.bold(`\u2713 ${projectName} created!
7821
+
7822
+ `) + chalk21.white("Next steps:\n\n") + chalk21.cyan("1. ") + "Go to your project:\n" + chalk21.dim(` cd ${displayPath}
7823
+
7824
+ `) + chalk21.cyan("2. ") + "Install dependencies:\n" + chalk21.dim(" npm install\n\n") + chalk21.cyan("3. ") + "Start the dev server:\n" + chalk21.dim(" npm run dev\n\n") + chalk21.cyan("4. ") + "Open in browser:\n" + chalk21.dim(" http://localhost:3000\n\n") + chalk21.white("Ready to deploy?\n") + chalk21.dim(" codebakers deploy"),
7825
+ { padding: 1, borderColor: "green", borderStyle: "round" }
7826
+ ));
7827
+ }
7729
7828
  function showHelp2() {
7730
- console.log(boxen(`
7829
+ console.log(boxen2(`
7731
7830
  ${chalk21.bold("CodeBakers CLI v" + VERSION2)} \u2014 AI dev team that follows the rules
7732
7831
 
7733
7832
  ${chalk21.bold.cyan("Getting Started:")}
7734
- ${chalk21.cyan("codebakers setup")} Connect your accounts (GitHub, Vercel, etc.)
7735
- ${chalk21.cyan("codebakers init")} Create a new project from scratch
7736
- ${chalk21.cyan("codebakers website")} Build a website by describing it
7737
- ${chalk21.cyan("codebakers build")} Build from PRD with parallel AI agents
7833
+ ${chalk21.cyan("codebakers")} Interactive menu
7834
+ ${chalk21.cyan("codebakers setup")} Connect API keys
7835
+ ${chalk21.cyan("codebakers website")} Build website by describing it
7836
+ ${chalk21.cyan("codebakers init")} Create new project
7738
7837
 
7739
- ${chalk21.bold.cyan("Daily Development:")}
7838
+ ${chalk21.bold.cyan("In a Project:")}
7740
7839
  ${chalk21.cyan("codebakers code")} Chat with AI to build features
7741
- ${chalk21.cyan("codebakers check")} Check code quality & patterns
7742
- ${chalk21.cyan("codebakers fix")} Auto-fix errors with AI
7743
7840
  ${chalk21.cyan("codebakers deploy")} Deploy to Vercel
7744
-
7745
- ${chalk21.bold.cyan("Integrations:")}
7746
- ${chalk21.cyan("codebakers integrate")} 50+ one-click integrations (Stripe, Supabase, etc.)
7747
- ${chalk21.cyan("codebakers gateway")} Connect WhatsApp, Telegram, Discord, etc.
7841
+ ${chalk21.cyan("codebakers check")} Check code quality
7842
+ ${chalk21.cyan("codebakers fix")} Auto-fix errors
7748
7843
 
7749
7844
  ${chalk21.bold.cyan("Planning:")}
7750
- ${chalk21.cyan("codebakers prd-maker")} Create PRD through interview (voice supported)
7751
- ${chalk21.cyan("codebakers advisors")} Consult AI experts (CEO, CTO, Designer, etc.)
7845
+ ${chalk21.cyan("codebakers prd-maker")} Create PRD through interview
7846
+ ${chalk21.cyan("codebakers build")} Build from PRD (parallel agents)
7847
+ ${chalk21.cyan("codebakers advisors")} Consult AI experts
7752
7848
 
7753
- ${chalk21.bold.cyan("Tips:")}
7754
- \u2022 Type naturally: ${chalk21.dim('codebakers "add a contact form"')}
7755
- \u2022 Voice input: Type ${chalk21.yellow('"v"')} at any prompt
7756
- \u2022 Clipboard: Type ${chalk21.yellow('"clip"')} to paste from clipboard
7849
+ ${chalk21.bold.cyan("Integrations:")}
7850
+ ${chalk21.cyan("codebakers integrate")} 50+ one-click integrations
7851
+ ${chalk21.cyan("codebakers gateway")} WhatsApp, Telegram, Discord
7757
7852
 
7758
7853
  ${chalk21.bold("Docs:")} ${chalk21.dim("https://codebakers.dev/docs")}
7759
7854
  `, { padding: 1, borderColor: "cyan", borderStyle: "round" }));
7760
7855
  }
7761
7856
  var program = new Command();
7762
7857
  program.name("codebakers").description("AI dev team that follows the rules").version(VERSION2).action(showMainMenu);
7763
- program.command("setup").description("Configure CodeBakers (first-time setup)").action(setupCommand);
7764
- program.command("init").description("Create a new project").option("-n, --name <name>", "Project name").option("-t, --template <template>", "Template (nextjs, voice-agent, saas)").option("--no-git", "Skip GitHub repo creation").option("--no-vercel", "Skip Vercel deployment").option("--no-supabase", "Skip Supabase setup").action(initCommand);
7765
- program.command("code [prompt]").description("Start AI coding session").option("-w, --watch", "Watch mode - continuous assistance").action(codeCommand);
7766
- program.command("check").description("Run CodeBakers pattern enforcement").option("-f, --fix", "Auto-fix violations").option("--watch", "Watch mode").action(checkCommand);
7767
- program.command("deploy").description("Deploy to production").option("-p, --preview", "Deploy to preview only").option("--no-check", "Skip pattern check").action(deployCommand);
7768
- program.command("fix").description("Auto-fix build and deployment errors").option("--auto", "Fix without asking").action(fixCommand);
7769
- program.command("generate <type>").alias("g").description("Generate components, pages, API routes").option("-n, --name <name>", "Name of the generated item").action(generateCommand);
7770
- program.command("connect [service]").description("Connect external services (Stripe, VAPI, etc.)").action(connectCommand);
7771
- program.command("gateway").description("Manage messaging channel gateway").option("--start", "Start the gateway").option("--stop", "Stop the gateway").option("--status", "Show gateway status").action(gatewayCommand);
7772
- program.command("status").description("View project status and health").option("-a, --all", "Show all projects").action(statusCommand);
7773
- program.command("security").description("Run security audit").option("--fix", "Auto-fix security issues").action(securityCommand);
7774
- 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);
7775
- program.command("design [action]").description("Manage design system (profile, palette, check)").action(designCommand);
7776
- program.command("prd [file]").description("Build entire project from a PRD document").action(prdCommand);
7777
- program.command("advisors").alias("dream-team").description("Consult with the CodeBakers Dream Team advisory board").action(advisorsCommand);
7778
- program.command("migrate").alias("db").description("Database migrations (push, generate, status)").option("--push", "Push migrations to database").option("--generate", "Generate new migration").option("--status", "Check migration status").action(migrateCommand);
7779
- program.command("prd-maker").alias("create-prd").description("Create a PRD through guided interview (supports voice input)").action(prdMakerCommand);
7780
- program.command("build [prd-file]").alias("swarm").description("Parallel build with 3 AI agents (self-healing)").option("--sequential", "Disable parallel execution").action(buildCommand);
7781
- program.command("integrate [integration]").alias("add").description("One-click integrations (50+ services with browser auth)").action(integrateCommand);
7782
- program.command("website").alias("site").description("Build a website by describing it in plain English").action(websiteCommand);
7858
+ program.command("setup").description("Configure CodeBakers (API keys)").action(setupCommand);
7859
+ program.command("init").description("Create a new project").option("-n, --name <n>", "Project name").option("-t, --template <t>", "Template").action(initCommand);
7860
+ program.command("code [prompt]").description("Start AI coding session").option("-w, --watch", "Watch mode").action(codeCommand);
7861
+ program.command("check").description("Run code quality checks").action(checkCommand);
7862
+ program.command("deploy").description("Deploy to production").option("-p, --preview", "Preview deployment").option("--no-check", "Skip quality check").action(deployCommand);
7863
+ program.command("fix").description("Auto-fix errors with AI").action(fixCommand);
7864
+ program.command("generate").alias("gen").description("Generate components, pages, etc.").action(generateCommand);
7865
+ program.command("status").description("View project status").action(statusCommand);
7866
+ program.command("connect").description("Connect external services").action(connectCommand);
7867
+ program.command("gateway").description("Manage messaging channels (WhatsApp, Telegram, etc.)").option("--start", "Start gateway").option("--stop", "Stop gateway").option("--status", "Show status").action(gatewayCommand);
7868
+ program.command("security").description("Run security audit").action(securityCommand);
7869
+ program.command("learn").description("View/manage what CodeBakers has learned").action(learnCommand);
7870
+ program.command("design").description("Manage design system").action(designCommand);
7871
+ program.command("prd [file]").description("Build project from PRD").action(prdCommand);
7872
+ program.command("advisors").alias("dream-team").description("Consult AI expert advisors").action(advisorsCommand);
7873
+ program.command("migrate").alias("db").description("Database migrations").option("--push", "Push migrations").option("--generate", "Generate migration").option("--status", "Check status").action(migrateCommand);
7874
+ program.command("prd-maker").alias("create-prd").description("Create PRD through guided interview").action(prdMakerCommand);
7875
+ program.command("build [prd-file]").alias("swarm").description("Parallel build with AI agents").option("--sequential", "Disable parallel").action(buildCommand);
7876
+ program.command("integrate [integration]").alias("add").description("One-click integrations (50+ services)").action(integrateCommand);
7877
+ program.command("website").alias("site").description("Build website by describing it").action(websiteCommand);
7878
+ program.command("help").description("Show help").action(showHelp2);
7783
7879
  async function handleNaturalLanguage(input) {
7784
7880
  const config = new Config();
7785
- console.log(chalk21.dim("\n Parsing your request...\n"));
7881
+ console.log(chalk21.dim("\n Understanding your request...\n"));
7786
7882
  const parsed = await parseNaturalLanguage(input, config);
7787
7883
  if (!parsed) {
7788
7884
  await codeCommand(input);
7789
7885
  return;
7790
7886
  }
7791
- const clarified = await clarifyCommand(parsed);
7792
- if (clarified.command === "cancel") {
7793
- return;
7794
- }
7795
- switch (clarified.command) {
7796
- case "init":
7797
- await initCommand();
7887
+ switch (parsed.command) {
7888
+ case "deploy":
7889
+ await deployCommand();
7798
7890
  break;
7799
7891
  case "build":
7800
- await buildCommand(clarified.args[0]);
7892
+ await buildCommand();
7801
7893
  break;
7802
7894
  case "code":
7803
- await codeCommand(clarified.args.join(" "));
7895
+ await codeCommand(input);
7896
+ break;
7897
+ case "init":
7898
+ await initCommand();
7899
+ break;
7900
+ case "website":
7901
+ await websiteCommand();
7804
7902
  break;
7805
7903
  case "check":
7806
7904
  await checkCommand();
7807
7905
  break;
7808
- case "deploy":
7809
- const target = await clarifyDeployTarget();
7810
- if (target) {
7811
- await deployCommand({ preview: target === "preview" });
7812
- }
7813
- break;
7814
7906
  case "fix":
7815
7907
  await fixCommand();
7816
7908
  break;
7817
- case "migrate":
7818
- await migrateCommand();
7819
- break;
7820
- case "design":
7821
- await designCommand();
7822
- break;
7823
- case "advisors":
7824
- await advisorsCommand();
7825
- break;
7826
- case "prd-maker":
7827
- await prdMakerCommand();
7828
- break;
7829
- case "security":
7830
- await securityCommand();
7831
- break;
7832
- case "status":
7833
- await statusCommand();
7834
- break;
7835
- case "setup":
7836
- await setupCommand();
7837
- break;
7838
- case "help":
7839
- showHelp2();
7840
- break;
7841
7909
  default:
7842
7910
  await codeCommand(input);
7843
7911
  }
@@ -7856,6 +7924,7 @@ if (args.length === 0) {
7856
7924
  "deploy",
7857
7925
  "fix",
7858
7926
  "generate",
7927
+ "gen",
7859
7928
  "connect",
7860
7929
  "status",
7861
7930
  "gateway",
@@ -7864,8 +7933,11 @@ if (args.length === 0) {
7864
7933
  "design",
7865
7934
  "prd",
7866
7935
  "advisors",
7936
+ "dream-team",
7867
7937
  "migrate",
7938
+ "db",
7868
7939
  "prd-maker",
7940
+ "create-prd",
7869
7941
  "build",
7870
7942
  "swarm",
7871
7943
  "integrate",
@@ -7886,3 +7958,6 @@ if (args.length === 0) {
7886
7958
  } else {
7887
7959
  program.parse();
7888
7960
  }
7961
+ export {
7962
+ showPostBuildInstructions
7963
+ };