ventureos 1.0.9 → 1.0.11

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 (3) hide show
  1. package/README.md +114 -105
  2. package/install.js +497 -292
  3. package/package.json +1 -1
package/README.md CHANGED
@@ -1,161 +1,170 @@
1
1
  # VentureOS
2
2
 
3
- **A multi-agent AI framework for structured venture building.**
3
+ **Your AI co-founder. From raw idea to investor-ready pitch — step by step.**
4
4
 
5
- VentureOS guides teams from a raw domain or idea all the way to an investor-ready pitch through a structured 12-week incubation process powered by specialized AI agents.
5
+ VentureOS gives you a team of AI specialists that guide you through building a startup: researching the market, finding real customer problems, designing your solution, stress-testing your business model, and preparing your pitch. It follows a proven 12-week process so nothing gets skipped.
6
6
 
7
7
  ---
8
8
 
9
- ## Getting Started
9
+ ## What you need before starting
10
10
 
11
- **Requirements:** Node.js 18+ — [download here](https://nodejs.org) if you don't have it.
11
+ **1. Node.js** (a small program that runs VentureOS)
12
+ - Check if you already have it: open your terminal and type `node --version`
13
+ - If you see a number like `v20.x.x` you're good
14
+ - If not, download it free at [nodejs.org](https://nodejs.org) → click the big green "LTS" button → install it like any app
12
15
 
13
- ### Step 1Create a project folder and install VentureOS inside it
16
+ **2. An AI tool** pick whichever you have:
14
17
 
15
- Open your terminal and run:
18
+ | You have this | You need |
19
+ |---|---|
20
+ | Cursor, Windsurf, or Antigravity | Nothing else — they include AI |
21
+ | Claude Code | Nothing else — it includes AI |
22
+ | None of the above | An API key (explained below) |
16
23
 
17
- ```bash
18
- mkdir my-venture && cd my-venture
19
- npx ventureos install
20
- ```
24
+ > **Don't have any of these?** Antigravity is free and takes 2 minutes to install: [antigravity.dev](https://antigravity.dev)
21
25
 
22
- > **Important:** always run this inside a project folder. VentureOS installs a `ventureOS/` directory in whatever folder you are in when you run the command.
26
+ ---
23
27
 
24
- The installer asks a few questions (your name, AI tool, research depth, execution mode), then sets up the full framework in under 30 seconds.
28
+ ## Get started
25
29
 
26
- ### Step 2 Start a session
30
+ Open your terminal, create a folder for your project, and run one command:
27
31
 
28
32
  ```bash
29
- npx ventureos start
33
+ mkdir my-venture
34
+ cd my-venture
35
+ npx ventureos
30
36
  ```
31
37
 
32
- Launches an interactive terminal chat with Victor no copy-pasting files. Connects directly to the LLM API of your choice.
38
+ That's it. VentureOS will detect what AI tools you have, ask you a few quick questions, and tell you exactly how to start.
33
39
 
34
- Supports **Claude (Anthropic)**, **ChatGPT (OpenAI)**, and **Gemini (Google)**. Set your API key as an environment variable to skip the prompt on future sessions:
40
+ > **What's a terminal?**
41
+ > On Mac: press `Cmd + Space`, type "Terminal", press Enter.
42
+ > On Windows: press the Windows key, type "cmd", press Enter.
35
43
 
36
- ```bash
37
- export ANTHROPIC_API_KEY=your-key # for Claude
38
- export OPENAI_API_KEY=your-key # for ChatGPT
39
- export GOOGLE_API_KEY=your-key # for Gemini
44
+ ---
45
+
46
+ ## What happens when you run it
47
+
48
+ **VentureOS scans your computer** and finds any AI tools you already have.
49
+
50
+ **Then it routes you to the best experience:**
51
+
52
+ ### If you have Cursor, Windsurf, Antigravity, or Claude Code
53
+
54
+ VentureOS installs itself and gives you one line to type in your AI tool:
55
+
56
+ ```
57
+ @ventureOS/venture-master.md
40
58
  ```
41
59
 
42
- **If you use Claude Code, Cursor, or Windsurf**, you can also load VentureOS directly in your AI tool instead of using the terminal see [SETUP.md](SETUP.md) for instructions.
60
+ Type that in your AI chat panel and Victor your AI co-founder introduces himself and takes it from there. No API keys. No extra setup.
61
+
62
+ ### If you have an API key
63
+
64
+ VentureOS asks which service (Claude, ChatGPT, or Gemini), walks you through entering your key, and launches the chat for you directly in the terminal.
65
+
66
+ **No key yet?** VentureOS will show you a link to get one. If you get stuck, it never just crashes — it always gives you options.
43
67
 
44
68
  ---
45
69
 
46
- ## What VentureOS Does
70
+ ## Changing your settings later
47
71
 
48
- - Tracks where your venture is in the incubation journey
49
- - Routes you to the right specialist agent for each phase
50
- - Generates first drafts of every deliverable so you never start from a blank page
51
- - Enforces evidence-based progression: guiding questions must be answered before advancing
52
- - Manages two decision gates where ventures are evaluated for continuation, pivot, or kill
72
+ ```bash
73
+ npx ventureos config
74
+ ```
75
+
76
+ Change your name, research depth, execution mode, or AI provider anytime without starting over.
53
77
 
54
78
  ---
55
79
 
56
- ## How It Works
80
+ ## Meet Victor and your AI team
81
+
82
+ When you start a session, **Victor** greets you. He's the orchestrator — think of him as your main point of contact. He knows where you are in the journey, what's been done, and what comes next.
57
83
 
58
- VentureOS is a collection of AI agent files and workflow files that you load into your preferred AI coding assistant. The agents collaborate through a shared venture state file to guide you through the full incubation lifecycle.
84
+ When you need deep specialist work, Victor brings in the right expert:
59
85
 
60
- **Entry points:**
61
- - **Domain exploration** — You have a domain (e.g., "energy management"). VentureOS maps the opportunity landscape first, then moves into incubation.
62
- - **Idea development** You have a specific idea. VentureOS jumps directly into incubation.
86
+ | Specialist | What they do |
87
+ |---|---|
88
+ | **Diana** | Researches your market competitors, trends, opportunities |
89
+ | **Clara** | Helps you find and validate real customer pain |
90
+ | **Paulo** | Designs your product wedge and early solution |
91
+ | **Bernard** | Builds your business model and revenue logic |
92
+ | **Fiona** | Sizes the market and builds your financial model |
93
+ | **Eva** | Plays the tough investor — stress-tests your venture |
94
+ | **Petra** | Creates your pitch deck and investor narrative |
95
+ | **Grace** | Builds your go-to-market and growth strategy |
96
+ | **Olivia** | Sets up your team structure and operations |
63
97
 
64
- **Final output:** Investor-ready pitch deck (Markdown + Excalidraw) or a documented pivot/kill decision with full rationale and archived artifacts.
98
+ You talk to Victor. He calls in the right specialist at the right time.
65
99
 
66
100
  ---
67
101
 
68
- ## The Incubation Journey (12 Weeks)
102
+ ## The journey (12 weeks)
103
+
104
+ VentureOS follows a structured process so you always know where you are and what's next.
69
105
 
70
106
  ```
71
- Week 1 Weeks 2-3 Weeks 4-7 Weeks 10-12
72
- ┌──────────┐ ┌──────────────┐ ┌────────────────────┐ ┌──────────────────┐
73
- SETUP │ │ UNDERSTAND │ │ DEFINE SOLUTION │ │ DESIGN BUSINESS │
74
- THE TEAM │ THE MARKET │ │ │ │ │
75
- └──────────┘ │ │ │ │ │ │
76
- │ FIND │ │ BUILD INITIAL │ │ │
77
- │ CUSTOMER │──▶│ BUSINESS CASE │──▶│
78
- PAIN │ │ │ │ │
79
- └──────────────┘ └──────┬─────────────┘ └────────┬─────────┘
80
- │ │
81
- CHECK-IN PITCH FINAL PITCH
82
- to Venture Board to Venture Board
83
- (Go/Pivot/Kill) (Go/Pivot/Kill)
107
+ Week 1 Weeks 23 Weeks 47 Weeks 8–12
108
+ ────────── ───────────── ───────────── ─────────────
109
+ Set up Understand Design your Build the
110
+ your team → the market → solution → business
111
+ Find customer
112
+ problems
113
+
114
+ CHECK-IN FINAL PITCH
115
+ with board to investors
116
+ (Go/Pivot/Kill) (Go/Pivot/Kill)
84
117
  ```
85
118
 
86
- ---
119
+ At each phase, VentureOS generates documents for you — market maps, interview guides, business model canvases, pitch decks — so you never start from a blank page.
87
120
 
88
- ## The Agents
89
-
90
- | Agent | Name | Role |
91
- |-------|------|------|
92
- | `venture-master.md` | Victor | Orchestrator — load this first |
93
- | `agents/domain-explorer.md` | Diana | Market & domain research |
94
- | `agents/customer-discovery.md` | Clara | Customer pain & interviews |
95
- | `agents/product-strategist.md` | Paulo | Wedge design & prototyping |
96
- | `agents/business-architect.md` | Bernard | Business model & revenue |
97
- | `agents/financial-analyst.md` | Fiona | Market sizing & financial modeling |
98
- | `agents/venture-evaluator.md` | Eva | Venture Board gate evaluation |
99
- | `agents/pitch-master.md` | Petra | Pitch deck creation |
100
- | `agents/growth-strategist.md` | Grace | GTM & market experiments |
101
- | `agents/venture-ops.md` | Olivia | Team setup & parent org alignment |
121
+ Everything is saved automatically. Come back tomorrow and Victor picks up exactly where you left off.
102
122
 
103
123
  ---
104
124
 
105
- ## Directory Structure
125
+ ## Two ways to work
106
126
 
107
- ```
108
- ventureOS/
109
- ├── venture-master.md ← START HERE — load this file first
110
- ├── workflow-engine.md ← Workflow execution engine
111
- ├── config.yaml ← Your configuration (edit before first use)
112
- ├── README.md ← This file
113
- ├── SETUP.md ← Installation guide
114
- ├── agents/ ← Specialist agents (loaded on demand)
115
- │ ├── domain-explorer.md
116
- │ ├── customer-discovery.md
117
- │ ├── product-strategist.md
118
- │ ├── business-architect.md
119
- │ ├── financial-analyst.md
120
- │ ├── venture-evaluator.md
121
- │ ├── pitch-master.md
122
- │ ├── growth-strategist.md
123
- │ └── venture-ops.md
124
- ├── workflows/ ← Phase-specific workflow definitions
125
- │ ├── 0-explore/
126
- │ ├── 1-setup-team/
127
- │ ├── 2-understand-market/
128
- │ ├── 3-find-pain/
129
- │ ├── 4-define-solution/
130
- │ ├── 5-business-case/
131
- │ ├── 6-design-business/
132
- │ └── venture-status/
133
- ├── templates/ ← Output document templates (30+)
134
- ├── scoring/ ← Gate rubric, pain scoring, pivot triggers
135
- ├── techniques/ ← Brainstorming techniques, synthetic tools
136
- └── _memory/
137
- └── venture-state.yaml ← Active venture state (auto-managed)
138
- ```
127
+ **Guided mode** (default) — Victor pauses after each step, shows you the output, and asks for your approval before moving on. Best for real ventures where decisions matter.
139
128
 
140
- Outputs are saved to: `_ventures/{venture_name}/`
129
+ **Auto mode** Victor runs the full phase on its own and shows you everything at the end. Best when you want to quickly screen an idea.
141
130
 
142
131
  ---
143
132
 
144
- ## Two Execution Modes
133
+ ## Your outputs
145
134
 
146
- **Guided mode (default):** The agent pauses at each checkpoint, shows you the output, and waits for your approval before proceeding. Best for real ventures where strategic decisions matter.
135
+ Everything VentureOS creates is saved as readable files in `_ventures/your-venture-name/`:
147
136
 
148
- **Yolo mode:** The agent runs the full workflow autonomously and presents all outputs at the end for batch review. Best for rapid idea screening.
137
+ - Market research and competitive analysis
138
+ - Customer interview scripts and synthesis
139
+ - Problem and solution definition documents
140
+ - Business model canvas
141
+ - Financial model
142
+ - Go-to-market plan
143
+ - Check-in pitch and final investor pitch deck
149
144
 
150
- Set your preferred default in `config.yaml` or switch modes per workflow.
145
+ If you pivot or decide to stop, VentureOS archives everything and documents the decision with full rationale — so the work is never lost.
151
146
 
152
147
  ---
153
148
 
154
- ## Pivot & Kill Mechanism
149
+ ## Common questions
150
+
151
+ **Do I need to know how to code?**
152
+ No. You type in plain English. VentureOS handles everything else.
153
+
154
+ **What's an API key?**
155
+ It's like a password that gives you access to an AI service (like ChatGPT or Claude). If you use Cursor, Windsurf, or Antigravity, you don't need one — they include AI access in their apps.
156
+
157
+ **Does it save my work?**
158
+ Yes. Every session is saved automatically. Start and stop whenever you like.
155
159
 
156
- VentureOS tracks every pivot and kill decision:
160
+ **Can I use it for multiple ideas?**
161
+ Yes. Run `npx ventureos config` to switch ventures or start a new one.
162
+
163
+ **What if something goes wrong?**
164
+ VentureOS never just crashes. If there's a problem (wrong key, no connection, etc.), it shows you your options and waits for you to decide what to do next.
165
+
166
+ ---
157
167
 
158
- - **Pivot:** Archives current artifacts, classifies pivot type (customer/problem/solution/model/market), identifies re-entry phase, preserves relevant work
159
- - **Kill:** Documents learnings, archives all artifacts, marks venture as killed with full rationale
168
+ ## Need help?
160
169
 
161
- Pivot history is preserved in `ventureOS/_memory/venture-state.yaml`.
170
+ Open an issue on GitHub: [github.com/ABTB93/ventureos/issues](https://github.com/ABTB93/ventureos/issues)
package/install.js CHANGED
@@ -2,9 +2,9 @@
2
2
  /**
3
3
  * VentureOS CLI
4
4
  * Usage:
5
- * npx ventureos install interactive installer
6
- * npx ventureos start launch Victor chat (Claude, ChatGPT, or Gemini)
7
- * npx ventureos same as install
5
+ * npx ventureos setup wizard + start (auto-detects your environment)
6
+ * npx ventureos config update your configuration
7
+ * npx ventureos start launch Victor chat (if already installed)
8
8
  *
9
9
  * Zero npm dependencies — pure Node.js (readline/promises, fs, path, url, fetch)
10
10
  * Requires Node.js >= 18.0.0
@@ -15,61 +15,140 @@ import { stdin as input, stdout as output } from 'process';
15
15
  import fs from 'fs';
16
16
  import path from 'path';
17
17
  import { fileURLToPath } from 'url';
18
- import { spawnSync, spawn } from 'child_process';
18
+ import { spawnSync } from 'child_process';
19
19
 
20
20
  const __filename = fileURLToPath(import.meta.url);
21
21
  const PACKAGE_ROOT = path.dirname(__filename);
22
22
 
23
- // Must be defined before startChat() runs (accessed synchronously before first await)
24
23
  let _spinner;
25
24
 
25
+ // ─── Providers ─────────────────────────────────────────────────────────────────
26
+
26
27
  const PROVIDERS = {
27
28
  anthropic: {
28
29
  label: 'Claude (Anthropic)',
29
30
  envVar: 'ANTHROPIC_API_KEY',
30
31
  defaultModel: 'claude-opus-4-6',
32
+ keyUrl: 'https://console.anthropic.com',
31
33
  },
32
34
  openai: {
33
35
  label: 'ChatGPT (OpenAI)',
34
36
  envVar: 'OPENAI_API_KEY',
35
37
  defaultModel: 'gpt-4o',
38
+ keyUrl: 'https://platform.openai.com/api-keys',
36
39
  },
37
40
  gemini: {
38
41
  label: 'Gemini (Google)',
39
42
  envVar: 'GOOGLE_API_KEY',
40
43
  defaultModel: 'gemini-2.0-flash',
44
+ keyUrl: 'https://aistudio.google.com/app/apikey',
41
45
  },
42
46
  };
43
47
 
44
- // CLI tools that can be used instead of an API key
45
- const CLI_TOOLS = {
46
- anthropic: { cmd: 'claude', label: 'Claude CLI' },
47
- };
48
+ // ─── Known AI IDEs ─────────────────────────────────────────────────────────────
49
+
50
+ const IDE_TOOLS = [
51
+ {
52
+ id: 'cursor',
53
+ label: 'Cursor',
54
+ description: 'no API key needed',
55
+ cmds: ['cursor'],
56
+ appPaths: ['/Applications/Cursor.app'],
57
+ instructions: (dir) => [
58
+ ' 1. Open this folder in Cursor',
59
+ ` cursor "${dir}"`,
60
+ ' (or: File → Open Folder → select this folder)',
61
+ '',
62
+ ' 2. In the Cursor chat panel, type exactly this:',
63
+ ' @ventureOS/venture-master.md',
64
+ '',
65
+ ' 3. Victor — your AI co-founder — will take it from there.',
66
+ '',
67
+ ' No API key. No extra setup. Just open and chat.',
68
+ ],
69
+ },
70
+ {
71
+ id: 'windsurf',
72
+ label: 'Windsurf',
73
+ description: 'no API key needed',
74
+ cmds: ['windsurf'],
75
+ appPaths: ['/Applications/Windsurf.app'],
76
+ instructions: (dir) => [
77
+ ' 1. Open this folder in Windsurf',
78
+ ` windsurf "${dir}"`,
79
+ ' (or: File → Open Folder → select this folder)',
80
+ '',
81
+ ' 2. In the Windsurf chat panel, type:',
82
+ ' @ventureOS/venture-master.md',
83
+ '',
84
+ ' 3. Victor — your AI co-founder — will take it from there.',
85
+ '',
86
+ ' No API key. No extra setup. Just open and chat.',
87
+ ],
88
+ },
89
+ {
90
+ id: 'claude',
91
+ label: 'Claude Code',
92
+ description: 'no API key needed',
93
+ cmds: ['claude'],
94
+ appPaths: [],
95
+ instructions: (dir) => [
96
+ ' 1. Open this folder in your terminal and start Claude Code',
97
+ ` cd "${dir}"`,
98
+ ' claude',
99
+ '',
100
+ ' 2. Type this to activate VentureOS:',
101
+ ' @ventureOS/venture-master.md',
102
+ '',
103
+ ' 3. Victor — your AI co-founder — will take it from there.',
104
+ '',
105
+ ' Full markdown rendering, streaming, all native Claude Code features.',
106
+ ],
107
+ },
108
+ {
109
+ id: 'antigravity',
110
+ label: 'Antigravity',
111
+ description: 'free, no API key needed',
112
+ cmds: ['antigravity'],
113
+ appPaths: ['/Applications/Antigravity.app'],
114
+ instructions: (dir) => [
115
+ ' 1. Open this folder in Antigravity',
116
+ ` antigravity "${dir}"`,
117
+ ' (or: File → Open Folder → select this folder)',
118
+ '',
119
+ ' 2. In the chat panel, type:',
120
+ ' @ventureOS/venture-master.md',
121
+ '',
122
+ ' 3. Victor — your AI co-founder — will take it from there.',
123
+ '',
124
+ ' Free to use. Supports Gemini, Claude, and more.',
125
+ ],
126
+ },
127
+ ];
128
+
129
+ // ─── Entry point ───────────────────────────────────────────────────────────────
48
130
 
49
131
  const cmd = process.argv[2];
50
132
 
51
133
  if (cmd === 'start') {
52
- startChat().catch(err => {
53
- if (err.code !== 'ERR_USE_AFTER_CLOSE') {
54
- console.error('\n ❌ Error:', err.message, '\n');
55
- process.exit(1);
56
- }
57
- });
134
+ legacyStart().catch(handleFatalError);
135
+ } else if (cmd === 'config') {
136
+ reconfigure().catch(handleFatalError);
58
137
  } else {
59
- install().catch(err => {
60
- if (err.code !== 'ERR_USE_AFTER_CLOSE') {
61
- console.error('\n ❌ Installation error:', err.message);
62
- process.exit(1);
63
- }
64
- });
138
+ main().catch(handleFatalError);
65
139
  }
66
140
 
67
- // ─── Shared Utilities ──────────────────────────────────────────────────────────
68
-
69
- function line() {
70
- return ' ' + '─'.repeat(50);
141
+ function handleFatalError(err) {
142
+ if (err.code !== 'ERR_USE_AFTER_CLOSE') {
143
+ console.error('\n Error:', err.message, '\n');
144
+ process.exit(1);
145
+ }
71
146
  }
72
147
 
148
+ // ─── Utilities ─────────────────────────────────────────────────────────────────
149
+
150
+ function line() { return ' ' + '─'.repeat(52); }
151
+
73
152
  function parseSimpleYaml(text) {
74
153
  const result = {};
75
154
  for (const rawLine of text.split('\n')) {
@@ -88,7 +167,39 @@ function parseSimpleYaml(text) {
88
167
  return result;
89
168
  }
90
169
 
91
- // ─── Install ───────────────────────────────────────────────────────────────────
170
+ function showBanner() {
171
+ console.log('\n');
172
+ console.log(' ┌' + '─'.repeat(52) + '┐');
173
+ console.log(' │ │');
174
+ console.log(' │ VentureOS │');
175
+ console.log(' │ AI-Powered Venture Building Framework │');
176
+ console.log(' │ │');
177
+ console.log(' │ Build your startup — step by step. │');
178
+ console.log(' │ │');
179
+ console.log(' └' + '─'.repeat(52) + '┘');
180
+ console.log('\n');
181
+ }
182
+
183
+ // ─── IDE Detection ─────────────────────────────────────────────────────────────
184
+
185
+ function detectIDEs() {
186
+ const found = [];
187
+ for (const ide of IDE_TOOLS) {
188
+ const byCLI = ide.cmds.some(c => {
189
+ try {
190
+ const r = spawnSync('which', [c], { encoding: 'utf8', stdio: 'pipe' });
191
+ return r.status === 0 && r.stdout.trim();
192
+ } catch { return false; }
193
+ });
194
+ const byApp = ide.appPaths.some(p => {
195
+ try { return fs.existsSync(p); } catch { return false; }
196
+ });
197
+ if (byCLI || byApp) found.push(ide);
198
+ }
199
+ return found;
200
+ }
201
+
202
+ // ─── File helpers ───────────────────────────────────────────────────────────────
92
203
 
93
204
  const SKIP = new Set([
94
205
  'install.js', 'package.json', 'package-lock.json',
@@ -129,7 +240,7 @@ output_folder: "_ventures"
129
240
  # deep = exhaustive multi-source research with cross-validation
130
241
  research_depth: "${researchDepth}"
131
242
 
132
- # Your AI provider
243
+ # Your AI provider (used when running via built-in chat)
133
244
  # Options: anthropic | openai | gemini
134
245
  llm: "${llm}"
135
246
 
@@ -140,220 +251,365 @@ default_mode: "${defaultMode}"
140
251
  `;
141
252
  }
142
253
 
143
- function showNextSteps(ventureOSDir, targetDir) {
254
+ function installFiles(targetDir, ventureOSDir, configYaml) {
255
+ copyDir(PACKAGE_ROOT, ventureOSDir, SKIP);
256
+ console.log(' ✓ Framework files installed → ventureOS/');
257
+
258
+ fs.writeFileSync(path.join(ventureOSDir, 'config.yaml'), configYaml, 'utf8');
259
+ console.log(' ✓ Configuration saved → ventureOS/config.yaml');
260
+
261
+ const venturesDir = path.join(targetDir, '_ventures');
262
+ if (!fs.existsSync(venturesDir)) {
263
+ fs.mkdirSync(venturesDir, { recursive: true });
264
+ fs.writeFileSync(path.join(venturesDir, '.gitkeep'), '', 'utf8');
265
+ }
266
+ console.log(' ✓ Output folder ready → _ventures/');
267
+
268
+ const gitignorePath = path.join(targetDir, '.gitignore');
269
+ if (!fs.existsSync(gitignorePath)) {
270
+ fs.writeFileSync(gitignorePath, '# VentureOS\n_ventures/\nnode_modules/\n.DS_Store\n', 'utf8');
271
+ console.log(' ✓ .gitignore created');
272
+ }
273
+ }
274
+
275
+ // ─── Setup Wizard ──────────────────────────────────────────────────────────────
276
+
277
+ async function runSetupWizard(rl, { forIDE = false } = {}) {
144
278
  console.log('\n' + line());
145
- console.log(' How to start VentureOS');
146
- console.log(line() + '\n');
147
- console.log(' Run this command from your project folder:\n');
148
- console.log(' npx ventureos start\n');
149
- console.log(' Victor (your VentureOS orchestrator) will:');
150
- console.log(line() + '\n');
151
- console.log(' 1. Read your config and venture state');
152
- console.log(' 2. Display the phase-aware menu');
153
- console.log(' 3. Guide you through your venture building journey\n');
154
- console.log(' Commands to get started:');
155
- console.log(' [NV] New Venture — start a new venture (idea or domain)');
156
- console.log(' [EX] Explore — run a domain deep dive first');
157
- console.log(' [VS] Status — view venture status and next actions\n');
279
+ console.log(' A few quick questions so Victor knows how to help you.');
158
280
  console.log(line() + '\n');
281
+
282
+ const nameInput = await rl.question(' Your name (press Enter for "Founder"): ');
283
+ const userName = nameInput.trim() || 'Founder';
284
+
285
+ console.log('\n How thorough should VentureOS be with research?\n');
286
+ console.log(' 1. Standard — structured analysis with sourced data (recommended)');
287
+ console.log(' 2. Light — quick overview, faster');
288
+ console.log(' 3. Deep — exhaustive, multi-source\n');
289
+ const depthInput = await rl.question(' Select [1-3]: ');
290
+ const researchDepth = ({ '1': 'standard', '2': 'light', '3': 'deep' })[depthInput.trim()] ?? 'standard';
291
+
292
+ console.log('\n How should workflows run by default?\n');
293
+ console.log(' 1. Guided — pauses so you review each step (recommended)');
294
+ console.log(' 2. Auto — runs everything on its own\n');
295
+ const modeInput = await rl.question(' Select [1-2]: ');
296
+ const defaultMode = modeInput.trim() === '2' ? 'yolo' : 'guided';
297
+
298
+ let llm = 'anthropic';
299
+ if (!forIDE) {
300
+ console.log('\n Which AI service will you use?\n');
301
+ console.log(' 1. Claude (Anthropic) (recommended)');
302
+ console.log(' 2. ChatGPT (OpenAI)');
303
+ console.log(' 3. Gemini (Google)\n');
304
+ const llmInput = await rl.question(' Select [1-3]: ');
305
+ llm = ({ '1': 'anthropic', '2': 'openai', '3': 'gemini' })[llmInput.trim()] ?? 'anthropic';
306
+ }
307
+
308
+ return { userName, researchDepth, llm, defaultMode };
159
309
  }
160
310
 
161
- async function install() {
162
- console.log('\n');
163
- console.log(' ┌' + '─'.repeat(52) + '┐');
164
- console.log(' │ │');
165
- console.log(' │ 🚀 VentureOS │');
166
- console.log(' │ AI-Powered Venture Building Framework │');
167
- console.log(' │ │');
168
- console.log(' └' + '─'.repeat(52) + '┘');
169
- console.log('\n');
311
+ // ─── API Key Recovery ──────────────────────────────────────────────────────────
170
312
 
171
- const rl = readline.createInterface({ input, output });
313
+ /**
314
+ * Prompts for an API key with a recovery menu.
315
+ * Returns the key string, or null if the user wants to switch provider.
316
+ * Exits the process if user picks "show free tools" or "exit".
317
+ */
318
+ async function promptForAPIKey(rl, providerKey) {
319
+ const provider = PROVIDERS[providerKey];
172
320
 
173
- try {
174
- // Step 1: Installation directory
175
- const defaultTarget = process.cwd();
176
- console.log(' 📁 Installation directory');
177
- console.log(` Default: ${defaultTarget}`);
178
- const targetInput = await rl.question(' Press Enter to confirm, or type a different path: ');
179
- const targetDir = path.resolve(targetInput.trim() || defaultTarget);
180
- const ventureOSDir = path.join(targetDir, 'ventureOS');
181
-
182
- if (fs.existsSync(ventureOSDir)) {
183
- console.log('\n ⚠️ VentureOS is already installed in this directory.');
184
- const ans = await rl.question(' Update/reinstall? (y/N): ');
185
- if (!ans.trim().toLowerCase().startsWith('y')) {
186
- console.log('\n Installation cancelled. Your existing installation is unchanged.\n');
187
- rl.close();
188
- return;
321
+ while (true) {
322
+ console.log(`\n No ${provider.envVar} found.\n`);
323
+ console.log(' 1. I\'ll paste my key now');
324
+ console.log(` 2. How to get a key → ${provider.keyUrl}`);
325
+ console.log(' 3. Switch to a different AI service');
326
+ console.log(' 4. Use an AI IDE instead no key needed');
327
+ console.log(' 5. Exit\n');
328
+
329
+ const choice = (await rl.question(' Select [1-5]: ')).trim();
330
+
331
+ if (choice === '1') {
332
+ const key = (await rl.question(`\n Paste your ${provider.label} API key: `)).trim();
333
+ if (key) {
334
+ console.log(`\n Tip: save this to skip the prompt next time:`);
335
+ console.log(` export ${provider.envVar}=your-key\n`);
336
+ return key;
189
337
  }
190
- console.log('\n Updating existing installation...');
338
+ console.log('\n No key entered.\n');
339
+ continue;
191
340
  }
192
341
 
193
- // Step 2: User name
194
- console.log('\n' + line());
195
- console.log(' About you');
196
- console.log(line() + '\n');
197
- const nameInput = await rl.question(' 👤 Your name: ');
198
- const userName = nameInput.trim() || 'Founder';
342
+ if (choice === '2') {
343
+ console.log(`\n Open this link to get your key:\n ${provider.keyUrl}\n`);
344
+ console.log(' Come back and run npx ventureos once you have it.\n');
345
+ rl.close();
346
+ process.exit(0);
347
+ }
199
348
 
200
- // Step 3: AI provider
201
- console.log('\n 🤖 Which AI provider do you use?\n');
349
+ if (choice === '3') return null; // signal: switch provider
350
+
351
+ if (choice === '4') {
352
+ showFreeToolsHelp();
353
+ rl.close();
354
+ process.exit(0);
355
+ }
356
+
357
+ if (choice === '5') {
358
+ rl.close();
359
+ process.exit(0);
360
+ }
361
+ }
362
+ }
363
+
364
+ /**
365
+ * Asks user to pick a provider, then prompts for its API key.
366
+ * Loops until a valid provider + key is chosen.
367
+ */
368
+ async function selectProviderAndKey(rl) {
369
+ while (true) {
370
+ console.log('\n Which AI service do you have a key for?\n');
202
371
  console.log(' 1. Claude (Anthropic) (recommended)');
203
372
  console.log(' 2. ChatGPT (OpenAI)');
204
- console.log(' 3. Gemini (Google)\n');
205
- const llmInput = await rl.question(' Select [1-3]: ');
206
- const llmMap = { '1': 'anthropic', '2': 'openai', '3': 'gemini' };
207
- const llm = llmMap[llmInput.trim()] ?? 'anthropic';
208
-
209
- // Step 4: Research depth
210
- console.log('\n 🔍 Research depth for market and domain analysis?\n');
211
- console.log(' 1. Standard — structured analysis with sourced data (recommended)');
212
- console.log(' 2. Light — high-level overview, fast');
213
- console.log(' 3. Deep — exhaustive multi-source research with validation\n');
214
- const depthInput = await rl.question(' Select [1-3]: ');
215
- const depthMap = { '1': 'standard', '2': 'light', '3': 'deep' };
216
- const researchDepth = depthMap[depthInput.trim()] ?? 'standard';
217
-
218
- // Step 6: Default mode
219
- console.log('\n ⚙️ Default workflow execution mode?\n');
220
- console.log(' 1. Guided — agent pauses for your review at each step (recommended)');
221
- console.log(' 2. Yolo — agent runs full workflows autonomously\n');
222
- const modeInput = await rl.question(' Select [1-2]: ');
223
- const defaultMode = modeInput.trim() === '2' ? 'yolo' : 'guided';
373
+ console.log(' 3. Gemini (Google)');
374
+ console.log(' 4. I don\'t have one yet — show me free options\n');
224
375
 
225
- rl.close();
376
+ const choice = (await rl.question(' Select [1-4]: ')).trim();
226
377
 
227
- // Install files
228
- console.log('\n' + line());
229
- console.log(' Installing...');
230
- console.log(line() + '\n');
378
+ if (choice === '4') {
379
+ showFreeToolsHelp();
380
+ rl.close();
381
+ process.exit(0);
382
+ }
231
383
 
232
- copyDir(PACKAGE_ROOT, ventureOSDir, SKIP);
233
- console.log(' ✓ Framework files installed');
384
+ const providerKey = ({ '1': 'anthropic', '2': 'openai', '3': 'gemini' })[choice] ?? 'anthropic';
385
+ const apiKey = await promptForAPIKey(rl, providerKey);
386
+ if (apiKey) return { providerKey, apiKey };
387
+ // null = user wants to switch provider — loop again
388
+ }
389
+ }
234
390
 
235
- const config = generateConfig({ userName, researchDepth, llm, defaultMode });
236
- fs.writeFileSync(path.join(ventureOSDir, 'config.yaml'), config, 'utf8');
237
- console.log(' Configuration written → ventureOS/config.yaml');
391
+ function showFreeToolsHelp() {
392
+ console.log('\n' + line());
393
+ console.log(' AI tools you can use for free — no API key needed:\n');
394
+ console.log(' Antigravity (Google) — free preview, Gemini + Claude + more');
395
+ console.log(' → https://antigravity.dev\n');
396
+ console.log(' Cursor — popular AI code editor');
397
+ console.log(' → https://cursor.com\n');
398
+ console.log(' Windsurf — AI IDE by Codeium');
399
+ console.log(' → https://windsurf.com\n');
400
+ console.log(' Once installed, run npx ventureos again and we\'ll detect it.');
401
+ console.log(line() + '\n');
402
+ }
403
+
404
+ // ─── Main Flow ─────────────────────────────────────────────────────────────────
405
+
406
+ async function main() {
407
+ showBanner();
408
+
409
+ const projectRoot = process.cwd();
410
+ const ventureOSDir = path.join(projectRoot, 'ventureOS');
411
+ const configPath = path.join(ventureOSDir, 'config.yaml');
412
+ const rl = readline.createInterface({ input, output });
238
413
 
239
- const venturesDir = path.join(targetDir, '_ventures');
240
- if (!fs.existsSync(venturesDir)) {
241
- fs.mkdirSync(venturesDir, { recursive: true });
242
- fs.writeFileSync(path.join(venturesDir, '.gitkeep'), '', 'utf8');
414
+ try {
415
+ // ── Already installed ──────────────────────────────────────────────────
416
+ if (fs.existsSync(configPath)) {
417
+ const config = parseSimpleYaml(fs.readFileSync(configPath, 'utf8'));
418
+ console.log(` Welcome back, ${config.user_name || 'Founder'}!\n`);
419
+ console.log(' VentureOS is already set up in this folder.');
420
+ console.log(' To update your settings, run: npx ventureos config\n');
421
+ await launchChat(rl, projectRoot, config);
422
+ return;
243
423
  }
244
- console.log(' ✓ Output folder ready → _ventures/');
245
424
 
246
- const gitignorePath = path.join(targetDir, '.gitignore');
247
- if (!fs.existsSync(gitignorePath)) {
248
- fs.writeFileSync(gitignorePath, '# VentureOS outputs\n_ventures/\nnode_modules/\n.DS_Store\n', 'utf8');
249
- console.log(' ✓ .gitignore created');
425
+ // ── Environment scan ───────────────────────────────────────────────────
426
+ console.log(' Scanning your environment...\n');
427
+ const detectedIDEs = detectIDEs();
428
+
429
+ if (detectedIDEs.length > 0) {
430
+ detectedIDEs.forEach(ide => {
431
+ console.log(` ✓ ${ide.label} detected — ${ide.description}`);
432
+ });
433
+ console.log('');
434
+ } else {
435
+ console.log(' No AI tools found on this computer.\n');
250
436
  }
251
437
 
438
+ // ── Route ──────────────────────────────────────────────────────────────
439
+ let chosenIDE = null;
440
+
441
+ if (detectedIDEs.length === 1) {
442
+ const ide = detectedIDEs[0];
443
+ console.log(` Good news: ${ide.label} comes with AI built in — ${ide.description}.\n`);
444
+ const ans = (await rl.question(` Set up VentureOS for ${ide.label}? (Y/n): `)).trim().toLowerCase();
445
+ if (!ans || ans === 'y' || ans === 'yes') {
446
+ chosenIDE = ide;
447
+ } else {
448
+ // User declined IDE — fall through to API key path
449
+ const { providerKey, apiKey } = await selectProviderAndKey(rl);
450
+ await installAndChat(rl, projectRoot, ventureOSDir, configPath, { forIDE: false, providerKey, apiKey });
451
+ return;
452
+ }
453
+ } else if (detectedIDEs.length > 1) {
454
+ console.log(' Which would you like to use?\n');
455
+ detectedIDEs.forEach((ide, i) => {
456
+ const tag = i === 0 ? ' ← recommended' : '';
457
+ console.log(` ${i + 1}. ${ide.label} — ${ide.description}${tag}`);
458
+ });
459
+ console.log(` ${detectedIDEs.length + 1}. I'd rather use my own API key\n`);
460
+ const idx = parseInt((await rl.question(' Select: ')).trim(), 10) - 1;
461
+ if (idx >= 0 && idx < detectedIDEs.length) {
462
+ chosenIDE = detectedIDEs[idx];
463
+ } else {
464
+ const { providerKey, apiKey } = await selectProviderAndKey(rl);
465
+ await installAndChat(rl, projectRoot, ventureOSDir, configPath, { forIDE: false, providerKey, apiKey });
466
+ return;
467
+ }
468
+ } else {
469
+ // Nothing detected
470
+ console.log(' How would you like to run VentureOS?\n');
471
+ console.log(' 1. I have an API key (OpenAI, Claude, or Gemini)');
472
+ console.log(' 2. Show me free options — no key needed\n');
473
+ const choice = (await rl.question(' Select [1-2]: ')).trim();
474
+ if (choice === '2') {
475
+ showFreeToolsHelp();
476
+ rl.close();
477
+ return;
478
+ }
479
+ const { providerKey, apiKey } = await selectProviderAndKey(rl);
480
+ await installAndChat(rl, projectRoot, ventureOSDir, configPath, { forIDE: false, providerKey, apiKey });
481
+ return;
482
+ }
483
+
484
+ // ── IDE setup ──────────────────────────────────────────────────────────
485
+ const { userName, researchDepth, defaultMode } = await runSetupWizard(rl, { forIDE: true });
486
+ rl.close();
487
+
252
488
  console.log('\n' + line());
253
- console.log(' ✅ VentureOS is ready!');
254
- console.log(line());
489
+ console.log(' Installing...');
490
+ console.log(line() + '\n');
255
491
 
256
- showNextSteps(ventureOSDir, targetDir);
492
+ const configYaml = generateConfig({ userName, researchDepth, llm: 'anthropic', defaultMode });
493
+ installFiles(projectRoot, ventureOSDir, configYaml);
494
+
495
+ console.log('\n' + line());
496
+ console.log(' VentureOS is ready!');
497
+ console.log(line() + '\n');
498
+ console.log(" Here's how to start:\n");
499
+ chosenIDE.instructions(projectRoot).forEach(l => console.log(l));
500
+ console.log('\n' + line() + '\n');
257
501
 
258
502
  } catch (err) {
259
503
  rl.close();
260
504
  if (err.code === 'ERR_USE_AFTER_CLOSE') return;
261
- console.error('\n ❌ Installation error:', err.message);
262
- process.exit(1);
505
+ throw err;
263
506
  }
264
507
  }
265
508
 
266
- // ─── Start / Chat ──────────────────────────────────────────────────────────────
509
+ async function installAndChat(rl, projectRoot, ventureOSDir, configPath, { forIDE, providerKey, apiKey }) {
510
+ const { userName, researchDepth, llm, defaultMode } = await runSetupWizard(rl, { forIDE });
267
511
 
268
- async function startChat() {
269
- console.log('\n');
270
- console.log(' ┌' + '─'.repeat(52) + '');
271
- console.log(' │ │');
272
- console.log(' │ 🚀 VentureOS Starting Victor │');
273
- console.log(' │ │');
274
- console.log(' └' + '─'.repeat(52) + '┘');
275
- console.log('\n');
512
+ console.log('\n' + line());
513
+ console.log(' Installing...');
514
+ console.log(line() + '\n');
515
+
516
+ const configYaml = generateConfig({ userName, researchDepth, llm, defaultMode });
517
+ installFiles(projectRoot, ventureOSDir, configYaml);
518
+
519
+ console.log('\n' + line());
520
+ console.log(' All set! Starting Victor...');
521
+ console.log(line() + '\n');
522
+
523
+ const config = parseSimpleYaml(configYaml);
524
+ await launchChat(rl, projectRoot, config, { providerKey, apiKey });
525
+ }
526
+
527
+ // ─── Reconfigure ───────────────────────────────────────────────────────────────
528
+
529
+ async function reconfigure() {
530
+ showBanner();
276
531
 
277
532
  const projectRoot = process.cwd();
278
533
  const configPath = path.join(projectRoot, 'ventureOS', 'config.yaml');
279
534
 
280
535
  if (!fs.existsSync(configPath)) {
281
- console.error(' VentureOS is not installed here. Run: npx ventureos install\n');
536
+ console.error(' VentureOS is not set up here. Run: npx ventureos\n');
282
537
  process.exit(1);
283
538
  }
284
539
 
540
+ const current = parseSimpleYaml(fs.readFileSync(configPath, 'utf8'));
541
+ console.log(' Current settings:\n');
542
+ console.log(` Name: ${current.user_name || '—'}`);
543
+ console.log(` Research: ${current.research_depth || '—'}`);
544
+ console.log(` Mode: ${current.default_mode || '—'}`);
545
+ console.log(` Provider: ${current.llm || '—'}\n`);
546
+
547
+ const rl = readline.createInterface({ input, output });
548
+ try {
549
+ const { userName, researchDepth, llm, defaultMode } = await runSetupWizard(rl, { forIDE: false });
550
+ rl.close();
551
+ const newConfig = generateConfig({ userName, researchDepth, llm, defaultMode });
552
+ fs.writeFileSync(configPath, newConfig, 'utf8');
553
+ console.log('\n ✓ Configuration updated → ventureOS/config.yaml\n');
554
+ } catch (err) {
555
+ rl.close();
556
+ if (err.code === 'ERR_USE_AFTER_CLOSE') return;
557
+ throw err;
558
+ }
559
+ }
560
+
561
+ // ─── Legacy start command ───────────────────────────────────────────────────────
562
+
563
+ async function legacyStart() {
564
+ showBanner();
565
+ const projectRoot = process.cwd();
566
+ const configPath = path.join(projectRoot, 'ventureOS', 'config.yaml');
567
+ if (!fs.existsSync(configPath)) {
568
+ console.error(' VentureOS is not set up here. Run: npx ventureos\n');
569
+ process.exit(1);
570
+ }
285
571
  const config = parseSimpleYaml(fs.readFileSync(configPath, 'utf8'));
286
572
  const rl = readline.createInterface({ input, output });
573
+ try {
574
+ await launchChat(rl, projectRoot, config);
575
+ } finally {
576
+ rl.close();
577
+ }
578
+ }
287
579
 
288
- // ── Select provider from config ────────────────────────────────────────────
289
- const providerKey = PROVIDERS[config.llm] ? config.llm : 'anthropic';
580
+ // ─── Chat ───────────────────────────────────────────────────────────────────────
581
+
582
+ async function launchChat(rl, projectRoot, config, credentials = null) {
583
+ const providerKey = credentials?.providerKey || (PROVIDERS[config.llm] ? config.llm : 'anthropic');
290
584
  const provider = PROVIDERS[providerKey];
291
585
 
292
- // ── Get API key or use CLI mode ────────────────────────────────────────────
293
- let apiKey = process.env[provider.envVar];
294
- let useCLI = false;
295
- let cliCmd = null;
586
+ // ── Resolve API key ────────────────────────────────────────────────────────
587
+ let apiKey = credentials?.apiKey || process.env[provider.envVar];
296
588
 
297
589
  if (!apiKey) {
298
- const cli = detectCLI(providerKey);
299
- if (cli) {
300
- console.log(`\n 🔑 ${provider.envVar} not set in environment.\n`);
301
- console.log(` How would you like to connect?\n`);
302
- console.log(` 1. Enter API key`);
303
- console.log(` 2. Use ${cli.label} (detected on your system)\n`);
304
- const choice = (await rl.question(' Select [1-2]: ')).trim();
305
- if (choice === '2') {
306
- useCLI = true;
307
- cliCmd = cli.cmd;
308
- } else {
309
- apiKey = (await rl.question(`\n Enter your ${provider.label} API key: `)).trim();
310
- if (!apiKey) {
311
- console.error('\n ❌ No API key provided.\n');
312
- rl.close();
313
- process.exit(1);
314
- }
315
- console.log(`\n 💡 Tip: export ${provider.envVar}=your-key to skip this next time.\n`);
316
- }
317
- } else {
318
- console.log(`\n 🔑 ${provider.envVar} not set in environment.`);
319
- apiKey = (await rl.question(` Enter your ${provider.label} API key: `)).trim();
320
- if (!apiKey) {
321
- console.error('\n ❌ No API key provided.\n');
322
- rl.close();
323
- process.exit(1);
324
- }
325
- console.log(`\n 💡 Tip: export ${provider.envVar}=your-key to skip this next time.\n`);
590
+ apiKey = await promptForAPIKey(rl, providerKey);
591
+ if (!apiKey) {
592
+ // user wants to switch provider tell them to reconfigure
593
+ console.log('\n Run npx ventureos config to change your AI provider.\n');
594
+ rl.close();
595
+ process.exit(0);
326
596
  }
327
597
  }
328
598
 
329
- // ── If using Claude CLI, redirect to native Claude Code experience ─────────
330
- if (useCLI && cliCmd === 'claude') {
331
- console.log(line());
332
- console.log(' Use Claude Code natively — it\'s a much better experience.\n');
333
- console.log(' In Claude Code, start your VentureOS session by typing:\n');
334
- console.log(' @ventureOS/venture-master.md\n');
335
- console.log(' That gives you full markdown rendering, streaming, and all');
336
- console.log(' native Claude Code features — no terminal wrapper needed.');
337
- console.log(line() + '\n');
338
- rl.close();
339
- process.exit(0);
340
- }
341
-
342
- // ── Load system prompt ─────────────────────────────────────────────────────
599
+ // ── Build system prompt ────────────────────────────────────────────────────
343
600
  const masterPath = path.join(projectRoot, 'ventureOS', 'venture-master.md');
344
- let systemPrompt = fs.readFileSync(masterPath, 'utf8')
345
- .replace(/\{project-root\}/g, projectRoot)
601
+ const systemPrompt = fs.readFileSync(masterPath, 'utf8')
602
+ .replace(/\{project-root\}/g, projectRoot)
346
603
  .replace(/\{communication_language\}/g, 'English')
347
- .replace(/\{user_name\}/g, config.user_name || 'Founder')
348
- .replace(/\{llm\}/g, config.llm || 'anthropic')
349
- .replace(/\{research_depth\}/g, config.research_depth || 'standard')
350
- .replace(/\{default_mode\}/g, config.default_mode || 'guided')
351
- .replace(/\{output_folder\}/g, config.output_folder || '_ventures');
352
-
353
- // ── Inject config + venture state as context ───────────────────────────────
354
- const configContent = fs.readFileSync(configPath, 'utf8');
355
- const statePath = path.join(projectRoot, 'ventureOS', '_memory', 'venture-state.yaml');
356
- const stateContent = fs.existsSync(statePath)
604
+ .replace(/\{user_name\}/g, config.user_name || 'Founder')
605
+ .replace(/\{llm\}/g, config.llm || 'anthropic')
606
+ .replace(/\{research_depth\}/g, config.research_depth || 'standard')
607
+ .replace(/\{default_mode\}/g, config.default_mode || 'guided')
608
+ .replace(/\{output_folder\}/g, config.output_folder || '_ventures');
609
+
610
+ const configContent = fs.readFileSync(path.join(projectRoot, 'ventureOS', 'config.yaml'), 'utf8');
611
+ const statePath = path.join(projectRoot, 'ventureOS', '_memory', 'venture-state.yaml');
612
+ const stateContent = fs.existsSync(statePath)
357
613
  ? fs.readFileSync(statePath, 'utf8')
358
614
  : 'No venture state yet — this is a fresh start.';
359
615
 
@@ -363,25 +619,23 @@ async function startChat() {
363
619
  `--- ventureOS/_memory/venture-state.yaml ---\n${stateContent}`;
364
620
 
365
621
  console.log(line());
366
- console.log(` Connected ${useCLI ? `via ${cliCmd} CLI` : `to ${provider.label}`}`);
367
- console.log(` Type your message and press Enter. Type "exit" or Ctrl+C to quit.`);
622
+ console.log(` Connected to ${provider.label}`);
623
+ console.log(' Type your message and press Enter. Type "exit" to quit.');
368
624
  console.log(line() + '\n');
369
625
 
370
626
  const messages = [];
371
627
 
372
- // ── Initial activation call ────────────────────────────────────────────────
628
+ // ── Activation call ────────────────────────────────────────────────────────
373
629
  showSpinner(' Victor is thinking');
374
630
  let firstResponse;
375
631
  try {
376
- firstResponse = useCLI
377
- ? await callViaCLI(cliCmd, systemPrompt, [{ role: 'user', content: activationMsg }])
378
- : await callLLM(providerKey, apiKey, provider.defaultModel, systemPrompt, [{ role: 'user', content: activationMsg }]);
632
+ firstResponse = await callLLM(providerKey, apiKey, provider.defaultModel, systemPrompt, [
633
+ { role: 'user', content: activationMsg },
634
+ ]);
379
635
  } catch (err) {
380
636
  stopSpinner();
381
- console.error(`\n ❌ API error: ${err.message}`);
382
- console.error(` Check your API key and try again.\n`);
383
- rl.close();
384
- process.exit(1);
637
+ await handleConnectionError(rl, err, providerKey, projectRoot, config);
638
+ return;
385
639
  }
386
640
  stopSpinner();
387
641
 
@@ -390,35 +644,30 @@ async function startChat() {
390
644
  messages.push({ role: 'assistant', content: firstResponse });
391
645
  await autoLoadAgents(firstResponse, messages, projectRoot);
392
646
 
393
- // ── Main chat loop ─────────────────────────────────────────────────────────
647
+ // ── Chat loop ──────────────────────────────────────────────────────────────
394
648
  while (true) {
395
649
  let userInput;
396
- try {
397
- userInput = await rl.question(' You: ');
398
- } catch {
399
- break; // Ctrl+C
400
- }
650
+ try { userInput = await rl.question(' You: '); }
651
+ catch { break; }
401
652
 
402
653
  const trimmed = userInput.trim();
403
654
  if (!trimmed) continue;
404
655
  if (['exit', 'quit', 'da', '/exit'].includes(trimmed.toLowerCase())) {
405
- console.log('\n Victor: Safe travels. Your venture state has been saved. 🚀\n');
656
+ console.log('\n Victor: Safe travels. Your venture state has been saved.\n');
406
657
  break;
407
658
  }
408
659
 
409
660
  messages.push({ role: 'user', content: trimmed });
410
-
411
661
  showSpinner(' Victor is thinking');
662
+
412
663
  let response;
413
664
  try {
414
- response = useCLI
415
- ? await callViaCLI(cliCmd, systemPrompt, messages)
416
- : await callLLM(providerKey, apiKey, provider.defaultModel, systemPrompt, messages);
665
+ response = await callLLM(providerKey, apiKey, provider.defaultModel, systemPrompt, messages);
417
666
  } catch (err) {
418
667
  stopSpinner();
419
- console.error(`\n ❌ API error: ${err.message}\n`);
668
+ console.error(`\n ❌ ${err.message}\n`);
420
669
  messages.pop();
421
- continue;
670
+ continue; // stay in the loop — user can retry
422
671
  }
423
672
  stopSpinner();
424
673
 
@@ -426,24 +675,37 @@ async function startChat() {
426
675
  messages.push({ role: 'assistant', content: response });
427
676
  await autoLoadAgents(response, messages, projectRoot);
428
677
  }
429
-
430
- rl.close();
431
678
  }
432
679
 
433
- // ─── CLI Detection ─────────────────────────────────────────────────────────────
680
+ async function handleConnectionError(rl, err, providerKey, projectRoot, config) {
681
+ const provider = PROVIDERS[providerKey];
682
+ console.error(`\n ❌ Could not connect to ${provider.label}`);
683
+ console.error(` ${err.message}\n`);
434
684
 
435
- function detectCLI(providerKey) {
436
- const tool = CLI_TOOLS[providerKey];
437
- if (!tool) return null;
438
- try {
439
- const result = spawnSync('which', [tool.cmd], { encoding: 'utf8', stdio: 'pipe' });
440
- return result.status === 0 && result.stdout.trim() ? tool : null;
441
- } catch {
442
- return null;
685
+ console.log(' What would you like to do?\n');
686
+ console.log(' 1. Try a different API key');
687
+ console.log(` 2. Get a new key → ${provider.keyUrl}`);
688
+ console.log(' 3. Exit\n');
689
+
690
+ const choice = (await rl.question(' Select [1-3]: ')).trim();
691
+
692
+ if (choice === '1') {
693
+ const key = (await rl.question(`\n Paste your ${provider.label} API key: `)).trim();
694
+ if (key) {
695
+ await launchChat(rl, projectRoot, config, { providerKey, apiKey: key });
696
+ return;
697
+ }
698
+ } else if (choice === '2') {
699
+ console.log(`\n Open: ${provider.keyUrl}`);
700
+ console.log(' Then run npx ventureos again.\n');
443
701
  }
702
+
703
+ rl.close();
704
+ process.exit(0);
444
705
  }
445
706
 
446
- // ─── Spinner ───────────────────────────────────────────────────────────────────
707
+ // ─── Spinner ────────────────────────────────────────────────────────────────────
708
+
447
709
  function showSpinner(msg) {
448
710
  const frames = ['⠋', '⠙', '⠹', '⠸', '⠼', '⠴', '⠦', '⠧', '⠇', '⠏'];
449
711
  let i = 0;
@@ -463,16 +725,13 @@ function stopSpinner() {
463
725
  async function autoLoadAgents(response, messages, projectRoot) {
464
726
  const pattern = /ventureOS\/agents\/([\w-]+\.md)/g;
465
727
  const files = [...new Set([...response.matchAll(pattern)].map(m => m[1]))];
466
-
467
728
  for (const filename of files) {
468
729
  const alreadyLoaded = messages.some(
469
730
  m => m.role === 'user' && m.content.includes(`ventureOS/agents/${filename}`)
470
731
  );
471
732
  if (alreadyLoaded) continue;
472
-
473
733
  const agentPath = path.join(projectRoot, 'ventureOS', 'agents', filename);
474
734
  if (!fs.existsSync(agentPath)) continue;
475
-
476
735
  const content = fs.readFileSync(agentPath, 'utf8');
477
736
  messages.push({
478
737
  role: 'user',
@@ -485,53 +744,39 @@ async function autoLoadAgents(response, messages, projectRoot) {
485
744
  }
486
745
  }
487
746
 
488
- // ─── Markdown renderer (terminal-friendly, zero deps) ─────────────────────────
747
+ // ─── Markdown renderer ────────────────────────────────────────────────────────
489
748
 
490
749
  function indentText(text) {
491
- const B = '\x1b[1m', D = '\x1b[2m', R = '\x1b[0m', C = '\x1b[36m';
750
+ const B = '\x1b[1m', D = '\x1b[2m', R = '\x1b[0m';
492
751
  let inCode = false;
493
752
  const out = [];
494
-
495
753
  for (const raw of text.split('\n')) {
496
- // Code fence toggle
497
754
  if (raw.trimStart().startsWith('```')) {
498
755
  inCode = !inCode;
499
756
  out.push(D + ' ' + '─'.repeat(40) + R);
500
757
  continue;
501
758
  }
502
- if (inCode) { out.push(D + ' ' + raw + R); continue; }
503
-
504
- // Horizontal rule
505
- if (/^[-─]{3,}$/.test(raw.trim())) { out.push(' ' + '─'.repeat(50)); continue; }
506
-
507
- // Headings
508
- if (raw.startsWith('### ')) { out.push('\n ' + B + raw.slice(4).trim() + R); continue; }
509
- if (raw.startsWith('## ')) { out.push('\n ' + B + raw.slice(3).trim() + R); continue; }
510
- if (raw.startsWith('# ')) { out.push('\n ' + B + raw.slice(2).trim().toUpperCase() + R); continue; }
511
-
512
- // Table separator — skip
759
+ if (inCode) { out.push(D + ' ' + raw + R); continue; }
760
+ if (/^[-─]{3,}$/.test(raw.trim())) { out.push(' ' + '─'.repeat(52)); continue; }
761
+ if (raw.startsWith('### ')) { out.push('\n ' + B + raw.slice(4).trim() + R); continue; }
762
+ if (raw.startsWith('## ')) { out.push('\n ' + B + raw.slice(3).trim() + R); continue; }
763
+ if (raw.startsWith('# ')) { out.push('\n ' + B + raw.slice(2).trim().toUpperCase() + R); continue; }
513
764
  if (/^\|[\s|:-]+\|$/.test(raw.trim())) continue;
514
-
515
- // Table row
516
765
  if (raw.trim().startsWith('|') && raw.trim().endsWith('|')) {
517
766
  const cells = raw.split('|').slice(1, -1).map(c => c.trim());
518
767
  out.push(' ' + cells.join(' │ ').replace(/\*\*(.+?)\*\*/g, B + '$1' + R));
519
768
  continue;
520
769
  }
521
-
522
- // Inline: bold, italic, code
523
- const line = raw
770
+ const ln = raw
524
771
  .replace(/\*\*(.+?)\*\*/g, B + '$1' + R)
525
772
  .replace(/\*(.+?)\*/g, '$1')
526
773
  .replace(/`([^`]+)`/g, D + '$1' + R);
527
-
528
- out.push(' ' + line);
774
+ out.push(' ' + ln);
529
775
  }
530
-
531
776
  return out.join('\n');
532
777
  }
533
778
 
534
- // ─── LLM API calls — zero dependencies, native fetch ──────────────────────────
779
+ // ─── LLM API calls ────────────────────────────────────────────────────────────
535
780
 
536
781
  async function callLLM(provider, apiKey, model, system, messages) {
537
782
  if (provider === 'anthropic') return callAnthropic(apiKey, model, system, messages);
@@ -540,46 +785,6 @@ async function callLLM(provider, apiKey, model, system, messages) {
540
785
  throw new Error(`Unknown provider: ${provider}`);
541
786
  }
542
787
 
543
- async function callViaCLI(cliCmd, system, messages) {
544
- // Build full context: system + conversation history + latest user message.
545
- // Sent via stdin to avoid ARG_MAX limits and CLI option-parsing issues
546
- // (e.g. prompts that start with "---" being misread as flags).
547
- let prompt = system + '\n\n';
548
-
549
- for (const msg of messages.slice(0, -1)) {
550
- const role = msg.role === 'user' ? 'Human' : 'Assistant';
551
- prompt += `${role}: ${msg.content}\n\n`;
552
- }
553
-
554
- const lastMsg = messages[messages.length - 1];
555
- prompt += `Human: ${lastMsg.content}`;
556
-
557
- return new Promise((resolve, reject) => {
558
- const proc = spawn(cliCmd, ['--print', '--dangerously-skip-permissions'], {
559
- stdio: ['pipe', 'pipe', 'pipe'],
560
- });
561
-
562
- let stdout = '';
563
- let stderr = '';
564
-
565
- proc.stdout.on('data', chunk => { stdout += chunk; });
566
- proc.stderr.on('data', chunk => { stderr += chunk; });
567
-
568
- proc.on('close', code => {
569
- if (code !== 0) {
570
- reject(new Error(stderr.trim() || `${cliCmd} CLI exited with code ${code}`));
571
- } else {
572
- resolve(stdout.trim());
573
- }
574
- });
575
-
576
- proc.on('error', reject);
577
-
578
- proc.stdin.write(prompt, 'utf8');
579
- proc.stdin.end();
580
- });
581
- }
582
-
583
788
  async function callAnthropic(apiKey, model, system, messages) {
584
789
  const res = await fetch('https://api.anthropic.com/v1/messages', {
585
790
  method: 'POST',
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "ventureos",
3
- "version": "1.0.9",
3
+ "version": "1.0.11",
4
4
  "description": "VentureOS — AI-powered venture building framework. From raw idea to investor-ready pitch in 12 structured weeks.",
5
5
  "type": "module",
6
6
  "bin": {