watch-for-changes
Check something on the web on a recurring cadence, compare it to what you saw last time, and only report back when there's an actual change.
Before running any command
If tvly is not found on PATH, see https://github.com/tavily-ai/tavily-cli for installation instructions.
Important: this is orchestration, not a Tavily platform feature
Tavily's API is stateless — it has no built-in scheduling, alerting, or "watch this" endpoint. This skill combines:
- Tavily (
tvly extract or tvly search) for the actual "check the thing" step
- Some recurring-task mechanism for the "keep doing this on a cadence" step. Use whatever your environment offers:
- Running in Claude Code: the
schedule skill (cron-based, unattended) or /loop (self-paced, session-scoped)
- Any other agent/CLI with its own scheduling or long-running-task primitive: use that
- No agent-level scheduler available: a plain OS cron job / systemd timer / Windows Task Scheduler entry that re-invokes the agent (or the diff script directly) on the target cadence, or a scheduled CI job (e.g. GitHub Actions
schedule trigger)
Be upfront with the user about this — "monitor" here means "something re-runs this check for you on a cadence," not "Tavily is watching this in the background on its own." Ask the user which mechanism is available/preferred if it isn't obvious.
When to use
- Watching a specific URL/page for content changes (pricing, terms, changelog, filing status)
- For a recurring summary of new coverage on a broad topic (rather than change-detection on one fixed page), that's a different pattern — see the
tavily-news-digest idea in this repo's suggestions doc. This skill is for detecting change, not aggregating new content.
How it works
- Baseline: extract the target page (or run the target search) once, save the content and a hash/fingerprint of it to a local snapshot file.
- Schedule: set up a recurring check at the cadence the user wants, using whatever recurring-task mechanism is available (Claude Code's
schedule skill or /loop, another agent's own scheduler, or plain cron/CI if running standalone).
- Each run: re-extract, compare to the saved snapshot.
- No meaningful difference → stay quiet, update the snapshot's "last checked" timestamp, don't bother the user.
- Real difference → summarize what changed and notify.
- Update the snapshot with the new content after each check, whether or not it changed.
Quick start
1. Take the baseline snapshot:
python3 << 'PYEOF'
import json, subprocess, hashlib, os
url = "https://example.com/pricing"
raw = subprocess.check_output(['tvly', 'extract', url, '--json'], stderr=subprocess.DEVNULL)
data = json.loads(raw)
content = data['results'][0]['raw_content']
os.makedirs('.tavily', exist_ok=True)
snapshot = {
"url": url,
"content": content,
"hash": hashlib.sha256(content.encode()).hexdigest(),
}
with open('.tavily/monitor_pricing.json', 'w') as f:
json.dump(snapshot, f)
print("Baseline saved.")
PYEOF
2. Set up the recurring check — point whatever recurring-task mechanism is available at the diff script below: the schedule skill or /loop <interval> in Claude Code, an equivalent scheduling primitive in another agent, or a plain cron entry / scheduled CI job if running standalone.
3. Each scheduled run — diff against the saved snapshot:
python3 << 'PYEOF'
import json, subprocess, hashlib
url = "https://example.com/pricing"
path = ".tavily/monitor_pricing.json"
with open(path) as f:
prev = json.load(f)
raw = subprocess.check_output(['tvly', 'extract', url, '--json'], stderr=subprocess.DEVNULL)
data = json.loads(raw)
content = data['results'][0]['raw_content']
new_hash = hashlib.sha256(content.encode()).hexdigest()
if new_hash != prev['hash']:
print(f"CHANGED: {url}")
# Optionally diff prev['content'] vs content and summarize the change in plain English
# (e.g. via a quick tavily-research call or a direct text diff) before alerting the user.
else:
print(f"No change: {url}")
with open(path, 'w') as f:
json.dump({"url": url, "content": content, "hash": new_hash}, f)
PYEOF
Options
| Consideration |
Guidance |
| Cadence |
Match check frequency to how often the thing actually changes — a pricing page doesn't need hourly checks; a live filing tracker might |
| Snapshot storage |
Keep one JSON file per monitored target under .tavily/, named for what it watches |
| Noisy pages |
If a page has content that changes trivially every load (timestamps, ad slots), hash a specific section's content, not the whole page — extract with --query/--chunks-per-source to narrow to the relevant section first |
| What changed |
For a human-readable summary of what changed (not just that it changed), diff the old and new text and optionally run it through tvly research for a plain-English summary |
Tips
- Don't over-schedule. Every check costs an API call — pick a cadence that matches how often the target realistically changes.
- Narrow what you hash. Whole-page hashing catches every cosmetic change (ads, timestamps, view counts) as a "change" — extract just the section that matters when possible.
- Say what kind of change, not just that one happened. "Changed" is a weak alert — "the Pro plan price moved from $49 to $59" is a useful one.
- Be explicit that some external mechanism is doing the scheduling, not a Tavily background service — if the session closes, the loop stops, or the cron/CI job isn't actually wired up, monitoring stops.
See also
- tavily-extract — the underlying content-fetch this skill re-runs on a schedule
- tavily-search — for monitoring a topic broadly rather than one fixed URL
1---2name: watch-for-changes-23description: Watch a page, site, or topic for changes on a recurring schedule and only speak up when something meaningfully changed. Use this skill when the user wants to track a competitor's pricing page, watch for regulatory filings, keep an eye on a changelog, or says "monitor this page", "watch for changes", "alert me if X changes", "track this site", or "let me know when this updates". This is an orchestration skill built from Tavily's extract/search plus a recurring-task mechanism — Tavily itself has no scheduling API, so this skill documents that explicitly rather than implying otherwise. The recurring-task step is written generically so it works under any agent/CLI, not just Claude Code.4---56# watch-for-changes78Check something on the web on a recurring cadence, compare it to what you saw last time, and only report back when there's an actual change.910## Before running any command1112If `tvly` is not found on PATH, see https://github.com/tavily-ai/tavily-cli for installation instructions.1314## Important: this is orchestration, not a Tavily platform feature1516Tavily's API is stateless — it has no built-in scheduling, alerting, or "watch this" endpoint. This skill combines:1718- **Tavily** (`tvly extract` or `tvly search`) for the actual "check the thing" step19- **Some recurring-task mechanism** for the "keep doing this on a cadence" step. Use whatever your environment offers:20 - Running in Claude Code: the `schedule` skill (cron-based, unattended) or `/loop` (self-paced, session-scoped)21 - Any other agent/CLI with its own scheduling or long-running-task primitive: use that22 - No agent-level scheduler available: a plain OS cron job / systemd timer / Windows Task Scheduler entry that re-invokes the agent (or the diff script directly) on the target cadence, or a scheduled CI job (e.g. GitHub Actions `schedule` trigger)2324Be upfront with the user about this — "monitor" here means "something re-runs this check for you on a cadence," not "Tavily is watching this in the background on its own." Ask the user which mechanism is available/preferred if it isn't obvious.2526## When to use2728- Watching a specific URL/page for content changes (pricing, terms, changelog, filing status)29- For a recurring *summary of new coverage* on a broad topic (rather than change-detection on one fixed page), that's a different pattern — see the `tavily-news-digest` idea in this repo's suggestions doc. This skill is for detecting *change*, not aggregating *new content*.3031## How it works32331. **Baseline:** extract the target page (or run the target search) once, save the content and a hash/fingerprint of it to a local snapshot file.342. **Schedule:** set up a recurring check at the cadence the user wants, using whatever recurring-task mechanism is available (Claude Code's `schedule` skill or `/loop`, another agent's own scheduler, or plain cron/CI if running standalone).353. **Each run:** re-extract, compare to the saved snapshot.36 - No meaningful difference → stay quiet, update the snapshot's "last checked" timestamp, don't bother the user.37 - Real difference → summarize what changed and notify.384. **Update the snapshot** with the new content after each check, whether or not it changed.3940## Quick start4142**1. Take the baseline snapshot:**4344```bash45python3 << 'PYEOF'46import json, subprocess, hashlib, os4748url = "https://example.com/pricing"49raw = subprocess.check_output(['tvly', 'extract', url, '--json'], stderr=subprocess.DEVNULL)50data = json.loads(raw)51content = data['results'][0]['raw_content']5253os.makedirs('.tavily', exist_ok=True)54snapshot = {55 "url": url,56 "content": content,57 "hash": hashlib.sha256(content.encode()).hexdigest(),58}59with open('.tavily/monitor_pricing.json', 'w') as f:60 json.dump(snapshot, f)6162print("Baseline saved.")63PYEOF64```6566**2. Set up the recurring check** — point whatever recurring-task mechanism is available at the diff script below: the `schedule` skill or `/loop <interval>` in Claude Code, an equivalent scheduling primitive in another agent, or a plain cron entry / scheduled CI job if running standalone.6768**3. Each scheduled run — diff against the saved snapshot:**6970```bash71python3 << 'PYEOF'72import json, subprocess, hashlib7374url = "https://example.com/pricing"75path = ".tavily/monitor_pricing.json"7677with open(path) as f:78 prev = json.load(f)7980raw = subprocess.check_output(['tvly', 'extract', url, '--json'], stderr=subprocess.DEVNULL)81data = json.loads(raw)82content = data['results'][0]['raw_content']83new_hash = hashlib.sha256(content.encode()).hexdigest()8485if new_hash != prev['hash']:86 print(f"CHANGED: {url}")87 # Optionally diff prev['content'] vs content and summarize the change in plain English88 # (e.g. via a quick tavily-research call or a direct text diff) before alerting the user.89else:90 print(f"No change: {url}")9192with open(path, 'w') as f:93 json.dump({"url": url, "content": content, "hash": new_hash}, f)94PYEOF95```9697## Options9899| Consideration | Guidance |100|---|---|101| Cadence | Match check frequency to how often the thing actually changes — a pricing page doesn't need hourly checks; a live filing tracker might |102| Snapshot storage | Keep one JSON file per monitored target under `.tavily/`, named for what it watches |103| Noisy pages | If a page has content that changes trivially every load (timestamps, ad slots), hash a specific section's content, not the whole page — extract with `--query`/`--chunks-per-source` to narrow to the relevant section first |104| What changed | For a human-readable summary of *what* changed (not just *that* it changed), diff the old and new text and optionally run it through `tvly research` for a plain-English summary |105106## Tips107108- **Don't over-schedule.** Every check costs an API call — pick a cadence that matches how often the target realistically changes.109- **Narrow what you hash.** Whole-page hashing catches every cosmetic change (ads, timestamps, view counts) as a "change" — extract just the section that matters when possible.110- **Say what kind of change, not just that one happened.** "Changed" is a weak alert — "the Pro plan price moved from $49 to $59" is a useful one.111- **Be explicit that some external mechanism is doing the scheduling**, not a Tavily background service — if the session closes, the loop stops, or the cron/CI job isn't actually wired up, monitoring stops.112113## See also114115- [tavily-extract](../tavily-extract/SKILL.md) — the underlying content-fetch this skill re-runs on a schedule116- [tavily-search](../tavily-search/SKILL.md) — for monitoring a topic broadly rather than one fixed URL