Tunneling & CLI
Tunneling streams incoming events — webhooks and emails — directly to your local machine over a WebSocket connection so you can debug against localhost without deploying.
Permanent endpoints require a paid account. Temporary endpoints can tunnel without login.
How it works
- The CatchHook CLI opens a WebSocket connection to CatchHook.
- Incoming events are streamed to the CLI in real time.
- The CLI forwards each event to your local URL.
- The CLI reports local delivery results back to CatchHook for metrics and alerts.
Webhook events are forwarded with the original HTTP method, headers, and body. Email events are forwarded as a normalized JSON POST containing the email's from, to, subject, text/HTML bodies, headers, attachments metadata, authentication results, and provider information.
Permanent endpoint flow
Use start directly. If no valid token is stored, the CLI opens browser auth automatically.
npx @catchhook/tunnel start --endpoint ep_abc123 --port 3000
Headless alternatives:
# One-off
npx @catchhook/tunnel start --endpoint ep_abc123 --port 3000 --token chk_dev_xxx
# Environment
CATCHHOOK_TOKEN=chk_dev_xxx npx @catchhook/tunnel start --endpoint ep_abc123 --port 3000
Temporary endpoint flow
Temporary endpoints include a tunnel_key:
npx @catchhook/tunnel ep_abc123 --key tkey_abc123 --port 3000
No account login required.
Provider presets
Use --provider to get provider-aware setup, signature verification, and richer event display:
# Create a new endpoint preconfigured for GitHub
npx @catchhook/tunnel start --provider github --port 3000
# Attach GitHub provider config to an existing endpoint
npx @catchhook/tunnel start --provider github --endpoint ep_abc123
Supported providers: github, stripe.
When --provider is used:
- New endpoint — the CLI creates an endpoint with provider metadata, generates a webhook signing secret, creates a signature verification config, and shows setup instructions (where to paste the URL and secret in the provider's dashboard).
- Existing endpoint — the CLI creates a signature config for that endpoint. If one already exists, it prompts before overwriting.
- Anonymous/temporary — full provider setup works with
--keytoo, including signature config and setup instructions. - Target URL — when the target is a port or omitted, the CLI appends the provider's default path (e.g.,
/webhooks/github). Full URLs are used as-is.
Restrictions:
--providerwith--allis not supported.--providerwith multiple--endpointvalues is not supported.
Incoming webhooks on all endpoints are automatically analyzed for provider detection. When a known provider is detected (from headers or body), the dashboard and CLI show the provider name, event type (e.g., "GitHub push" or "Stripe invoice.paid"), and replay warnings for dangerous events. This works regardless of whether --provider was used.
Active connections
The Tunnel tab on each endpoint shows a table of active connections with:
- User — the signed-in user (or "Anonymous" for temporary endpoints).
- Target — the local URL the CLI is forwarding to.
- Client — hostname, OS, and CLI version reported by the connected client.
- Connected since — how long the connection has been open.
- Status — Healthy (heartbeat within the last minute) or Stale.
Authentication model
- CLI auth creates a token scoped for tunneling and reads.
- CLI tokens expire after 30 days.
- Re-authenticating revokes older CLI tokens for that user/account.
- Browser callback uses a one-time auth code exchanged for the token by the CLI.
Connection limits
| Plan | Concurrent tunnel connections |
|---|---|
| Pro | 1 |
| Business | 5 |
Troubleshooting
| Problem | Solution |
|---|---|
| Invalid token | Re-authenticate (npx @catchhook/tunnel auth login) or pass a fresh token with --token. |
| Auth code expired | Re-run auth and use the new code. |
| Rate limited | Wait for the retry window and reconnect. |
| Local server unreachable | Verify the local target URL/port is running. |