npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@hookflo/tern-dev

v0.2.4

Published

Local webhook tunnel and inspector. Zero storage.

Downloads

51

Readme

tern-dev

npm version MIT License Node 18+ Zero Storage

Local webhook tunnel. No ngrok. No account. Nothing stored.

Everything lives in RAM. Gone the moment you Ctrl+C.


Quickstart

npx @hookflo/tern-dev --port 3000
  ████████╗███████╗██████╗ ███╗  ██╗
     ██║   ██╔════╝██╔══██╗████╗ ██║
     ██║   █████╗  ██████╔╝██╔██╗██║
     ██║   ██╔══╝  ██╔══██╗██║╚████║
     ██║   ███████╗██║  ██║██║ ╚███║
     ╚═╝   ╚══════╝╚═╝  ╚═╝╚═╝  ╚══╝

  v0.2.2 · open source webhook tunnel

  tunnel    →  https://abc123.relay.tern.hookflo.com
  dashboard →  http://localhost:2019
  forwarding →  localhost:3000

  Ctrl+C to end session · use --ttl 60 to auto-kill

  no ttl set — tunnel runs until Ctrl+C
  1. Paste the tunnel URL into your webhook provider (Stripe, GitHub, Sentry, etc.)
  2. Open http://localhost:2019 to see events arrive live
  3. Ctrl+C when done — everything clears instantly

Or use --forward for a full path

npx @hookflo/tern-dev --forward localhost:3000/api/webhooks/stripe

Parses port and path in one flag. No need for separate --port and --path.


How it works

tern-dev opens a WebSocket to the relay server and receives a public tunnel URL. When a platform sends a webhook to that URL, the relay pipes the raw request to your machine over the WebSocket. Your local server receives it exactly as if the platform called it directly.

Stripe → https://abc123.relay.tern.hookflo.com
              ↓
         relay (Cloudflare Workers)
              ↓  WebSocket
         tern-dev (your machine)
              ↓  HTTP
         localhost:3000/api/webhooks

Dashboard

Open http://localhost:2019 after starting tern-dev.

| Feature | Description | |---------|-------------| | Live event log | Every webhook that arrives, in real time | | Payload tab | Full request body, pretty-printed JSON | | Headers tab | All headers, signature headers highlighted | | Response tab | HTTP status, latency, response body | | Verify tab | Signature verification guidance per provider | | Payload diff | Cmd+Click any two events → git-style side-by-side comparison | | Headers diff | Diff request headers between any two events | | Metadata | Timestamp delta, latency diff, payload size, provider detection | | Ignore fields | Exclude dynamic fields (id, timestamp) from diff | | DLQ | Failed events (4xx/5xx) grouped for easy replay | | Replay | Re-send any event to localhost with one click | | Replay all | Bulk replay all failed events | | Copy as curl | Get a curl command for any captured event | | Copy as fetch | Get a fetch() snippet for any captured event |

Keyboard shortcuts

| Key | Action | |-----|--------| | ↑↓ | Navigate events | | R | Replay selected event | | C | Copy tunnel URL | | D | Open compare panel | | 1 2 3 4 | Switch compare tabs | | Escape | Close compare / deselect |


CLI flags

| Flag | Default | Description | |------|---------|-------------| | --port | required | Local port to forward to | | --forward | — | Full address e.g. localhost:3000/api/webhooks | | --path | / | Path prefix on local server | | --ui-port | 2019 | Dashboard port | | --no-ui | false | Disable dashboard | | --relay | wss://tern-relay.hookflo-tern.workers.dev | Custom relay URL | | --max-events | 500 | Events kept in memory | | --ttl | unset | Auto-kill session after N minutes | | --rate-limit | unset | Max incoming requests/min; excess returns 429 | | --allow-ip | unset | Comma-separated allowlist of IPs/CIDR ranges (IPv4) | | --block-paths | unset | Comma-separated blocked path prefixes | | --block-methods | unset | Comma-separated blocked HTTP methods | | --block-headers | unset | Comma-separated name:glob block rules | | --log | unset | Append audit lines to a file | | --local-cert | unset | TLS cert path for local forwarding | | --local-key | unset | TLS key path for local forwarding | | --version | — | Print version | | --help | — | Print help |


Configuration file

tern-dev searches for tern.config.json or .ternrc.json from your current directory upward.

Priority: CLI flags > tern.config.json > built-in defaults

{
  "$schema": "./tern-config.schema.json",
  "port": 3000,
  "path": "/webhooks",
  "uiPort": 2019,
  "relay": "wss://tern-relay.hookflo-tern.workers.dev",
  "maxEvents": 500,
  "ttl": 60,
  "rateLimit": 100,
  "allowIp": ["54.187.174.169", "192.30.252.0/22"],
  "block": {
    "paths": ["/admin", "/debug"],
    "methods": ["DELETE"],
    "headers": { "user-agent": "curl*" }
  },
  "log": "./tern-audit.log"
}

Add "$schema" for full VS Code autocomplete on all fields.


Audit log

When --log is set, tern-dev appends one line per completed request:

[2025-01-15T10:23:45.123Z] POST /webhooks/stripe from 54.187.174.169 → 200 OK 45ms

Nothing is written to disk unless you explicitly set this flag.


Signature verification

tern-dev intentionally does not verify signatures at the tunnel layer. Verification belongs in your app handler using the raw body and headers.

Use @hookflo/tern for cross-platform signature verification:

import { WebhookVerificationService } from '@hookflo/tern'

app.post('/webhook', express.raw({ type: '*/*' }), async (req, res) => {
  const result = await WebhookVerificationService.verifyWithPlatformConfig(
    req,
    'stripe',
    process.env.STRIPE_WEBHOOK_SECRET!
  )
  if (!result.isValid) return res.status(400).json({ error: result.error })
  console.log('✅ verified:', result.payload.type)
  res.json({ received: true })
})

Always use express.raw({ type: '*/*' }). Never express.json() — it re-parses the body and breaks HMAC verification.


Self-hosting the relay

For full data isolation, run your own relay:

git clone https://github.com/hookflo/tern-relay
# deploy to Cloudflare Workers — follow its README
# then point tern-dev to it:

npx @hookflo/tern-dev --port 3000 --relay wss://your-relay.your-domain.com

Or in tern.config.json:

{
  "relay": "wss://your-relay.your-domain.com"
}

Privacy

| What | Where | Persists? | |------|-------|-----------| | Captured events | RAM only | ❌ cleared on exit | | Rate limit counters | RAM only | ❌ cleared on exit | | Config | Your tern.config.json | ✅ your file | | Audit log | Your log file (opt-in) | ✅ append-only | | Transit traffic | Cloudflare Workers relay | ❌ not stored |

For stricter trust boundaries, self-host the relay — zero third-party infrastructure in your request path.


Related

| Package | Description | |---------|-------------| | @hookflo/tern | Webhook signature verification SDK | | @hookflo/tern-mcp | MCP server for AI-assisted webhook debugging | | tern-relay | Self-hostable relay server (Cloudflare Workers) |


License

MIT © Hookflo