coverage-check — Claude Code skill: what it does, how to install
Counts independent news origins behind a claim via GDELT instead of counting links. Useful when confirming if coverage comes from multiple outlets or one wire story.
npx skills add SerhiiKorniienko/bullshit-detector --skill coverage-check -a claude-codeWhat coverage-check does
This skill checks claims across GDELT DOC 2.0 to separate genuine multi-outlet reporting from syndicated press releases. Instead of tallying bare URLs, it groups articles by headline similarity and tracks publication spikes within 24 hours. Reprints and wire copies from services like AP or Reuters collapse into single clusters.
Execution relies on uv running scripts/coverage.py. The script accepts GDELT query syntax, strips tracking parameters from links, and scans a rolling three-month window. Each request returns at most 250 records. Reaching this cap turns the reported count into a lower bound.
GDELT public endpoints frequently throttle traffic. The script retries with backoff and exits with code 3 when rate-limited. Exit code 3 means the check was aborted by throttling, not that the claim lacks coverage.
What it helps with
- separate independent news reporting from syndicated wire copy
- count distinct origin clusters for a claim in GDELT
- collapse duplicate URLs and tracking parameters
- identify rapid publication bursts within a 24-hour window
Example prompts for the agent
- Check how many independent sources cover the claim:
uv run scripts/coverage.py '"quantum breakthrough" AND university' - Inspect syndicated coverage for quarterly revenue news across the last 7 days
- Run coverage-check on a quoted phrase with
--timespan 3mand--json
How to install coverage-check
1Skills CLI (Vercel)
npx skills add SerhiiKorniienko/bullshit-detector --skill coverage-check -a claude-code2Manually: put the files in place
~/.claude/skills/coverage-check/SKILL.mdCopy the whole skill folder; for one project use .claude/skills/coverage-check/
1Skills CLI (Vercel)
npx skills add SerhiiKorniienko/bullshit-detector --skill coverage-check -a codex2Manually: put the files in place
.agents/skills/coverage-check/SKILL.mdFor all projects use ~/.agents/skills/
1Skills CLI (Vercel)
npx skills add SerhiiKorniienko/bullshit-detector --skill coverage-check -a cursor2Manually: put the files in place
.cursor/skills/coverage-check/SKILL.mdCursor also reads .agents/skills/ and .claude/skills/
1GitHub CLI
gh skill install SerhiiKorniienko/bullshit-detector coverage-check2Manually: put the files in place
.github/skills/coverage-check/SKILL.md1Skills CLI (Vercel)
npx skills add SerhiiKorniienko/bullshit-detector --skill coverage-check -a gemini-cli2Platform CLI
gemini skills install https://github.com/SerhiiKorniienko/bullshit-detector --path skills/ingestion/coverage-checkManually: put the files in place
.devin/skills/coverage-check/SKILL.mdThe legacy .windsurf/skills/ path still works
Skills CLI (Vercel)
npx skills add SerhiiKorniienko/bullshit-detector --skill coverage-check -a opencodeClaude.ai
Zip the folder and upload it in Settings → Capabilities → Skills
Step by step, with commands for each platform: How to install skills in Claude Code: five ways
Questions about coverage-check
How do I install coverage-check in Claude Code?
Run npx skills add SerhiiKorniienko/bullshit-detector --skill coverage-check -a claude-code. The skill definition will be placed in ~/.claude/skills/coverage-check/SKILL.md.
What does coverage-check do?
It queries GDELT to cluster news coverage by headline similarity, detecting wire syndication and press release reprints. This gives a defensible count of distinct reporting origins rather than a plain tally of web links.
What does exit code 3 mean?
Exit 3 indicates GDELT rate throttling prevented the measurement from finishing. It signals an unmeasured check, so agents must not interpret this exit code as zero coverage or a debunked claim.
Source text
SKILL.md · MIT
--- name: coverage-check description: Count how many independent origins are behind news coverage of a claim, instead of counting URLs. Queries GDELT for matching articles, collapses reprints and wire copy into single origins, and flags publication bursts that indicate syndication. Use when a claim appears to be confirmed by many outlets and you need to know whether that's many sources or one source many times. --- # coverage-check Ten URLs are not ten sources. This turns "lots of outlets reported it" into a number you can defend. ## When to reach for it During claim verification, when a claim looks *corroborated by volume* — a pile of search results all saying the same thing. That pattern has two very different causes: - Many newsrooms independently established the fact → genuinely strong evidence - One press release, wire story, or study got reprinted 40 times → **one** source Search results look identical in both cases. This tells them apart. ## Usage ```bash uv run scripts/coverage.py "<query>" [--timespan 3m] [--max 250] [--sort dateasc] [--timeout 120] [--json] ``` **It is slow. This is normal.** GDELT takes ~15s for a trivial one-day query and considerably longer for a 3-month window at 250 records. The script prints progress to stderr and how long the call took, so you can tell "working" from "hung" — if you see the querying line, wait. Narrowing `--timespan` is the speed lever; raise `--timeout` before assuming it's broken. The query accepts GDELT operators: `"exact phrase"`, `(a OR b)`, `-exclude`, `domain:example.com`, `sourcelang:english`. Quote the distinctive phrasing of the claim — a verbatim phrase is what catches reprints. ```bash # Is this "40 outlets confirmed it" or one wire story? uv run scripts/coverage.py '"quantum breakthrough" AND university' # Narrow to the week the claim surfaced uv run scripts/coverage.py '"record quarterly revenue" domain:reuters.com' --timespan 7d ``` ## Reading the output The first line is the verdict the detector needs. The rest supports it. - **Distinct story clusters** — articles grouped by headline similarity. This is the origin estimate. Outlets ≫ clusters means syndication. - **⚠️ syndicated** on a cluster — multiple outlets published the same story inside 24h. Treat the whole cluster as one source. - **wire-attributed headline** on a cluster — a headline names a wire service or press-release distributor (Reuters, AP, PR Newswire…). The strongest mechanical one-origin signal available at headline level; bodies would catch more, but GDELT returns none. - **Duplicate URLs collapsed** — the same page counted twice behind tracking params, `www.`, or a trailing slash. Collapsed before anything else is counted, so every number below it is already deduplicated. - **Span (hours)** — a tight burst points at a press release or embargo lift; coverage developed over weeks is more likely independent. Feed the result into the report's evidence column as an origin count: *"6 results, 1 origin (all reprints of the company's press release)"* is worth more than six links. ## Limits — read these before trusting a number - **Rolling 3-month window only.** GDELT DOC 2.0 does not reach further back. For an older claim this returns nothing, and **nothing does not mean unreported**. The script says so in its output; don't let the agent quietly read empty as disconfirming. - **Clustering is headline similarity**, on two measures: sequence ratio for reworded headlines and token overlap for the same facts in a different order. Grouping is transitive — three outlets on one wire story stay together even when the two extremes score below the bar individually. Verbatim reprints, rewritten wire copy and reordered headlines all collapse correctly. What it still won't catch: two newsrooms that independently reached the same finding and described it in genuinely different words. Those show as separate clusters, which is the safe direction to be wrong in — it *under*-reports syndication rather than inventing it. Thresholds were tuned against real GDELT output, not guessed. If you see false merges, raise `TITLE_MATCH`/`TOKEN_MATCH` in the script; if wire copy slips through as distinct, lower them. - **Presence is not credibility.** A claim covered by 200 outlets in 30 distinct clusters is *widely reported*, not *true*. Verdicts still need the source hierarchy in the detector's [RUBRIC.md](../../analysis/bullshit-detector/RUBRIC.md). - **Results cap at 250 per query.** When the cap is hit the output says so — every count becomes a lower bound, and the honest fix is a narrower `--timespan`, not a bigger number. - **The free endpoint is unreliable, and this is the important one.** GDELT returns *"Please limit requests to one every 5 seconds"* well below that rate whenever its public API is busy — independent of IP, User-Agent, and query size. Measured behaviour: identical calls succeed and fail minutes apart. The script retries with growing backoff and then **exits 3**. **Exit 3 means "unmeasured", not "no coverage".** Never let a failed check weaken or strengthen a verdict, and never record it as though the search came back empty. If the tool can't measure, the report says the origin count is unknown and falls back to the eyeball tells in [RUBRIC.md](../../analysis/bullshit-detector/RUBRIC.md). Retry in a few minutes, or skip it. | Exit | Meaning | |---|---| | 0 | measurement succeeded (including a legitimate zero-result window) | | 1 | bad input or unreachable host | | 3 | GDELT throttled — no measurement, claim is unmeasured | - **No API key, no auth, free.** Nothing to configure, nothing to rotate. ## What it does not do It counts and groups coverage. It does not fetch article text — that's [fetch-content](../fetch-content/SKILL.md) — and it does not judge anything. Analysis skills read its output; they never call it to decide a verdict on their own.
© SerhiiKorniienko · MIT · SerhiiKorniienko/bullshit-detector