Quickstart
By the end of this page Watcher will have collected real content from a real website, asked a model whether your condition was met, and printed its verdict.
Before you start
Section titled “Before you start”You need:
- Node.js 20+ and pnpm — check with
node --versionandpnpm --version - A MongoDB connection string — a free Atlas cluster works, so does a local
mongodb://localhost:27017 - A Google AI Studio API key — the model that evaluates conditions
-
Install dependencies
Terminal window pnpm install -
Create your
.envTerminal window cp .env.example .envOpen
.envand set the two required values:.env GOOGLE_GENERATIVE_AI_API_KEY=<your-google-ai-studio-key>MongoDB_URI=<your-mongodb-connection-string>Without a Google key Watcher will not start at all — the evaluator, the embedder and the AI drafter are all built from it.
-
Write a watch
Create
watches/my-first-watch.yml:watches/my-first-watch.yml id: nodejs-securityname: Node.js security releasessources:- type: rssvalue: "https://nodejs.org/en/feed/blog.xml"trust: officialschedule: "0 * * * *"condition: "A new Node.js security release or vulnerability announcement"channels: [telegram]threshold: 0.6weakThreshold: 0.4enabled: trueYou have just declared where to look (an RSS feed), what counts (the condition), how often (hourly, in UTC), and how sure the model must be (0.6) before this counts as a confirmed alert.
-
Import it into the database
Watch files are an import source, not the live source of truth. The running system reads watches from MongoDB:
Terminal window pnpm watches:importYou should see
Imported 1 watch(es) … created. Re-running is safe: the import is an idempotent upsert. -
Run it once, now
Terminal window pnpm run-due:force--forceignores the cron schedule so you need not wait for the top of the hour. Watcher collects the feed, drops anything it has already seen, asks the model about the fresh items, and prints one line per watch:Ran 1 watch(es) from MongoDB (force)• nodejs-security: not-triggered (collected 10, fresh 10, sent 0) -
Read the outcome
That line is the whole system in miniature.
collectedis how many items the sources returned,freshis how many were new since the last run, and the outcome word is what the engine decided.not-triggeredmeans the model looked and found nothing matching your condition — the correct result on a quiet day.Every possible outcome is listed in Run outcomes.
-
Run it a second time
Terminal window pnpm run-due:forceNow you should see
nothing-newandfresh 0. Watcher remembers content it has already evaluated, so it never pays for the same judgement twice. That memory is explained in What Watcher remembers.
Where alerts go
Section titled “Where alerts go”With no Telegram credentials configured, the telegram channel falls back to
printing the alert to your console — exactly what you want while testing. To
deliver to a real device, continue to Get the alerts.
Useful commands
Section titled “Useful commands”pnpm run-due # run only watches whose schedule is duepnpm run-due:force # run every enabled watch nowpnpm serve # start the API + admin panel backendpnpm watches:import # upsert watches/*.yml into the databasepnpm watches:list # list stored watchespnpm watches history <id> # recent runs for one watchpnpm watches disable <id> # stop running it, keep itpnpm verify # typecheck + lint + tests + buildpnpm test # tests only (no network, no keys needed)- Deploy it for real so it keeps running without you.
- Create your first watch properly, with the condition patterns that actually work.