claude-code-remote-pilot 0.5.8 → 0.5.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.
@@ -459,6 +459,7 @@ ${HELP}`);
459
459
  console.log(' Starting cloudflared tunnel...');
460
460
  webServer.startTunnel().then(publicUrl => {
461
461
  console.log(` ✓ Tunnel ready: ${publicUrl}`);
462
+ console.log(' Note: first visit may show a Cloudflare warning — click "Proceed" to open the dashboard.');
462
463
  if (!webPassword) console.log(' ⚠ Reminder: no password set. Restart with a password for security.');
463
464
  if (telegram.token && telegram.chatId) {
464
465
  notifier.send(telegram.token, telegram.chatId,
@@ -538,6 +539,7 @@ ${HELP}`);
538
539
  console.log(' Starting cloudflared tunnel...');
539
540
  webServer.startTunnel().then(publicUrl => {
540
541
  console.log(` ✓ Tunnel ready: ${publicUrl}`);
542
+ console.log(' Note: first visit may show a Cloudflare warning — click "Proceed" to open the dashboard.');
541
543
  if (telegram.token && telegram.chatId) {
542
544
  notifier.send(telegram.token, telegram.chatId,
543
545
  `Claude Remote Pilot tunnel ready: ${publicUrl}${webServer.password ? ' (password protected)' : ' ⚠ no password set'}`);
@@ -564,6 +566,7 @@ ${HELP}`);
564
566
  console.log(' Starting cloudflared tunnel...');
565
567
  webServer.startTunnel().then(publicUrl => {
566
568
  console.log(` ✓ Tunnel ready: ${publicUrl}`);
569
+ console.log(' Note: first visit may show a Cloudflare warning — click "Proceed" to open the dashboard.');
567
570
  if (!password) console.log(' ⚠ Reminder: add a password with: web <port> <host> <password> --tunnel');
568
571
  if (telegram.token && telegram.chatId) {
569
572
  notifier.send(telegram.token, telegram.chatId,
package/lib/WebServer.js CHANGED
@@ -18,6 +18,7 @@ class WebServer {
18
18
  this.server = null;
19
19
  this._clients = new Set();
20
20
  this._broadcastInterval = null;
21
+ this._heartbeatInterval = null;
21
22
  this._tunnelProcess = null;
22
23
  this._tunnelUrl = null;
23
24
  }
@@ -201,6 +202,7 @@ class WebServer {
201
202
  'Content-Type': 'text/event-stream',
202
203
  'Cache-Control': 'no-cache',
203
204
  'Connection': 'keep-alive',
205
+ 'X-Accel-Buffering': 'no', // prevent Cloudflare/nginx from buffering the stream
204
206
  });
205
207
  this._clients.add(res);
206
208
  res.write(`data: ${JSON.stringify(this._buildAllSessions())}\n\n`);
@@ -217,6 +219,12 @@ class WebServer {
217
219
  });
218
220
 
219
221
  this._broadcastInterval = setInterval(() => this._broadcast(), 3000);
222
+ // Keep SSE connections alive through proxies (Cloudflare timeout is ~100s)
223
+ this._heartbeatInterval = setInterval(() => {
224
+ for (const res of this._clients) {
225
+ try { res.write(': heartbeat\n\n'); } catch { this._clients.delete(res); }
226
+ }
227
+ }, 20000);
220
228
  this.server.listen(this.port, this.host);
221
229
  return this.port;
222
230
  }
@@ -259,6 +267,7 @@ class WebServer {
259
267
  stop() {
260
268
  this.stopTunnel();
261
269
  clearInterval(this._broadcastInterval);
270
+ clearInterval(this._heartbeatInterval);
262
271
  for (const res of this._clients) { try { res.end(); } catch {} }
263
272
  this._clients.clear();
264
273
  if (this.server) this.server.close();
package/lib/ui.html CHANGED
@@ -1094,6 +1094,21 @@ function App() {
1094
1094
  return () => { if (esRef.current) esRef.current.close(); };
1095
1095
  }, []);
1096
1096
 
1097
+ // Fallback polling — loads sessions immediately and keeps them fresh when
1098
+ // SSE is blocked (e.g. through a Cloudflare tunnel that buffers streams).
1099
+ useEffect(() => {
1100
+ let mounted = true;
1101
+ const poll = () => {
1102
+ apiFetch('/api/sessions', { cache: 'no-store' })
1103
+ .then(r => r.json())
1104
+ .then(data => { if (mounted) setSessions(data); })
1105
+ .catch(() => {});
1106
+ };
1107
+ poll();
1108
+ const t = setInterval(poll, 5000);
1109
+ return () => { mounted = false; clearInterval(t); };
1110
+ }, []);
1111
+
1097
1112
  const handleLogin = useCallback(() => {
1098
1113
  setNeedsLogin(false);
1099
1114
  apiFetch('/api/status').then(r => r.json()).then(setServerStatus).catch(() => {});
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "claude-code-remote-pilot",
3
- "version": "0.5.8",
3
+ "version": "0.5.9",
4
4
  "description": "Interactive Claude Code supervisor — spawn and monitor multiple Claude sessions from a single terminal.",
5
5
  "type": "commonjs",
6
6
  "repository": {