Getting Started

Installation

Install dread with a single command. The script downloads the correct binary for your platform and sets up a background service for desktop notifications.

curl -sSL dread.sh/install | sh

This will:

  • Download the dread binary to ~/.local/bin
  • Automatically add ~/.local/bin to your PATH (no sudo required)
  • Set up a background service (launchd on macOS, systemd on Linux, Task Scheduler on Windows) for desktop notifications
  • Start listening for webhook events immediately

Supported platforms: macOS, Linux, and Windows (amd64 and arm64). Re-run the same command to update to the latest version.

Your First Channel

A channel is a webhook endpoint. Create one for each service you want to receive events from.

$ dread new "Stripe Prod"

Created channel: Stripe Prod (ch_stripe-prod_a1b2c3)
Webhook URL:     https://dread.sh/wh/ch_stripe-prod_a1b2c3

The command prints the channel ID and a webhook URL you can paste into any service's webhook settings.

Wire Up a Webhook

Copy the webhook URL from the previous step and paste it into your service's webhook configuration (Stripe dashboard, GitHub repo settings, Slack app config, etc.).

Once the service starts sending events, you'll see them immediately:

# paste the URL into Stripe, GitHub, Slack, Linear...
# notifications start automatically

$ dread  # open the TUI to see events live

Desktop notifications fire automatically from the background service. Open the TUI anytime to browse events with full payload inspection.

TUI Features

Header & Logo

When you launch dread, the TUI displays a 3-column header inside a rounded box:

  • Left column — ASCII art DREAD logo in the brand brown colour, with the version number below
  • Centre column — time-of-day greeting, connected channel count, session uptime, channel health dots, and success/failure/neutral event counts
  • Right column — total event count, events-per-minute rate, a sparkline showing event volume over the last hour, and rotating command tips that cycle every 5 seconds

The header is always visible and updates in real time as events arrive.

Status Indicators

Each event in the TUI list (and in the web dashboard) is classified and shown with a coloured dot:

  • ● Green — success events (keywords: succeeded, completed, paid, captured, created, active, resolved, delivered, merged, approved, ready)
  • ● Red — failure events (keywords: fail, error, denied, declined, expired, canceled, refused, rejected, dispute, alert, incident, critical, warning, overdue)
  • ● Gray — neutral events that don't match either category

Classification is based on keyword matching against the event type and summary fields. This works automatically with any webhook source.

Sparkline & Health

The header's right column includes a Unicode sparkline (using block characters ▁▂▃▄▅▆▇█) that visualises event volume over the last 60 minutes in twelve 5-minute buckets.

Channel health dots appear in the centre column. Each channel shows a dot that is green if it received an event within the last 30 minutes, or gray if it's stale. This gives a quick at-a-glance view of which integrations are actively sending.

The TUI also checks /api/version on startup and displays a notification in the header if a newer version of dread is available.

Split Pane

Press s to toggle a master-detail split view. The screen divides into two halves: the event list on the left and the payload detail on the right. Selecting an event in the list instantly updates the right pane without leaving the list.

This is ideal for debugging — you can navigate through events with j/k while continuously seeing the full payload beside it.

Tabs & Stats

The TUI has three tabs, switched with number keys:

  • 1 Live — the full event stream (default)
  • 2 Errors — auto-filtered to show only failure events (errors, denials, alerts, etc.)
  • 3 Stats — bar charts showing events by source, success/failure/neutral breakdown with percentages, and a 7-day × 24-hour activity heatmap

The Errors tab directly serves the core use case: quickly seeing what failed. The Stats tab gives a bird's-eye view of webhook traffic patterns.

Pause & Toasts

Press p or Space to pause the live event feed. While paused, new events are buffered in the background and a counter shows how many are waiting. Press p again to unpause and flush all buffered events.

When a failure event arrives (regardless of pause state), a red toast notification appears above the footer showing the source and summary. Toasts auto-dismiss after 5 seconds. Up to 3 toasts can be visible at once.

Advanced Filters

Press / to open the filter prompt. The filter supports several modes:

  • Substring match — type any text to match against source, type, summary, channel, and the raw JSON payload
  • Exclusion — prefix with ! to exclude matching events (e.g., !test)
  • Field-specific — use source:stripe, type:checkout, or channel:prod to filter by a specific field
  • Filter history — press / in the filter prompt to browse previous filters

Deep payload search is also supported — filtering searches inside the raw JSON body, so you can find events by a customer ID or charge amount buried in the payload.

Bookmarks

Press f to star/bookmark any event. Bookmarked events show a ★ indicator in the event list and the header shows a total bookmark count.

Press F to toggle bookmark-only view, filtering the list to show only bookmarked events. Press F again to return to the full list.

Auto-Diff

Press d in the detail view to see a line-by-line diff of the current event's payload compared to the previous event from the same source. Added lines are shown in green, removed lines in red. Press d again to return to the normal payload view.

Event Grouping

Press g to toggle event grouping. When enabled, consecutive events with the same source and type within 60 seconds are collapsed into a single row with a ×N badge showing the burst count. This reduces noise from high-volume event sources.

Command Palette

Press Ctrl+P to open a command palette overlay with fuzzy search. Type to filter commands, use ↑↓ to navigate, and Enter to execute. All major TUI actions are available through the palette.

Mouse Support

The TUI supports mouse interaction. Click on an event in the list to select it. Scroll to navigate. In split pane mode, clicking an event also updates the detail pane.

HTML Export

Press x to export the current session as a styled HTML report. The export includes all filtered events with timestamps, sources, types, summaries, status classification, and collapsible JSON payloads. The file is saved to the current directory.

Forward Response Capture

When using --forward, each forwarded event now shows a status badge in the event list (e.g. →200 for success, →err for failures). In the detail view, the full forward response is shown including HTTP status code, response headers, response body, and round-trip duration.

Swimlane Timeline

The Stats tab (press 3) now includes a swimlane timeline visualization showing per-source event activity over the last 60 minutes. Each source gets its own horizontal lane with filled blocks indicating minutes with activity.

CLI Reference

dread

Launch the interactive terminal UI. Shows a live feed of webhook events across all your channels with full payload inspection.

$ dread [flags]
FlagDefaultDescription
--serverdread.shServer URL to connect to
--filterFilter events by substring (source, type, summary, channel)
--forwardForward incoming events to a URL

Keybindings:

KeyAction
qQuit
j / kNavigate up / down
enterView event detail & payload
/Filter events
rReplay event
cCopy webhook URL (list) or payload (detail)
p / SpacePause / resume live feed
sToggle split pane (list + detail side-by-side)
?Show help overlay with all keybindings
1Live tab (all events)
2Errors tab (failures only)
3Stats tab (charts, heatmap & swimlane)
fBookmark / unbookmark event
FToggle bookmarks-only view
dDiff with previous same-source event
gToggle event grouping
xExport session as HTML
Ctrl+PCommand palette
escBack / clear filter

dread new

Create a new webhook channel. Returns the channel ID and the webhook URL to paste into your service.

$ dread new <name>

Example:

$ dread new "GitHub Deploys"

Created channel: GitHub Deploys (ch_github-deploys_d4e5f6)
Webhook URL:     https://dread.sh/wh/ch_github-deploys_d4e5f6

dread list

Show all channels with their IDs and webhook URLs.

$ dread list

Stripe Prod      ch_stripe-prod_a1b2c3       https://dread.sh/wh/ch_stripe-prod_a1b2c3
GitHub Deploys   ch_github-deploys_d4e5f6    https://dread.sh/wh/ch_github-deploys_d4e5f6
Sentry Alerts    ch_sentry-alerts_g7h8i9     https://dread.sh/wh/ch_sentry-alerts_g7h8i9

dread logs

Print recent webhook events to stdout. Useful for scripting or quick checks without opening the TUI.

$ dread logs [--limit N]
FlagDefaultDescription
--limit20Number of events to show

Example:

$ dread logs --limit 5

2m ago   stripe   invoice.paid $249.00
5m ago   github   PR merged #139 → main
12m ago  sentry   TypeError: Cannot read prop…
18m ago  linear   Issue ENG-481 moved to Done
25m ago  slack    #deploys: Production deploy v2.4.1

dread status

Show channel overview, last event timestamps, and background service info.

$ dread status

Channels: 3
  Stripe Prod      last event 2m ago
  GitHub Deploys   last event 5m ago
  Sentry Alerts    last event 12m ago

Service: running (launchd)
Server:  dread.sh (connected)

dread test

Send a test webhook event to a channel. Useful for verifying your setup end-to-end.

$ dread test <channel-id>

Example:

$ dread test ch_stripe-prod_a1b2c3

Sent test event to Stripe Prod (ch_stripe-prod_a1b2c3)

dread add / remove

Manually subscribe to or unsubscribe from individual channels by ID.

$ dread add <channel-id> "Display Name"
$ dread remove <channel-id>

Example:

$ dread add ch_stripe-prod_a1b2c3 "Stripe Prod"
Added channel: Stripe Prod

$ dread remove ch_stripe-prod_a1b2c3
Removed channel: ch_stripe-prod_a1b2c3

dread watch

Run in headless notification mode. No TUI — just desktop notifications. The background service uses this internally, but you can run it manually too.

$ dread watch [flags]
FlagDefaultDescription
--serverdread.shServer URL to connect to
--filterOnly notify on matching events

Auto-reconnects after 3 seconds if the connection drops.

dread service

Install or remove a background service so dread watch runs automatically — even after the terminal is closed or the machine restarts.

$ dread service install
Background service installed and started.
  Plist:  ~/Library/LaunchAgents/dev.dread.watch.plist
  Logs:   ~/Library/Logs/dread.log

Notifications will now appear even when the terminal is closed.
SubcommandDescription
installInstall and start the background service (launchd on macOS, systemd on Linux, Task Scheduler on Windows)
uninstallStop and remove the background service

On macOS, this creates a launchd agent that starts at login and auto-restarts on failure. On Linux, it creates a systemd user service. On Windows, it creates a Task Scheduler task that runs at logon. Logs are written to ~/Library/Logs/dread.log (macOS) or available via journalctl --user -u dread-watch (Linux).

Use dread status to check whether the background service is running.

dread replay

Re-forward a past event to a URL. Fetches the full event payload from the server and POSTs it to the target.

$ dread replay <event-id> --forward <url>

Example:

$ dread replay evt_abc123 --forward http://localhost:3000/webhook

Replayed evt_abc123 → http://localhost:3000/webhook (200 OK)

Webhooks

How It Works

When a service sends a POST request to your channel's webhook URL:

  1. The server receives the payload at POST /wh/{channel-id}
  2. It auto-detects the source (Stripe, GitHub, etc.) from request headers
  3. It extracts the event type and a human-readable summary
  4. The event is stored server-side and broadcast to all connected clients via WebSocket
  5. Your desktop notification fires, and the TUI updates in real time

Supported Sources

dread auto-detects 60+ webhook sources from HTTP headers. Any unrecognised source is labelled "webhook" — add ?source=name to your webhook URL to label it yourself.

CategorySources
Payment & FinanceStripe, PayPal, Square, Razorpay, Paddle, Recurly, Coinbase, Plaid, Xero, QuickBooks
Dev & CodeGitHub, GitLab, Bitbucket, CircleCI, Travis CI, Buildkite
InfrastructureVercel, Heroku, AWS SNS, Cloudflare
CommunicationSlack, Discord, Twilio, SendGrid, Mailchimp, Zendesk, Telegram, LINE
Project ManagementLinear, Jira, Notion, Trello, Airtable
MonitoringSentry, PagerDuty, Grafana, Pingdom
CMS & CommerceShopify, WooCommerce, Contentful, Sanity, BigCommerce
Auth & IdentityAuth0, WorkOS, Svix (Clerk, Resend)
DatabaseSupabase, PlanetScale
SaaSHubSpot, Typeform, Calendly, DocuSign, Zoom, Figma, Knock, Novu, LaunchDarkly, Customer.io, Pusher, Ably, Twitch, Zapier

Custom Webhooks

You can send webhooks from your own services. Just POST JSON to your channel URL:

$ curl -X POST https://dread.sh/wh/ch_my-channel_abc123 \
  -H "Content-Type: application/json" \
  -d '{"event": "deploy.success", "env": "production"}'

To set a custom source name, add ?source=name to your webhook URL:

https://dread.sh/wh/ch_my-channel_abc123?source=trigger.dev

This works with any service — just append ?source= when pasting the URL into your webhook settings. You can also use the X-Dread-Source header for programmatic control:

$ curl -X POST https://dread.sh/wh/ch_my-channel_abc123 \
  -H "Content-Type: application/json" \
  -H "X-Dread-Source: my-app" \
  -d '{"event": "deploy.success", "env": "production"}'

Team Workspaces

Sharing a Workspace

A workspace is your collection of channels. Share it with your team so everyone gets the same webhook feeds.

$ dread share

Share this with your team:
  dread follow ws_a1b2c3d4e5f6

They'll get all your channels (and any you add later).

The workspace ID is generated from your local config. Running dread share publishes your current channel list to the server.

Following a Workspace

Teammates run a single command to subscribe to all channels in a workspace:

$ dread follow ws_a1b2c3d4e5f6

Following workspace ws_a1b2... (3 channels):
  Stripe Prod        ch_stripe-prod_a1b2c3
  GitHub Deploys     ch_github-deploys_d4e5f6
  Sentry Alerts      ch_sentry-alerts_g7h8i9

New channels will sync automatically.

To stop following:

$ dread unfollow ws_a1b2c3d4e5f6
Unfollowed workspace ws_a1b2c3d4e5f6

Auto-Sync

When the workspace owner adds new channels, followers pick them up automatically on their next reconnect. No action needed — the background service handles it.

The sync happens every time the WebSocket connection is established (on startup, after a network drop, etc.). Any new channels in the workspace are added to the follower's local config automatically.

Notifications

Desktop Notifications

dread sends native desktop notifications for every webhook event. Run dread service install to set up a background service that starts at login and keeps running even after the terminal is closed.

$ dread service install
  • macOS — uses a native notifier with sound. Notifications appear in Notification Centre.
  • Linux — uses notify-send. Works with any desktop environment that supports freedesktop notifications.
  • Windows — uses Windows toast notifications via PowerShell. Works on Windows 10 and later.

This installs a launchd agent (macOS), systemd user service (Linux), or Task Scheduler task (Windows) that auto-restarts on failure. To remove it, run dread service uninstall.

Custom notification sound

Set the "sound" field in your config to change the notification sound (default: Sosumi):

{
  "token": "dk_...",
  "channels": [...],
  "sound": "Hero"
}

macOS built-in sounds: Basso, Blow, Bottle, Frog, Funk, Glass, Hero, Morse, Ping, Pop, Purr, Sosumi, Submarine, Tink

You can also use custom sounds on macOS by placing a .aiff file in ~/Library/Sounds/ and referencing it by name (without extension).

Linux: uses freedesktop sound names (e.g. message-new-instant). Support varies by desktop environment.

You can also change the sound from the web dashboard — open the sidebar and use the Notification Sound dropdown. Changes are saved to the workspace and synced to team members.

Watch Mode

Run the notification daemon manually without the TUI:

$ dread watch

Watch mode is headless — it connects to the server, listens for events, and fires desktop notifications. If the connection drops, it auto-reconnects after 3 seconds.

This is the same process the background service runs. You can use it directly for debugging or if you prefer to manage the process yourself.

Filtering Events

Use the --filter flag to only see events matching a pattern. The filter is a case-insensitive substring match against source, type, summary, and channel name.

# only show Stripe events in the TUI
$ dread --filter stripe

# only get notifications for payment events
$ dread watch --filter payment

# filter for a specific channel
$ dread --filter "GitHub Deploys"

In the TUI, press / to open the filter prompt interactively.

Forwarding & Replay

Forward to Localhost

Forward webhook events to a local development server in real time:

$ dread --forward http://localhost:3000/webhook

Every event that arrives is POSTed to the target URL with the original payload. dread adds the following headers for context:

HeaderDescription
X-Dread-SourceDetected source (stripe, github, etc.)
X-Dread-Event-TypeEvent type (invoice.paid, push, etc.)
X-Dread-ChannelChannel ID
X-Dread-Event-IdUnique event ID

Forwarding uses a 10-second timeout per request. The TUI continues to work normally while forwarding.

Replay Past Events

Re-forward any past event to a URL. Useful for debugging webhook handlers without waiting for the real event to happen again.

$ dread replay <event-id> --forward <url>

Example:

$ dread replay evt_abc123 --forward http://localhost:3000/webhook

Replayed evt_abc123 → http://localhost:3000/webhook (200 OK)

The event is fetched from the server and POSTed to the target with the same X-Dread-* headers. You can find event IDs in the TUI detail view or from dread logs.

Web Dashboard

Overview

The web dashboard at /dashboard lets you view your live event feed in the browser without installing the CLI. It uses the same APIs as the CLI — no extra backend required.

The workspace ID in the URL is the access key, same as the rest of the app. Anyone with the workspace ID can view the dashboard.

Connecting

Visit /dashboard and enter your workspace ID (e.g. ws_230a2bc06cb0). Find your workspace ID by running:

$ dread share

The dashboard remembers your last workspace ID in localStorage. You can also share direct links:

https://dread.sh/dashboard?ws=ws_230a2bc06cb0

Features

  • Channel sidebar — lists all channels with their webhook URLs and copy buttons
  • Live event feed — events stream in real-time via WebSocket, with channel name, source, type, and summary
  • JSON payload viewer — click any event row to expand and see the full payload with syntax highlighting
  • Filter — search events by source, type, channel, or summary text
  • Pause/resume — pause the live stream to inspect events; buffered events flush on resume
  • Load more — scroll to the bottom and load older events with pagination
  • Tab notifications — unread event count appears in the browser tab title when the tab is in the background
  • Theme toggle — dark/light theme, same as the rest of the site
  • Mobile responsive — sidebar collapses to a hamburger menu on small screens
  • Mute toggle — per-channel mute via localStorage, suppresses browser notifications
  • Export — download events as JSON or CSV from the toolbar, or export as styled HTML
  • Replay — re-send any event to a URL from the event detail view
  • Bookmarks — star/bookmark events with ★, toggle bookmark-only view to filter to important events
  • Advanced filteringsource:stripe, type:checkout, !error exclusion, and free-text search
  • Stats panel — toggle source breakdown bars, success/failure/neutral status chart, and per-source swimlane timeline
  • Diff view — compare any event with the previous event from the same source, showing added/removed lines
  • Keyboard shortcutsj/k navigate, / filter, f bookmark, d diff, s stats, ? help overlay
  • HTML export — download the current session as a styled HTML report with collapsible payloads

Muting Channels

Temporarily silence a noisy channel without unsubscribing:

dread mute ch_noisy_abc123
dread unmute ch_noisy_abc123

Muted channels continue receiving events server-side but won't trigger desktop notifications in watch mode or the TUI. The dashboard also offers a per-channel mute toggle saved in localStorage.

Alert Rules

Set threshold alerts to fire when a pattern matches too many events in a time window:

# Alert when 5+ sentry events in 10 minutes
dread alert add sentry 5 10

# List configured rules
dread alert list

# Remove a rule by index
dread alert remove 0

When the threshold is reached, you'll get a desktop notification. If Slack/Discord forwarding is configured, the alert is forwarded there too. Counters are in-memory and reset on restart.

Slack / Discord Forwarding

Forward webhook events to Slack or Discord in real time via dread watch:

dread watch --slack https://hooks.slack.com/services/T.../B.../xxx
dread watch --discord https://discord.com/api/webhooks/123/abc

Or set the URLs in ~/.config/dread/config.json:

{
  "slack_url": "https://hooks.slack.com/services/...",
  "discord_url": "https://discord.com/api/webhooks/..."
}

Forwarding runs client-side in your dread watch process. Events are sent as rich messages — Slack uses blocks, Discord uses embeds.

Export Events

Download events as JSON or CSV via the API (capped at 1000 per request):

curl "https://dread.sh/api/export?channels=ch_xxx&format=csv" -o events.csv
curl "https://dread.sh/api/export?channels=ch_xxx&format=json" -o events.json

The dashboard also includes an Export button in the toolbar.

Daily Digest

Get a summary of recent event activity:

dread digest            # last 24 hours
dread digest --hours 8  # last 8 hours

Shows total event count, breakdown by source, and the 10 most recent events. Also available via API: GET /api/digest?channels=ch_xxx&hours=24

Status Page

Every workspace gets a public status page showing channel freshness:

https://dread.sh/status/ws_abc123def456

Channels are colour-coded by time since last event: green (<5min), yellow (<30min), red (>30min), grey (no events). The page auto-refreshes every 30 seconds.