Verify citation
Skill youngeun1209/oh-my-claudecode-research/skills/verify-citation
Verify that academic citations exist and match the metadata claimed for them, and optionally write verification results into a project summary table. Looks up DOIs against CrossRef, fetches canonical authors/title/year/journal and the abstract via OpenAlex, and reports any mismatch against a BibTeX entry or a free-form DOI. Use to gate every citation `literature-curator` adds, to audit an existing BibTeX file for fabricated or wrong entries, or to retrieve an abstract so the calling agent can judge whether the paper actually supports a given claim.From its SKILL.md
npx -y skills add youngeun1209/oh-my-claudecode-research --skill verify-citationAssembled from the repository path, not quoted from the project. Check it against their README if it does not work.
SKILL.md
7.2 KB, as published. Nobody here has run it
<Use_When>
literature-curatoris about to add a new entry to the project BibTeX file.- A reviewer / supervisor asks "is this citation real?" or "does this paper actually say X?".
- Auditing an existing BibTeX file (e.g. after a co-author imports references from another project).
- Resolving a
[CITE: ...]placeholder — verify the candidate before committing. - Refreshing the
verified_on/verify_statuscolumns of the project summary table. </Use_When>
<Do_Not_Use_When>
- Only the citation format needs fixing (use a BibTeX prettifier, not this).
- The user wants to find a citation from scratch with no candidate yet — that is
literature-curator's WebSearch task; this skill verifies once a candidate exists. - Offline-only environment with no network — skill requires CrossRef/OpenAlex. </Do_Not_Use_When>
| Variable | Default | Purpose |
|---|---|---|
BIB_FILE | references.bib | Path to project BibTeX. Used when verifying by citekey. |
SUMMARY_FILE | references.csv | Project literature summary table. When --summary-csv is set (or this is configured in CLAUDE.md), verified_on / verify_status are written back per citekey. |
CITATION_VERIFY_EMAIL | (unset) | Polite-pool email for CrossRef/OpenAlex. Strongly recommended — gives a higher rate limit and prioritizes your requests. |
CITATION_VERIFY_TIMEOUT | 15 | Request timeout in seconds. |
Resolution order on each invocation:
- Command-line flags (highest priority).
- Environment variables.
- Project CLAUDE.md "Research stack" block — fields
BibTeX file,Summary file,CrossRef email. - Defaults above.
If BIB_FILE is not configured on first use, ask the user once and offer to persist it.
</Configuration>
Step 1 — Pick the input mode
Four modes:
# Verify a single DOI
python3 verify_citation.py --doi 10.1038/s41586-023-XXXXX-X
# Verify one citekey from the BibTeX file
python3 verify_citation.py --bib references.bib --key smith2023connectome
# Audit the whole BibTeX file
python3 verify_citation.py --bib references.bib
# Audit and also update the project summary table in place
python3 verify_citation.py --bib references.bib --summary-csv references.csv
Optional flags:
--claim "<one-line claim>"attaches the claim to the report so downstream logs show what was being supported. The skill does NOT decide whether the abstract supports it — that is the calling agent's call.--jsonemits structured JSON instead of the human report.
Step 2 — Run the verifier
python3 "$CLAUDE_PLUGIN_ROOT"/skills/verify-citation/verify_citation.py \
--bib "$BIB_FILE" \
--summary-csv "$SUMMARY_FILE"
The script:
- Parses the requested entry(ies) from the BibTeX file.
- Hits CrossRef (
api.crossref.org/works/<DOI>) for canonical metadata. - Falls back to a CrossRef title+author search if no DOI is present in the BibTeX.
- Hits OpenAlex (
api.openalex.org/works/doi:<DOI>) for the abstract. - Compares author / title / year between BibTeX and CrossRef; flags mismatches.
- If
--summary-csvis set, writesverified_on(today, YYYY-MM-DD) andverify_statusto the matchingcitekeyrow. Other columns (our_use,paper_says,bucket,cited_sections) are never overwritten.
Step 3 — Read the report
Human report (per entry):
[PASS|MISMATCH|NOT_FOUND] <citekey or DOI>
DOI: <doi> → CrossRef: <found / not found>
Title: crossref="..." match=<true/false>
Author: crossref="..." (+N more) match=<true/false>
Year: crossref=YYYY match=<true/false>
Abstract (first 500 chars):
"..."
Claim: <if --claim was provided>
→ Read the abstract above and confirm whether it supports the claim.
Note: <any flags>
Statuses:
PASS— DOI resolves AND title/authors/year all match (case-insensitive, normalized).MISMATCH— found at CrossRef but at least one metadata field disagrees with the BibTeX entry.NOT_FOUND— DOI does not resolve and title+author search returns no plausible match.NOT_VERIFIED— network error, surfaced separately; not treated as a pass.
Step 4 — Caller assesses claim-fit
The script does NOT decide whether the abstract supports the claim — that requires reading. The calling agent reads the abstract from the report and answers the claim-fit question. The skill provides the evidence; the agent provides the judgment.
</Steps><Output_Contract>
stdout: human-readable report (one block per entry) — or JSON if --json was passed.
Exit codes:
0— all entries PASS.1— at least one entry MISMATCH or NOT_FOUND.2— script error (network down on every retry, malformed BibTeX, missing file, etc.).
When --summary-csv is set:
- Columns updated:
verified_on,verify_status(per-citekey). - Columns added if the citekey row does not exist: a new row with
citekey,verified_on,verify_statusfilled and human-curated columns left blank forliterature-curatorto fill. - Columns the skill never touches:
our_use,paper_says,bucket,cited_sections,authors,year,title,venue,doi. These belong to the curator.
</Output_Contract>
<Failure_Modes>
| Symptom | Cause | Action |
|---|---|---|
urllib.error.URLError / timeout | Network unreachable, CrossRef down | Retry once; if still failing, report affected entries as NOT_VERIFIED (network) and do NOT mark them PASS |
Title matches but DOI does not resolve | BibTeX has a typo in DOI | Report as MISMATCH; the curator agent fixes the DOI |
Author count differs | BibTeX truncates with "et al." | Soft MISMATCH — flagged in notes but does not necessarily fail (curator decides) |
Abstract empty in OpenAlex | Publisher does not deposit abstracts | Skill still PASSes on metadata; caller must verify claim-fit via manuscript download |
Summary file does not exist | First run, no summary table yet | Skill creates the file with the canonical header row |
</Failure_Modes>
<Files> - `SKILL.md` — this file. - `verify_citation.py` — the verifier. Stdlib-only (`urllib`, `json`, `csv`, `re`). Runnable as a script or importable. </Files>