Tunneling & CLI
The CatchHook CLI provides a fast-ack local relay over a WebSocket connection so you can debug against localhost without deploying.
CatchHook captures the request and returns the endpoint's configured response to the provider before local delivery completes. The CLI then sends the captured request to your local URL and reports the local status and timing separately. The local response is not returned to the webhook provider.
Permanent endpoints require a paid account. Temporary endpoints can tunnel without login.
How it works
- The CatchHook CLI opens a WebSocket connection to CatchHook.
- CatchHook captures an incoming event and acknowledges the provider.
- The saved event is streamed to the CLI.
- The CLI delivers it 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.
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 where the CLI delivers events.
- 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.
Delivery gaps and recovery
Authenticated permanent endpoints remember that they are expected to be tunneling. If a webhook arrives while the monitored tunnel is disconnected, CatchHook:
- captures the webhook normally;
- records one durable delivery gap for the outage;
- notifies the endpoint's workspace through email, Slack, or a generic webhook; and
- offers deliberate recovery the next time the CLI connects.
The existing short-window catch-up remains automatic. Longer durable gaps use the --catch-up safety modes:
| Mode | Behavior |
|---|---|
prompt |
Interactive default. Shows the gap and asks before replaying it. |
recent |
Headless default. Automatically replays only the existing 120-minute window. |
all |
Explicitly pages through all retained requests in unresolved gaps, oldest first. |
none |
Starts live delivery without catch-up and reports the unresolved count. |
# Recover every retained request without an interactive prompt
npx @catchhook/tunnel start --endpoint ep_abc123 --catch-up all
# Start live delivery only
npx @catchhook/tunnel start --endpoint ep_abc123 --catch-up none
Recovery always sends to the current command target. The CLI displays a historical target when it differs, records every local delivery result, and leaves failed or expired requests marked as partial rather than claiming the gap was recovered.
The Tunnel panel contains the monitoring toggle, outage boundary, retained missed count, recovery status, and an explicit dismiss action. Disabling monitoring prevents future gaps without deleting history.
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 |
| Team | 3 |
| 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. |