claude.symlink/skills/funnel-config/SKILL.md
Manage Tailscale Funnel routes for multi-service coexistence. Use when checking funnel status, adding/removing service routes, diagnosing tunnel connectivity, or when "funnel", "tailscale", "tunnel", "port routing" is mentioned. Also use proactively when deploying new services that need external HTTPS access.
npx skillsauth add htlin222/dotfiles funnel-configInstall this skill globally with one command. Works with Claude Code, Cursor, and Windsurf.
3 of 9 scanners reported clean
Some scanners were skipped, did not run, or reported a non-clean status. Review each row below.
# Get hostname
tailscale status --json | jq -r '.Self.DNSName' | sed 's/\.$//'
# List all routes
tailscale funnel status
# Check what's listening on which ports
lsof -i -P -n | grep LISTEN | grep -E ':(8080|3000|3030|5000)'
# Root path (only one service can own /)
tailscale funnel --bg <port>
# Sub-path (multiple can coexist)
tailscale serve --bg --set-path /<path> http://localhost:<port>
Rule: Routes coexist. Adding a root route does NOT remove sub-path routes. Adding a sub-path does NOT remove the root route.
# Remove root
tailscale funnel --https=443 off
# Remove a sub-path
tailscale serve --https=443 --set-path /<path> off
After any route change, verify both local and external:
HOSTNAME=$(tailscale status --json | jq -r '.Self.DNSName' | sed 's/\.$//')
# Local
curl -s --max-time 5 http://127.0.0.1:<port>/health
# External (proves funnel works end-to-end)
curl -s --max-time 10 "https://${HOSTNAME}/<path>" -o /dev/null -w "%{http_code}\n"
| Symptom | Cause | Fix |
|---------|-------|-----|
| External returns nothing | Funnel not active | tailscale funnel --bg <port> |
| External returns 502 | Service not running on that port | Start the service, check lsof -i :<port> |
| Route disappeared after restart | Funnel routes persist, but tailscale serve routes may not | Re-add with tailscale serve --bg --set-path ... |
| New route killed existing service | Won't happen — routes coexist | Verify with tailscale funnel status |
| GitHub webhooks not arriving | Hostname mismatch or funnel off | Check tailscale funnel status, compare with webhook URL |
testing
Converts narrative medical text into Pocket Medicine bullet-style notes with proper abbreviations, then modularizes sections exceeding 20 lines into linked standalone files.
devops
Use when deploying Docker services on the local VM (hostname: vm, Pop!_OS) with Traefik reverse proxy and Homepage dashboard. Covers crane image workflow, Traefik file-provider registration, Homepage services.yaml entries, and compose templates on the traefik-proxy network.
development
Use when reviewing a data visualization or figure for clarity, checking if a graph communicates its message without additional context, or iterating on R/Python plot scripts until a naive reader can fully understand the figure.
development
Runs Vale prose linter on markdown/text files and auto-fixes issues. Use when the user asks to lint, proofread, or improve writing quality of markdown or text files.