Summary
Currently, the project recommends ngrok for exposing the webhook server, requiring users to manually copy/paste the tunnel URL into .env every time they restart. This proposal adds:
- Cloudflare Tunnel (
cloudflared) as a free alternative to ngrok (no account required)
- A daemon script that automatically manages the full lifecycle: tunnel start → URL extraction →
.env update → DNS propagation wait → webhook registration (with retry) → process monitoring → auto-restart
- macOS LaunchAgent for auto-start on login
Problem
- ngrok free tier has session limits and requires an account
- Every restart generates a new URL → manual
.env edit + webhook re-registration
- No built-in process supervision — if cloudflared/ngrok or the webhook server crashes, it stays down
- Webhook registration can fail if DNS hasn't propagated yet (especially with Cloudflare quick tunnels)
Proposed Solution
1. Daemon script (start-daemon.sh)
A single script that handles the full lifecycle:
start_tunnel() → cloudflared tunnel --url → parse URL from logs → update .env
→ wait for DNS propagation (nslookup retry loop)
start_webhook() → start webhook server → register Telegram webhook (retry up to 5 times)
main loop → monitor both processes every 10s → auto-restart on crash
→ send Telegram notification on start/restart
Key features:
- Auto URL refresh: Parses tunnel URL from cloudflared stdout, updates
TELEGRAM_WEBHOOK_URL in .env
- DNS propagation wait:
nslookup retry loop before attempting webhook registration
- Webhook registration retry: Up to 5 attempts with 5s intervals (handles the "Failed to resolve host" error)
- Process monitoring: 10s interval health check, auto-restart both processes if tunnel dies
- Graceful shutdown: SIGINT/SIGTERM trap with cleanup
2. macOS LaunchAgent
<plist>
RunAtLoad: true
KeepAlive: true
ThrottleInterval: 30
</plist>
3. Could also support ngrok
The same daemon pattern could work with ngrok by using ngrok api or parsing its local API (http://localhost:4040/api/tunnels) to extract the URL.
Implementation
I have a working implementation and am happy to submit a PR. The daemon script is ~170 lines of bash.
Management commands
# Start
launchctl load ~/Library/LaunchAgents/com.claude-remote.plist
# Logs
tail -f /tmp/claude-remote.log
# Restart
launchctl unload ~/Library/LaunchAgents/com.claude-remote.plist
launchctl load ~/Library/LaunchAgents/com.claude-remote.plist
Alternatives Considered
- systemd (Linux): Could add Linux support with a systemd unit file alongside the LaunchAgent
- PM2 / forever: Node-based process managers, but adds another dependency
- Docker Compose: Heavier, but could bundle cloudflared + webhook server together
Summary
Currently, the project recommends ngrok for exposing the webhook server, requiring users to manually copy/paste the tunnel URL into
.envevery time they restart. This proposal adds:cloudflared) as a free alternative to ngrok (no account required).envupdate → DNS propagation wait → webhook registration (with retry) → process monitoring → auto-restartProblem
.envedit + webhook re-registrationProposed Solution
1. Daemon script (
start-daemon.sh)A single script that handles the full lifecycle:
Key features:
TELEGRAM_WEBHOOK_URLin.envnslookupretry loop before attempting webhook registration2. macOS LaunchAgent
3. Could also support ngrok
The same daemon pattern could work with ngrok by using
ngrok apior parsing its local API (http://localhost:4040/api/tunnels) to extract the URL.Implementation
I have a working implementation and am happy to submit a PR. The daemon script is ~170 lines of bash.
Management commands
Alternatives Considered