tern-cli/Open source · MIT · npm

Local webhook
tunnel.

A public HTTPS URL for the webhooks you are building, with a live inspector on localhost. No ngrok account. Payloads stay in memory on your machine.

Zero setup

Zero infrastructure.

$npx @hookflo/tern-dev --port 3000
  1. 01Run the command
  2. 02Paste the URL into your provider
  3. 03Watch events at localhost:2019

Getting started

Three steps to live

No install step, no config file required, no account. Run npx and the tunnel is up.

  • Start a tunnel on any local port with a single command
  • Get a public HTTPS URL and paste it into any webhook provider
  • Watch events arrive in real time at localhost:2019
  • Inspect payloads, headers, status codes, and latency
  • Replay any event with one click
  • Ctrl+C erases the session — nothing is left on disk
$ terminalLive
# 1. Start the tunnel$ npx @hookflo/tern-dev --port 3000   ████████╗███████╗██████╗  ███╗  ██╗     ██║   ██╔════╝██╔══██╗ ████╗ ██║     ██║   █████╗  ██████╔╝ ██╔██╗██║     ██║   ██╔══╝  ██╔══██╗ ██║╚████║     ██║   ███████╗██║  ██║ ██║ ╚███║     ╚═╝   ╚══════╝╚═╝  ╚═╝ ╚═╝  ╚══╝  tunnel → https://abc123.relay.tern.hookflo.com dashboard → http://localhost:2019 forwarding → localhost:3000 # 2. Paste the tunnel URL into your webhook provider# 3. Open the dashboard and watch events arrive ✓ Tunnel live · Ctrl+C to end and erase the session

Core capabilities

Everything for local webhook dev

Tunnel, inspect, replay, and verify — without a third-party account or a cloud log of your payloads.

Instant public tunnel

One command returns a public HTTPS URL. No account, no signup. Webhooks land on your machine in milliseconds.

Live event dashboard

A local log at localhost:2019 with payloads, headers, response codes, and latency for every delivery.

Zero persistence

Events stay in RAM. Nothing is written to disk, and nothing is indexed in the cloud. Ctrl+C clears the session.

Signature verification

Guidance for Stripe, GitHub, Clerk, and custom HMAC webhooks, so you can check integrity while you build.

One-click replay

Resend a captured webhook to your local server. Test failures without asking the provider to fire again.

Dead letter queue

Failed events sit in their own view. Inspect them, fix the handler, and replay without scrolling the full log.

Export as cURL or fetch

Copy any event as a ready-to-run request. Share the exact payload with a teammate in one click.

Config file support

Keep ports, rate limits, IP rules, path blocks, session TTL, and audit logs in tern.config.json.

Self-hostable relay

Run hookflo/tern-relay on your own infrastructure and point the CLI at it with --relay.

Live dashboard

Inspect every byte in real time

The dashboard at localhost:2019 shows each webhook as it arrives — body, headers, signature, and how long your handler took.

  • JSON payloads with formatting you can actually read
  • Full HTTP headers and signature status
  • Response code, body, and latency for every event
  • Side-by-side comparison when two deliveries disagree
  • A dead-letter view that only shows failures
  • One-click replay back to your local server
  • Export any event as curl or fetch
  • Live updates over WebSocket — no polling
EventsLive logDLQ (1)Connected
POST/stripe/webhook2002.4ms
POST/github/events50045ms
POST/clerk/hooks2001.1ms
POST/custom/handler2021.8ms
4Events
1Failures
0BPersisted

CLI reference

All flags, at a glance

Every option the CLI accepts. The same keys can live in tern.config.json so you do not retype them each session.

FlagTypeDefaultDescription
--portnumberrequiredLocal app port to forward requests to
--pathstring/Path prefix for forwarded requests
--ui-portnumber2019Dashboard HTTP port
--no-uibooleanfalseDisable the dashboard and browser WebSocket server
--relaystringwss://relay.tern.hookflo.comOverride the relay WebSocket URL for self-hosting
--max-eventsnumber500Maximum events buffered in session memory

Configuration

Persistent setup with tern.config.json

Drop tern.config.json in the project root. CLI flags merge over the file, so a one-off --port still wins.

  • Port, path prefix, and UI port
  • Rate limiting per IP
  • IP allowlists and blocklists
  • Blocked paths and HTTP methods
  • A custom relay URL for self-hosting
  • Session TTL and auto-kill timers
  • Audit logging to a file you choose
  • JSON Schema with editor autocomplete
tern.config.jsonJSON
{
  // $schema: "schemastore.org/tern-dev"
  "port": 3000,
  "path": "/webhooks",
  "uiPort": 2019,
  "rateLimit": 100,
  "maxEvents": 500,
  "allowIp": [
    "54.187.174.169",
    "52.86.47.0/24"
  ],
  "blockPaths": ["/health"],
  "relay": "wss://relay.yourinfra.com",
  "noUi": false
}

Privacy by design

Your data stays on your machine

RAM-only storage

Captured events live in the process. A session does not write webhook bodies to disk.

No cloud log

The relay forwards payloads as they arrive. It does not store, index, or replay them later.

Instant erasure

Ctrl+C ends the process. Events, headers, and the dashboard session go with it.

Ready to test webhooks locally?

No account. No ngrok. No stored payloads. One command and you are debugging the real request.

$npx @hookflo/tern-dev --port 3000