A scan is a photograph. Most vulnerabilities arrive after the shutter closes — the code did not change, the advisory did. This tutorial sets up a watch so that matters.
You should have completed the first tutorial.
Start a watch#

ztvs watch ./my-project --interval 6h
ZTVS resolves the target once, then re-evaluates it against the advisory database on each interval. It does not re-resolve the filesystem unless it changed — re-matching is cheap, re-resolving is not.
watching ./my-project · interval 6h
[04:00] advisories refreshed · no change
[10:00] advisories refreshed · 1 new finding
HIGH ZTVS-2026-0052 serde_json 1.0.114 → 1.0.121
Get told about it#
Polling a terminal is not a notification. Point it at a webhook:
ztvs watch ./my-project \
--interval 6h \
--on-finding webhook \
--webhook-url https://hooks.example.com/ztvs
Only new findings fire the hook. A finding you have already seen is not news.
Run it as a service#
# /etc/systemd/system/ztvs-watch.service
[Service]
ExecStart=/usr/local/bin/ztvs watch /srv/api --interval 6h --on-finding webhook
Restart=on-failure
User=ztvs
Run the watcher as an unprivileged user with read-only access to the target. It needs to read the artefact and reach the advisory database. Nothing else.
How it decides something is new#
Suppressed findings are still recorded. The difference between suppressed and hidden is the difference between a decision and a lie.