Stable public URLs for webhooks, forwarded in real time to your localhost — through an interactive terminal dashboard. Runs 100% on your machine; the only external piece is the ngrok tunnel.
📚 Documentation site — a full Docusaurus site lives in
website/: get-started guides, concepts, a dashboard tour, a CLI reference and architecture, with generated terminal screenshots throughout. Run it withcd website && npm install && npm start.The original Markdown notes are still in
docs/: current state · usage · motivation · architecture · development
wi opens an interactive dashboard (built with OpenTUI
- Solid). From it you start/stop the daemon, manage endpoints, watch webhooks arrive live, and replay events — all from the keyboard.
╭ webhook-it ──────────────────────────── running (tunnel) — https://you.ngrok-free.app ╮
╭ Endpoints ─────────╮╭ Events — stripe-dev ───────────────────────────────────────────╮
│ > stripe-dev ││ 14:02:51 a1b2c3d4e5 POST 200 │
│ github-app ││ 14:02:31 f6g7h8i9j0 POST/refunds 200 │
│ ... ││ ... │
╰────────────────────╯╰───────────────────────────────────────────────────────────────╯
╭ up/down select - u start/stop - n new - c domain - d delete - r replay - q quit ──────╮
- Press
uin the dashboard to start the local daemon + an ngrok tunnel. - A webhook arrives at the stable public URL → the daemon saves the event and
forwards it to your
localhost, with headers and body intact. - History and replay live in a local SQLite database — nothing leaves your machine.
A repo can commit a .webhook-it.json listing its webhook endpoints. A teammate
then provisions all of them with a single command — wi apply — instead of
creating each by hand:
{
"project": "acme-api",
"endpoints": {
"stripe": { "target": "http://localhost:3000/webhooks/stripe" }
}
}Endpoints are namespaced by project, so two repositories never collide. Full
reference in docs/USAGE.md.
apps/
cli/ interactive dashboard (OpenTUI + Solid) — `webhook-it` / `wi`
packages/
core/ daemon, bun:sqlite storage, forwarder, ngrok adapter
shared/ shared types and zod schemas
tsconfig/ base TypeScript configs
docs/
README.md (index), STATE.md, USAGE.md, MOTIVATION.md,
PROJECT.md, ARCHITECTURE.md, DEVELOPMENT.md
- Bun 1.3+ — the runtime, package manager and bundler (install).
- ngrok — only for tunnel mode: installed and authenticated
(
ngrok config add-authtoken <token>), plus a free static domain reserved at https://dashboard.ngrok.com/domains. Local-only testing needs none of this.
bun install
bun run typecheck
bun run dev # runs the dashboard from source (hot reload)
bun run build # compiles a standalone binary at apps/cli/dist/wiAfter bun run build, run the binary (it is self-contained — no Bun needed to run it):
./apps/cli/dist/wiInside the dashboard: u start/stop the daemon · n new endpoint · c set the
ngrok domain · t toggle tunnel/local mode · r replay · d delete · q quit.
wi apply (the one subcommand) provisions endpoints from a project's
.webhook-it.json. See docs/USAGE.md for the full reference.
MVP in development. What already works is in docs/STATE.md;
the backlog is in docs/PROJECT.md.