protovibe 1.0.0 → 1.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (2) hide show
  1. package/dist/index.mjs +224 -53
  2. package/package.json +1 -1
package/dist/index.mjs CHANGED
@@ -69,7 +69,7 @@ import { Box as Box2, Text as Text3 } from "ink";
69
69
  var WIDTH = 42;
70
70
  function InfoBox() {
71
71
  const separator = "\u2500".repeat(WIDTH);
72
- return /* @__PURE__ */ React3.createElement(Box2, { flexDirection: "column" }, /* @__PURE__ */ React3.createElement(Text3, { color: "#3a1a6a" }, "\u256D" + "\u2500".repeat(WIDTH) + "\u256E"), /* @__PURE__ */ React3.createElement(Text3, { color: "#3a1a6a" }, "\u2502", /* @__PURE__ */ React3.createElement(Text3, { color: "#b39ddb" }, " version "), /* @__PURE__ */ React3.createElement(Text3, { color: "#ffffff" }, "1.0.0"), " ".repeat(WIDTH - 17), "\u2502"), /* @__PURE__ */ React3.createElement(Text3, { color: "#3a1a6a" }, "\u2502", /* @__PURE__ */ React3.createElement(Text3, { color: "#b39ddb" }, " by "), /* @__PURE__ */ React3.createElement(Text3, { color: "#ffffff" }, "razorgojo"), " ".repeat(WIDTH - 15), "\u2502"), /* @__PURE__ */ React3.createElement(Text3, { color: "#3a1a6a" }, "\u2502 ", /* @__PURE__ */ React3.createElement(Text3, { color: "#b39ddb" }, "powered by "), /* @__PURE__ */ React3.createElement(Gradient, { text: "Claude Code", fromHex: "#7B2FBE", toHex: "#3B82F6" }), " ".repeat(WIDTH - 25), "\u2502"), /* @__PURE__ */ React3.createElement(Text3, { color: "#3a1a6a" }, "\u251C" + separator + "\u2524"), /* @__PURE__ */ React3.createElement(Text3, { color: "#3a1a6a" }, "\u2502", /* @__PURE__ */ React3.createElement(Text3, { color: "#6d5a8a", italic: true }, " Vibecode your prototypes."), " ".repeat(WIDTH - 28), "\u2502"), /* @__PURE__ */ React3.createElement(Text3, { color: "#3a1a6a" }, "\u2570" + "\u2500".repeat(WIDTH) + "\u256F"));
72
+ return /* @__PURE__ */ React3.createElement(Box2, { flexDirection: "column" }, /* @__PURE__ */ React3.createElement(Text3, { color: "#3a1a6a" }, "\u256D" + "\u2500".repeat(WIDTH) + "\u256E"), /* @__PURE__ */ React3.createElement(Text3, { color: "#3a1a6a" }, "\u2502", /* @__PURE__ */ React3.createElement(Text3, { color: "#b39ddb" }, " version "), /* @__PURE__ */ React3.createElement(Text3, { color: "#ffffff" }, "1.0.0"), " ".repeat(WIDTH - 17), "\u2502"), /* @__PURE__ */ React3.createElement(Text3, { color: "#3a1a6a" }, "\u2502", /* @__PURE__ */ React3.createElement(Text3, { color: "#b39ddb" }, " by "), /* @__PURE__ */ React3.createElement(Text3, { color: "#ffffff" }, "razorgojo"), " ".repeat(WIDTH - 15), "\u2502"), /* @__PURE__ */ React3.createElement(Text3, { color: "#3a1a6a" }, "\u2502 ", /* @__PURE__ */ React3.createElement(Text3, { color: "#b39ddb" }, "powered by "), /* @__PURE__ */ React3.createElement(Gradient, { text: "Claude Code", fromHex: "#7B2FBE", toHex: "#3B82F6" }), " ".repeat(WIDTH - 25), "\u2502"), /* @__PURE__ */ React3.createElement(Text3, { color: "#3a1a6a" }, "\u251C" + separator + "\u2524"), /* @__PURE__ */ React3.createElement(Text3, { color: "#3a1a6a" }, "\u2502", /* @__PURE__ */ React3.createElement(Text3, { color: "#6d5a8a", italic: true }, " Vibecode your prototypes."), " ".repeat(WIDTH - 28), "\u2502"), /* @__PURE__ */ React3.createElement(Text3, { color: "#3a1a6a" }, "\u251C" + separator + "\u2524"), /* @__PURE__ */ React3.createElement(Text3, { color: "#3a1a6a" }, "\u2502", /* @__PURE__ */ React3.createElement(Text3, { color: "#b39ddb" }, " commands"), " ".repeat(WIDTH - 11), "\u2502"), /* @__PURE__ */ React3.createElement(Text3, { color: "#3a1a6a" }, "\u2502", /* @__PURE__ */ React3.createElement(Text3, { color: "#ffffff" }, " /exit"), /* @__PURE__ */ React3.createElement(Text3, { color: "#6d5a8a" }, " \u2014 quit ProtoVibe at any time"), " ".repeat(WIDTH - 37), "\u2502"), /* @__PURE__ */ React3.createElement(Text3, { color: "#3a1a6a" }, "\u2570" + "\u2500".repeat(WIDTH) + "\u256F"));
73
73
  }
74
74
 
75
75
  // src/auth.ts
@@ -121,15 +121,18 @@ function spawnClaude(projectPath) {
121
121
 
122
122
  // src/scaffold.ts
123
123
  import { mkdirSync, writeFileSync, existsSync as existsSync2, readdirSync, statSync } from "fs";
124
- import { join as join2, dirname } from "path";
124
+ import { join as join2, dirname, resolve } from "path";
125
125
  import { homedir as homedir2 } from "os";
126
126
  import * as clack from "@clack/prompts";
127
127
 
128
128
  // src/templates/CLAUDE.md.ts
129
129
  var CLAUDE_MD = `# CLAUDE.md
130
130
 
131
- When you start, your first and only task is to run /protovibe.
132
- Do not wait for user input. Do not do anything else first.
131
+ IMMEDIATE INSTRUCTION \u2014 execute this before doing anything else, before reading any other file, before responding to the user in any way:
132
+
133
+ Run /protovibe now.
134
+
135
+ Do not greet the user. Do not ask what they want. Do not wait for input. Do not explain what you are about to do. Just run /protovibe immediately and silently.
133
136
 
134
137
  At any point during the workflow, the user can type /takeover to exit ProtoVibe and work directly in Claude Code with full context preserved.
135
138
  `;
@@ -143,7 +146,16 @@ You are running the ProtoVibe automated project setup workflow. Follow these sta
143
146
 
144
147
  ## Stage 0 \u2014 Mode Selection
145
148
 
146
- Present the user with two options:
149
+ Present the following immediately. Do not wait for any prior input:
150
+
151
+ First, show the available commands:
152
+
153
+ > **Available commands** (use these at any time during your session):
154
+ > - \`/summarise\` \u2014 get a plain-language summary of what's been done so far
155
+ > - \`/takeover\` \u2014 exit the ProtoVibe workflow and work directly in Claude Code
156
+ > - \`/protovibe\` \u2014 restart the ProtoVibe workflow from the beginning
157
+
158
+ Then immediately ask:
147
159
 
148
160
  > "Welcome to ProtoVibe. What would you like to do?"
149
161
  > 1. **Build from scratch** \u2014 start a new project
@@ -197,31 +209,41 @@ Wait for a free-text response. Accept anything. Do not proceed until you have an
197
209
 
198
210
  ## Stage 2 \u2014 Deep Requirements Probing
199
211
 
200
- Ask follow-up questions **one at a time**. Each question must be directly informed by all previous answers. Never ask about something already covered.
212
+ Your goal is to achieve complete, end-to-end clarity on this product before moving on. You must fully understand the user flow, product requirements, and all edge cases \u2014 with zero ambiguity.
201
213
 
202
- You must reach complete, unambiguous clarity on all of the following before moving on:
203
- - **Who** are the target users? (be specific \u2014 not just "everyone")
204
- - **What** does each core feature actually do? (behavior, not just names)
205
- - **Platform** \u2014 web, mobile, desktop, CLI, or multiple?
206
- - **Auth** \u2014 is user login required? If yes, what type?
207
- - **Data** \u2014 what data is created, stored, read? Any real-time requirements?
208
- - **Integrations** \u2014 any third-party services, APIs, or existing systems?
209
- - **Constraints** \u2014 performance, offline support, team size, timeline, existing tech choices?
214
+ **How to probe:**
210
215
 
211
- **There is no question limit.** Keep probing until you have zero unanswered questions. Do not summarize until everything is fully clear.
216
+ Ask your questions in **grouped batches** \u2014 not one at a time. Group related questions together so the user can answer them in one response. After receiving answers, analyse them carefully. If anything is still unclear, incomplete, or raises new questions, ask a follow-up batch. Repeat until you have full clarity.
212
217
 
213
- When you are confident nothing is ambiguous, present a complete structured summary:
218
+ You must cover all of the following \u2014 do not move on until every point is resolved:
219
+
220
+ - **Who** are the target users? (be specific \u2014 demographics, roles, technical level)
221
+ - **What** does each core feature actually do? (exact behavior, not just feature names)
222
+ - **User Flow** \u2014 how does a user move through the product from first open to completing each core action? Walk through every key path.
223
+ - **Platform** \u2014 web, mobile, desktop, CLI, or multiple? Any specific device or OS constraints?
224
+ - **Auth** \u2014 is login required? What type? (email, social, SSO?) Any roles or permission levels?
225
+ - **Data** \u2014 what data is created, stored, read, or deleted? Any real-time or sync requirements?
226
+ - **Integrations** \u2014 any third-party services, APIs, payment systems, or external tools?
227
+ - **Constraints** \u2014 performance targets, offline support, accessibility needs, team size, timeline, existing tech choices the user wants to keep?
228
+ - **Edge cases** \u2014 what happens when things go wrong? Any critical failure states to handle?
229
+
230
+ **There is no question limit.** If the user's answers raise new questions, ask them. Keep going until you have the full picture.
231
+
232
+ When you are confident everything is fully clear, present a complete structured summary:
214
233
 
215
234
  ---
216
235
  **Project:** [name]
217
- **Users:** [specific description]
236
+ **Type:** [web app / mobile app / desktop app / CLI tool / etc.]
237
+ **Target Users:** [specific description]
238
+ **Summary:** [2\u20133 sentences describing what the app does and the problem it solves]
218
239
  **Core Features:**
219
- [bulleted list \u2014 each with a one-line description of its behavior]
220
- **Platform:** [web / mobile / desktop / CLI]
221
- **Auth:** [yes/no and type]
222
- **Data & Storage:** [summary]
223
- **Integrations:** [summary]
224
- **Constraints:** [summary]
240
+ [bulleted list \u2014 each feature with a precise one-line description of its behavior]
241
+ **User Flow:** [step-by-step walkthrough of the primary user journey]
242
+ **Platform:** [web / mobile / desktop / CLI \u2014 with any specific constraints]
243
+ **Auth:** [yes/no, type, roles if any]
244
+ **Data & Storage:** [what data exists, how it's stored, any real-time needs]
245
+ **Integrations:** [third-party services and how they connect]
246
+ **Constraints & Requirements:** [all hard constraints, performance targets, non-negotiables]
225
247
  ---
226
248
 
227
249
  Then ask: "Does this capture everything? Confirm to continue."
@@ -269,13 +291,21 @@ Ask the user:
269
291
 
270
292
  Wait for confirmation. Do not create the file without it.
271
293
 
272
- On confirmation, write **specs.md** in the current working directory. It must contain:
273
- - **Tech Stack** \u2014 chosen stack with a one-line justification for each major choice
274
- - **User Flow** \u2014 step-by-step description of how a user moves through the app from first open to completing a core action
275
- - **Feature List** \u2014 all features with priority labels (P0 = must have for MVP, P1 = important but not blocking, P2 = nice to have)
276
- - **Data Model** \u2014 key entities, their fields, and relationships
277
- - **Integration Notes** \u2014 any third-party services and how they connect
278
- - **Constraints & NFRs** \u2014 performance targets, platform requirements, any hard constraints
294
+ On confirmation, write **specs.md** in the current working directory. It must be detailed but concise \u2014 every section should give enough information to build from, without padding. Include the following:
295
+
296
+ - **App Overview** \u2014 what the app is, what problem it solves, and what type of app it is (web, mobile, CLI, etc.)
297
+ - **Target Audience** \u2014 who the users are, their roles, technical level, and any relevant context
298
+ - **Summary** \u2014 a short paragraph (3\u20135 sentences) describing what the app does end-to-end
299
+ - **App Features** \u2014 full list of features with priority labels:
300
+ - P0 = must have for MVP
301
+ - P1 = important but not blocking launch
302
+ - P2 = nice to have / future iteration
303
+ Each feature should include a one-line description of its exact behavior.
304
+ - **Complete User Flow** \u2014 step-by-step walkthrough of every key user journey, from first open through all core actions. Cover the primary flow and any critical alternate paths.
305
+ - **Tech Stack** \u2014 chosen stack with a one-line justification for each major technology choice
306
+ - **Data Model** \u2014 key entities, their fields, types, and relationships
307
+ - **Integration Notes** \u2014 any third-party services, APIs, or external tools and how they connect
308
+ - **Additional Requirements** \u2014 any extra constraints, performance targets, accessibility needs, non-functional requirements, or specific details the user provided that don't fit above
279
309
 
280
310
  After writing, tell the user:
281
311
 
@@ -290,6 +320,8 @@ Without asking the user, do the following in order:
290
320
  1. Delete the existing CLAUDE.md file in the current directory
291
321
  2. Run /init \u2014 this will analyze the project (including specs.md) and generate a new, project-aware CLAUDE.md
292
322
 
323
+ The generated CLAUDE.md must contain full, detailed context to help Claude with all future development on this project. /init should produce a CLAUDE.md that includes: the project purpose and scope, the full tech stack with reasoning, the architecture overview, key entities and data relationships, the complete feature set, user flow summary, coding conventions and patterns to follow, known constraints, and any integration details. It should be a complete reference document \u2014 not a summary.
324
+
293
325
  After /init completes, confirm:
294
326
 
295
327
  > "CLAUDE.md \u2713 \u2014 your project is initialized."
@@ -302,9 +334,13 @@ Do not mention the deletion to the user. Do not ask permission. Just do it silen
302
334
 
303
335
  Tell the user:
304
336
 
305
- > "You can now go for building out the code."
337
+ > "Your project is fully scoped and ready to build."
338
+ >
339
+ > "Type **Build it** to start building, or ask me anything about the project first."
306
340
 
307
- Stop all automation. From this point forward, respond only to direct user requests. The ProtoVibe workflow is complete.
341
+ Wait for the user to type "Build it" (or a clear equivalent). Do not start writing any code until they do.
342
+
343
+ Once they confirm, begin building the project according to the specs.md and CLAUDE.md. Work systematically through the P0 features first.
308
344
 
309
345
  ---
310
346
 
@@ -336,6 +372,66 @@ When this command is run:
336
372
  4. From this point forward, respond normally to all user requests. No more workflow stages. No more automation. Just Claude Code.
337
373
  `;
338
374
 
375
+ // src/templates/summarise.md.ts
376
+ var SUMMARISE_MD = `# /summarise \u2014 Session Summary
377
+
378
+ When this command is run, provide a concise summary in simple, plain language of everything that has happened in the current session.
379
+
380
+ Structure your summary like this:
381
+
382
+ **What we're building:** [one sentence describing the project]
383
+ **What's been decided so far:**
384
+ [bullet list \u2014 each decision made, e.g. tech stack chosen, features confirmed, architecture selected]
385
+ **What's been done:**
386
+ [bullet list \u2014 any files created, code written, or stages completed]
387
+ **What comes next:**
388
+ [bullet list \u2014 the immediate next steps]
389
+
390
+ Rules:
391
+ - Keep it short \u2014 no more than 10 bullet points total across all sections
392
+ - Use plain words. No jargon. Write as if explaining to someone who hasn't been in the conversation.
393
+ - If nothing has happened yet, say: "Nothing has been decided yet. We're just getting started."
394
+ - After giving the summary, ask: "Would you like to continue where we left off?"
395
+ `;
396
+
397
+ // src/templates/CLAUDE-analyse.md.ts
398
+ var CLAUDE_ANALYSE_MD = `# CLAUDE.md
399
+
400
+ IMMEDIATE INSTRUCTION \u2014 execute this before doing anything else, before reading any other file, before responding to the user in any way:
401
+
402
+ Run /analyse now.
403
+
404
+ Do not greet the user. Do not ask what they want. Do not wait for input. Do not explain what you are about to do. Just run /analyse immediately and silently.
405
+ `;
406
+
407
+ // src/templates/analyse.md.ts
408
+ var ANALYSE_MD = `# /analyse \u2014 Project Analysis
409
+
410
+ When this command is run:
411
+
412
+ 1. Read every source file, configuration file, and documentation file in the current working directory, recursively. Include: all code files, package.json / pyproject.toml / Cargo.toml or equivalent, README files, config files.
413
+
414
+ 2. Build a complete understanding of the codebase. Do not ask the user any questions during this step.
415
+
416
+ 3. Present a structured summary in exactly this format:
417
+
418
+ ---
419
+ **Project:** [inferred project name from package.json, directory name, or equivalent]
420
+ **What it does:** [1\u20132 sentences describing the project's purpose and who it is for]
421
+ **Tech Stack:** [comma-separated list of languages, frameworks, and major libraries]
422
+ **Key Features:**
423
+ [bulleted list \u2014 one sentence per feature]
424
+ **Project Structure:** [2\u20133 sentences on key directories, entry points, and separation of concerns]
425
+ **Current State:** [one sentence: scaffold, early prototype, partially built, or mature codebase \u2014 based on file count, TODOs, and feature completeness]
426
+ ---
427
+
428
+ 4. After presenting the summary, say exactly:
429
+
430
+ > "I've analysed your project. I'm ready to help \u2014 what would you like to work on?"
431
+
432
+ 5. STOP. Do not suggest tasks. Do not ask questions. Wait for the user.
433
+ `;
434
+
339
435
  // src/scaffold.ts
340
436
  function getSubdirectories(dirPath) {
341
437
  try {
@@ -357,6 +453,7 @@ async function browseForDirectory() {
357
453
  const subdirs = getSubdirectories(currentPath);
358
454
  const isRoot = dirname(currentPath) === currentPath;
359
455
  const options = [
456
+ { value: "__exit__", label: "\u238B Exit ProtoVibe" },
360
457
  { value: "__select__", label: `\u2713 Use this folder \u2014 ${currentPath}` },
361
458
  ...!isRoot ? [{ value: "__up__", label: "\u2191 Go up" }] : [],
362
459
  ...subdirs.map((dir) => ({ value: join2(currentPath, dir), label: `\u{1F4C1} ${dir}` }))
@@ -369,7 +466,10 @@ async function browseForDirectory() {
369
466
  clack.cancel("Cancelled.");
370
467
  process.exit(0);
371
468
  }
372
- if (choice === "__select__") {
469
+ if (choice === "__exit__") {
470
+ clack.cancel("Exiting ProtoVibe. See you next time.");
471
+ process.exit(0);
472
+ } else if (choice === "__select__") {
373
473
  return currentPath;
374
474
  } else if (choice === "__up__") {
375
475
  currentPath = dirname(currentPath);
@@ -378,32 +478,103 @@ async function browseForDirectory() {
378
478
  }
379
479
  }
380
480
  }
381
- async function scaffoldProject() {
382
- clack.intro("");
383
- const projectName = await clack.text({
384
- message: "Project name:",
481
+ function writeProtovibeTemplates(targetDir) {
482
+ mkdirSync(join2(targetDir, ".claude", "commands"), { recursive: true });
483
+ writeFileSync(join2(targetDir, "CLAUDE.md"), CLAUDE_MD, "utf-8");
484
+ writeFileSync(join2(targetDir, ".claude", "commands", "protovibe.md"), PROTOVIBE_MD, "utf-8");
485
+ writeFileSync(join2(targetDir, ".claude", "commands", "takeover.md"), TAKEOVER_MD, "utf-8");
486
+ writeFileSync(join2(targetDir, ".claude", "commands", "summarise.md"), SUMMARISE_MD, "utf-8");
487
+ }
488
+ function writeAnalyseTemplates(targetDir) {
489
+ mkdirSync(join2(targetDir, ".claude", "commands"), { recursive: true });
490
+ writeFileSync(join2(targetDir, "CLAUDE.md"), CLAUDE_ANALYSE_MD, "utf-8");
491
+ writeFileSync(join2(targetDir, ".claude", "commands", "analyse.md"), ANALYSE_MD, "utf-8");
492
+ }
493
+ async function handleExistingProject() {
494
+ const rawPath = await clack.text({
495
+ message: "Path to your existing project:",
496
+ placeholder: "/Users/you/my-project",
385
497
  validate(value) {
386
- if (!value.trim()) return "Project name is required.";
387
- if (/[^a-zA-Z0-9\-_]/.test(value)) return "Use only letters, numbers, hyphens, and underscores.";
498
+ if (!value.trim()) return "Path is required.";
499
+ const resolved = resolve(value.trim().replace(/^~/, homedir2()));
500
+ if (!existsSync2(resolved)) return "That path does not exist.";
501
+ try {
502
+ if (!statSync(resolved).isDirectory()) return "That path is not a directory.";
503
+ } catch {
504
+ return "Could not read that path.";
505
+ }
388
506
  }
389
507
  });
390
- if (clack.isCancel(projectName)) {
391
- clack.cancel("Cancelled.");
508
+ if (clack.isCancel(rawPath)) {
509
+ clack.cancel("Exiting ProtoVibe. See you next time.");
392
510
  process.exit(0);
393
511
  }
394
- clack.log.info("Select where to create your project:");
395
- const parentDir = await browseForDirectory();
396
- const targetDir = join2(parentDir, String(projectName));
397
- if (existsSync2(targetDir)) {
398
- clack.cancel(`Directory already exists: ${targetDir}`);
399
- process.exit(1);
512
+ const existingPath = resolve(String(rawPath).trim().replace(/^~/, homedir2()));
513
+ writeAnalyseTemplates(existingPath);
514
+ clack.outro(`\u2713 Ready to analyse ${existingPath}`);
515
+ return existingPath;
516
+ }
517
+ async function handleNewProject() {
518
+ let parentDir = null;
519
+ while (true) {
520
+ const nameInput = await clack.text({
521
+ message: "Project name:",
522
+ placeholder: "my-project",
523
+ validate(value) {
524
+ if (value.trim() === "/exit") return void 0;
525
+ if (!value.trim()) return "Project name is required.";
526
+ if (/[^a-zA-Z0-9\-_]/.test(value)) return "Use only letters, numbers, hyphens, and underscores.";
527
+ }
528
+ });
529
+ if (clack.isCancel(nameInput) || String(nameInput).trim() === "/exit") {
530
+ clack.cancel("Exiting ProtoVibe. See you next time.");
531
+ process.exit(0);
532
+ }
533
+ if (parentDir === null) {
534
+ clack.log.info("Select where to create your project:");
535
+ parentDir = await browseForDirectory();
536
+ }
537
+ const targetDir = join2(parentDir, String(nameInput).trim());
538
+ if (!existsSync2(targetDir)) {
539
+ writeProtovibeTemplates(targetDir);
540
+ clack.outro(`\u2713 Project created at ${targetDir}`);
541
+ return targetDir;
542
+ }
543
+ clack.log.error(`A project named '${String(nameInput).trim()}' already exists at this location.`);
544
+ const conflictChoice = await clack.select({
545
+ message: "What would you like to do?",
546
+ options: [
547
+ { value: "rename", label: "Choose a different name for my new project" },
548
+ { value: "continue", label: "Continue with the existing project" }
549
+ ]
550
+ });
551
+ if (clack.isCancel(conflictChoice)) {
552
+ clack.cancel("Exiting ProtoVibe. See you next time.");
553
+ process.exit(0);
554
+ }
555
+ if (conflictChoice === "continue") {
556
+ writeProtovibeTemplates(targetDir);
557
+ clack.outro(`\u2713 Ready to continue at ${targetDir}`);
558
+ return targetDir;
559
+ }
400
560
  }
401
- mkdirSync(join2(targetDir, ".claude", "commands"), { recursive: true });
402
- writeFileSync(join2(targetDir, "CLAUDE.md"), CLAUDE_MD, "utf-8");
403
- writeFileSync(join2(targetDir, ".claude", "commands", "protovibe.md"), PROTOVIBE_MD, "utf-8");
404
- writeFileSync(join2(targetDir, ".claude", "commands", "takeover.md"), TAKEOVER_MD, "utf-8");
405
- clack.outro(`\u2713 Project created at ${targetDir}`);
406
- return targetDir;
561
+ }
562
+ async function scaffoldProject() {
563
+ const modeChoice = await clack.select({
564
+ message: "What would you like to do?",
565
+ options: [
566
+ { value: "new", label: "Start a new project" },
567
+ { value: "existing", label: "Continue with an existing project" }
568
+ ]
569
+ });
570
+ if (clack.isCancel(modeChoice)) {
571
+ clack.cancel("Exiting ProtoVibe. See you next time.");
572
+ process.exit(0);
573
+ }
574
+ if (modeChoice === "existing") {
575
+ return handleExistingProject();
576
+ }
577
+ return handleNewProject();
407
578
  }
408
579
 
409
580
  // src/cli.tsx
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "protovibe",
3
- "version": "1.0.0",
3
+ "version": "1.1.0",
4
4
  "description": "A branded CLI platform layer on top of Claude Code",
5
5
  "author": "razorgojo",
6
6
  "license": "MIT",