BridgeHook
The browser tab is the tunnel. There is nothing to install because there is nothing to install.
Every webhook tunnel makes you install something — an ngrok binary, cloudflared, an npm package, an SSH client. That is fine until you are on a locked-down laptop, or demoing in thirty seconds, or teaching somebody who should not have to learn a package manager before they can test a Stripe webhook.
The observation underneath BridgeHook is that the browser is already a perfectly good tunnel agent. It can hold a stream open, and it is allowed to reach localhost from an HTTPS page — so the thing you were going to install is a page you already have open.
A Worker has a 30-second CPU limit per request, so an SSE stream held in a Worker would simply die. The stream lives in a per-channel Durable Object instead, which holds writers indefinitely and hibernates when idle — which is what makes leaving a bridge open all day cost nothing. The relay is a dumb pipe: store the event, hold the stream, correlate request with response.
POST /api/channels returns a channel id and a secret. The secret is generated in the browser, SHA-256 hashed, and only the hash is sent.
GET /hook/:channelId/events holds an SSE connection open against the Durable Object, authenticated by that hash in constant time.
The agent fetch()es http://localhost:3000 with the path, method, headers and body it was handed.
POST /hook/:channelId/response correlates by id, so the original sender gets your dev server’s real answer rather than a fabricated 200.
We are not the first to relay webhooks over SSE. smee.io has done this since 2017 and inspired a lot of the wire shape here.
the BridgeHook README, on prior artA tunnel moves bytes. This one keeps them and lets you argue with them.
- Every event is capturedFull request and response detail in Neon Postgres — method, path, headers, body, status and latency — so the feed is a record rather than a tail.
- Replay, and edit-then-replayRe-fire any captured event at localhost, or change the headers, body or method first. Reproducing a webhook bug stops involving the sender entirely.
- Signature verificationStripe, GitHub and Shopify are verified against a signing secret you paste once, with constant-time comparison. Slack is detected and shown but not yet verified; Clerk and Linear are in the secrets manager only.
- Mock-response modeAnswer the sender with a canned response without forwarding at all — which is what you want when the dev server is not running.
- Copy as cURLTurn any captured webhook into a terminal command, which is usually the fastest route into a debugger.
It is generated client-side and hashed before transmission. The relay stores a hash, compares in constant time, and could not replay your traffic if it wanted to.
It can deliver bytes to a tab that holds the channel secret. It cannot run code on your machine, and it cannot reach your machine at all on its own.
There is no daemon left behind and no background process to remember to kill — which is the flip side of the same design that removed the install.
Built and open, not yet hosted — and the README is ahead of the code in two places.
- Not deployedFour workspaces are built — the relay Worker at about 2,500 lines, the React dashboard, a Chrome extension and a Tauri desktop shell — but
bridgehook.devdoes not currently resolve. You can run the whole stack yourself; there is no hosted instance to point you at. - One releasev0.0.1. The README advertises Homebrew, Scoop and Snap channels for the desktop app; those do not exist yet.
- No testsThere is CI, linting and typechecking, and no test files anywhere in the repository. That is the largest gap in it.
- Six providers claimed, three verifiedCorrected on this page rather than repeated. The README is being fixed.
- Chrome moved the goalpostsSince Chrome 142, a public page reaching localhost triggers a one-time Local Network Access prompt — so the extension, which sits outside the page sandbox, is now the sensible default rather than the tab.
The install was never load-bearing.
Everything that made a webhook tunnel feel like infrastructure — the binary, the daemon, the account — turned out to be removable. What is left is a page, a stream, and a database that remembers what came through.