Skip to content

feat: remote session notifications via Tailscale, tmux, and ntfy#286

Open
tfriedel wants to merge 2 commits intobacknotprop:mainfrom
tfriedel:feat/remote-notifications
Open

feat: remote session notifications via Tailscale, tmux, and ntfy#286
tfriedel wants to merge 2 commits intobacknotprop:mainfrom
tfriedel:feat/remote-notifications

Conversation

@tfriedel
Copy link

@tfriedel tfriedel commented Mar 14, 2026

Summary

Fixes #192 — remote Claude Code sessions can now open the plan review UI without port forwarding.

Note: This is not a general-purpose solution — it relies on Tailscale, tmux, and/or ntfy, which are not common dependencies. It's shared as a working proof-of-concept and inspiration for how remote access can work. A more general solution (e.g., a session router on a fixed port, or first-class support for Claude Code surfacing hook messages) is still needed for broad adoption. See #192 for discussion.

What's here

  • Tailscale auto-detection: Detects Tailscale hostname via tailscale status --self --json, so the server URL is directly reachable (e.g. http://mybox.ts.net:PORT). Also supports explicit PLANNOTATOR_HOSTNAME env var.
  • Random ports in remote mode: Removed the fixed port 19432 default, so parallel Claude sessions work without port conflicts.
  • 0.0.0.0 binding: Server binds to all interfaces when a non-localhost hostname is detected.
  • tmux popup: When $TMUX is set, shows a tmux display-popup with the server URL — works inside Claude Code's TUI since it's a tmux-layer overlay that bypasses Claude's stdio capture.
  • ntfy push notification: When CLAUDE_HOOKS_NTFY_URL is set (compatible with existing claude-code ntfy hooks), sends a push notification with a clickable link.
  • Short URLs via paste service: Uses the existing paste service (zero-knowledge encrypted) for compact share links when the server isn't directly reachable.

Why this isn't the general solution

The core problem is that Claude Code doesn't surface hook stderr to the user — it captures it to a socket. This means there's no built-in way for a hook to communicate a URL (or anything else) to the user while it's running.

The workarounds here are all external channels:

  • Tailscale — requires the user to have a mesh VPN set up
  • tmux popup — requires the user to be running inside tmux
  • ntfy — requires a push notification service

For users without any of these, the only option remains manual SSH port forwarding (ssh -L PORT:localhost:PORT), which is fragile since ports are now random.

Ideas for a general solution

  1. Claude Code feature request: A hook progress/message channel that surfaces stderr (or a dedicated stream) to the user's terminal. This would solve the problem at the root.
  2. Session router: A long-lived server on a fixed port that multiplexes multiple plan sessions on subpaths (/session/<id>). Users forward one port, all sessions are accessible. More complex but works without external dependencies.
  3. VS Code Remote auto-forwarding: VS Code Remote already auto-forwards ports. If the server prints a localhost:PORT URL to stderr, VS Code picks it up. This works today for VS Code Remote users — the missing piece is just surfacing the URL.

Test plan

  • Tested on remote SSH session with Tailscale — tmux popup shows http://hostname:port, opens in local browser, full approve/deny works
  • Tested ntfy push notification — clickable link arrives on phone
  • Verify local (non-remote) mode is unchanged — should still open browser directly
  • Verify parallel Claude sessions get different random ports
  • Verify fallback when Tailscale is not installed (falls back to localhost + share URL)

🤖 Generated with Claude Code

Auto-detect Tailscale hostname so remote users can open the plan review
server directly in their browser without port forwarding. Server binds
to 0.0.0.0 when a reachable hostname is detected, and uses random ports
so parallel Claude sessions work.

Notification delivery: tmux display-popup (primary), ntfy push
notification (optional via PLANNOTATOR_NTFY_TOPIC), stderr (fallback).
Short URLs via paste service for compact share links.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Remote Claude Code sessions: no way to open plan review UI without a local browser

1 participant