tunnel Command
Forward webhooks to localhost from the CLI
The quickest way to forward webhooks to localhost from the command line is a tunnel CLI. Install the Hooklistener CLI, run hooklistener login once, then hooklistener tunnel --port 3000. You get a public HTTPS URL that forwards each request to your local server and keeps a copy you can inspect and replay.
npm i -g hooklistener # or: brew tap hooklistener/tap && brew install hooklistener
hooklistener login # one-time browser sign-in
hooklistener tunnel --port 3000
# Public URL: https://abc123.hook.events → http://localhost:3000The tunnel command creates a public HTTPS URL that tunnels all traffic to your local development server. This is the fastest way to test webhooks from services like Stripe, GitHub, Slack, and more. If you'd rather give the provider a URL that never changes, use listen with a hosted endpoint instead.
This is the most commonly used CLI command. Start your local server, run hooklistener tunnel --port 3000, and you're ready to receive webhooks.
Usage
hooklistener tunnel --port <PORT> [OPTIONS]Options
| Option | Description |
|---|---|
--port <PORT> | (Required) Local port to tunnel to |
--host <HOST> | Local host to tunnel to (default: localhost) |
--subdomain <NAME> | Request a specific subdomain (requires paid plan) |
--scheme <SCHEME> | Protocol to use locally: http or https (default: http) |
--help | Show help information |
How It Works
- Establish connection: The CLI opens a secure WebSocket connection to Hooklistener's edge servers.
- Get public URL: You receive a unique HTTPS URL (e.g.,
https://abc123.hook.events). - Receive requests: Any HTTP request to your public URL is streamed to the CLI.
- Forward locally: The CLI forwards the request to your local server with all headers and body intact.
- Return response: Your server's response is sent back through the tunnel to the original caller.
Security:All traffic is encrypted with TLS. Your local server never needs to be directly exposed to the internet.
Examples
Basic Tunnel
Expose localhost:3000 with a public URL:
hooklistener tunnel --port 3000Output:
✓ Tunnel established
Public URL: https://abc123.hook.events
Forwarding: https://abc123.hook.events → http://localhost:3000
Ready to receive webhooks. Press Ctrl+C to stop.Custom Subdomain
Request a memorable subdomain (paid plans):
hooklistener tunnel --port 3000 --subdomain my-appThis gives you https://my-app.hook.events — useful for webhook configurations you don't want to update frequently.
Tunnel to Docker Container
Forward to a service running in Docker:
hooklistener tunnel --port 8080 --host host.docker.internalLocal HTTPS Server
If your local server uses HTTPS:
hooklistener tunnel --port 3000 --scheme httpsChecked September 2026
Hooklistener vs ngrok http vs hookdeck listen
All four commands forward webhooks to a local port. They differ in which URL the provider sees and what happens to a request after it arrives.
| Criteria | hooklistener tunnel | hooklistener listen | ngrok http | hookdeck listen |
|---|---|---|---|---|
| Command | hooklistener tunnel --port 3000 | hooklistener listen YOUR_ENDPOINT_SLUG --target http://localhost:3000 | ngrok http 3000 | hookdeck listen 3000 <source> |
| URL you give the provider | Random hook.events subdomain on Free; a static subdomain on paid plans | Your hosted endpoint URL, which doesn't change, on Free too | 1 static dev domain on Free | A permanent event URL per source |
| When your machine is offline | Requests aren't delivered while the tunnel is closed | The endpoint still captures requests; replay them later | Requests aren't delivered while the agent is stopped | Not documented |
| History and replay | Stored in the cloud: 1 day on Free, up to 90 days on Scale; replay to localhost | Stored in the cloud: 1 day on Free, up to 90 days on Scale; replay to localhost | Traffic Inspector, 24-hour retention on Free; replay needs opt-in Full Capture | CLI Events page and local retry (not in guest mode) |
| Free tier | 1 CLI tunnel at a time, 50 stored requests | 1 hosted endpoint, 50 stored requests | 20,000 HTTP requests/mo, 1 GB transfer; interstitial page on HTTP endpoints | Developer plan: 10,000 events/mo, 3-day retention |
| Pick it when | You want a public URL for a local port right now | You want a provider URL that never changes and no lost webhooks | You also need TCP/TLS tunnels or non-webhook traffic | You already route production events through Hookdeck |
Sources: ngrok pricing, ngrok Traffic Inspector, Hookdeck CLI docs, Hookdeck pricing, Hooklistener pricing.
Common Integrations
Once your tunnel is running, configure these services with your public URL:
- Stripe: Dashboard → Developers → Webhooks →
{tunnel_url}/stripe/webhook - GitHub: Repo Settings → Webhooks →
{tunnel_url}/github/events - Slack: App Settings → Event Subscriptions →
{tunnel_url}/slack/events - Twilio: Phone Number → Messaging →
{tunnel_url}/twilio/sms
Troubleshooting
Connection refused
Make sure your local server is running on the specified port. The tunnel forwards requests, but they'll fail if nothing is listening.
Tunnel disconnects frequently
This usually indicates network instability. Check your internet connection, VPN, or firewall settings. The CLI will attempt to reconnect automatically.
Subdomain already taken
Custom subdomains are first-come, first-served. Choose a different subdomain or upgrade to a plan with reserved subdomains.