Skip to content

manni cite

Pin a sentence to the source lines it rests on, and find out when those lines change.

A citation has two ends, and both are pinned the same way. The claim is the page lines the sentence occupies, and a hash of them. The source is the file, the lines it rests on, a hash of those, and the commit they were read at. manni cite checks both ends and tells you which sentence stopped being true, not which page to re-read.

It runs from git alone. No model, no network, one hash per end on a clean run. A line that gained neighbours above it is moved, and one command fixes that. A line whose bytes changed is changed, with the commits since, and a person decides whether the prose or the pin is wrong. Nothing on the page repeats the sentence, so a copy edit beside it is not a false alarm.

Command Does
manni cite add <page>:L <src>:L Mints a citation over the page lines and the source range, and writes the entry to the page’s frontmatter or to a sidecar manifest.
manni cite check [paths...] Classifies each end of every citation, and reports the findings through the same formats manni meta uses.
manni cite update [paths...] Rewrites moved ends in place, on either side. With --accept, re-pins changed ones.

You don’t need to install anything. Say docs/limits.md says on line 9 that the fetch timeout is 10 seconds, and that sentence rests on line 2 of lib/limits.ts. Pin both ends:

Terminal window
npx @hawkeyexl/manni cite add docs/limits.md:9 lib/limits.ts:2 --id fetch-timeout
docs/limits.md: added fetch-timeout to frontmatter (claim at line 15, sha256-c41f09aa…; source lib/limits.ts:2, sha256-78af1d33…, 9265563)

The entry pushed the sentence down the file, and the stored claim line did not move: it counts the body, not the file. Check it:

Terminal window
npx @hawkeyexl/manni cite check docs/limits.md
✓ docs/limits.md
✓ fetch-timeout :15 current lib/limits.ts:2 current
1 file checked, 1 passed, 0 failed, 0 findings

Then someone raises the timeout to 30 seconds and commits. The page has not changed, so metadata validation still passes. The citation check does not:

✗ docs/limits.md
✗ fetch-timeout :15 current lib/limits.ts:2 changed since 9265563, 1 commit
1 file checked, 0 passed, 1 failed, 1 finding

The finding is annotated on line 15, the sentence. The exit code is 1, so CI goes red on the line that needs a person, and nowhere else. That’s the whole loop: pin, check, read the finding, fix the sentence, re-pin.

The reference shelf holds the exhaustive detail. The CLI reference covers every flag of check, add and update. The configuration reference covers the cite: keys of manni.config.yaml. The citations reference covers the entry shape, the file grammar, the hashing rule, markers and the sidecar manifest.

What manni cite checks, and what it doesn’t

Section titled “What manni cite checks, and what it doesn’t”

It checks

That the lines a sentence cites are still the bytes they were when the citation was written, and that the sentence itself is. Where either end went if it moved. What changed and in which commits if the source did not survive. That every marker names a real entry, and every entry has one anchor.

It doesn't

Judge whether the sentence was ever right, read the source for meaning, call a model, or reach the network. A source-changed finding is a question for a person; the check only makes sure it is asked about one sentence rather than a whole page.

Citations are written in the manni:citations vocabulary, which manni meta publishes and manni cite implements. manni meta validate checks that an entry is well-formed; only manni cite check can say whether it still holds. Both tools ship in one package and read one manni.config.yaml, under their own keys.