Create your first watch
A watch is four decisions. Everything else has a sensible default.
id: product-restock # a stable slug — this is its identityname: Studio monitor restock # what you will see in the alertsources: # 1. WHERE to look - type: page value: "https://example.com/products/monitor"schedule: "0 */6 * * *" # 2. HOW OFTEN (cron, UTC)condition: > # 3. WHAT COUNTS The product page shows the monitor as in stock and orderable — not "notify me when available", and not a pre-order.channels: [telegram] # 4. WHERE to send itthreshold: 0.6enabled: true1. Where to look
Section titled “1. Where to look”Three source types, each good at something different:
| Type | Use it for | Notes |
|---|---|---|
rss |
Blogs, release feeds, anything with a feed | Cheapest and most reliable |
page |
A specific URL you already know | Extraction is best-effort on JS-heavy pages |
search |
“Anything, anywhere, about X” | Needs a Tavily key |
Two sources are usually better than one: an official page for authority, plus a search for coverage. See Choosing sources.
Sources also accept an optional hints object that tunes collection — pinning a
search to official domains, narrowing a time window, or enabling a heavier
extraction tier for a JavaScript-rendered page:
sources: - type: search value: "2026 examination result declared" hints: officialDomains: ["example.gov"] recencyDays: 30 topic: newsEvery hint is documented in Sources and Watch schema.
2. How often
Section titled “2. How often”schedule is a cron expression in UTC. "0 */6 * * *" is every six hours;
"30 3 * * *" is 03:30 UTC daily. Your real check frequency is also limited by
how often the instance itself runs — see Scheduling.
3. What counts
Section titled “3. What counts”The condition is the heart of the watch. A language model reads it, so write it the way you would brief a careful assistant: say what should trigger, and say what should not.
condition: > Alert when the official result for the 2026 examination is declared or the scorecard is published. Do NOT alert on exam-date announcements, admit cards, answer keys, coaching articles, or speculation about when the result might come.Watcher will not fire unless it can quote a sentence from the collected page that proves the condition — so a condition it cannot verify from text will never trigger. Writing a condition collects the patterns that work and the ones that do not.
4. Where to send it
Section titled “4. Where to send it”channels: [telegram] # the configured default chatchannels: [{ type: telegram, chatId: "-1001234567890" }] # a specific chatchannels: [telegram, push] # Telegram and the Android appConfidence, and the second bar
Section titled “Confidence, and the second bar”threshold: 0.6 # confirmed alert at or above this confidenceweakThreshold: 0.4 # 0.4–0.6 arrives labelled "unconfirmed / possible update"minSources: 2 # optional: require two sources to agree for a confirmed alertSetting weakThreshold gives you a low-priority tier instead of silence for
borderline evidence. Omit it and anything below threshold is dropped. See
Confidence and alert tiers.
Save it
Section titled “Save it”- Put the file in
watches/and runpnpm watches:import, or create it in the admin panel, orPOST /watchesover the API. - Test it immediately with
pnpm run-due:force, or “Run now” in the panel. - Read the outcome. If it did not fire and you expected it to, go straight to Why didn’t my watch fire?.