@hmduc16031996/claude-mb-bridge 2.4.6 → 2.4.8
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/dist/index.js +24 -25
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -2,34 +2,39 @@
|
|
|
2
2
|
import { Command } from 'commander';
|
|
3
3
|
import { CloudflareTunnel } from './tunnel.js';
|
|
4
4
|
import { startTerminalServer } from './server.js';
|
|
5
|
+
// ─── Built-in Cloudflare named tunnel (mobileideforusers.kanddlabs.com) ───────
|
|
6
|
+
// These are embedded at publish time. End-users don't need to supply them.
|
|
7
|
+
const BUILTIN_CF_TOKEN = 'eyJhIjoiZmM5YTQ4ZTU3NjY4NjI3MjY2OWE3YzBiMTliNTcyYzgiLCJ0IjoiMjgzM2E5NjMtNTBiYi00YThjLWJhMGMtNDI4NWE4ZTJkZmJjIiwicyI6IllqYzVaakF3T1RJdFpEWXdZeTAwWkRFNUxUZzVNR0l0WXpBeE1UazJNamc1T1dZeCJ9';
|
|
8
|
+
const BUILTIN_TUNNEL_URL = 'https://mobileideforusers.kanddlabs.com';
|
|
9
|
+
// ──────────────────────────────────────────────────────────────────────────────
|
|
5
10
|
const program = new Command();
|
|
6
11
|
program
|
|
7
12
|
.name('claude-mobile-bridge')
|
|
8
13
|
.description('Bridge Claude Code CLI to mobile via WebView')
|
|
9
|
-
.version('2.4.
|
|
14
|
+
.version('2.4.7')
|
|
10
15
|
.option('--token <token>', 'Pairing token from mobile app')
|
|
11
16
|
.option('--server <url>', 'Backend server URL', 'http://127.0.0.1:3110')
|
|
12
17
|
.option('--path <path>', 'Working directory', process.cwd())
|
|
13
18
|
.option('--port <port>', 'Local port for terminal server', '38473')
|
|
14
19
|
.option('--ide <type>', 'IDE type: claude_code, cursor, or gemini', 'claude_code')
|
|
15
|
-
//
|
|
16
|
-
.option('--cloudflare-token <cfToken>', 'Cloudflare tunnel token
|
|
17
|
-
.option('--tunnel-url <url>', '
|
|
20
|
+
// Advanced: override the built-in tunnel with your own
|
|
21
|
+
.option('--cloudflare-token <cfToken>', 'Override built-in Cloudflare tunnel token')
|
|
22
|
+
.option('--tunnel-url <url>', 'Override built-in tunnel public URL')
|
|
23
|
+
// Escape hatch: fall back to ephemeral trycloudflare
|
|
24
|
+
.option('--quick-tunnel', 'Use ephemeral trycloudflare.com tunnel instead of the named tunnel')
|
|
18
25
|
.action(async (options) => {
|
|
19
|
-
const { token, server, path, port, ide,
|
|
26
|
+
const { token, server, path, port, ide, quickTunnel } = options;
|
|
20
27
|
if (!token) {
|
|
21
28
|
console.error('Error: --token is required');
|
|
22
29
|
process.exit(1);
|
|
23
30
|
}
|
|
24
|
-
//
|
|
25
|
-
const
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
process.exit(1);
|
|
29
|
-
}
|
|
31
|
+
// Resolve tunnel config: cli overrides > built-ins > quick tunnel
|
|
32
|
+
const cfToken = options.cloudflareToken ?? BUILTIN_CF_TOKEN;
|
|
33
|
+
const tunnelUrl = options.tunnelUrl ?? BUILTIN_TUNNEL_URL;
|
|
34
|
+
const useNamedTunnel = !quickTunnel;
|
|
30
35
|
let tunnelResult = null;
|
|
31
36
|
let terminalServer = null;
|
|
32
|
-
//
|
|
37
|
+
// Cleanup
|
|
33
38
|
const cleanup = async () => {
|
|
34
39
|
console.log('\n👋 Cleaning up session and shutting down...');
|
|
35
40
|
try {
|
|
@@ -47,11 +52,11 @@ program
|
|
|
47
52
|
const { server: ts, actualPort } = await startTerminalServer(localPort, path, token, ide);
|
|
48
53
|
terminalServer = ts;
|
|
49
54
|
console.log(`✅ Terminal server started on port ${actualPort}`);
|
|
50
|
-
// 2. Start Cloudflare Tunnel
|
|
55
|
+
// 2. Start Cloudflare Tunnel
|
|
51
56
|
const tunnel = new CloudflareTunnel();
|
|
52
57
|
if (useNamedTunnel) {
|
|
53
|
-
console.log(`🌐 Connecting
|
|
54
|
-
tunnelResult = await tunnel.startNamed(
|
|
58
|
+
console.log(`🌐 Connecting tunnel → ${tunnelUrl} ...`);
|
|
59
|
+
tunnelResult = await tunnel.startNamed(cfToken, tunnelUrl);
|
|
55
60
|
}
|
|
56
61
|
else {
|
|
57
62
|
console.log('🌐 Establishing ephemeral Cloudflare tunnel...');
|
|
@@ -62,21 +67,16 @@ program
|
|
|
62
67
|
process.exit(1);
|
|
63
68
|
}
|
|
64
69
|
console.log(`✅ Tunnel active: ${tunnelResult.url}`);
|
|
65
|
-
// 3. Validate token
|
|
70
|
+
// 3. Validate token with central server
|
|
66
71
|
console.log('🔑 Validating session token...');
|
|
67
72
|
try {
|
|
68
73
|
const res = await fetch(`${server}/api/sessions/${token}/validate`, {
|
|
69
74
|
method: 'POST',
|
|
70
|
-
headers: {
|
|
71
|
-
|
|
72
|
-
},
|
|
73
|
-
body: JSON.stringify({
|
|
74
|
-
public_url: tunnelResult.url
|
|
75
|
-
})
|
|
75
|
+
headers: { 'Content-Type': 'application/json' },
|
|
76
|
+
body: JSON.stringify({ public_url: tunnelResult.url })
|
|
76
77
|
});
|
|
77
|
-
if (!res.ok)
|
|
78
|
+
if (!res.ok)
|
|
78
79
|
throw new Error('Invalid token or session expired');
|
|
79
|
-
}
|
|
80
80
|
console.log('✅ Session connected and authorized');
|
|
81
81
|
console.log(`📱 Mobile app can now connect via: ${tunnelResult.url}`);
|
|
82
82
|
}
|
|
@@ -85,7 +85,6 @@ program
|
|
|
85
85
|
console.error(' Ensure the central server is available');
|
|
86
86
|
await cleanup();
|
|
87
87
|
}
|
|
88
|
-
// Handle graceful shutdown signals
|
|
89
88
|
process.on('SIGINT', cleanup);
|
|
90
89
|
process.on('SIGTERM', cleanup);
|
|
91
90
|
process.on('SIGHUP', cleanup);
|