{"slug": "show-hn-citeguard-local-cli-for-checking-citations-in-markdown-reports", "title": "Show HN: CiteGuard – local CLI for checking citations in Markdown reports", "summary": "CiteGuard, a new open-source command-line tool released under the MIT license, checks citations in Markdown reports generated by AI agents and deep-research tools, flagging dead links, title mismatches, weak claim-source overlap, and suspicious redirects without requiring API keys or sending telemetry. The tool, available on GitHub from developer larrylot, offers deterministic per-URL verdicts, an offline fixtures mode for CI, and JSON output for audit trails, positioning itself as a local alternative to asking an LLM to verify citations.", "body_md": "**Local CLI that verifies citations in agent / deep-research Markdown reports.**\n\n`citeguard check report.md` → per-citation verdicts: URL resolve, title/host soft-match, optional claim–source overlap.\n\n- **No API keys** for core checks\n- **No telemetry** , no SaaS, no account\n- **Offline `--fixtures` mode** for CI\n- MIT licensed\n\nExploration bet for The Lord (0 SEK). Not a merchant product.\n\n|  | CiteGuard | Ask ChatGPT / another LLM | \n|---|---|---|\n| Reproducible | Deterministic resolve + scores | Non-deterministic prose | \n| Offline CI | `--fixtures` planted cases | Needs network + model | \n| Cost / keys | Free local HTTP | API key / subscription | \n| Audit trail | JSON verdicts per URL | Chat transcript | \n| Hallucination check on the checker | No LLM in the loop | Can invent “looks fine” | \n\nCiteGuard does **not** claim to prove a source supports a legal/scientific conclusion. It flags **dead links, title bait, weak overlap, and shady redirects** — the failure modes that show up in agent research dumps.\n\nPortable `SKILL.md` (Cursor / Claude / Codex / agentskills.io format):\n\n- Canonical: [`skill/SKILL.md`](/larrylot/citeguard/blob/main/skill/SKILL.md)\n- Cursor mirror: [`.cursor/skills/citeguard/SKILL.md`](/larrylot/citeguard/blob/main/.cursor/skills/citeguard/SKILL.md)\n- skills CLI layout: [`skills/citeguard/SKILL.md`](/larrylot/citeguard/blob/main/skills/citeguard/SKILL.md)\n\n```\nnpx skills add larrylot/citeguard -s citeguard -y\ncd citeguard\npython3 -m venv .venv\nsource .venv/bin/activate\npip install -e \".[dev]\"\n# Offline CI-style check on a clean planted report\nciteguard check fixtures/clean.md --fixtures\n\n# A bad report (dead links) — exits 1\nciteguard check fixtures/dead_link.md --fixtures\n\n# Title-bait SEO farm planted as \"asyncio docs\"\nciteguard check fixtures/title_mismatch.md --fixtures\n\n# Machine-readable\nciteguard check fixtures/mixed.md --fixtures --json\n```\n\nExample human output:\n\n```\nCiteGuard — fixtures/mixed.md\nSummary: {'clean': 3, 'dead': 1, 'title_mismatch': 1, 'total': 5}\n------------------------------------------------------------\n[OK] L3 https://docs.github.com/en/actions\n...\n[DEAD] L7 https://example.invalid/dead-citation-404\n...\n[TITLE] L9 https://example.invalid/python-asyncio-guide\n```\n\nLive network check (no fixtures):\n\n```\nciteguard check path/to/agent-report.md\nciteguard check path/to/agent-report.md --json --no-overlap\n```\n\n| Verdict | Meaning | \n|---|---|\n| `clean` | Resolved; title/claim checks passed | \n| `dead` | 404 or network failure | \n| `http_error` | Non-success HTTP (e.g. 500) | \n| `title_mismatch` | Link text soft-match vs `<title>` too low | \n| `claim_weak` | Claim sentence tokens barely appear in page text | \n| `redirect_suspect` | Cross-host redirect without strong title match | \n| `unresolved` | URL missing from fixtures catalog (fixtures mode only) | \n\nSynthetic agent-style Markdown under [`examples/realworld/`](/larrylot/citeguard/blob/main/examples/realworld) (dead links, DNS failures, title bait on `example.com`, plus working RFC / Example Domain controls).\n\n- Findings table (FACT counts): [`examples/realworld/REPORT.md`](/larrylot/citeguard/blob/main/examples/realworld/REPORT.md)\n- Per-dump JSON + text: [`examples/realworld/out/`](/larrylot/citeguard/blob/main/examples/realworld/out)\n- Live demo page: [https://larrylot.github.io/citeguard/](https://larrylot.github.io/citeguard/)\n\n[`corpus/`](/larrylot/citeguard/blob/main/corpus) — 20 short public-domain-style fake agent-research Markdown snippets with planted failures (`example.invalid`, title bait via `example.com` / `httpbin.org`). Documented for benchmarks. See [` corpus/README.md`](/larrylot/citeguard/blob/main/corpus/README.md).\n\nOne-page JSON output demo: [`docs/index.html`](/larrylot/citeguard/blob/main/docs/index.html) (GitHub Pages: [https://larrylot.github.io/citeguard/](https://larrylot.github.io/citeguard/)).\n\n- [CiteGuard vs alternatives](/larrylot/citeguard/blob/main/docs/vs-alternatives.md) — honest comparison vs “ask ChatGPT”, LinkChecker, html-proofer, ReportBench (FACT / ASSUMPTION labeled)\n\n```\ndocker build -t citeguard .\ndocker run --rm -v \"$PWD\":/data -w /data citeguard check fixtures/mixed.md --fixtures\n```\n\n`fixtures/` ships **9** Markdown reports + `*.expected.json` + HTML pages + `catalog.json` for offline resolve:\n\n- clean cites, dead links, title mismatch, claim–source mismatch, redirect suspect, HTTP error, footnotes, mixed, bare URLs\n\n```\npytest -q\n# accuracy gate: ≥80% resolve+classify on fixtures\n```\n\nFree form — **HUMAN SETUP** ≤10 min: see [`WAITLIST.md`](/larrylot/citeguard/blob/main/WAITLIST.md). Paste the public URL below when ready:\n\nWaitlist: `<!-- HUMAN: paste Tally or Google Form URL -->`\n\n- [`SHOW_HN.md`](/larrylot/citeguard/blob/main/SHOW_HN.md) — Show HN draft\n- [`POSTS.md`](/larrylot/citeguard/blob/main/POSTS.md) — Reddit / LinkedIn templates\n\nAgent does **not** post or outreach.\n\nSee [`STATUS.md`](/larrylot/citeguard/blob/main/STATUS.md). Kill if <10 stars **and** <10 waitlist after 7 days with ≥1 human public post, or fixture accuracy <80%, or HN reads it as a chatbot wrapper.\n\nMIT — see [`LICENSE`](/larrylot/citeguard/blob/main/LICENSE).", "url": "https://wpnews.pro/news/show-hn-citeguard-local-cli-for-checking-citations-in-markdown-reports", "canonical_source": "https://github.com/larrylot/citeguard", "published_at": "2026-09-07 05:59:14+00:00", "updated_at": "2026-09-07 06:26:26.932853+00:00", "lang": "en", "topics": ["developer-tools", "ai-tools", "ai-agents"], "entities": ["CiteGuard", "larrylot", "GitHub", "MIT"], "alternates": {"html": "https://wpnews.pro/news/show-hn-citeguard-local-cli-for-checking-citations-in-markdown-reports", "markdown": "https://wpnews.pro/news/show-hn-citeguard-local-cli-for-checking-citations-in-markdown-reports.md", "text": "https://wpnews.pro/news/show-hn-citeguard-local-cli-for-checking-citations-in-markdown-reports.txt", "jsonld": "https://wpnews.pro/news/show-hn-citeguard-local-cli-for-checking-citations-in-markdown-reports.jsonld"}}