Skip to content
catchook

Reference

CLI

catchook listen, replay and events — command and option reference.

npm i -g @catchook/cli    # then: catchook listen …
npx @catchook/cli listen  # or no install at all

Needs Node 22+ (for a global WebSocket) or any recent Bun. The published binary is a single bundled file with no dependencies.

Commands

Command
loginPrompts for an API key, verifies it, and saves it to $XDG_CONFIG_HOME/catchook/config.json with mode 600
listenStreams events as they arrive and forwards each to a local URL
replay [event]Re-sends an event already received. With no argument, the most recent one
eventsLists recent events, to pick an id from

Options

Option
--forward-to <url>Where to send the request. Remembered, so later runs need no flag
--endpoint <end_…>Only handle this endpoint. Filtered server-side for listen
--last <n>replay: the last n events, oldest first
--to-destinationsreplay: send through real delivery instead of to your machine
--sign-with <secret>Add a catchook-signature computed exactly as production does
--limit <n>events: how many rows. Default 20
--timeout <ms>How long to wait for your local server. Default 30000
--printNon-interactive only: print the body and the response
--jsonNDJSON on stdout, for jq

listen is a full-screen view

Given a terminal, listen takes over the screen: events on the left, the selected one in full on the right — headers, body, and every attempt at putting it on your machine.

catchook listen  http://localhost:3000                    ● live  ·  4 ev · 3 ✓ · 1 ✗
─ events (4) ───────────────────────────────┬─ detail ───────────────────────────────
  15:05:12  stripe    200 1ms               │ evt_d70ac86334f448f78e20822e647c583d
▸ 15:05:11  stripe    500 1ms   ×2          │
  15:05:10  github    ✗                     │ endpoint  end_60e42bf9513149f2b89ddd…
                                            │ provider  stripe
                                            │ signature valid
                                            │ ── local forwards ───────────────────
                                            │ 15:05:11  live    200 1ms
                                            │ 15:05:15  replay  500 1ms
                                            │     ↩ TypeError: cannot read property
Key
↑ ↓ / k jMove through the events
pgup pgdn, g GPage, jump to newest / oldest
enter / rReplay the selected event onto your machine
aReplay the whole session, oldest first
tabSwitch focus between list and detail, then scroll it
spacePause / resume forwarding
wPretty or raw body
cClear the session
qQuit

Piped, redirected, or with --json, none of this applies: the output is one plain line per event, which is what grep and jq expect.

Configuration

Precedence is flag > environment > saved config > default.

Variable
CATCHOOK_API_KEYAPI key, instead of login
CATCHOOK_API_URLControl-plane base URL
CATCHOOK_EVENTS_URLEvent-stream base URL
CATCHOOK_FORWARD_TODefault --forward-to

Known limits

  • The reconnect gap. The stream only pushes to subscribers connected at that instant; anything that arrives during an outage reaches nobody. The CLI says so on reconnect — catchook replay --last N is the answer.
  • A refused handshake carries no HTTP status. The CLI asks the API whether your key is at fault: if so it stops, otherwise it retries and tells you the key is fine so you look at your server.
  • 14-day retention. Past that an event is no longer replayable.
  • 100 KB per body. An ingestion limit, not a CLI one.