
source-watch
Local, deterministic change-monitoring for the web sources your agent depends on.
本地的、确定性的「信源变更监控」工具:给 Agent 一份信源清单,init 建基线,check 精准报告「哪些信源变了、正文改了哪几段、是否命中你关心的关键词、哪些 404 了」。

Before / After
Before — Your agent quotes an external page (library changelog, rival pricing,
API docs, a regulation page) but has no idea it changed. It either re-fetches the
whole noisy page every time (slow, buried in nav/ads/timestamps) or answers from
stale context.
After — You keep a sources.yml. source-watch tells the agent exactly what
moved, in a diff it can parse, and flags the changes you care about as HIGH.
No more guessing whether the page is current.
What it does
init — baseline every source: noise-reduced body text + title + fingerprint.
check — re-fetch and classify each source as content / title / new / gone.
- Noise reduction — strips
script/style/nav/footer/header, optional CSS selector,
defaults to the longest text block.
- Severity — any change whose text matches a
watch keyword/regex is flagged HIGH.
- Output —
WATCH_REPORT.md (human) + watch-state.json (machine-readable baseline
and last report, so an agent can read it directly).
- Offline-friendly —
file:// sources and a pure-stdlib fetcher; zero third-party
dependencies.
Install
Clone into your agent's skills directory. No pip install required.
Codex
git clone https://github.com/whaojie797-design/source-watch ~/.codex/skills/source-watch
Claude Code
git clone https://github.com/whaojie797-design/source-watch ~/.claude/skills/source-watch
Cursor
git clone https://github.com/whaojie797-design/source-watch ~/.cursor/skills/source-watch
Quick start
# 1. describe what to watch
cp sources.example.yml sources.yml
# edit urls / selectors / watch keywords
# 2. baseline
python scripts/watch.py init --config sources.yml --store .watchstore
# 3. later: what changed?
python scripts/watch.py check --config sources.yml --store .watchstore
# 4. acknowledge the change and re-baseline
python scripts/watch.py check --config sources.yml --store .watchstore --update
sources.yml:
sources:
- name: next-changelog
url: https://nextjs.org/changelog
selector: "main article"
watch:
- "breaking"
- "deprecat"
- name: rival-pricing
url: https://example.com/pricing
watch: ["price", "plan"]
Sample report (real)
$ python scripts/watch.py init --config sources.yml --store .ws
[BASE] next-changelog — 124 chars, fingerprint 2b299333df8099b6
[BASE] rival-pricing — 88 chars, fingerprint 7c1ae0b4f2c9d3e1
[BASE] acme-docs — 220 chars, fingerprint 9412af520f24141e
Baseline saved: .ws/watch-state.json (3 sources)
$ python scripts/watch.py check --config sources.yml --store .ws
[HIGH] next-changelog — content — matched: breaking
[OK] rival-pricing — unchanged
[UNREACHABLE] acme-docs — file not found: .../simple.html
3 sources watched · 1 changed · 1 HIGH · 1 unreachable
WATCH_REPORT.md (excerpt):
## HIGH
### next-changelog — content
- url: file:///.../changelog.html
- matched: breaking
- diff:
@@
- Fix: improved caching for static assets.
+ BREAKING: removed legacy config format, migrate before upgrading.
How it works
- Fetch each
url (urllib for http(s), direct read for file://).
- Extract body text with
html.parser, dropping noise tags; optional selector
narrows the region, with silent full-document fallback if it matches nothing.
- Hash the normalized body →
fingerprint. Compare to the baseline.
- Classify the delta and, if
watch patterns hit, raise severity to HIGH.
- Write
WATCH_REPORT.md + update watch-state.json (baseline + last report).
Everything is deterministic and offline-capable; the test suite runs entirely
against local file:// fixtures.
Limitations
- It compares fetched, extractable text. Pages that render content purely via
JavaScript (no server HTML) need a pre-rendered snapshot or a
selector over
static markup.
file:// sources are great for offline docs and tests, but can't see live sites.
- The "longest text block" heuristic is a reasonable default, not a full reader; use
selector on noisy pages for precision.
watch matches on the new body text only (not the diff) — keep patterns specific.
License
MIT © 2026 whaojie797-design