ngrok alternatives for sharing a local report
The pattern is familiar. A script writes report.html, you run
python -m http.server, you ngrok http 8000, you paste the URL in Slack,
and someone says "nice, I'll look after standup."
By standup the laptop is closed and the link is dead.
What a tunnel is and isn't
ngrok is excellent at what it does: it makes a process on your machine reachable from the internet. Webhooks, mobile testing against a dev server, pairing on a live bug — nothing else is as fast.
It is a poor fit for sharing a document, for four reasons:
- Its lifetime is your process's lifetime. Close the terminal, sleep the laptop, lose Wi-Fi — the URL is gone. Free tunnels also get a new address every restart, so re-sharing means re-pasting.
- It exposes more than you think.
http.serverserves the directory. A tunnel in a project folder can hand out.env, raw CSVs and source alongside the report. - It is open by default on free tiers. No identity, no record of who opened it, plus an interstitial page in the reader's way.
- Your machine is the CDN. Latency, uptime and bandwidth are whatever your laptop and hotel Wi-Fi are today.
The shortlist
1. Upload the file — Comma
If the other person needs your output, not your process, the tunnel is solving the wrong problem. Publish the artifact and the link outlives the session:
curl -X POST https://commareports.com/api/v1/reports \
-H "Authorization: Bearer $COMMA_API_TOKEN" \
-H "Content-Type: application/json" \
-d "$(jq -n --arg h "$(cat report.html)" \
'{title:"Local run", html:$h, visibility:"team"}')"
Or drag the file into /new if you would rather not touch a
terminal. Multi-file output — a folder with assets/ and images — uploads
as a zip bundle so relative paths still resolve.
The link stays up when your machine doesn't, visibility is private / team / email-domain / registered / link rather than "whoever has the URL", and the reader can leave a comment anchored to the chart instead of describing it in chat.
Not for: anything that needs your local process to respond. Keep the tunnel for webhooks.
Pricing: Free — unlimited reports, viewers, commenters and revisions.
Upload an HTML file, get a link →
2. Cloudflare Tunnel — a better tunnel, still a tunnel
cloudflared tunnel is free, gives stable named hostnames, and can sit
behind Cloudflare Access so the tunnel is actually authenticated. If you
genuinely need the local process reachable, this is the upgrade. It still
dies with the process.
3. VS Code / GitHub Codespaces port forwarding
If you already work in a Codespace or use the built-in port forwarding, sharing a forwarded port is one click and respects your GitHub identity — no third-party proxy. Same lifetime caveat.
4. Just serve it locally, for yourself
Half the time nobody else is involved and you only wanted to see the page
with working relative paths. python -m http.server and stop there. See
serving an HTML file locally.
At a glance
| Option | Survives laptop sleep | Authenticated | Exposes your machine | Comments |
|---|---|---|---|---|
| Comma | Yes | Yes, per report | No | Yes |
| ngrok (free) | No | No | Yes | No |
| Cloudflare Tunnel | No | With Access | Yes | No |
| Codespaces forward | While running | GitHub identity | Sandbox | No |
| Local server | n/a | n/a | LAN only | No |
Checked September 2026.
How to choose
- Webhook callbacks or live debugging? ngrok, or Cloudflare Tunnel if you want it authenticated.
- Testing on a phone against your dev server? A tunnel, obviously.
- "Take a look at this report when you get a minute"? That is a file, not a process — upload it.