Global settings
The [notify] table is where the daemon-wide knobs live: which channels
catch every failure, how long an outbound delivery keeps retrying, how
much bell history to hang onto, how hard to coalesce. Every key is
optional, and the defaults are tuned for a single-machine setup.
This isn’t the page for declaring channels or routing rules, though —
that’s [[notifier]]
and [[notification_route]].
[notify]global_notifiers = ["inapp"] # default — bell on# default_timeout = "30s" # unset — uses the built-in 5-min retry budgethistory_keep = 1024 # defaulthistory_keep_for = "90d" # defaultcoalesce_window = "1h" # defaultoccurrence_ring = 10 # defaultcoalesce_outbound = true # default| Key | Default | What it does |
|---|---|---|
global_notifiers | ["inapp"] | Channels added to every per-task notify list (deduplicated), and catch-all for tasks without one. Set [] to silence the bell. |
default_timeout | (unset) | Caps the total retry budget for one outbound delivery. Unset = 5 minutes. |
history_keep | 1024 | Cap on bell rows kept in SQLite. Older rows are pruned in one pass. |
history_keep_for | 90d | Maximum age of bell rows. Accepts d and w units. |
coalesce_window | 1h | Window during which repeats with the same kind for the same task update one row instead of writing a new one. |
occurrence_ring | 10 | Recent timestamps kept on each coalesced row. |
coalesce_outbound | true | Coalesce outbound deliveries too, not just bell rows. Set false to send one message per event. |
Set both history_keep and history_keep_for and they both apply at
once — whichever trims harder is the one that bites.
The bell — global_notifiers
Section titled “The bell — global_notifiers”[notify]global_notifiers = [] # silence the bell entirely# global_notifiers = ["slack-ops"] # or: every failure goes to that channelglobal_notifiers = [] switches off the bell in both the Web UI and the
TUI footer, and it also stops "inapp" from being slipped into your
per-task fields. With it empty, notify_on_failure = ["slack-ops"] goes
to slack-ops and nowhere else.
Reach for the empty form when the daemon runs unattended — a build agent, a CI shard — and nobody’s ever looking at the Web UI. Reach for a non-empty list when you want every failure funneled to one channel without sprinkling per-task fields all over the file.
Retry budget — default_timeout
Section titled “Retry budget — default_timeout”When an outbound delivery hits a transient failure, it retries with
exponential backoff. default_timeout is the cap on how much
wall-clock time that whole retry loop is allowed to burn.
Leave it unset and the budget is 5 minutes — a delivery can keep
trying for that long. Set default_timeout = "30s" and you cut it to
half a minute, so a hard outage shows up in the bell that much sooner.
The per-attempt HTTP timeout is a separate thing entirely. Set
default_timeout shorter than a single attempt and you’ve effectively
asked for one try and no retries.
Bell history
Section titled “Bell history”Bell rows live in SQLite, kept separate from run rows. Two knobs prune them:
history_keep— keep at most N rows; older ones are pruned in one pass.history_keep_for— delete rows older than this duration.
Both run at once, and the stricter one wins. A background sweeper takes care of it — there’s nothing for you to trigger.
Coalescing
Section titled “Coalescing”RunWisp folds together repeat events of the same kind for the same task, so you don’t get paged twice for the same thing. A task failing every minute leaves you one bell row that ticks upward, not 60 separate ones.
coalesce_window— within this window, repeats update the same row:countclimbs and the latest timestamp is recorded.occurrence_ring— how many recent timestamps to keep on the row. The UI uses these to draw a sparkline.
Outbound channels coalesce on the same key by default too
(coalesce_outbound) — the
Coalescing section of the model page
has the full timeline and the check-in/summary cadence.
There is currently no way to turn coalescing off — setting
coalesce_window = "0s" falls back to the default of 1h.
To minimise grouping, set a very short window like "1s".
Worked examples
Section titled “Worked examples”A small server with one outbound channel that wants delivery failures to surface quickly:
[notify]global_notifiers = ["inapp"] # keep the belldefault_timeout = "30s" # cap retry budget at 30shistory_keep = 2000history_keep_for = "60d"coalesce_window = "30m"occurrence_ring = 20A headless build agent that sends everything off-host:
[notify]global_notifiers = [] # nobody reads the bell