vibepup 1.0.2 → 1.0.3

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.
@@ -0,0 +1,189 @@
1
+ INFO 2026-01-26T13:18:12 +54ms service=models.dev file={} refreshing
2
+ |  Bash List top-level directory contents
3
+
4
+ total 28
5
+ drwxr-xr-x 1 shantanu shantanu 204 Jan 26 18:43 .
6
+ drwxr-xr-x 1 shantanu shantanu 266 Jan 26 15:08 ..
7
+ drwxr-xr-x 1 shantanu shantanu 16 Jan 26 13:39 bin
8
+ drwxr-xr-x 1 shantanu shantanu 70 Jan 26 13:39 lib
9
+ -rw-r--r-- 1 shantanu shantanu 39 Jan 24 17:28 .npmignore
10
+ -rw-r--r-- 1 shantanu shantanu 832 Jan 26 18:10 package.json
11
+ -rw-r--r-- 1 shantanu shantanu 132 Jan 26 13:39 prd.md
12
+ -rw-r--r-- 1 shantanu shantanu 3 Jan 26 13:39 prd.state.json
13
+ -rw-r--r-- 1 shantanu shantanu 0 Jan 26 18:46 progress.log
14
+ -rw-r--r-- 1 shantanu shantanu 1541 Jan 26 18:10 PUBLISHING.md
15
+ drwxr-xr-x 1 shantanu shantanu 8 Jan 26 18:43 .ralph
16
+ -rw-r--r-- 1 shantanu shantanu 7218 Jan 26 15:08 README.md
17
+ -rw-r--r-- 1 shantanu shantanu 0 Jan 26 14:33 repo-map.md
18
+ drwxr-xr-x 1 shantanu shantanu 178 Jan 26 18:48 tui
19
+
20
+ |  Bash Recursively list repository tree
21
+
22
+ .:
23
+ bin
24
+ lib
25
+ package.json
26
+ prd.md
27
+ prd.state.json
28
+ progress.log
29
+ PUBLISHING.md
30
+ README.md
31
+ repo-map.md
32
+ tui
33
+
34
+ ./bin:
35
+ ralph.js
36
+
37
+ ./lib:
38
+ agents
39
+ prompt.md
40
+ ralph.sh
41
+ ralph-win.js
42
+
43
+ ./lib/agents:
44
+ architect.md
45
+ reviewer.md
46
+
47
+ ./tui:
48
+ animations
49
+ config
50
+ data
51
+ go.mod
52
+ go.sum
53
+ main.go
54
+ motion
55
+ persona
56
+ process
57
+ progress.log
58
+ theme
59
+ ui
60
+ vibepup-tui
61
+
62
+ ./tui/animations:
63
+ loaders.go
64
+ memes.go
65
+ registry.go
66
+
67
+ ./tui/config:
68
+ flags.go
69
+
70
+ ./tui/data:
71
+
72
+ ./tui/motion:
73
+ engine.go
74
+
75
+ ./tui/persona:
76
+ quip.go
77
+
78
+ ./tui/process:
79
+ runner.go
80
+
81
+ ./tui/theme:
82
+ registry.go
83
+
84
+ ./tui/ui:
85
+ layout.go
86
+ statusbar.go
87
+ viewport.go
88
+
89
+ |  Bash Show git status with untracked files
90
+
91
+ MM npm-package/PUBLISHING.md
92
+ M npm-package/bin/ralph.js
93
+ M npm-package/lib/ralph.sh
94
+ M npm-package/package.json
95
+ M npm-package/tui/config/flags.go
96
+ M npm-package/tui/go.mod
97
+ M npm-package/tui/go.sum
98
+ M npm-package/tui/main.go
99
+ M npm-package/tui/motion/engine.go
100
+ M npm-package/tui/persona/quip.go
101
+ ?? npm-package/.ralph/runs/iter-0001/agent_response.txt
102
+ ?? npm-package/.ralph/runs/latest
103
+ ?? npm-package/tui/process/runner.go
104
+ ?? npm-package/tui/ui/viewport.go
105
+
106
+ [Category+Skill Reminder]
107
+
108
+ You are an orchestrator agent. Consider whether this work should be delegated:
109
+
110
+ **DELEGATE when:**
111
+ - UI/Frontend work → category: "visual-engineering", skills: ["frontend-ui-ux"]
112
+ - Complex logic/architecture → category: "ultrabrain"
113
+ - Quick/trivial tasks → category: "quick"
114
+ - Git operations → skills: ["git-master"]
115
+ - Browser automation → skills: ["playwright"] or ["agent-browser"]
116
+
117
+ **DO IT YOURSELF when:**
118
+ - Gathering context/exploring codebase
119
+ - Simple edits that are part of a larger task you're coordinating
120
+ - Tasks requiring your full context understanding
121
+
122
+ Example delegation:
123
+ ```
124
+ delegate_task(
125
+ category="visual-engineering",
126
+ load_skills=["frontend-ui-ux"],
127
+ description="Implement responsive navbar with animations",
128
+ run_in_background=true
129
+ )
130
+ ```
131
+
132
+ |  Bash Show repo root, branch, recent commits
133
+
134
+ /home/shantanu/ralph-project
135
+ master
136
+ b968a2c changes as per the new anim and blocking
137
+ 63735d8 docs: enhance README with TUI build instructions and local development setup
138
+ 038ab49 feat: add Windows mode selection and project documentation
139
+ c36c7da feat: optimize TUI command execution with direct vibepup invocation
140
+ 6025683 Add Windows mode selection with interactive prompt and comprehensive docs
141
+ 78c051f feat: revamp TUI with charm.sh libraries and enhance CLI flags
142
+ 170b4ae chore: update package version to 1.0.2
143
+ 67ba775 docs: add vibepup free setup command
144
+ 57c7095 feat: add vibepup free setup and improve TUI flow
145
+ cc7d3e5 chore: update package version to 1.0.1 and specify bin entry for vibepup
146
+
147
+ |  Glob {"pattern":"**/package.json","path":"/home/shantanu/ralph-project/npm-package"}
148
+ |  Glob {"pattern":"**/{tsconfig*.json,jsconfig*.json}","path":"/home/shantanu/ralph-project/npm-package"}
149
+ |  Glob {"pattern":"**/{README*,readme*,CHANGELOG*,LICENSE*,CONTRIBUTING*}","path":"/home/shantanu/ralph-project/npm-package"}
150
+ |  Glob {"pattern":"**/{src,index.* ,cli.* ,bin/*,lib/*,dist/*}","path":"/home/shantanu/ralph-project/npm-package"}
151
+ |  Grep {"pattern":"\"(name|version|type|main|module|types|exports|bin|files|scripts|dependencies|devDependencies)\"\\s*:","include":"package.json","path":"/home/shantanu/ralph-project/npm-package"}
152
+ |  ast_grep_search {"pattern":"export $$$","lang":"typescript","paths":["/home/shantanu/ralph-project/npm-package"],"context":2}
153
+ |  delegate_task {"subagent_type":"explore","run_in_background":true,"load_skills":[],"description":"Map codebase structure","prompt":"1. TASK: Map the repository's high-level structure and identify key subsystems (CLI, core library, build tooling, tests).\n2. EXPECTED OUTCOME: A concise structural map listing top-level dirs/files, entrypoints, and where core logic likely lives.\n3. REQUIRED TOOLS: functions.glob, functions.grep, functions.read (no bash).\n4. MUST DO: Find package entrypoints (bin/main/exports), identify src/lib/dist layout, note test framework and config files.\n5. MUST NOT DO: Do not propose implementations; do not modify files; do not run commands.\n6. CONTEXT: Repo at /home/shantanu/ralph-project/npm-package; goal is to populate repo-map.md."}
154
+ |  delegate_task {"subagent_type":"explore","run_in_background":true,"load_skills":[],"description":"Find patterns & conventions","prompt":"1. TASK: Discover coding conventions and patterns used across the repo (TS/JS module style, lint/format, error handling, logging, config).\n2. EXPECTED OUTCOME: A checklist of conventions + where they are defined (configs, sample files).\n3. REQUIRED TOOLS: functions.grep, functions.glob, functions.read.\n4. MUST DO: Locate ESLint/Prettier configs, tsconfig settings, test runner config, Node ESM/CJS conventions.\n5. MUST NOT DO: Do not change files; do not run builds/tests.\n6. CONTEXT: PLAN mode mapping only."}
155
+ |  delegate_task {"subagent_type":"explore","run_in_background":true,"load_skills":[],"description":"AST surface scan","prompt":"1. TASK: Use AST-oriented searching to identify the public API surface (exported functions/classes) and main modules.\n2. EXPECTED OUTCOME: A short list of key exported symbols and their defining files; note any CLI command registration.\n3. REQUIRED TOOLS: functions.ast_grep_search, functions.grep, functions.glob, functions.read.\n4. MUST DO: Focus on top-level exports and any CLI entry file.\n5. MUST NOT DO: No edits; no speculative design.\n6. CONTEXT: Repo /home/shantanu/ralph-project/npm-package."}
156
+ 1076 | const info = provider.models[modelID]
157
+ 1077 | if (!info) {
158
+ 1078 | const availableModels = Object.keys(provider.models)
159
+ 1079 | const matches = fuzzysort.go(modelID, availableModels, { limit: 3, threshold: -10000 })
160
+ 1080 | const suggestions = matches.map((m) => m.target)
161
+ 1081 | throw new ModelNotFoundError({ providerID, modelID, suggestions })
162
+ ^
163
+ ProviderModelNotFoundError: ProviderModelNotFoundError
164
+ data: {
165
+ providerID: "opencode",
166
+ modelID: "glm-4.7-free",
167
+ suggestions: [],
168
+ },
169
+
170
+ at getModel (src/provider/provider.ts:1081:13)
171
+
172
+ |  delegate_task {"subagent_type":"librarian","run_in_background":true,"load_skills":[],"description":"External: package name intel","prompt":"1. TASK: Infer likely usage patterns for this npm package based on its name once discovered (from package.json).\n2. EXPECTED OUTCOME: A brief note: comparable OSS packages, typical file layout, and what docs to mirror.\n3. REQUIRED TOOLS: functions.websearch_web_search_exa (or functions.grep_app_searchGitHub if name known).\n4. MUST DO: Wait until you know the package name; then search for similar packages and patterns.\n5. MUST NOT DO: Do not suggest code changes; do not fetch irrelevant sources.\n6. CONTEXT: We are mapping architecture only."}
173
+ 1076 | const info = provider.models[modelID]
174
+ 1077 | if (!info) {
175
+ 1078 | const availableModels = Object.keys(provider.models)
176
+ 1079 | const matches = fuzzysort.go(modelID, availableModels, { limit: 3, threshold: -10000 })
177
+ 1080 | const suggestions = matches.map((m) => m.target)
178
+ 1081 | throw new ModelNotFoundError({ providerID, modelID, suggestions })
179
+ ^
180
+ ProviderModelNotFoundError: ProviderModelNotFoundError
181
+ data: {
182
+ providerID: "opencode",
183
+ modelID: "glm-4.7-free",
184
+ suggestions: [],
185
+ },
186
+
187
+ at getModel (src/provider/provider.ts:1081:13)
188
+
189
+ |  delegate_task {"subagent_type":"librarian","run_in_background":true,"load_skills":[],"description":"External: tooling configs","prompt":"1. TASK: If the repo uses common tooling (TypeScript, eslint, prettier, vitest/jest), collect best-practice structure references.\n2. EXPECTED OUTCOME: A short set of pointers to official docs about config file roles and typical layouts.\n3. REQUIRED TOOLS: functions.websearch_web_search_exa, functions.context7_resolve-library-id, functions.context7_query-docs.\n4. MUST DO: Focus on docs about package exports/bin fields, TS project structuring for npm packages.\n5. MUST NOT DO: No implementation guidance beyond architecture mapping.\n6. CONTEXT: Used to enrich repo-map.md mapping."}
package/PUBLISHING.md CHANGED
@@ -1,5 +1,43 @@
1
1
  # Vibepup npm Publishing (from any machine)
2
2
 
3
+ cd np ## 0) Test from build (before pushing to dev npm)
4
+
5
+ Run and test the package **from the built artifacts** before publishing.
6
+
7
+ **Option A – Run from repo (fast iteration)**
8
+ Requires Go 1.22+ for TUI.
9
+
10
+ ```bash
11
+ cd npm-package
12
+ npm run build # build TUI binary (tui/vibepup-tui)
13
+ npm run run:local -- --tui # test TUI
14
+ npm run run:local -- --watch # test CLI engine
15
+ npm run run:local -- 3 # test N-iteration run
16
+ ```
17
+
18
+ **Option B – Install from local tarball (simulate npm install)**
19
+ Same as users installing from registry.
20
+
21
+ ```bash
22
+ cd npm-package
23
+ npm run pack:local # build TUI + npm pack → vibepup-1.0.2.tgz
24
+ npm install -g ./vibepup-1.0.2.tgz
25
+ vibepup --tui # or vibepup --watch, vibepup 3, etc.
26
+ ```
27
+
28
+ **Option C – `npm link` (global symlink for development)**
29
+ Changes in the repo are reflected immediately when you run `vibepup`.
30
+
31
+ ```bash
32
+ cd npm-package
33
+ npm run build
34
+ npm link
35
+ cd /any/project
36
+ vibepup --tui
37
+ ```
38
+
39
+ ---
40
+
3
41
  ## 1) Login
4
42
  ```bash
5
43
  npm adduser
@@ -19,4 +57,4 @@ npm publish --access public
19
57
  ## Notes
20
58
  - Publish must be run inside `npm-package/`.
21
59
  - If you see a `bin` warning, ensure `package.json` has: `"bin": "bin/ralph.js"`.
22
- - Windows users should have Git Bash or WSL installed to run the CLI.
60
+ - Windows users: WSL2 mode is recommended for publishing to ensure consistent environment behavior. Windows-native mode is supported but may lack some Linux-parity features.
package/README.md CHANGED
@@ -35,13 +35,44 @@ Most AI agents are black boxes that overwrite your files and get stuck in loops.
35
35
  ## 🚀 Get Started
36
36
 
37
37
  ### ✅ Works Everywhere
38
- Linux, macOS, and Windows (via Git Bash or WSL). Vibepup is portable and requires only Bash + `opencode`.
38
+ Linux, macOS, and Windows. **Recommended:** use WSL2 on Windows for full Linux parity.
39
39
 
40
40
  ### 1. Install
41
41
  ```bash
42
42
  npm install -g vibepup
43
43
  ```
44
44
 
45
+ ### Windows (choose your mode)
46
+
47
+ Vibepup supports two modes on Windows. If a TTY is detected, it will prompt you to choose; otherwise, it defaults to WSL if installed.
48
+
49
+ **Recommended: WSL2 Mode**
50
+ Best parity with Linux/macOS. Requires [WSL2](https://learn.microsoft.com/en-us/windows/wsl/install) installed.
51
+ ```bash
52
+ vibepup --platform=wsl
53
+ # or
54
+ vibepup --wsl
55
+ ```
56
+ * **Note:** When using WSL mode, run from a WSL shell or ensure paths are WSL-formatted (e.g., `/home/...` or `/mnt/c/...`). `wsl.exe` forwards arguments without path translation. [Microsoft Path Docs](https://learn.microsoft.com/en-us/windows/wsl/filesystems#mixing-linux-and-windows-commands).
57
+
58
+ **Windows-native Mode**
59
+ Simpler setup, but with limitations.
60
+ ```bash
61
+ vibepup --platform=windows
62
+ # or
63
+ vibepup --windows
64
+ ```
65
+
66
+ **Windows-native Limitations:**
67
+ - **No Bash/Curl Helpers:** Linux-specific shell scripts or `curl`-based skills may fail.
68
+ - **Reduced Parity:** Some advanced agent behaviors optimized for Linux environments might be unavailable.
69
+ - **No Design-Mode Injection:** Environment-based skill injection (like `DESIGN_MODE`) is not supported in native mode.
70
+ - **Path Differences:** Uses Windows backslashes (`\`) which can occasionally confuse agents expecting POSIX paths.
71
+
72
+ **Auto-selection Behavior:**
73
+ - If WSL is detected, Vibepup defaults to WSL mode unless explicitly overridden.
74
+ - Use `--platform=windows` or `--windows` to force native mode.
75
+
45
76
  ### 1b. bunx (no global install)
46
77
  ```bash
47
78
  bunx vibepup --watch
@@ -119,12 +150,26 @@ export OPENCODE_ANTIGRAVITY_TOKEN="<token>"
119
150
  ```
120
151
 
121
152
  ### TUI build (optional)
122
- TUI requires Go 1.22+.
153
+ TUI requires Go 1.22+. If you skip this, `vibepup --tui` will try `go run .` and needs `go` in your PATH.
123
154
  ```bash
124
155
  cd npm-package/tui
125
-
126
- go build -o vibepup-tui
156
+ go build -o vibepup-tui .
127
157
  ```
158
+ Or from `npm-package`: `npm run build:tui`.
159
+
160
+ ### Run locally (development)
161
+ To test the Vibepup CLI from this repo without publishing:
162
+
163
+ 1. **Build the TUI** (needed for `--tui`; avoids "spawn go ENOENT"):
164
+ ```bash
165
+ cd npm-package && npm run build:tui
166
+ ```
167
+ 2. **Run the local package:**
168
+ ```bash
169
+ cd npm-package && npx . --tui
170
+ ```
171
+ Or run the CLI engine: `npx . --watch`, `npx . 3`, etc.
172
+ 3. **Optional – use globally while developing:** `cd npm-package && npm link`, then `vibepup --tui` (or `vibepup --watch`) from any directory.
128
173
 
129
174
  Vibepup also supports manual config in `~/.config/ralph/config.json`:
130
175
 
@@ -145,5 +190,25 @@ Vibepup also supports manual config in `~/.config/ralph/config.json`:
145
190
  * **Build Mode**: When `repo-map.md` exists, Vibepup executes tasks from `prd.md`.
146
191
 
147
192
 
193
+ ## 🎛️ TUI flags (Go)
194
+ TUI lives in `npm-package/tui` (Go 1.22+). Helpful flags:
195
+
196
+ - `--quiet` reduce motion/sass; `--dense` increase animation density.
197
+ - `--no-emoji` force ASCII frames; `--theme <name>` swap palettes.
198
+ - `--snark mild|spicy|unhinged` choose persona spice level.
199
+ - `--anim <preset>` pick loader (e.g., `vhs-scan`, `matrix-rain`).
200
+ - `--fx fire|matrix|none` sysc-Go header effect toggle (when wired).
201
+ - `--perf-low` lower FPS; `--no-alt` avoid alt-screen; `--force-run` bypass TTY check (CI/non-interactive).
202
+
203
+ Hotkeys: `q` quits (kills child process), `?` toggles help. Palette/anim/snark switching via command palette is planned.
204
+
205
+ ## 🛠️ Troubleshooting
206
+
207
+ - **TUI fails in CI/non-TTY**: use `--force-run` to skip TTY enforcement; add `--no-alt` to avoid alt-screen.
208
+ - **Multiple terminals keep running after quit**: press `q`; the TUI now tracks and kills the child process before exit.
209
+ - **Emoji render poorly**: add `--no-emoji` or pick a theme with `--theme=mono-chill`.
210
+ - **High CPU from animations**: add `--perf-low` or `--quiet` to slow ticks and reduce density.
211
+
212
+
148
213
  ## License
149
214
  MIT
package/bin/ralph.js CHANGED
@@ -1,74 +1,190 @@
1
1
  #!/usr/bin/env node
2
2
 
3
- const { spawn } = require('child_process');
3
+ const { spawn, spawnSync } = require('child_process');
4
4
  const path = require('path');
5
5
  const os = require('os');
6
6
  const fs = require('fs');
7
+ const readline = require('readline');
7
8
 
8
- const scriptPath = path.join(__dirname, '../lib/ralph.sh');
9
- const allArgs = process.argv.slice(2);
10
- const useTui = allArgs.includes('--tui');
11
- const args = allArgs.filter((arg) => arg !== '--tui');
9
+ async function promptPlatform() {
10
+ return new Promise((resolve) => {
11
+ const rl = readline.createInterface({
12
+ input: process.stdin,
13
+ output: process.stdout
14
+ });
12
15
 
13
- try {
14
- fs.chmodSync(scriptPath, '755');
15
- } catch (err) {}
16
+ rl.question(
17
+ '\n🐾 Vibepup on Windows! Choose your mode:\n' +
18
+ ' 1) WSL (recommended) - Full Linux parity\n' +
19
+ ' 2) Windows-native - Simpler setup\n' +
20
+ 'Select (1 or 2): ',
21
+ (answer) => {
22
+ rl.close();
23
+ const choice = answer.trim();
24
+ if (choice === '1') {
25
+ resolve('wsl');
26
+ } else if (choice === '2') {
27
+ resolve('windows');
28
+ } else {
29
+ console.log('Invalid choice. Defaulting to WSL...');
30
+ resolve('wsl');
31
+ }
32
+ }
33
+ );
34
+ });
35
+ }
16
36
 
17
- console.log('🐾 Vibepup is waking up...');
37
+ async function main() {
38
+ const scriptPath = path.join(__dirname, '../lib/ralph.sh');
39
+ const windowsRunnerPath = path.join(__dirname, '../lib/ralph-win.js');
40
+ const allArgs = process.argv.slice(2);
41
+ const useTui = allArgs.includes('--tui');
18
42
 
19
- const shellOptions = { stdio: 'inherit', shell: false };
43
+ let selectedPlatform = null;
44
+ let explicitPlatformFlag = false;
45
+ const args = [];
46
+ for (const arg of allArgs) {
47
+ if (arg === '--tui') continue;
48
+ if (arg === '--wsl') {
49
+ selectedPlatform = 'wsl';
50
+ explicitPlatformFlag = true;
51
+ continue;
52
+ }
53
+ if (arg === '--windows') {
54
+ selectedPlatform = 'windows';
55
+ explicitPlatformFlag = true;
56
+ continue;
57
+ }
58
+ if (arg.startsWith('--platform=')) {
59
+ selectedPlatform = arg.split('=')[1];
60
+ explicitPlatformFlag = true;
61
+ continue;
62
+ }
63
+ args.push(arg);
64
+ }
20
65
 
21
- if (useTui) {
22
- const tuiDir = path.join(__dirname, '../tui');
23
- const binName = os.platform() === 'win32' ? 'vibepup-tui.exe' : 'vibepup-tui';
24
- const binPath = path.join(tuiDir, binName);
66
+ try {
67
+ fs.chmodSync(scriptPath, '755');
68
+ } catch (err) {}
25
69
 
26
- if (fs.existsSync(binPath)) {
27
- const tui = spawn(binPath, args, shellOptions);
28
- tui.on('error', (err) => {
29
- console.error('❌ Failed to start Vibepup TUI.');
30
- console.error(String(err));
31
- process.exit(1);
32
- });
33
- tui.on('close', (code) => process.exit(code));
34
- return;
35
- }
70
+ console.log('🐾 Vibepup is waking up...');
36
71
 
37
- if (os.platform() !== 'win32' && fs.existsSync(tuiDir)) {
38
- const goCmd = spawn('go', ['run', '.', ...args], { ...shellOptions, cwd: tuiDir });
39
- goCmd.on('error', (err) => {
40
- console.error('❌ Failed to start Vibepup TUI.');
41
- console.error(String(err));
42
- process.exit(1);
43
- });
44
- goCmd.on('close', (code) => process.exit(code));
45
- return;
46
- }
72
+ const shellOptions = { stdio: 'inherit', shell: false };
73
+ const isWindows = os.platform() === 'win32';
47
74
 
48
- console.error('❌ Vibepup TUI not available.');
49
- console.error(' Build it with:');
50
- console.error(' cd ' + tuiDir + ' && go build -o ' + binName);
51
- process.exit(1);
52
- }
75
+ const hasWsl = () => {
76
+ if (!isWindows) return false;
77
+ const res = spawnSync('wsl.exe', ['-l', '-q'], { stdio: 'ignore' });
78
+ return res.status === 0;
79
+ };
53
80
 
54
- let command = 'bash';
55
- let cmdArgs = [scriptPath, ...args];
56
- if (os.platform() === 'win32') {
57
- shellOptions.shell = true;
58
- }
81
+ const toWslPath = (winPath) => {
82
+ const resolved = path.resolve(winPath);
83
+ const drive = resolved[0].toLowerCase();
84
+ const rest = resolved.slice(2).replace(/\\/g, '/');
85
+ return `/mnt/${drive}${rest}`;
86
+ };
59
87
 
60
- const vibepup = spawn(command, cmdArgs, shellOptions);
88
+ if (useTui) {
89
+ const tuiDir = path.join(__dirname, '../tui');
90
+ const binName = os.platform() === 'win32' ? 'vibepup-tui.exe' : 'vibepup-tui';
91
+ const binPath = path.join(tuiDir, binName);
61
92
 
62
- vibepup.on('error', (err) => {
93
+ if (fs.existsSync(binPath)) {
94
+ const tuiArgs = ['--runner', scriptPath, ...args];
95
+ const tui = spawn(binPath, tuiArgs, shellOptions);
96
+ tui.on('error', (err) => {
97
+ console.error('❌ Failed to start Vibepup TUI.');
98
+ console.error(String(err));
99
+ process.exit(1);
100
+ });
101
+ tui.on('close', (code) => process.exit(code));
102
+ return;
103
+ }
104
+
105
+ if (os.platform() !== 'win32' && fs.existsSync(tuiDir)) {
106
+ const goArgs = ['run', '.', '--runner', scriptPath, ...args];
107
+ const goCmd = spawn('go', goArgs, { ...shellOptions, cwd: tuiDir });
108
+ goCmd.on('error', (err) => {
109
+ console.error('❌ Failed to start Vibepup TUI.');
110
+ console.error(String(err));
111
+ process.exit(1);
112
+ });
113
+ goCmd.on('close', (code) => process.exit(code));
114
+ return;
115
+ }
116
+
117
+ console.error('❌ Vibepup TUI not available.');
118
+ console.error(' Build it with:');
119
+ console.error(' cd ' + tuiDir + ' && go build -o ' + binName);
120
+ process.exit(1);
121
+ }
122
+
123
+ let command = 'bash';
124
+ let cmdArgs = [scriptPath, ...args];
125
+
126
+ if (isWindows) {
127
+ const wslAvailable = hasWsl();
128
+
129
+ // Interactive prompt for Windows when no explicit platform flag provided
130
+ if (!explicitPlatformFlag && process.stdin.isTTY) {
131
+ if (wslAvailable) {
132
+ selectedPlatform = await promptPlatform();
133
+ } else {
134
+ console.warn('⚠️ WSL not detected. Using Windows-native mode.');
135
+ console.warn(' 💡 Tip: install WSL2 for full Linux parity.');
136
+ selectedPlatform = 'windows';
137
+ }
138
+ } else if (!explicitPlatformFlag) {
139
+ // No TTY: auto-select WSL if available, else Windows
140
+ selectedPlatform = wslAvailable ? 'wsl' : 'windows';
141
+ if (!wslAvailable) {
142
+ console.warn('⚠️ WSL not detected. Using Windows-native mode.');
143
+ console.warn(' 💡 Tip: install WSL2 for full Linux parity.');
144
+ }
145
+ }
146
+
147
+ const normalizedPlatform = (selectedPlatform || '').toLowerCase();
148
+
149
+ if (normalizedPlatform === 'wsl' || (!normalizedPlatform && wslAvailable)) {
150
+ if (!wslAvailable) {
151
+ console.error('❌ WSL not found. Install WSL2 or use --platform=windows.');
152
+ process.exit(1);
153
+ }
154
+ const wslScriptPath = toWslPath(scriptPath);
155
+ const wslCwd = toWslPath(process.cwd());
156
+ command = 'wsl.exe';
157
+ cmdArgs = ['--cd', wslCwd, '--', 'bash', wslScriptPath, ...args];
158
+ } else {
159
+ console.warn('⚠️ Using Windows-native mode.');
160
+ console.warn(' 💡 Tip: install WSL2 for full Linux parity.');
161
+ command = process.execPath;
162
+ cmdArgs = [windowsRunnerPath, ...args];
163
+ }
164
+ }
165
+
166
+ const vibepup = spawn(command, cmdArgs, shellOptions);
167
+
168
+ vibepup.on('error', (err) => {
63
169
  console.error('❌ Failed to start Vibepup.');
64
170
  if (err.code === 'ENOENT') {
65
- console.error(' Error: Bash not found. Please install Git Bash or WSL.');
171
+ if (command === 'bash') {
172
+ console.error(' Error: Bash not found. Install WSL2 or use --platform=windows.');
173
+ } else {
174
+ console.error(' Error: Required runtime not found on PATH.');
175
+ }
66
176
  } else {
67
- console.error(String(err));
177
+ console.error(String(err));
68
178
  }
69
179
  process.exit(1);
70
- });
180
+ });
71
181
 
72
- vibepup.on('close', (code) => {
182
+ vibepup.on('close', (code) => {
73
183
  process.exit(code);
184
+ });
185
+ }
186
+
187
+ main().catch((err) => {
188
+ console.error('❌ Error:', err.message);
189
+ process.exit(1);
74
190
  });