vibepup 1.0.2 → 1.0.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -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
@@ -62,6 +93,11 @@ vibepup --tui
62
93
  vibepup free
63
94
  ```
64
95
 
96
+ ### 1f. Doctor (diagnose setup issues)
97
+ ```bash
98
+ vibepup doctor
99
+ ```
100
+
65
101
  ### 2. Fetch!
66
102
  Go to any empty folder and tell Vibepup what to build.
67
103
 
@@ -105,6 +141,52 @@ Vibepup works out of the box. For the easiest free-tier bootstrap, run:
105
141
  vibepup free
106
142
  ```
107
143
 
144
+ ### ✅ Full Onboarding (step-by-step)
145
+
146
+ #### Step 0: Diagnose (recommended)
147
+ ```bash
148
+ vibepup doctor
149
+ ```
150
+ This checks Node/npm/opencode and your model registry.
151
+
152
+ #### Step 1: Install Node 20+
153
+ Free auth requires Node 20+.
154
+ - **WSL/Linux:** `nvm install 20 && nvm use 20`
155
+ - **Windows:** https://nodejs.org/en/download
156
+
157
+ #### Step 2: Fix npm permissions (WSL/Linux)
158
+ If npm fails with `EACCES`:
159
+ ```bash
160
+ mkdir -p ~/.npm-global
161
+ npm config set prefix ~/.npm-global
162
+ echo 'export PATH=~/.npm-global/bin:$PATH' >> ~/.bashrc
163
+ source ~/.bashrc
164
+ ```
165
+ Then retry the install.
166
+
167
+ #### Step 3: Install opencode
168
+ ```bash
169
+ npm install -g opencode-ai
170
+ ```
171
+
172
+ #### Step 4: Free-tier auth
173
+ ```bash
174
+ npm install -g opencode-antigravity-auth
175
+ opencode auth login antigravity
176
+ opencode models --refresh
177
+ ```
178
+
179
+ If you cannot open a browser:
180
+ ```bash
181
+ opencode auth print-token antigravity
182
+ export OPENCODE_ANTIGRAVITY_TOKEN="<token>"
183
+ ```
184
+
185
+ #### Step 5: Run Vibepup
186
+ ```bash
187
+ vibepup --watch
188
+ ```
189
+
108
190
  If `opencode` is missing, Vibepup will try to install it on Linux/macOS and then guide you. You can also set up a free tier manually:
109
191
 
110
192
  ```bash
@@ -119,12 +201,26 @@ export OPENCODE_ANTIGRAVITY_TOKEN="<token>"
119
201
  ```
120
202
 
121
203
  ### TUI build (optional)
122
- TUI requires Go 1.22+.
204
+ TUI requires Go 1.22+. If you skip this, `vibepup --tui` will try `go run .` and needs `go` in your PATH.
123
205
  ```bash
124
206
  cd npm-package/tui
125
-
126
- go build -o vibepup-tui
207
+ go build -o vibepup-tui .
127
208
  ```
209
+ Or from `npm-package`: `npm run build:tui`.
210
+
211
+ ### Run locally (development)
212
+ To test the Vibepup CLI from this repo without publishing:
213
+
214
+ 1. **Build the TUI** (needed for `--tui`; avoids "spawn go ENOENT"):
215
+ ```bash
216
+ cd npm-package && npm run build:tui
217
+ ```
218
+ 2. **Run the local package:**
219
+ ```bash
220
+ cd npm-package && npx . --tui
221
+ ```
222
+ Or run the CLI engine: `npx . --watch`, `npx . 3`, etc.
223
+ 3. **Optional – use globally while developing:** `cd npm-package && npm link`, then `vibepup --tui` (or `vibepup --watch`) from any directory.
128
224
 
129
225
  Vibepup also supports manual config in `~/.config/ralph/config.json`:
130
226
 
@@ -145,5 +241,25 @@ Vibepup also supports manual config in `~/.config/ralph/config.json`:
145
241
  * **Build Mode**: When `repo-map.md` exists, Vibepup executes tasks from `prd.md`.
146
242
 
147
243
 
244
+ ## 🎛️ TUI flags (Go)
245
+ TUI lives in `npm-package/tui` (Go 1.22+). Helpful flags:
246
+
247
+ - `--quiet` reduce motion/sass; `--dense` increase animation density.
248
+ - `--no-emoji` force ASCII frames; `--theme <name>` swap palettes.
249
+ - `--snark mild|spicy|unhinged` choose persona spice level.
250
+ - `--anim <preset>` pick loader (e.g., `vhs-scan`, `matrix-rain`).
251
+ - `--fx fire|matrix|none` sysc-Go header effect toggle (when wired).
252
+ - `--perf-low` lower FPS; `--no-alt` avoid alt-screen; `--force-run` bypass TTY check (CI/non-interactive).
253
+
254
+ Hotkeys: `q` quits (kills child process), `?` toggles help. Palette/anim/snark switching via command palette is planned.
255
+
256
+ ## 🛠️ Troubleshooting
257
+
258
+ - **TUI fails in CI/non-TTY**: use `--force-run` to skip TTY enforcement; add `--no-alt` to avoid alt-screen.
259
+ - **Multiple terminals keep running after quit**: press `q`; the TUI now tracks and kills the child process before exit.
260
+ - **Emoji render poorly**: add `--no-emoji` or pick a theme with `--theme=mono-chill`.
261
+ - **High CPU from animations**: add `--perf-low` or `--quiet` to slow ticks and reduce density.
262
+
263
+
148
264
  ## License
149
265
  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/runner/index.js');
39
+ const windowsRunnerPath = path.join(__dirname, '../lib/runner/index.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 = process.execPath;
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, '--', 'node', 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
  });
@@ -0,0 +1,8 @@
1
+ #!/usr/bin/env node
2
+
3
+ const path = require('path');
4
+ const { spawnSync } = require('child_process');
5
+
6
+ const runnerPath = path.join(__dirname, 'runner', 'index.js');
7
+ const result = spawnSync(process.execPath, [runnerPath, ...process.argv.slice(2)], { stdio: 'inherit' });
8
+ process.exit(result.status || 0);