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.d.ts +3 -0
- package/dist/index.js +441 -366
- package/installers/CodeBakers-Install.bat +207 -0
- package/installers/CodeBakers-Install.command +232 -0
- package/installers/README.md +157 -0
- package/installers/mac/assets/README.txt +31 -0
- package/installers/mac/build-mac-installer.sh +240 -0
- package/installers/windows/CodeBakers.iss +256 -0
- package/installers/windows/assets/README.txt +16 -0
- package/installers/windows/scripts/post-install.bat +15 -0
- package/package.json +1 -1
- package/src/commands/setup.ts +306 -172
- package/src/index.ts +295 -198
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
|
|
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
|
|
53
|
+
whyNeeded: "This is REQUIRED. Without it, CodeBakers cannot generate any code.",
|
|
52
54
|
url: "https://console.anthropic.com/settings/keys",
|
|
53
|
-
|
|
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: "
|
|
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
|
-
|
|
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_...
|
|
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: "
|
|
103
|
+
whyNeeded: "Needed to deploy apps automatically. Skip if you'll deploy manually.",
|
|
90
104
|
url: "https://vercel.com/account/tokens",
|
|
91
|
-
|
|
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: "
|
|
123
|
+
whyNeeded: "Needed for database features. Skip if you'll set up databases manually.",
|
|
103
124
|
url: "https://supabase.com/dashboard/account/tokens",
|
|
104
|
-
|
|
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
|
|
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
|
|
142
|
+
whyNeeded: "Optional. Only if you want to use OpenAI alongside Claude.",
|
|
116
143
|
url: "https://platform.openai.com/api-keys",
|
|
117
|
-
|
|
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
|
|
159
|
+
whyNeeded: "Optional. Only if your app accepts payments.",
|
|
129
160
|
url: "https://dashboard.stripe.com/apikeys",
|
|
130
|
-
|
|
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
|
|
175
|
+
whyNeeded: "Optional. Only if your app sends SMS or makes calls.",
|
|
142
176
|
url: "https://console.twilio.com/",
|
|
143
|
-
|
|
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
|
|
199
|
+
whyNeeded: "Optional. Only if your app sends emails.",
|
|
162
200
|
url: "https://resend.com/api-keys",
|
|
163
|
-
|
|
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
|
|
216
|
+
whyNeeded: "Optional. Only if you're building voice agents.",
|
|
175
217
|
url: "https://dashboard.vapi.ai/",
|
|
176
|
-
|
|
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
|
|
233
|
+
whyNeeded: "Optional. Only if you want AI-generated voices.",
|
|
188
234
|
url: "https://elevenlabs.io/app/settings/api-keys",
|
|
189
|
-
|
|
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
|
-
|
|
202
|
-
if (
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
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(
|
|
214
|
-
|
|
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
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
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(
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
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 (
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
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
|
-
|
|
277
|
-
|
|
278
|
-
)
|
|
279
|
-
|
|
280
|
-
\
|
|
281
|
-
|
|
282
|
-
|
|
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
|
-
|
|
286
|
-
|
|
287
|
-
|
|
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
|
|
294
|
-
|
|
295
|
-
{ value: "
|
|
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))
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
${service.
|
|
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
|
|
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:
|
|
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
|
-
|
|
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(`
|
|
405
|
+
console.log(chalk2.green(`
|
|
406
|
+
\u2713 ${service.name} connected successfully!
|
|
407
|
+
`));
|
|
343
408
|
return true;
|
|
344
409
|
}
|
|
345
|
-
function
|
|
346
|
-
console.log(chalk2.bold("\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
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
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
|
-
|
|
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
|
|
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
|
-
|
|
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
|
|
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?
|
|
487
|
+
message: "Are you sure?",
|
|
400
488
|
initialValue: false
|
|
401
489
|
});
|
|
402
|
-
if (!confirm13 || p.isCancel(confirm13))
|
|
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
|
-
|
|
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.
|
|
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
|
-
|
|
7623
|
-
|
|
7624
|
-
|
|
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
|
|
7632
|
-
|
|
7633
|
-
|
|
7634
|
-
|
|
7635
|
-
|
|
7636
|
-
|
|
7637
|
-
|
|
7638
|
-
|
|
7639
|
-
|
|
7640
|
-
|
|
7641
|
-
|
|
7642
|
-
|
|
7643
|
-
|
|
7644
|
-
|
|
7645
|
-
|
|
7646
|
-
|
|
7647
|
-
|
|
7648
|
-
|
|
7649
|
-
|
|
7650
|
-
|
|
7651
|
-
|
|
7652
|
-
|
|
7653
|
-
|
|
7654
|
-
|
|
7655
|
-
|
|
7656
|
-
|
|
7657
|
-
|
|
7658
|
-
|
|
7659
|
-
|
|
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 "
|
|
7684
|
-
await
|
|
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
|
-
|
|
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(
|
|
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
|
|
7735
|
-
${chalk21.cyan("codebakers
|
|
7736
|
-
${chalk21.cyan("codebakers website")} Build
|
|
7737
|
-
${chalk21.cyan("codebakers
|
|
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("
|
|
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.
|
|
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
|
|
7751
|
-
${chalk21.cyan("codebakers
|
|
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("
|
|
7754
|
-
|
|
7755
|
-
|
|
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 (
|
|
7764
|
-
program.command("init").description("Create a new project").option("-n, --name <
|
|
7765
|
-
program.command("code [prompt]").description("Start AI coding session").option("-w, --watch", "Watch mode
|
|
7766
|
-
program.command("check").description("Run
|
|
7767
|
-
program.command("deploy").description("Deploy to production").option("-p, --preview", "
|
|
7768
|
-
program.command("fix").description("Auto-fix
|
|
7769
|
-
program.command("generate
|
|
7770
|
-
program.command("
|
|
7771
|
-
program.command("
|
|
7772
|
-
program.command("
|
|
7773
|
-
program.command("security").description("Run security audit").
|
|
7774
|
-
program.command("learn").description("View
|
|
7775
|
-
program.command("design
|
|
7776
|
-
program.command("prd [file]").description("Build
|
|
7777
|
-
program.command("advisors").alias("dream-team").description("Consult
|
|
7778
|
-
program.command("migrate").alias("db").description("Database migrations
|
|
7779
|
-
program.command("prd-maker").alias("create-prd").description("Create
|
|
7780
|
-
program.command("build [prd-file]").alias("swarm").description("Parallel build with
|
|
7781
|
-
program.command("integrate [integration]").alias("add").description("One-click integrations (50+ services
|
|
7782
|
-
program.command("website").alias("site").description("Build
|
|
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
|
|
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
|
-
|
|
7792
|
-
|
|
7793
|
-
|
|
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(
|
|
7892
|
+
await buildCommand();
|
|
7801
7893
|
break;
|
|
7802
7894
|
case "code":
|
|
7803
|
-
await codeCommand(
|
|
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
|
+
};
|