Skip to content

[defaults]

[defaults] is the one section in runwisp.toml that doesn’t define something to run. It defines fallback values that every [tasks.*] and [services.*] inherits unless they override the field themselves.

It exists because writing the same keep_for = "30d" and log_max_size = "100mb" on twenty tasks gets tedious. Pull those into [defaults] once, override per-task only when the value is different.

[defaults]
timeout = "1h"
log_max_size = "100mb"
log_on_full = "drop_old"
keep_runs = 50
keep_for = "30d"
KeyTypeBuilt-in defaultWhat it does
timeoutduration0 (no limit)Default per-attempt wall-clock cap. Go duration string.
log_max_sizebyte size100MBDefault per-run log cap. Units b/kb/mb/gb/tb.
log_on_fullenum"drop_old"Default overflow policy: drop_new, drop_old, kill_task.
keep_runsint0 (no row cap)Default row-count retention. -1 means explicit unlimited; positive N keeps N.
keep_forduration0 (no time cap)Default age-based retention. Accepts d/w/h/m units. "unlimited" opts out.

There is no default cron, no default on_overlap, no default retry_*. Those vary per task by intent; defaulting them would hide behaviour.

For each task or service:

  1. If the field is set on the [tasks.*] / [services.*] table, use that.
  2. Else if it’s set in [defaults], use that.
  3. Else fall back to the built-in default (100MB, drop_old, 0, etc.).

Both retention fields are tri-state, so the precedence is unambiguous even when [defaults] sets a value:

Per-task keep_runsEffect
omitted or 0Inherit [defaults] keep_runs; if that’s also 0, no row-count cap.
-1Explicit unlimited — overrides any positive default.
N (positive)Cap at N. Wins over the default.
Per-task keep_forEffect
omitted or ""Inherit [defaults] keep_for; if that’s also unset, no time-based cap.
"unlimited"Explicit unlimited — overrides any positive default.
"30d" (duration)Delete runs older than this. Wins over the default.

So a task that wants to opt out of an inherited cap writes keep_runs = -1 / keep_for = "unlimited", not 0 / "" (which would silently use the default).

[defaults]
timeout = "30m" # most tasks should die after 30 minutes
log_max_size = "50mb" # smaller default, override for noisy tasks
keep_runs = 100
keep_for = "30d"
[tasks.heartbeat]
cron = "*/5 * * * *"
run = "/usr/local/bin/heartbeat"
# inherits 30m timeout, 50mb log cap, 100 runs, 30d retention
[tasks.nightly-export]
cron = "0 2 * * *"
timeout = "4h" # overrides default — exports take longer
log_max_size = "500mb" # overrides default — output is large
run = "/usr/local/bin/export"
[tasks.audit-log]
cron = "0 0 * * *"
keep_runs = -1 # explicit unlimited — override defaults' 100
keep_for = "unlimited" # also opt out of the inherited 30d window
run = "/usr/local/bin/audit"
  • It doesn’t apply to [storage] — that’s a global cap, not a per-task default.
  • It doesn’t apply to [notify] settings (coalesce_window, queue_size, etc.).
  • Notification routing (notify_on_failure, notify_on_success) has no defaulting layer — you set it per task.