minivibe 0.2.6 → 0.2.9
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/agent/agent.js +3 -3
- package/package.json +1 -1
- package/vibe.js +36 -25
package/agent/agent.js
CHANGED
|
@@ -9,7 +9,7 @@
|
|
|
9
9
|
* - Stop running sessions
|
|
10
10
|
*
|
|
11
11
|
* Usage:
|
|
12
|
-
* vibe-agent
|
|
12
|
+
* vibe-agent login Sign in (one-time)
|
|
13
13
|
* vibe-agent Start agent daemon
|
|
14
14
|
*/
|
|
15
15
|
|
|
@@ -736,7 +736,7 @@ function handleMessage(msg) {
|
|
|
736
736
|
authToken = newToken;
|
|
737
737
|
send({ type: 'authenticate', token: newToken });
|
|
738
738
|
} else {
|
|
739
|
-
log('Please re-login: vibe-agent
|
|
739
|
+
log('Please re-login: vibe-agent login', colors.red);
|
|
740
740
|
}
|
|
741
741
|
})();
|
|
742
742
|
break;
|
|
@@ -1345,7 +1345,7 @@ ${colors.cyan}${colors.bold}vibe-agent${colors.reset} - Persistent daemon for re
|
|
|
1345
1345
|
|
|
1346
1346
|
${colors.bold}Usage:${colors.reset}
|
|
1347
1347
|
vibe-agent Start agent daemon
|
|
1348
|
-
vibe-agent login Sign in
|
|
1348
|
+
vibe-agent login Sign in (one-time)
|
|
1349
1349
|
vibe-agent logout Sign out and clear credentials
|
|
1350
1350
|
vibe-agent status Show agent status
|
|
1351
1351
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "minivibe",
|
|
3
|
-
"version": "0.2.
|
|
3
|
+
"version": "0.2.9",
|
|
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
|
@@ -38,9 +38,9 @@ MiniVibe lets you control Claude Code from your iPhone.
|
|
|
38
38
|
|
|
39
39
|
To get started:
|
|
40
40
|
1. Download MiniVibe from the App Store
|
|
41
|
-
2. Run: vibe
|
|
41
|
+
2. Run: vibe login
|
|
42
42
|
|
|
43
|
-
For help: vibe
|
|
43
|
+
For help: vibe help
|
|
44
44
|
`);
|
|
45
45
|
}
|
|
46
46
|
|
|
@@ -55,7 +55,7 @@ Install Claude Code:
|
|
|
55
55
|
https://claude.ai/download
|
|
56
56
|
|
|
57
57
|
After installing, run:
|
|
58
|
-
vibe
|
|
58
|
+
vibe login
|
|
59
59
|
`);
|
|
60
60
|
}
|
|
61
61
|
|
|
@@ -353,6 +353,7 @@ let skipPermissions = false; // --dangerously-skip-permissions mode
|
|
|
353
353
|
let listSessions = false; // --list mode: list running sessions
|
|
354
354
|
let remoteAttachMode = false; // --remote with --bridge: pure remote control (no local Claude)
|
|
355
355
|
let e2eEnabled = false; // --e2e mode: enable end-to-end encryption
|
|
356
|
+
let verboseMode = false; // --verbose mode: show [vibe] debug messages
|
|
356
357
|
|
|
357
358
|
for (let i = 0; i < args.length; i++) {
|
|
358
359
|
if (args[i] === '--help' || args[i] === '-h') {
|
|
@@ -362,7 +363,7 @@ vibe - Claude Code with mobile remote control
|
|
|
362
363
|
Usage:
|
|
363
364
|
vibe Start session (connects to bridge)
|
|
364
365
|
vibe "prompt" Start with initial prompt
|
|
365
|
-
vibe login Sign in
|
|
366
|
+
vibe login Sign in (Apple or Google)
|
|
366
367
|
vibe logout Sign out
|
|
367
368
|
|
|
368
369
|
Commands:
|
|
@@ -376,6 +377,7 @@ Options:
|
|
|
376
377
|
--name <name> Name this session (shown in mobile app)
|
|
377
378
|
--resume <id> Resume a previous session
|
|
378
379
|
--e2e Enable end-to-end encryption
|
|
380
|
+
--verbose, -v Show detailed [vibe] status messages
|
|
379
381
|
|
|
380
382
|
Advanced:
|
|
381
383
|
--bridge <url> Override bridge URL (default: wss://ws.minivibeapp.com)
|
|
@@ -399,6 +401,8 @@ For local-only use without remote control, run 'claude' directly.
|
|
|
399
401
|
process.exit(0);
|
|
400
402
|
} else if (args[i] === '--headless') {
|
|
401
403
|
headlessMode = true;
|
|
404
|
+
} else if (args[i] === '--verbose' || args[i] === '-v') {
|
|
405
|
+
verboseMode = true;
|
|
402
406
|
} else if (args[i] === '--login') {
|
|
403
407
|
// Defer login handling until we know if --headless is also present
|
|
404
408
|
// Will be handled after the loop
|
|
@@ -558,7 +562,11 @@ if (e2eEnabled) {
|
|
|
558
562
|
// Note: E2E key exchange now works automatically since bridge is defaulted when authenticated
|
|
559
563
|
|
|
560
564
|
// Session state
|
|
565
|
+
// Support VIBE_SESSION_ID env var for fixed session IDs (e.g., playground)
|
|
566
|
+
// Bridge session ID can be any string, but Claude needs a valid UUID
|
|
567
|
+
const bridgeSessionId = process.env.VIBE_SESSION_ID;
|
|
561
568
|
const sessionId = resumeSessionId || uuidv4();
|
|
569
|
+
const effectiveSessionId = bridgeSessionId || sessionId; // Use for bridge registration
|
|
562
570
|
let claudeProcess = null;
|
|
563
571
|
let isRunning = false;
|
|
564
572
|
let isShuttingDown = false;
|
|
@@ -600,6 +608,9 @@ function logStderr(msg, color = '') {
|
|
|
600
608
|
}
|
|
601
609
|
|
|
602
610
|
function logStatus(msg) {
|
|
611
|
+
// Only log status messages in verbose mode
|
|
612
|
+
if (!verboseMode) return;
|
|
613
|
+
|
|
603
614
|
// Use stderr when Claude is running to avoid corrupting PTY output
|
|
604
615
|
if (isRunning) {
|
|
605
616
|
logStderr(`[vibe] ${msg}`, colors.dim);
|
|
@@ -852,7 +863,7 @@ function connectToBridge() {
|
|
|
852
863
|
Cannot connect to vibe-agent at ${targetUrl}
|
|
853
864
|
|
|
854
865
|
Make sure vibe-agent is running:
|
|
855
|
-
vibe-agent
|
|
866
|
+
vibe-agent login # First time
|
|
856
867
|
vibe-agent # Start daemon
|
|
857
868
|
`);
|
|
858
869
|
process.exit(1);
|
|
@@ -928,7 +939,7 @@ function handleBridgeMessage(msg) {
|
|
|
928
939
|
// This is required before E2E key exchange so our keys can reach viewers
|
|
929
940
|
bridgeSocket.send(JSON.stringify({
|
|
930
941
|
type: 'register_session',
|
|
931
|
-
sessionId,
|
|
942
|
+
sessionId: effectiveSessionId, // Use VIBE_SESSION_ID if set for fixed playground IDs
|
|
932
943
|
path: process.cwd(),
|
|
933
944
|
name: sessionName || path.basename(process.cwd()), // Use --name or fallback to directory name
|
|
934
945
|
e2e: e2eEnabled // Indicate if this session has E2E enabled
|
|
@@ -942,7 +953,7 @@ function handleBridgeMessage(msg) {
|
|
|
942
953
|
// Must be AFTER register_session so our type is 'provider' and keys reach viewers
|
|
943
954
|
if (e2eEnabled && e2e.isEnabled()) {
|
|
944
955
|
const keyExchangeMsg = e2e.createKeyExchangeMessage(true); // needsResponse=true
|
|
945
|
-
keyExchangeMsg.sessionId =
|
|
956
|
+
keyExchangeMsg.sessionId = effectiveSessionId; // Include sessionId for routing
|
|
946
957
|
bridgeSocket.send(JSON.stringify(keyExchangeMsg));
|
|
947
958
|
log('[E2E] Sent public key to bridge (waiting for peer)', colors.cyan);
|
|
948
959
|
}
|
|
@@ -981,7 +992,7 @@ function handleBridgeMessage(msg) {
|
|
|
981
992
|
log('║ Your token is invalid or expired. ║', colors.red);
|
|
982
993
|
log('║ Please re-login: ║', colors.red);
|
|
983
994
|
log('║ ║', colors.red);
|
|
984
|
-
log('║ vibe
|
|
995
|
+
log('║ vibe login ║', colors.red);
|
|
985
996
|
log('║ ║', colors.red);
|
|
986
997
|
log('╚════════════════════════════════════════════╝', colors.red);
|
|
987
998
|
log('', colors.red);
|
|
@@ -1042,7 +1053,7 @@ function handleBridgeMessage(msg) {
|
|
|
1042
1053
|
if (!msg.data || msg.data.length === 0 || !msg.fileName) {
|
|
1043
1054
|
sendToBridge({
|
|
1044
1055
|
type: 'error',
|
|
1045
|
-
sessionId:
|
|
1056
|
+
sessionId: effectiveSessionId,
|
|
1046
1057
|
message: 'Invalid file upload: missing data or fileName'
|
|
1047
1058
|
});
|
|
1048
1059
|
break;
|
|
@@ -1053,7 +1064,7 @@ function handleBridgeMessage(msg) {
|
|
|
1053
1064
|
if (msg.data.length > MAX_BASE64_SIZE) {
|
|
1054
1065
|
sendToBridge({
|
|
1055
1066
|
type: 'error',
|
|
1056
|
-
sessionId:
|
|
1067
|
+
sessionId: effectiveSessionId,
|
|
1057
1068
|
message: 'File too large (max 10MB)'
|
|
1058
1069
|
});
|
|
1059
1070
|
break;
|
|
@@ -1147,7 +1158,7 @@ function handleBridgeMessage(msg) {
|
|
|
1147
1158
|
// Echo the message back using claude_message type (matches iOS handler)
|
|
1148
1159
|
sendToBridge({
|
|
1149
1160
|
type: 'claude_message',
|
|
1150
|
-
sessionId:
|
|
1161
|
+
sessionId: effectiveSessionId,
|
|
1151
1162
|
message: {
|
|
1152
1163
|
id: uuidv4(),
|
|
1153
1164
|
sender: 'user',
|
|
@@ -1167,7 +1178,7 @@ function handleBridgeMessage(msg) {
|
|
|
1167
1178
|
// Also send file_received confirmation
|
|
1168
1179
|
sendToBridge({
|
|
1169
1180
|
type: 'file_received',
|
|
1170
|
-
sessionId:
|
|
1181
|
+
sessionId: effectiveSessionId,
|
|
1171
1182
|
fileName: safeName,
|
|
1172
1183
|
localPath: filePath,
|
|
1173
1184
|
size: fileBuffer.length
|
|
@@ -1177,7 +1188,7 @@ function handleBridgeMessage(msg) {
|
|
|
1177
1188
|
log(`❌ Failed to save file: ${err.message}`, colors.red);
|
|
1178
1189
|
sendToBridge({
|
|
1179
1190
|
type: 'error',
|
|
1180
|
-
sessionId:
|
|
1191
|
+
sessionId: effectiveSessionId,
|
|
1181
1192
|
message: `Failed to upload file: ${err.message}`
|
|
1182
1193
|
});
|
|
1183
1194
|
}
|
|
@@ -1192,7 +1203,7 @@ function handleBridgeMessage(msg) {
|
|
|
1192
1203
|
if (!msg.images || !Array.isArray(msg.images) || msg.images.length === 0) {
|
|
1193
1204
|
sendToBridge({
|
|
1194
1205
|
type: 'error',
|
|
1195
|
-
sessionId:
|
|
1206
|
+
sessionId: effectiveSessionId,
|
|
1196
1207
|
message: 'Invalid file upload: missing or empty images array'
|
|
1197
1208
|
});
|
|
1198
1209
|
break;
|
|
@@ -1204,7 +1215,7 @@ function handleBridgeMessage(msg) {
|
|
|
1204
1215
|
if (totalBase64Size > MAX_TOTAL_BASE64_SIZE) {
|
|
1205
1216
|
sendToBridge({
|
|
1206
1217
|
type: 'error',
|
|
1207
|
-
sessionId:
|
|
1218
|
+
sessionId: effectiveSessionId,
|
|
1208
1219
|
message: 'Total file size too large (max 50MB combined)'
|
|
1209
1220
|
});
|
|
1210
1221
|
break;
|
|
@@ -1319,7 +1330,7 @@ function handleBridgeMessage(msg) {
|
|
|
1319
1330
|
// Echo the message back with attachments array
|
|
1320
1331
|
sendToBridge({
|
|
1321
1332
|
type: 'claude_message',
|
|
1322
|
-
sessionId:
|
|
1333
|
+
sessionId: effectiveSessionId,
|
|
1323
1334
|
message: {
|
|
1324
1335
|
id: uuidv4(),
|
|
1325
1336
|
sender: 'user',
|
|
@@ -1332,7 +1343,7 @@ function handleBridgeMessage(msg) {
|
|
|
1332
1343
|
// Send confirmation
|
|
1333
1344
|
sendToBridge({
|
|
1334
1345
|
type: 'files_received',
|
|
1335
|
-
sessionId:
|
|
1346
|
+
sessionId: effectiveSessionId,
|
|
1336
1347
|
count: savedFiles.length,
|
|
1337
1348
|
files: savedFiles.map(f => ({ fileName: f.name, localPath: f.path }))
|
|
1338
1349
|
});
|
|
@@ -1343,7 +1354,7 @@ function handleBridgeMessage(msg) {
|
|
|
1343
1354
|
log(`❌ Failed to process files: ${err.message}`, colors.red);
|
|
1344
1355
|
sendToBridge({
|
|
1345
1356
|
type: 'error',
|
|
1346
|
-
sessionId:
|
|
1357
|
+
sessionId: effectiveSessionId,
|
|
1347
1358
|
message: `Failed to upload files: ${err.message}`
|
|
1348
1359
|
});
|
|
1349
1360
|
}
|
|
@@ -1472,7 +1483,7 @@ function handleBridgeMessage(msg) {
|
|
|
1472
1483
|
log(`║ ${(msg.message || 'Invalid token').padEnd(42)}║`, colors.red);
|
|
1473
1484
|
log('║ ║', colors.red);
|
|
1474
1485
|
log('║ Please re-login: ║', colors.red);
|
|
1475
|
-
log('║ vibe
|
|
1486
|
+
log('║ vibe login ║', colors.red);
|
|
1476
1487
|
log('║ ║', colors.red);
|
|
1477
1488
|
log('╚════════════════════════════════════════════╝', colors.red);
|
|
1478
1489
|
log('', colors.red);
|
|
@@ -1867,7 +1878,7 @@ function processSessionMessage(msg) {
|
|
|
1867
1878
|
|
|
1868
1879
|
sendToBridge({
|
|
1869
1880
|
type: 'permission_request',
|
|
1870
|
-
sessionId:
|
|
1881
|
+
sessionId: effectiveSessionId,
|
|
1871
1882
|
requestId: tool.id,
|
|
1872
1883
|
command: tool.name,
|
|
1873
1884
|
question: question,
|
|
@@ -1958,7 +1969,7 @@ function processSessionMessage(msg) {
|
|
|
1958
1969
|
const usage = msg.message.usage;
|
|
1959
1970
|
sendToBridge({
|
|
1960
1971
|
type: 'token_usage',
|
|
1961
|
-
sessionId:
|
|
1972
|
+
sessionId: effectiveSessionId,
|
|
1962
1973
|
model: msg.message.model || null,
|
|
1963
1974
|
usage: {
|
|
1964
1975
|
input_tokens: usage.input_tokens || 0,
|
|
@@ -2300,7 +2311,7 @@ function handleRemoteAttachMessage(msg) {
|
|
|
2300
2311
|
|
|
2301
2312
|
case 'auth_error':
|
|
2302
2313
|
log(`✗ Authentication failed: ${msg.message}`, colors.red);
|
|
2303
|
-
log(' Run: vibe
|
|
2314
|
+
log(' Run: vibe login --bridge ' + bridgeUrl, colors.dim);
|
|
2304
2315
|
process.exit(1);
|
|
2305
2316
|
break;
|
|
2306
2317
|
|
|
@@ -2455,7 +2466,7 @@ function setupRemoteAttachInput() {
|
|
|
2455
2466
|
if (pendingPermission) {
|
|
2456
2467
|
sendRemoteCommand({
|
|
2457
2468
|
type: 'approve_permission',
|
|
2458
|
-
sessionId:
|
|
2469
|
+
sessionId: effectiveSessionId,
|
|
2459
2470
|
requestId: pendingPermission.id
|
|
2460
2471
|
});
|
|
2461
2472
|
log('Sent approval', colors.green);
|
|
@@ -2467,7 +2478,7 @@ function setupRemoteAttachInput() {
|
|
|
2467
2478
|
if (pendingPermission) {
|
|
2468
2479
|
sendRemoteCommand({
|
|
2469
2480
|
type: 'deny_permission',
|
|
2470
|
-
sessionId:
|
|
2481
|
+
sessionId: effectiveSessionId,
|
|
2471
2482
|
requestId: pendingPermission.id
|
|
2472
2483
|
});
|
|
2473
2484
|
log('Sent denial', colors.yellow);
|
|
@@ -2503,7 +2514,7 @@ function setupRemoteAttachInput() {
|
|
|
2503
2514
|
// Send message to Claude
|
|
2504
2515
|
sendRemoteCommand({
|
|
2505
2516
|
type: 'send_message',
|
|
2506
|
-
sessionId:
|
|
2517
|
+
sessionId: effectiveSessionId,
|
|
2507
2518
|
content: input
|
|
2508
2519
|
});
|
|
2509
2520
|
log(`📤 Sent: ${truncateText(input, 50)}`, colors.dim);
|