minivibe 0.2.0 → 0.2.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +27 -37
- package/agent/agent.js +42 -34
- package/package.json +1 -1
- package/vibe.js +118 -65
package/README.md
CHANGED
|
@@ -16,21 +16,19 @@ CLI wrapper for Claude Code with mobile remote control via MiniVibe iOS app.
|
|
|
16
16
|
## Quick Start
|
|
17
17
|
|
|
18
18
|
```bash
|
|
19
|
-
# Install
|
|
19
|
+
# Install
|
|
20
20
|
npm install -g minivibe
|
|
21
21
|
|
|
22
|
-
#
|
|
23
|
-
vibe --login
|
|
24
|
-
vibe --login --headless # Server/EC2 (device code)
|
|
25
|
-
|
|
26
|
-
# Option 1: Direct bridge connection
|
|
27
|
-
vibe --bridge wss://ws.minivibeapp.com
|
|
22
|
+
# Login (one-time)
|
|
23
|
+
vibe --login
|
|
28
24
|
|
|
29
|
-
#
|
|
30
|
-
vibe
|
|
31
|
-
vibe
|
|
25
|
+
# Start coding with remote control!
|
|
26
|
+
vibe
|
|
27
|
+
vibe "Fix the bug in main.js"
|
|
32
28
|
```
|
|
33
29
|
|
|
30
|
+
> **Note:** For local-only use without remote control, just run `claude` directly.
|
|
31
|
+
|
|
34
32
|
## Installation
|
|
35
33
|
|
|
36
34
|
### From npm (Recommended)
|
|
@@ -80,22 +78,24 @@ Get token from MiniVibe iOS app: Settings > Copy Token for CLI.
|
|
|
80
78
|
|
|
81
79
|
## Usage Modes
|
|
82
80
|
|
|
83
|
-
### Direct
|
|
81
|
+
### Direct Mode (Default)
|
|
84
82
|
|
|
85
|
-
|
|
83
|
+
Just run `vibe` after logging in:
|
|
86
84
|
|
|
87
85
|
```bash
|
|
88
|
-
vibe
|
|
89
|
-
vibe
|
|
86
|
+
vibe # Start session
|
|
87
|
+
vibe "Fix the bug" # With initial prompt
|
|
88
|
+
vibe --e2e # With end-to-end encryption
|
|
90
89
|
```
|
|
91
90
|
|
|
92
91
|
### Agent Mode (Recommended for Servers)
|
|
93
92
|
|
|
94
|
-
Use a local agent to manage sessions:
|
|
93
|
+
Use a local agent to manage multiple sessions:
|
|
95
94
|
|
|
96
95
|
```bash
|
|
97
96
|
# Terminal 1: Start the agent (runs continuously)
|
|
98
|
-
vibe-agent --
|
|
97
|
+
vibe-agent --login # First time only
|
|
98
|
+
vibe-agent # Start daemon
|
|
99
99
|
|
|
100
100
|
# Terminal 2+: Create sessions via agent
|
|
101
101
|
vibe --agent
|
|
@@ -109,34 +109,25 @@ vibe --agent --name "Backend Work"
|
|
|
109
109
|
- Sessions survive network hiccups
|
|
110
110
|
- Cleaner process management
|
|
111
111
|
|
|
112
|
-
### Local Mode (No Bridge)
|
|
113
|
-
|
|
114
|
-
Run without remote control:
|
|
115
|
-
|
|
116
|
-
```bash
|
|
117
|
-
vibe # Interactive
|
|
118
|
-
vibe "Explain this code" # With prompt
|
|
119
|
-
```
|
|
120
|
-
|
|
121
112
|
## Options
|
|
122
113
|
|
|
123
114
|
### vibe
|
|
124
115
|
|
|
125
116
|
| Option | Description |
|
|
126
117
|
|--------|-------------|
|
|
127
|
-
| `--
|
|
118
|
+
| `--login` | Sign in with Google |
|
|
119
|
+
| `--headless` | Use device code flow for headless environments |
|
|
128
120
|
| `--agent [url]` | Connect via local vibe-agent (default: auto-discover) |
|
|
129
121
|
| `--name <name>` | Name this session (shown in mobile app) |
|
|
130
122
|
| `--resume <id>` | Resume a previous session (auto-detects directory) |
|
|
131
123
|
| `--attach <id>` | Attach to running session via local agent |
|
|
132
124
|
| `--remote <id>` | Remote control session via bridge (no local Claude needed) |
|
|
133
125
|
| `--list` | List running sessions on local agent |
|
|
134
|
-
| `--
|
|
135
|
-
| `--
|
|
126
|
+
| `--e2e` | Enable end-to-end encryption (auto key exchange with iOS) |
|
|
127
|
+
| `--dangerously-skip-permissions` | Auto-approve all tool executions |
|
|
128
|
+
| `--bridge <url>` | Override bridge URL (default: wss://ws.minivibeapp.com) |
|
|
136
129
|
| `--token <token>` | Set Firebase auth token manually |
|
|
137
130
|
| `--logout` | Remove stored auth token |
|
|
138
|
-
| `--dangerously-skip-permissions` | Auto-approve all tool executions |
|
|
139
|
-
| `--e2e` | Enable end-to-end encryption (auto key exchange with iOS) |
|
|
140
131
|
| `--node-pty` | Use Node.js PTY wrapper (required for Windows) |
|
|
141
132
|
| `--help, -h` | Show help message |
|
|
142
133
|
|
|
@@ -144,11 +135,11 @@ vibe "Explain this code" # With prompt
|
|
|
144
135
|
|
|
145
136
|
| Option | Description |
|
|
146
137
|
|--------|-------------|
|
|
147
|
-
| `--
|
|
148
|
-
| `--login` | Start device code login flow |
|
|
149
|
-
| `--token <token>` | Use specific Firebase token |
|
|
138
|
+
| `--login` | Sign in via device code flow |
|
|
150
139
|
| `--name <name>` | Set host display name |
|
|
151
140
|
| `--status` | Show current status and exit |
|
|
141
|
+
| `--bridge <url>` | Override bridge URL (default: wss://ws.minivibeapp.com) |
|
|
142
|
+
| `--token <token>` | Use specific Firebase token |
|
|
152
143
|
| `--help, -h` | Show help message |
|
|
153
144
|
|
|
154
145
|
## Skip Permissions Mode
|
|
@@ -156,7 +147,7 @@ vibe "Explain this code" # With prompt
|
|
|
156
147
|
For automated/headless environments where you trust the execution context:
|
|
157
148
|
|
|
158
149
|
```bash
|
|
159
|
-
vibe --dangerously-skip-permissions
|
|
150
|
+
vibe --dangerously-skip-permissions
|
|
160
151
|
vibe --dangerously-skip-permissions --agent
|
|
161
152
|
```
|
|
162
153
|
|
|
@@ -168,7 +159,7 @@ Enable E2E encryption to ensure the bridge server cannot read your message conte
|
|
|
168
159
|
|
|
169
160
|
```bash
|
|
170
161
|
# Start with E2E encryption enabled
|
|
171
|
-
vibe --e2e
|
|
162
|
+
vibe --e2e
|
|
172
163
|
```
|
|
173
164
|
|
|
174
165
|
Key exchange happens automatically when both CLI and iOS connect to the bridge:
|
|
@@ -207,7 +198,7 @@ Key exchange happens automatically when both CLI and iOS connect to the bridge:
|
|
|
207
198
|
└─────────────┘ └─────────────┘ └─────────────┘ └─────────────┘
|
|
208
199
|
```
|
|
209
200
|
|
|
210
|
-
**Direct mode:** `vibe
|
|
201
|
+
**Direct mode:** `vibe` connects directly to bridge server
|
|
211
202
|
|
|
212
203
|
**Agent mode:** `vibe --agent` connects to local `vibe-agent`, which manages bridge connection
|
|
213
204
|
|
|
@@ -238,7 +229,6 @@ May also need Visual Studio Build Tools and Python for native compilation.
|
|
|
238
229
|
| Path | Description |
|
|
239
230
|
|------|-------------|
|
|
240
231
|
| `~/.vibe/auth.json` | Stored authentication (token + refresh token) |
|
|
241
|
-
| `~/.vibe/token` | Legacy token file |
|
|
242
232
|
| `~/.vibe/e2e-keys.json` | E2E encryption keypair and peer info |
|
|
243
233
|
| `~/.vibe-agent/port` | Agent port file for auto-discovery |
|
|
244
234
|
|
package/agent/agent.js
CHANGED
|
@@ -9,8 +9,8 @@
|
|
|
9
9
|
* - Stop running sessions
|
|
10
10
|
*
|
|
11
11
|
* Usage:
|
|
12
|
-
* vibe-agent --
|
|
13
|
-
* vibe-agent
|
|
12
|
+
* vibe-agent --login Sign in (one-time)
|
|
13
|
+
* vibe-agent Start agent daemon
|
|
14
14
|
*/
|
|
15
15
|
|
|
16
16
|
const { spawn, execSync } = require('child_process');
|
|
@@ -35,6 +35,22 @@ const HEARTBEAT_INTERVAL_MS = 30000;
|
|
|
35
35
|
const LOCAL_SERVER_PORT = 9999;
|
|
36
36
|
const PORT_FILE = path.join(os.homedir(), '.vibe-agent', 'port');
|
|
37
37
|
const MAX_SESSION_HISTORY_AGE_DAYS = 30;
|
|
38
|
+
const DEFAULT_BRIDGE_URL = 'wss://ws.minivibeapp.com';
|
|
39
|
+
|
|
40
|
+
// Show welcome message for first-time users (no auth)
|
|
41
|
+
function showWelcomeMessage() {
|
|
42
|
+
console.log(`
|
|
43
|
+
Welcome to vibe-agent!
|
|
44
|
+
|
|
45
|
+
vibe-agent lets you manage Claude Code sessions from your iPhone.
|
|
46
|
+
|
|
47
|
+
To get started:
|
|
48
|
+
1. Download MiniVibe from the App Store
|
|
49
|
+
2. Run: vibe-agent --login
|
|
50
|
+
|
|
51
|
+
For help: vibe-agent --help
|
|
52
|
+
`);
|
|
53
|
+
}
|
|
38
54
|
|
|
39
55
|
// Colors for terminal output
|
|
40
56
|
const colors = {
|
|
@@ -225,9 +241,10 @@ const localClients = new Map();
|
|
|
225
241
|
// ====================
|
|
226
242
|
|
|
227
243
|
function connect() {
|
|
244
|
+
// Bridge URL should always be set (defaults to DEFAULT_BRIDGE_URL)
|
|
228
245
|
if (!bridgeUrl) {
|
|
229
|
-
log('No bridge URL configured', colors.red);
|
|
230
|
-
|
|
246
|
+
log('No bridge URL configured (this should not happen)', colors.red);
|
|
247
|
+
process.exit(1);
|
|
231
248
|
}
|
|
232
249
|
|
|
233
250
|
log(`Connecting to ${bridgeUrl}...`, colors.cyan);
|
|
@@ -244,11 +261,13 @@ function connect() {
|
|
|
244
261
|
log('Connected to bridge', colors.green);
|
|
245
262
|
clearTimeout(reconnectTimer);
|
|
246
263
|
|
|
247
|
-
// Authenticate
|
|
264
|
+
// Authenticate (auth is required, so this should always be true)
|
|
248
265
|
if (authToken) {
|
|
249
266
|
send({ type: 'authenticate', token: authToken });
|
|
250
267
|
} else {
|
|
251
|
-
|
|
268
|
+
// Failsafe - should not reach here due to startup check
|
|
269
|
+
showWelcomeMessage();
|
|
270
|
+
process.exit(1);
|
|
252
271
|
}
|
|
253
272
|
});
|
|
254
273
|
|
|
@@ -1319,27 +1338,24 @@ function printHelp() {
|
|
|
1319
1338
|
${colors.cyan}${colors.bold}vibe-agent${colors.reset} - Persistent daemon for remote Claude Code sessions
|
|
1320
1339
|
|
|
1321
1340
|
${colors.bold}Usage:${colors.reset}
|
|
1322
|
-
vibe-agent
|
|
1323
|
-
vibe-agent --login
|
|
1324
|
-
vibe-agent --status
|
|
1341
|
+
vibe-agent Start agent daemon
|
|
1342
|
+
vibe-agent --login Sign in with Google (one-time)
|
|
1343
|
+
vibe-agent --status Show agent status
|
|
1325
1344
|
|
|
1326
1345
|
${colors.bold}Options:${colors.reset}
|
|
1327
|
-
--
|
|
1328
|
-
--login Start device code login flow
|
|
1329
|
-
--token <token> Use specific Firebase token
|
|
1346
|
+
--login Sign in via device code flow
|
|
1330
1347
|
--name <name> Set host display name
|
|
1331
1348
|
--status Show current status and exit
|
|
1332
1349
|
--help, -h Show this help
|
|
1333
1350
|
|
|
1334
|
-
${colors.bold}
|
|
1335
|
-
|
|
1336
|
-
|
|
1337
|
-
|
|
1338
|
-
# Start agent daemon
|
|
1339
|
-
vibe-agent --bridge wss://ws.minivibeapp.com
|
|
1351
|
+
${colors.bold}Advanced:${colors.reset}
|
|
1352
|
+
--bridge <url> Override bridge URL (default: wss://ws.minivibeapp.com)
|
|
1353
|
+
--token <token> Use specific Firebase token
|
|
1340
1354
|
|
|
1341
|
-
|
|
1342
|
-
vibe-agent --
|
|
1355
|
+
${colors.bold}Examples:${colors.reset}
|
|
1356
|
+
vibe-agent --login Sign in (one-time setup)
|
|
1357
|
+
vibe-agent Start agent
|
|
1358
|
+
vibe-agent --name "EC2" Start with custom name
|
|
1343
1359
|
`);
|
|
1344
1360
|
}
|
|
1345
1361
|
|
|
@@ -1397,7 +1413,7 @@ async function main() {
|
|
|
1397
1413
|
// Load saved config
|
|
1398
1414
|
const config = loadConfig();
|
|
1399
1415
|
|
|
1400
|
-
bridgeUrl = options.bridge || config.bridgeUrl;
|
|
1416
|
+
bridgeUrl = options.bridge || config.bridgeUrl || DEFAULT_BRIDGE_URL;
|
|
1401
1417
|
hostName = options.name || config.hostName || os.hostname();
|
|
1402
1418
|
agentId = config.agentId || null; // Load persisted agentId
|
|
1403
1419
|
|
|
@@ -1410,7 +1426,7 @@ async function main() {
|
|
|
1410
1426
|
}
|
|
1411
1427
|
|
|
1412
1428
|
// Save config for next time
|
|
1413
|
-
if (
|
|
1429
|
+
if (options.bridge) {
|
|
1414
1430
|
config.bridgeUrl = bridgeUrl;
|
|
1415
1431
|
}
|
|
1416
1432
|
if (options.name) {
|
|
@@ -1420,7 +1436,7 @@ async function main() {
|
|
|
1420
1436
|
|
|
1421
1437
|
// Status check
|
|
1422
1438
|
if (options.status) {
|
|
1423
|
-
console.log(`Bridge URL: ${bridgeUrl
|
|
1439
|
+
console.log(`Bridge URL: ${bridgeUrl}`);
|
|
1424
1440
|
console.log(`Host Name: ${hostName}`);
|
|
1425
1441
|
console.log(`Auth Token: ${authToken ? 'Configured' : 'Not configured'}`);
|
|
1426
1442
|
console.log(`Agent ID: ${agentId || 'Will be assigned on first connect'}`);
|
|
@@ -1429,23 +1445,15 @@ async function main() {
|
|
|
1429
1445
|
|
|
1430
1446
|
// Login flow
|
|
1431
1447
|
if (options.login) {
|
|
1432
|
-
if (!bridgeUrl) {
|
|
1433
|
-
log('--bridge URL required for login', colors.red);
|
|
1434
|
-
process.exit(1);
|
|
1435
|
-
}
|
|
1436
1448
|
const httpUrl = bridgeUrl.replace('wss://', 'https://').replace('ws://', 'http://');
|
|
1437
1449
|
await startHeadlessLogin(httpUrl);
|
|
1438
1450
|
return;
|
|
1439
1451
|
}
|
|
1440
1452
|
|
|
1441
|
-
//
|
|
1442
|
-
if (!bridgeUrl) {
|
|
1443
|
-
log('No bridge URL. Run: vibe-agent --bridge wss://ws.minivibeapp.com', colors.red);
|
|
1444
|
-
process.exit(1);
|
|
1445
|
-
}
|
|
1446
|
-
|
|
1453
|
+
// Require auth (block instead of warn)
|
|
1447
1454
|
if (!authToken) {
|
|
1448
|
-
|
|
1455
|
+
showWelcomeMessage();
|
|
1456
|
+
process.exit(1);
|
|
1449
1457
|
}
|
|
1450
1458
|
|
|
1451
1459
|
// Banner
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "minivibe",
|
|
3
|
-
"version": "0.2.
|
|
3
|
+
"version": "0.2.2",
|
|
4
4
|
"description": "CLI wrapper for Claude Code with mobile remote control via MiniVibe iOS app",
|
|
5
5
|
"author": "MiniVibe <hello@minivibeapp.com>",
|
|
6
6
|
"homepage": "https://github.com/minivibeapp/minivibe",
|
package/vibe.js
CHANGED
|
@@ -19,6 +19,49 @@ const os = require('os');
|
|
|
19
19
|
const crypto = require('crypto');
|
|
20
20
|
const e2e = require('./e2e');
|
|
21
21
|
|
|
22
|
+
// Check if Claude Code is installed
|
|
23
|
+
function checkClaudeInstalled() {
|
|
24
|
+
try {
|
|
25
|
+
execSync('claude --version', { stdio: 'ignore' });
|
|
26
|
+
return true;
|
|
27
|
+
} catch {
|
|
28
|
+
return false;
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
// Show welcome message for first-time users (no auth)
|
|
33
|
+
function showWelcomeMessage() {
|
|
34
|
+
console.log(`
|
|
35
|
+
Welcome to MiniVibe!
|
|
36
|
+
|
|
37
|
+
MiniVibe lets you control Claude Code from your iPhone.
|
|
38
|
+
|
|
39
|
+
To get started:
|
|
40
|
+
1. Download MiniVibe from the App Store
|
|
41
|
+
2. Run: vibe --login
|
|
42
|
+
|
|
43
|
+
For help: vibe --help
|
|
44
|
+
`);
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
// Show error when Claude Code is not installed
|
|
48
|
+
function showClaudeNotFoundMessage() {
|
|
49
|
+
console.log(`
|
|
50
|
+
Claude Code not found
|
|
51
|
+
|
|
52
|
+
MiniVibe requires Claude Code CLI to be installed.
|
|
53
|
+
|
|
54
|
+
Install Claude Code:
|
|
55
|
+
https://claude.ai/download
|
|
56
|
+
|
|
57
|
+
After installing, run:
|
|
58
|
+
vibe --login
|
|
59
|
+
`);
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
// Default bridge URL
|
|
63
|
+
const DEFAULT_BRIDGE_URL = 'wss://ws.minivibeapp.com';
|
|
64
|
+
|
|
22
65
|
// Find claude executable
|
|
23
66
|
function findClaudePath() {
|
|
24
67
|
try {
|
|
@@ -273,9 +316,6 @@ async function startLoginFlow(openBrowser = true) {
|
|
|
273
316
|
}
|
|
274
317
|
}
|
|
275
318
|
|
|
276
|
-
// Default bridge URL for headless login
|
|
277
|
-
const DEFAULT_BRIDGE_URL = 'wss://ws.minivibeapp.com';
|
|
278
|
-
|
|
279
319
|
// Production web app URL for device pairing
|
|
280
320
|
const WEB_APP_URL = 'https://minivibeapp.com';
|
|
281
321
|
|
|
@@ -303,54 +343,41 @@ let e2eEnabled = false; // --e2e mode: enable end-to-end encryption
|
|
|
303
343
|
for (let i = 0; i < args.length; i++) {
|
|
304
344
|
if (args[i] === '--help' || args[i] === '-h') {
|
|
305
345
|
console.log(`
|
|
306
|
-
vibe
|
|
346
|
+
vibe - Claude Code with mobile remote control
|
|
307
347
|
|
|
308
348
|
Usage:
|
|
309
|
-
vibe
|
|
310
|
-
vibe
|
|
311
|
-
vibe --
|
|
312
|
-
vibe --
|
|
313
|
-
vibe --attach <id> Attach to session via local agent (full terminal)
|
|
314
|
-
vibe --remote <id> --bridge <url> Remote control session (no local Claude needed)
|
|
315
|
-
vibe --list List running sessions on local agent
|
|
316
|
-
vibe --login Sign in via minivibeapp.com (opens browser)
|
|
317
|
-
vibe --login --headless Sign in on headless server (no browser)
|
|
318
|
-
vibe Start interactive session
|
|
349
|
+
vibe Start session (connects to bridge)
|
|
350
|
+
vibe "prompt" Start with initial prompt
|
|
351
|
+
vibe --login Sign in with Google
|
|
352
|
+
vibe --agent Connect via local vibe-agent
|
|
319
353
|
|
|
320
354
|
Options:
|
|
321
|
-
--
|
|
322
|
-
--
|
|
355
|
+
--login Sign in via minivibeapp.com (opens browser)
|
|
356
|
+
--headless Use device code flow for servers (no browser)
|
|
357
|
+
--agent [url] Connect via local vibe-agent (default: auto-discover)
|
|
323
358
|
--name <name> Name this session (shown in mobile app)
|
|
324
|
-
--resume <id> Resume a previous session
|
|
325
|
-
--
|
|
326
|
-
|
|
359
|
+
--resume <id> Resume a previous session
|
|
360
|
+
--e2e Enable end-to-end encryption
|
|
361
|
+
|
|
362
|
+
Advanced:
|
|
363
|
+
--bridge <url> Override bridge URL (default: wss://ws.minivibeapp.com)
|
|
364
|
+
--attach <id> Attach to session via local agent (full terminal)
|
|
365
|
+
--remote <id> Remote control session via bridge (no local Claude needed)
|
|
327
366
|
--list List running sessions on local agent
|
|
328
|
-
--login Sign in via minivibeapp.com (opens browser)
|
|
329
|
-
--headless Don't open browser (for servers without display)
|
|
330
367
|
--token <token> Set Firebase auth token manually
|
|
331
368
|
--logout Remove stored auth token
|
|
332
|
-
--node-pty Use Node.js PTY wrapper (required for Windows
|
|
333
|
-
--dangerously-skip-permissions
|
|
334
|
-
--e2e Enable end-to-end encryption (auto key exchange with iOS)
|
|
369
|
+
--node-pty Use Node.js PTY wrapper (required for Windows)
|
|
370
|
+
--dangerously-skip-permissions Auto-approve all tool executions
|
|
335
371
|
--help, -h Show this help message
|
|
336
372
|
|
|
337
|
-
Attach vs Remote:
|
|
338
|
-
--attach <id> LOCAL: Full terminal passthrough via local vibe-agent
|
|
339
|
-
--remote <id> --bridge <url> REMOTE: Chat-style control via bridge server
|
|
340
|
-
- No local agent or Claude Code needed
|
|
341
|
-
- Control sessions running on any host
|
|
342
|
-
|
|
343
|
-
Authentication:
|
|
344
|
-
Use --login to sign in via minivibeapp.com (opens browser automatically).
|
|
345
|
-
Use --login --headless on servers without a display (EC2, etc.)
|
|
346
|
-
|
|
347
373
|
Examples:
|
|
348
|
-
vibe --login
|
|
349
|
-
vibe
|
|
350
|
-
vibe
|
|
351
|
-
vibe --
|
|
352
|
-
vibe --
|
|
353
|
-
|
|
374
|
+
vibe --login Sign in (one-time setup)
|
|
375
|
+
vibe Start session
|
|
376
|
+
vibe "Fix the bug" Start with prompt
|
|
377
|
+
vibe --e2e Enable encryption
|
|
378
|
+
vibe --agent Use local agent
|
|
379
|
+
|
|
380
|
+
For local-only use without remote control, run 'claude' directly.
|
|
354
381
|
`);
|
|
355
382
|
process.exit(0);
|
|
356
383
|
} else if (args[i] === '--headless') {
|
|
@@ -442,6 +469,39 @@ if (!authToken) {
|
|
|
442
469
|
authToken = getStoredToken();
|
|
443
470
|
}
|
|
444
471
|
|
|
472
|
+
// ====================
|
|
473
|
+
// Startup Checks
|
|
474
|
+
// ====================
|
|
475
|
+
|
|
476
|
+
// Skip checks if in login mode (already handled above)
|
|
477
|
+
if (!loginMode) {
|
|
478
|
+
const isAgentMode = !!agentUrl || listSessions;
|
|
479
|
+
|
|
480
|
+
// 1. --remote mode doesn't need local Claude (controls remote session)
|
|
481
|
+
// 2. --list mode doesn't need local Claude (just queries agent)
|
|
482
|
+
// 3. All other modes need Claude installed
|
|
483
|
+
if (!remoteAttachMode && !listSessions && !checkClaudeInstalled()) {
|
|
484
|
+
showClaudeNotFoundMessage();
|
|
485
|
+
process.exit(1);
|
|
486
|
+
}
|
|
487
|
+
|
|
488
|
+
// 3. Check auth (unless agent mode - agent handles its own auth)
|
|
489
|
+
if (!isAgentMode && !authToken) {
|
|
490
|
+
showWelcomeMessage();
|
|
491
|
+
process.exit(1);
|
|
492
|
+
}
|
|
493
|
+
|
|
494
|
+
// 4. Default to bridge URL when authenticated (and not in agent mode)
|
|
495
|
+
if (!isAgentMode && !bridgeUrl && authToken) {
|
|
496
|
+
bridgeUrl = DEFAULT_BRIDGE_URL;
|
|
497
|
+
}
|
|
498
|
+
|
|
499
|
+
// 5. --remote without --bridge: use default bridge
|
|
500
|
+
if (remoteAttachMode && !bridgeUrl) {
|
|
501
|
+
bridgeUrl = DEFAULT_BRIDGE_URL;
|
|
502
|
+
}
|
|
503
|
+
}
|
|
504
|
+
|
|
445
505
|
// Initialize E2E encryption if enabled
|
|
446
506
|
// Track if E2E is pending (enabled but not yet established)
|
|
447
507
|
let e2ePending = false;
|
|
@@ -458,20 +518,7 @@ if (e2eEnabled) {
|
|
|
458
518
|
}
|
|
459
519
|
}
|
|
460
520
|
|
|
461
|
-
//
|
|
462
|
-
if (remoteAttachMode && !bridgeUrl) {
|
|
463
|
-
console.error('Error: --remote requires --bridge <url>');
|
|
464
|
-
console.error('Example: vibe --remote abc123 --bridge wss://ws.minivibeapp.com');
|
|
465
|
-
process.exit(1);
|
|
466
|
-
}
|
|
467
|
-
|
|
468
|
-
// Validate E2E requires bridge (for key exchange)
|
|
469
|
-
if (e2ePending && !bridgeUrl && !agentUrl) {
|
|
470
|
-
console.error('Error: --e2e with no saved peer requires --bridge <url>');
|
|
471
|
-
console.error('E2E encryption needs a bridge to exchange keys with iOS app.');
|
|
472
|
-
console.error('Example: vibe --e2e --bridge wss://ws.minivibeapp.com');
|
|
473
|
-
process.exit(1);
|
|
474
|
-
}
|
|
521
|
+
// Note: E2E key exchange now works automatically since bridge is defaulted when authenticated
|
|
475
522
|
|
|
476
523
|
// Session state
|
|
477
524
|
const sessionId = resumeSessionId || uuidv4();
|
|
@@ -693,13 +740,10 @@ function connectToBridge() {
|
|
|
693
740
|
|
|
694
741
|
const isAgentMode = !!agentUrl;
|
|
695
742
|
|
|
696
|
-
//
|
|
743
|
+
// Auth should already be checked in startup, but double-check here
|
|
697
744
|
if (!isAgentMode && !authToken) {
|
|
698
|
-
|
|
699
|
-
|
|
700
|
-
log(' Get your token from the MiniVibe mobile app.', colors.dim);
|
|
701
|
-
log('', '');
|
|
702
|
-
log(' Continuing without authentication (bridge may reject connection)', colors.dim);
|
|
745
|
+
showWelcomeMessage();
|
|
746
|
+
process.exit(1);
|
|
703
747
|
}
|
|
704
748
|
|
|
705
749
|
if (isAgentMode) {
|
|
@@ -765,6 +809,17 @@ function connectToBridge() {
|
|
|
765
809
|
});
|
|
766
810
|
|
|
767
811
|
bridgeSocket.on('error', (err) => {
|
|
812
|
+
if (isAgentMode && err.code === 'ECONNREFUSED') {
|
|
813
|
+
// Agent not running - show helpful message
|
|
814
|
+
console.log(`
|
|
815
|
+
Cannot connect to vibe-agent at ${targetUrl}
|
|
816
|
+
|
|
817
|
+
Make sure vibe-agent is running:
|
|
818
|
+
vibe-agent --login # First time
|
|
819
|
+
vibe-agent # Start daemon
|
|
820
|
+
`);
|
|
821
|
+
process.exit(1);
|
|
822
|
+
}
|
|
768
823
|
logStatus(`Bridge connection error: ${err.message}`);
|
|
769
824
|
});
|
|
770
825
|
}
|
|
@@ -2122,18 +2177,16 @@ function setupShutdown() {
|
|
|
2122
2177
|
// ====================
|
|
2123
2178
|
|
|
2124
2179
|
function remoteAttachMain() {
|
|
2125
|
-
// Validate before displaying banner
|
|
2180
|
+
// Validate before displaying banner (redundant with startup checks, but good failsafe)
|
|
2126
2181
|
if (!authToken) {
|
|
2127
|
-
|
|
2128
|
-
log('❌ Remote attach requires authentication', colors.red);
|
|
2129
|
-
log(' Run: vibe --login --bridge ' + bridgeUrl, colors.dim);
|
|
2182
|
+
showWelcomeMessage();
|
|
2130
2183
|
process.exit(1);
|
|
2131
2184
|
}
|
|
2132
2185
|
|
|
2133
2186
|
if (!resumeSessionId) {
|
|
2134
2187
|
console.log('');
|
|
2135
2188
|
log('❌ Remote mode requires a session ID', colors.red);
|
|
2136
|
-
log(' Run: vibe --remote <session-id>
|
|
2189
|
+
log(' Run: vibe --remote <session-id>', colors.dim);
|
|
2137
2190
|
process.exit(1);
|
|
2138
2191
|
}
|
|
2139
2192
|
|