dingduff/dingduff-public/dingduff-citation-check

Claude Code and agent skill by dingduff/dingduff-public

Trust tier 2
  • community
LLM review pending
Source check pending

Checking that the SKILL.md file is still in the repository.

Verify every citation in a drafted legal memo (Markdown, Word, or Google Docs) against stored opinions and statutes plus any other source documents the attorney supplies (a Restatement section, an off-CourtListener case, an opposing brief, a factual PDF). Use after drafting a memo when the user asks to cite-check, citecheck, verify citations, verify quotes, check cites, or validate authorities. Produces cites.json, quality-checks the anchors for substance, and opens the interactive attorney review panel (or a standalone review.html that can display supplied PDF/Word sources in native format with the verified highlights overlaid) for the attorney to review. NOTE: a full cite-check reads every cited source and enumerates every citation instance, so it is context-heavy — run it in a subagent, delegating the cite-check task rather than loading the full skill and every source into the main context window. (v2.5.9)

Install

npx vskill@latest install dingduff/dingduff-public/dingduff-citation-check

SKILL.md

Cite-Check: verify a memo's citations against stored sources

Run this in a subagent. A full cite-check reads every cited source end to
end and enumerates every citation instance — it is context-heavy. Delegate the
whole cite-check task to a subagent rather than loading this skill and all the
sources into the main context window. (The subagent can build
proposals.json / cites.json / review.html; open the citecheck_review
panel from the main thread so it renders for the attorney.)

You orchestrate a propose-and-verify loop: YOU propose verbatim supporting quotes; a deterministic local script verifies them and computes anchors. A hallucinated quote cannot become a highlight — the script only accepts text that actually exists in the source file.

Privacy: verification runs entirely in this session. When the review panel opens via citecheck_review, the memo transits the DingDuff server once as tool arguments and is never stored or logged. The standalone review.html fallback never leaves the machine at all; when it shows a PDF or Word source in native format, it downloads only the open-source viewer libraries (PDF.js, docx-preview, JSZip) from DingDuff's public GitHub repository and checks each against a pinned checksum. State this plainly if the user asks.

Step 0 — Preflight

  1. Run python3 --version. If python3 is missing, stop and tell the user it

is required (macOS: xcode-select --install or brew install python3).

  1. Resolve <skill-dir> — the directory holding this skill's scripts/:
  • If the CLAUDE_PLUGIN_ROOT environment variable is set (the skill was

installed as a plugin), use ${CLAUDE_PLUGIN_ROOT}/skills/dingduff-citation-check.

  • Otherwise (running from a source checkout) use the absolute directory

containing this SKILL.md. Confirm <skill-dir>/scripts/verify_anchors.py exists before proceeding.

  1. Run every script from the PROJECT ROOT (the working folder containing the

memo), so all recorded paths are project-root-relative.

Step 1 — Locate and normalize the memo

Cite-check verifies plain UTF-8 text, so accept the memo in any common form and convert it to a Markdown working file first. That converted `.md` is the memo of record — its path and SHA-256 are what flows through cites.json and what the audit certifies, so everything below uses it as memo.path. Tell the user plainly which file you are checking.

  • Markdown / plain text (.md, .txt): use as-is.
  • Word (.docx): convert with the bundled extractor —

`` python3 <skill-dir>/scripts/extract_docx.py --in <memo>.docx --out <memo>.md `` It keeps paragraph order and pulls in footnotes and endnotes (where legal cites often live) and the accept-all view of tracked changes. If its stderr warns about unaccepted tracked changes, say so — the check ran against the accepted text — and ask the user to confirm that is the version they mean.

  • Google Docs: export/download the doc to .docx (the connected Google

Drive tool's export, or in the browser File → Download → Microsoft Word), then convert it the same way.

  • PDF (only when the PDF itself is the work product): extract its text layer

to .md/.txt with available PDF tooling, then check that. There is no OCR — a scanned PDF with no text layer cannot be checked.

If multiple memo candidates exist, ask the user which to check.

Step 2 — Inventory the stored sources

Convention: source files live in sources/ under the project root, saved there from fetch_opinion_file/fetch_statute_file download URLs. (Going forward, always save those downloads into sources/.)

Also search the rest of the working folder for strays:

  • Opinion files contain a **Cluster ID:** <id> line.
  • Statute files start with # <citation> and contain **Code:** and

**Section:** lines.

If the same cluster is stored twice, use the newest file and tell the user.

Build the sources map:

  • Opinions: key cl-{cluster_id} (cluster id from the FILE's Cluster ID

line), with type, path, cluster_id, case_name, citation.

  • Statutes: key stat-{filename stem}, with `type, path, statute_id, code,

section, jurisdiction. statute_id is the [jurisdiction]/[code]/[section] identifier used with fetch_statute_file (e.g. TX/property/92.006, US/18-usc/1001`) — reconstruct it from the file's metadata block. The review panel needs it to re-fetch the statute, so get it right.

Working-file sources (non-DingDuff)

The DingDuff corpus isn't comprehensive. The attorney can also cite-check against sources they supply — a Restatement section, a case missing from CourtListener, the other side's brief, a factual PDF. Treat any such file as a document source:

  • Accept it as text/markdown (pasted in or saved into sources/), or extract

it first:

  • .docx via `python3 <skill-dir>/scripts/extract_docx.py --in <file>.docx

--out sources/<name>.md`.

  • a text-layer PDF: extract preserving page breaks — `pdftotext -layout

<file>.pdf <tmp>.txt (or any tool that emits form-feed \f page delimiters) — then convert the form feeds to visible page markers: ` python3 <skill-dir>/scripts/mark_pdf_pages.py --in <tmp>.txt --out sources/<name>.md ` The <<pg. N>> markers become page pills in the review panel (real PDF page numbers for pin-cite checking) and are invisible to quote matching. If the document's printed page numbers don't start at 1 (an exhibit excerpt), pass --first-page <n>`. If the script warns about empty pages, the PDF is likely scanned — there is no OCR; tell the attorney the file can't be checked.

  • ORDERING RULE (load-bearing): page markers and any other text fixes

happen BEFORE verify_anchors.py runs. Never edit an extracted file after verification — cites.json hashes the file and records offsets into it, so any later edit invalidates the whole check.

  • Always keep the original PDF/Word file alongside the extraction, at

sources/originals/<name>.pdf (or .docx), and record it in the source's proposals entry — this `original` block is what makes the review DISPLAY THE PDF/Word document (Step 7); do not skip it for a PDF or Word source: ``json "original": { "path": "sources/originals/<name>.pdf", "media_type": "application/pdf", "pages": 24, "extracted_by": "pdftotext -layout + mark_pdf_pages.py" } ` (media_type for Word files: application/vnd.openxmlformats-officedocument.wordprocessingml.document.) The standalone review.html then shows the attorney the ORIGINAL document — real pages, native formatting — with the verified highlights overlaid, all fully local. (Only review.html renders natively; the in-conversation panel is text-only — see Step 7.) The verifier recomputes the hash and size itself; if it warns original_missing or original_bad_media_type`, the original was dropped and that source silently falls back to text — fix the path or media_type before building the bundle. Originals over 20 MB won't embed (the text view still works); say so up front.

  • For a deposition/hearing transcript supplied as text, set

"render_hint": "transcript" on the source so the panel renders it in transcript format (monospace, line-number gutter, page pills). If the transcript has machine-regular page headers, convert them to <<pg. N>> markers during prep (before verification) so its page pills line up with page:line pin cites.

  • Map it as key doc-{filename stem}, with type: "document", path, title

(a human label, e.g. "Defendant's MSJ Brief", "Restatement (Second) of Torts § 46") and kind ∈ case | secondary | brief | evidence | other.

  • Two honest limits to state to the attorney: the tool verifies only that the

quoted/paraphrased text appears in the file — for an off-CourtListener "case" it does not confirm the case is real or still good law; and a document is only as trustworthy as the file supplied (extraction can be lossy, so a noisy PDF yields more anchor_failed rows to eyeball).

Step 3 — Enumerate every citation INSTANCE

Read the memo end to end. Every citation instance gets its own entry — the same case cited five times yields five entries, and Id., supra, and short forms count. Resolve what each Id./short cite refers to by reading context.

For each instance record:

  • id: c001, c002, … in memo order.
  • cite_text: the citation EXACTLY as it appears in the memo.
  • memo_context: ~40+ chars of surrounding memo text containing cite_text.

REQUIRED whenever cite_text appears more than once in the memo (always required for Id. forms); the snippet itself must be unique in the memo.

  • pin: the pin-cite page, if any (e.g. "461").
  • proposition: one sentence stating what this citation is offered to

support — the claim the attorney will verify.

  • support_type: "quotation" if the memo quotes the source, else

"paraphrase".

  • anchors_proposed: 1–3 quotes copied VERBATIM from the stored source

file that support the proposition.

Hard rules for quotes:

  • Open the stored file and COPY the passage — reproduce the source's own

punctuation and capitalization, not the memo's bracketed alterations or cleaned-up quotation marks.

  • Use ... only for genuine omissions; every segment around an ellipsis

must be at least ~10 characters, segments must appear in document order, and they must be reasonably close together.

  • NEVER quote from the ## Citing Cases section or the file footer — only

the opinion body (the verifier rejects these). This guard is opinion-only; for a document source the whole file is quotable.

  • Signal cites (see generally, string-cite tails) where no specific

passage is claimable: set "no_quote_claimed": true with empty anchors_proposed. Use sparingly — every no-quote citation is one the attorney must verify entirely by hand.

Step 4 — Missing sources

If a cited authority has no stored file, first attempt to fetch from DingDuff (fetch_opinion_file / fetch_statute_file → save into sources/). If you cannot locate the source, tell the user and still include the citation, with a source entry of {"type": "opinion"|"statute", "missing": true, "case_name"/"citation": ...} so it is tracked as unverifiable rather than silently dropped.

Step 5 — Write proposals and verify

Write .cite-check/proposals.json (create the scratch dir):

This is the start of the file. Read the full SKILL.md on GitHub.

Security

  • Security scanPassed, 100 of 100Pattern checks on the skill's files.
  • Model reviewNot runA model review is scheduled for the next rescan.

Quality evaluation

  • Task evaluationNot runNo evaluation yet. Run one in Skill Studio.

Source

Popularity

Repository stars
61
Repository forks
8
7-day trend score
0

Stars and forks are for the whole GitHub repository, not this skill alone. Refreshed 16 Oct 2026, 24 days ago.

Works with

Any agent vskill installs to: 56 targets in all. These 39 have a page on this site.

  • Claude Code
  • Cursor
  • GitHub Copilot
  • Windsurf
  • Codex
  • Gemini CLI
  • Cline
  • Amp
  • Roo Code
  • Goose
  • Continue
  • Kilo Code
  • Junie
  • Trae
  • OpenHands
  • Qwen Code
  • AI Agent
  • Tabnine Chat
  • Sourcegraph Cody
  • Amazon Q
  • Firebase Genkit
  • Sweep
  • Devin
  • Phind
  • Mentat
  • Claude Desktop
  • Aider
  • GPT Pilot
  • Plandex
  • bolt.new
  • v0
  • Replit Agent
  • Anse
  • TypingMind
  • BetterChatGPT
  • LibreChat
  • Warp AI
  • Pieces
  • Fig AI
Embed badge
vskill VERIFIED badge
[![vskill VERIFIED](https://verified-skill.com/api/v1/skills/dingduff/dingduff-public/dingduff-citation-check/badge)](https://verified-skill.com/skills/dingduff/dingduff-public/dingduff-citation-check)

Something wrong with this skill or its page? Tell us.