Building a Claude Code Skill to Fact-Check the News
- Published on
- ·13 min read
This skill relies on an LLM (Claude) to orchestrate searches and synthesize results. Despite cross-referencing sources (web, fact-checking APIs, scientific publications) and built-in verification steps, an LLM can still produce factual errors, shortcuts, or omissions. The generated reports are a starting point for your own judgment, not an absolute truth.
The problem
A LinkedIn post lands in your feed: "The world's largest natural hydrogen reserve discovered in Moselle, France! Moselle, the new center of the world!" With a nice Sciences et Avenir visual.
True? Exaggerated? Total nonsense? Here's what you'd need to do to find out:
- Track down the original article
- Figure out the primary source (who made the discovery? which lab?)
- Verify the claimed numbers
- Check if other fact-checkers have already looked into it
- Compare with other deposits worldwide
- Spot presentation bias (conditional tense turned into affirmative, "unique in the world" when other deposits exist...)
That's a solid 1 to 2 hours of work. And we're supposed to do this every time some dubious headline shows up? Nah.
I'd already built a skill for verifying scientific claims (/science-check). But fact-checking news is a completely different game. You're not verifying a PubMed study - you're verifying a newspaper headline. The biases aren't the same at all: sensationalism, missing context, confusing resource with reserve, conditional tense vanishing in reprints...
So I built /fact-check.
What it looks like in practice
The command:
/fact-check "the world's largest natural hydrogen reserve" in Moselle France
Or directly with a screenshot:
/fact-check /path/to/screenshot.png
And roughly 2 minutes later:
- [x] Claim extracted and decomposed into sub-claims
- [x] Source classified (reliability)
- [x] PRE-CHECK phase: fact-checking APIs queried
- [x] RESEARCH phase: 4 parallel searches launched
- [x] DEEP DIVE phase: primary sources consulted
- [x] CROSS-CHECK phase: key facts cross-verified
- [x] BIAS phase: bias and manipulation detected
- [x] SYNTHESIS phase: report generated with verdict
# Fact Check
**Claim:** "The world's largest natural hydrogen reserve"
in Moselle, a "unique" discovery
**Source:** Sciences et Avenir - Reliability: Tier 2
**Overall verdict:** EXAGGERATED
**Confidence:** HIGH
---
## Summary
The natural hydrogen discovery in Moselle is real and scientifically
documented by CNRS. The measured concentrations (15% at 1,100m) are
indeed unprecedented. However, "world's largest reserve" relies on
theoretical estimates (34-46 Mt) that the researchers themselves
present in conditional tense. "Unique in the world" is misleading:
other deposits exist (Mali, Australia, Oman).
## Claim breakdown
Sub-claim | Verdict | Confidence
-----------------------------|--------------|---------------------------
H2 deposit in Moselle | TRUE | HIGH (CNRS, FDE, AFP)
"Largest reserve" | MOSTLY TRUE | MEDIUM (conditional)
"Unique in the world" | MISLEADING | HIGH (Mali, Australia)
"New center of the world" | EXAGGERATED | HIGH (LinkedIn addition)
## Biases detected
- Conditional removed: CNRS titles "A giant deposit?"
with a question mark, reprints drop the "?"
- Resource/reserve confusion: 34-46 Mt = theoretical resource,
not proven exploitable reserve
- "Unique in the world": unique by concentration, not by
the existence of the phenomenon (Mali since 1987)
## Sources consulted (12)
[1] CNRS Le journal - "A giant hydrogen deposit?"
[2] CNRS News - "A gigantic hydrogen deposit?"
[3] Ministry of Economy - PER Trois-Eveches permit
[4] The Conversation - Pironon & de Donato (2023)
[5] France Bleu - Moselle drilling (Jan. 2026)
[6] Connaissance des Energies / AFP (Jan. 2026)
[7] Techniques de l'Ingenieur - Cautious analysis
[8] Reporterre - Environmental criticism
[9] Royal Society - "Scientific rigor needed"
[10] Nature - Mali deposit study
[11] Science Advances - Global H2 model
[12] World Economic Forum - 5 critical questions
The verdict isn't "FALSE". It's "EXAGGERATED". That distinction matters a lot. The discovery is real, the numbers are plausible, but the media presentation smooths out the uncertainties and kills the researchers' conditional tense.
Why not just extend /science-check?
Quick answer: different job.
| Aspect | /science-check | /fact-check |
|---|---|---|
| Target | Scientific/health claims | News, headlines, social posts |
| Sources | PubMed, Cochrane, Semantic Scholar | Web, fact-check APIs, primary sources |
| Verdicts | CONFIRMED / REFUTED / PREMATURE | TRUE / EXAGGERATED / MISLEADING / FALSE |
| Biases sought | Industry funding, small samples | Sensationalism, omission, clickbait |
| Parallel agents | 3 (meta-analyses, risks, critique) | 4 (facts, official, debunk, context) |
| Unique phase | Auto-verification (quality checklist) | Bias detection (patterns) |
I tried cramming both into one skill early on. It was a mess - the prompts got confused, the agents were pulling in the wrong direction. Two skills, clean separation.
The Google Fact Check API
This is new compared to /science-check. Before launching web searches, we query the global database of professional fact-checks. AFP Factuel, Snopes, PolitiFact, Les Decodeurs... If somebody already did the work, we want to know upfront.
Getting the API key
Free. Takes about 3 minutes:
- Go to Google Cloud Console
- Create a project (or pick an existing one)
- Enable "Fact Check Tools API"
- Create an API key
Then add it to your shell config:
export GOOGLE_FACTCHECK_API_KEY="your_key_here"
What it returns
curl -s "https://factchecktools.googleapis.com/v1alpha1/claims:search\
?query=natural+hydrogen+largest+reserve+Moselle\
&languageCode=en\
&key=${GOOGLE_FACTCHECK_API_KEY}" | python3 -m json.tool
If a professional fact-check exists, you get the verdict, the fact-checker (e.g., AFP Factuel), and the link to the full article. If nothing comes back (just {}), that's useful too - you know you're on your own.
The skill handles both cases gracefully. No API key configured? It skips straight to web research, no crash, no error.
The MCP servers
Same MCPs as /science-check for scientific/technical topics:
- PubMed MCP (
mcp-simple-pubmed) - Direct access to PubMed's Entrez API - Paper Search MCP (
paper-search-mcp) - Multi-source: PubMed, arXiv, bioRxiv, Google Scholar
Agent D (the context and nuance agent) uses these when the topic calls for it. For hydrogen in Moselle, it searched Google Scholar for publications on global natural H2 reserves. For a political fact-check, it just falls back to WebSearch. No fancy logic - the agent decides based on the claim.
If you already set up ~/.claude/mcp.json for /science-check, you're good. Nothing to add.
6 files, not one big blob
The skill lives in ~/.claude/skills/fact-check/ (browse on GitHub):
fact-check/
├── SKILL.md # Main instructions (148 lines)
├── VERDICT_SCALE.md # 8-level verdict scale
├── SOURCE_RELIABILITY.md # Source reliability grid (5 tiers)
├── BIAS_PATTERNS.md # Bias and manipulation patterns
├── REPORT_TEMPLATE.md # Final report template
└── API_INTEGRATION.md # Google Fact Check API integration
Same philosophy as /science-check: SKILL.md stays short, reference docs live in their own files, Claude loads them on demand. Progressive disclosure - Claude only reads what it needs for the current phase.
Main difference: 5 reference files instead of 3. News fact-checking needs more grids (media biases, source reliability by media type, a finer verdict scale than just confirmed/refuted).
The SKILL.md
The YAML frontmatter tells Claude when to trigger the skill, the markdown body tells it how. Here's the beginning:
name: fact-check
description: "Verifie la veracite d'une information, article ou affirmation
en croisant sources web, papers scientifiques, APIs de fact-checking et
positions officielles..."
user-invocable: true
argument-hint: "[URL, texte ou description de l'affirmation a verifier]"
allowed-tools:
- Agent
- Bash
- Read
- WebSearch
- WebFetch
- mcp__pubmed__search_pubmed
- ...
The full 8-phase workflow (extraction → classification → API pre-check → 4 parallel searches → deep dive → cross-check → bias → synthesis) and all rules are in the SKILL.md on GitHub.
Things worth noting in the frontmatter
The description is long on purpose. Same lesson as /science-check - Claude tends to under-trigger skills. By explicitly listing domains (science, technology, energy, economics, geopolitics) and trigger phrases ("if an info is true, reliable, exaggerated, or fake"), you increase the automatic trigger rate. Honestly though, I just type /fact-check directly most of the time.
$ARGUMENTS saves a round-trip. My first version always asked the user to confirm the claim. Totally pointless. If you type /fact-check "hydrogen Moselle", Claude already has everything it needs. The AskUserQuestion fallback only fires when you type /fact-check with nothing after it.
Read in allowed-tools is what enables screenshots. Claude Code is multimodal - Read on a .png returns the visual content. So you can literally screenshot a tweet or LinkedIn post and feed it straight to the skill. I use this more than I expected.
The 8-phase workflow
Phase 1-2: Extraction and classification
Claude figures out what it's looking at (URL, text, screenshot), pulls out the key claims, and classifies the source using a 5-tier grid. A CNRS article (Tier 1) doesn't carry the same weight as some random LinkedIn post (Tier 4). Sounds obvious, but it changes how the rest of the analysis runs.
Phase 3: PRE-CHECK - the shortcut
This is what /science-check doesn't have. Before spinning up 4 agents, we check if somebody already did the work. AFP Factuel, Snopes, PolitiFact... professionals who do this for a living. If they've already verified the claim, their verdict goes straight in as a Tier 2 source.
For hydrogen in Moselle, the API returned {}. Nobody had formally checked it. That's actually valuable information - it tells you you're in uncharted territory and need to do the legwork yourself.
Phase 4: 4 agents in parallel
The core of the whole thing. Four sub-agents fire simultaneously, each attacking from a different angle:
- Agent A hunts for raw facts, in both French and English
- Agent B goes after official sources (CNRS, BRGM, government ministries)
- Agent C looks specifically for counter-arguments and criticism
- Agent D provides scientific context (via MCP when relevant)
Why 4 instead of 3 like /science-check? News needs a dedicated agent for institutional sources. In science, PubMed is your source of truth. In news, the primary source could be hiding anywhere - a CNRS press release, a Ministry of Economy permit, a State Council ruling... You need an agent whose whole job is hunting those down.
Phase 5-6: Deep dive and cross-checking
Claude traces back to the primary source. Always. For hydrogen in Moselle, that meant actually reading the CNRS Le journal article - not the France Bleu or Sciences et Avenir rewrite. And that's where you find the question mark in the title ("A giant hydrogen deposit in Lorraine**?**") and the systematic conditional tense ("could be", "might contain").
The reprints dropped both. Classic.
Phase 7: Bias detection
This is where it gets interesting. Claude runs the original article through a grid of bias patterns:
- Presentation bias: clickbait, unjustified superlatives, numbers without context
- Reasoning bias: correlation/causation confusion, cherry-picking, hasty generalization
- Omission bias: missing context, smoothed-out uncertainties, unmentioned risks
- Source bias: conflict of interest, echo chamber, disguised press release
For hydrogen in Moselle, it caught three things: conditional tense removed, resource/reserve confusion, and "unique in the world" implying no other deposits exist (Mali has had one since 1987). None of these are lies - they're omissions and subtle framing. Which is almost worse, because readers don't notice.
Phase 8: Synthesis with ultrathink
The word ultrathink in SKILL.md activates Claude's extended thinking. This is what lets it weigh "TRUE on substance but EXAGGERATED in presentation" instead of just picking one box. The nuance between EXAGGERATED and MISLEADING and MOSTLY TRUE - that's where extended thinking earns its keep.
The reference files
VERDICT_SCALE.md
An 8-level scale. Because true/false is rarely enough:
See the full scale on GitHub.
Here's the thing - an article can be TRUE on substance and EXAGGERATED in presentation. Both get flagged. That's exactly the hydrogen case: real discovery, real numbers, terrible framing.
SOURCE_RELIABILITY.md
5-tier reliability grid:
See the full grid on GitHub.
BIAS_PATTERNS.md
Four bias categories plus a quick checklist:
See the full checklist on GitHub.
REPORT_TEMPLATE.md
Forces a complete structure: summary, sub-claims table with individual verdicts, missing context, detected biases, primary sources vs media reprints comparison, official positions, and consulted sources with their reliability tier. No shortcuts - if the template says it needs a field, Claude fills it.
API_INTEGRATION.md
Google Fact Check API docs: endpoint, parameters, response format, required env var. Kept it minimal because there's honestly not much to it.
Testing
Restart Claude Code (skills load at startup), then try it:
/fact-check coffee increases cancer risk
Or with a URL:
/fact-check https://www.example.com/dubious-article
Or with a screenshot:
/fact-check /path/to/screenshot.png
Give it 1 to 3 minutes depending on how complex the topic is and how many sources it needs to chase down.
What I learned building this
Conditional tense is everything. The gap between a correct article and an exaggerated one often comes down to a single word. CNRS says "could be the largest reserve". Sciences et Avenir puts quotes around "unique in the world". The LinkedIn post turns it into "Moselle, the new center of the world!" Each reprint drops a conditional. By the time it hits your feed, the uncertainty is gone. The skill catches that drift, and honestly, it's the most valuable thing it does.
4 agents beat 3 for news. Started with 3 agents, same as /science-check. Didn't work well. News needs a dedicated agent just for institutional sources. In science, PubMed is the source of truth. In news? The primary source might be buried in a CNRS press release, a mining permit from the Ministry of Economy, or a State Council ruling. You need someone looking specifically for that stuff.
The Google Fact Check API is seriously underrated. Free, dead simple, and sometimes it saves you 90% of the work. For political or viral claims, AFP Factuel or Snopes have usually already done the heavy lifting. For niche technical topics like hydrogen geology, it returns empty - but at least you know immediately that nobody's verified it yet.
Omission bias is the sneakiest. The article doesn't have to lie to mislead you. Just omit that the 46 million tonnes are a theoretical estimate. Don't mention that "reserve" and "resource" mean completely different things in geology. Skip the part where the State Council struck down the same operator's methane project. None of these are false statements. They're strategic silences, and they're way harder to spot than an outright fabrication.
Limitations
Look, it's a tool, not an oracle. The skill is only as good as what's available online and Claude's ability to make sense of it. Very recent or very local stories might not have enough sources yet. Highly technical topics (deep geology, nuclear physics...) can trip Claude up.
But for the main use case - a LinkedIn post, a headline that feels off, a tweet that sounds too good to be true - it's become a reflex. Two minutes, a verdict with nuance, and most importantly: the reasoning behind it. That's the part that matters.