Skip to main content

touchneedle

Citiation tool that verifies the citations in a document are real, accurately described, and consistently used.

Useful for both students and examiners who wish to corroborate citations.

It works standalone, or as a coding agent skill.

Most commercial citation checkers want a .bib file and check it against academic databases. That covers journal articles but misses standards, specifications, vendor documentation, and blog posts. In a lot of real bibliographies, this is half the list.

So this tool parses a prose reference list straight out of Markdown or .docx, in the four style families a real document uses — author-date (Harvard, APA, Chicago author-date), numeric (IEEE, Vancouver/AMA), MLA, and footnote styles (Chicago notes, MHRA) — and routes each entry to whichever authority can actually confirm it. The style is auto-detected, or forced with --style.

What it checks

Existence and metadata — scripted and deterministic:

Entry carries Checked against
arXiv id arXiv API
DOI Crossref
RFC number IETF datatracker, falling back to rfc-editor
draft-* name IETF datatracker, including whether the cited revision is still current
Quoted title in an academic venue Crossref, then OpenAlex, by title
A URL and nothing else Fetched live; page title compared with the cited title

Entries with both an identifier and a URL get both, so a real paper behind a dead link is still reported. Detects the fabricated-citation signature — a real title carrying the wrong authors — as MISMATCH.

Internal consistency — every in-text citation resolves to a list entry, every list entry is cited somewhere, and 2025a/2025b suffixes are used unambiguously. Bracket markers resolve by number, author-page citations by surname, footnote markers through their note — a shortened note or an Ibid. links to the full citation it repeats.

Claim support — the pass that needs reading rather than fetching. claims emits a worklist pairing each in-text citation with the sentence making the claim and a locator for the source; the model then reads each source and rules SUPPORTED / PARTIAL / UNSUPPORTED / INACCESSIBLE. This catches the failure the database checks cannot: a genuine source attached to a claim it does not make.

Install

As a command-line tool:

pip install touchneedle

As a Claude Code skill:

git clone https://github.com/nicoleman0/touchneedle ~/.claude/skills/touchneedle

Or as a Claude Code plugin:

/plugin marketplace add nicoleman0/touchneedle
/plugin install touchneedle

There are no dependencies beyond Python 3.11+. pandoc is needed only for .docx input.

Then, in Claude Code: "check the citations in thesis.docx".

Use directly

touchneedle check thesis.docx --out report.md --json data.json
touchneedle claims thesis.docx --out claims.md

From a clone, without installing, that is python3 scripts/touchneedle.py … — the same file either way.

Options: --offline (parse and cross-check only, no network), --style {auto,author-date,numeric,mla,notes} (default auto, detected from the list and the in-text markers), --cache DIR (HTTP cache, 7-day TTL, so re-runs are nearly free), --timeout N, and --mailto you@example.com for Crossref and OpenAlex's polite rate-limit pool. --mailto is off by default and never inferred — it sends an address to third parties.

check exits 2 when something needs attention, 0 when clean, so it drops into CI.

Statuses

MISMATCH and NOT_FOUND are the ones that damage a submission. LINK_DEAD and STALE need a fix but not a retraction. PARTIAL, LINK_MOVED and UNVERIFIABLE are for a glance — notably, PDFs and JS-rendered pages land in PARTIAL routinely, because no <title> can be read from them. A PARTIAL is a limit of the check, not evidence against the citation.

Limits

Page numbers, edition and publisher details are not checked.

MLA narrative citations that end in a bare page number (Smith argues the point (42)) are not matched, because a bare parenthesised number cannot be told from any other parenthesised digit. A shortened footnote note that cannot be linked to its full citation is kept as an entry with a caveat rather than silently merged.

The list of in-text citations with no matching entry has expected false positives: a regex cannot distinguish (Smith, 2024) from (ICLR 2023), or [12] from a figure reference. The report says which shape to expect per style.

Sources behind paywalls cannot be verified beyond their metadata record.

Development

python3 -m unittest discover -s tests -t tests

See CONTRIBUTING.md before opening a pull request.

The short version: standard library only, tests stay offline, and never let a coverage gap report itself as a finding.

Licence

MIT — see LICENSE.

Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

touchneedle-0.2.0.tar.gz (42.8 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

touchneedle-0.2.0-py3-none-any.whl (26.0 kB view details)

Uploaded Python 3

File details

Details for the file touchneedle-0.2.0.tar.gz.

File metadata

  • Download URL: touchneedle-0.2.0.tar.gz
  • Upload date:
  • Size: 42.8 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/7.0.0 CPython/3.13.14

File hashes

Hashes for touchneedle-0.2.0.tar.gz
Algorithm Hash digest
SHA256 ea3770c1060864f1e77025ea98447e3ed43dd929c8fbbc488de980cc1d9645d1
MD5 7c6a5e3660549aa3404a006561e3465a
BLAKE2b-256 a181b269d5a516c0686f4b1730e162bac60483a1d3e5402d79390d1a281e08a0

See more details on using hashes here.

Provenance

The following attestation bundles were made for touchneedle-0.2.0.tar.gz:

Publisher: publish.yml on nicoleman0/touchneedle

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file touchneedle-0.2.0-py3-none-any.whl.

File metadata

  • Download URL: touchneedle-0.2.0-py3-none-any.whl
  • Upload date:
  • Size: 26.0 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/7.0.0 CPython/3.13.14

File hashes

Hashes for touchneedle-0.2.0-py3-none-any.whl
Algorithm Hash digest
SHA256 768fff7d009ba6a9947822c6604873d29cf3a8cb275108732403650304ac44a6
MD5 4c309db145ac2f30d94ae5282b6168f7
BLAKE2b-256 6a73abb8d70d9f52369fc51a285707aad2e897dc294528dc6f8cc2fcbbed4931

See more details on using hashes here.

Provenance

The following attestation bundles were made for touchneedle-0.2.0-py3-none-any.whl:

Publisher: publish.yml on nicoleman0/touchneedle

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Release history Release notifications | RSS feed

0.2.2

2 files

0.2.1

2 files

This release

0.2.0 This release

2 files

0.1.0

2 files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page