work / bridgehook

BridgeHook

An open-source webhook tunnel and inspector where your browser, not a binary, forwards to localhost.

Years
2026
Status
active
Live
bridgehook.dev
Source
hallelx2/bridgehook

What it is

BridgeHook gives you a public webhook URL that reaches localhost without installing a tunnel. A Cloudflare Worker receives the webhook; a Durable Object holds one Server-Sent Events stream open to your browser tab, the Chrome extension or the Tauri desktop app, which calls localhost and posts the response back. A per-channel Durable Object matches each reply to the sender still waiting for it.

Read more

Durable Objects are what make it work: the stream outlives the Worker's CPU limit, events land in D1, and a sync channel holds the sender for up to 25 seconds while an async one answers 202 at once. The client generates an ECDSA P-256 key pair and only the public key reaches the relay, which checks a signature on every claim and every response.

On top sits the part you use every day: a live feed, replay (a copy of the stored event with a new id), edit-and-replay, signature checks for Stripe, GitHub, Shopify and Slack, setup presets for more providers, mock responses and latency stats. Hosting costs nothing at current traffic.

Stack

  • TypeScript
  • Cloudflare Workers
  • Durable Objects
  • D1
  • Server-Sent Events
  • Chrome extension
  • Tauri
  • Rust

Counted

  • 153commits
    git rev-list, 2026-04-09 → 10-11
  • 3client agents
    web, Chrome extension, Tauri
  • 4signature providers verified
    apps/web signatures.ts, desktop bridge.rs
  • 21test files
    repo count

How it works

The system as a machine on a bench. Hover or use the arrow keys to drive it.

9f3a:3000
The webhook canister, then its replyOne wire, strung for as long as the client stays openLedger drum: every event kept, any one replayableA webhook is tagged, written to the ledger and carried along a line that stays open to the client, which opens it at localhost:3000 and sends back a reply signed with a key that never leaves it, matched to the sender by its tag. Signatures are checked for Stripe, GitHub, Shopify and Slack; a sync channel holds the sender up to 25 s for that reply, an async one answers 202 at once.

The path through it

  1. POST /hook/:channelIdStripe, GitHub or any sender hits the Worker.
  2. Durable ObjectsThe user's object holds the SSE stream (a heartbeat every 20 s); the channel's object stores the event in D1 and waits for the reply.
  3. SSE to the agentA browser tab, the Chrome extension or the Tauri app receives the event.
  4. fetch(localhost)The agent calls your local server with the original method, path, headers and body.
  5. POST /hook/:channelId/responseThe signed response goes back; the relay matches it by event id and answers a waiting sync sender (≤ 25 s); async senders already have their 202.
  6. InspectSignature verification for Stripe, GitHub, Shopify and Slack, replay, edit-and-replay, mocks and latency.