Documentation
From two lines to a reader that checks itself.
Start with the shortest thing that works. Reach for the next page only when something downstream starts acting on the rows.
npm install truecopyStart here
Quickstart
Two lines give you rows and cells, plus the one field that separates this from an extractor. Three more steps turn a reading into one that checks itself.
Tutorial - a reader that checks itself
Build a complete statement reader from an empty file. It takes six steps. Each one runs, and each one adds a guarantee the step before did not have.
The command
npx truecopy a-document.pdf is the shortest way to find out whether this library is any use on your own files, before installing anything.
mcp - the reading as a tool an assistant can call
truecopy/mcp
An assistant handed somebody's statement has a tool call and nothing else. It offers two tools over stdio. One reads the table, the other checks the values against the rows they were cited from, and the file never leaves the machine.
Why refusing matters
Two readers written for different documents, sharing no line of code, arrived at the same five rules. When two teams converge without speaking, that is not a preference. It is the shape of the problem.
Reading a document
readTable - the two-line path
truecopy/table
It gets rows and cells out of a file with no configuration at all, plus the field that says what the reading could not vouch for.
open - the door
truecopy/open
It is the only way from bytes to rows. It enforces the caps and the deadline, and it releases the engine. Its refusal is one your application can say in its own language.
layout - the cut, and where every value came from
truecopy/layout
It is pure geometry over plain data. It offers three ways to find columns, and the coordinates that let a person point at a value instead of hunting for it.
notation - how a page writes a figure
truecopy/notation
That 1 234,50 and 1,234.50 are the same quantity says nothing about banks. It says how the page was typeset. Everybody rewrites that part, and everybody gets it wrong once.
records - which rows belong to the same record
truecopy/records
A record often occupies two or three printed rows. Every mechanism here works on the printed row, so one row per record undercounts a real document by three to five times, without a word.
labels - which cells could be the value a label announces
truecopy/labels
A label and its figure are scattered by the layout, not by the domain. Three applications wrote the same search three times, in three geometries, with no domain word in any of them.
Trusting a reading
How do you know the reading is right?
The checks that actually catch a wrong table extraction, which of them a library can run for you, and the one thing none of them prove. Written because the question has plenty of articles and almost no code.
Check what a model extracted
The rows came back from a model, not from this library. The check that can still say they are wrong costs one object, and it never looks at how they were obtained.
cite - the rows a model read, and whether they carry the value
truecopy/cite
A model cannot produce a fact, only point at one. Number the rows, take back the numbers it cited, and look every value up in THOSE rows and nowhere else.
anchor - the passage a stored value came from, found again
truecopy/anchor
A value read once and served for months cannot re-run its extraction per reader. What proves it is the sentence, found again from a short anchor kept beside the value. The figures the value announces are checked against that sentence.
signature - the schema learned from the rows
truecopy/signature
A table describes itself. The row that breaks what every other row does is a total, a balance or a footer. Recognising it needs no list of words.
contract - what an honest reading looks like
truecopy/contract
You write three methods, and two of them have safe defaults. The pipeline enforces one rule. A reading that contradicts its document never comes back as sound.
kit - six rules, in your own test suite
truecopy/kit
An interface is dodged with a return null. An assertion is not. Drop the conformance kit into your gate with a corpus of your own documents.
schema - one declaration, two outputs
truecopy/schema
Write the schema once and get the check and the record type. Or bring the one you already wrote in Zod, Valibot or ArkType.
explain - see what the reading decided
truecopy/explain
The popular extractors have this feature, and the careful ones forget it. It prints text, not an image, so it goes into a terminal, a CI log, a bug report and a test.
classify - is this the kind of document expected
truecopy/classify
A statement quoting the word invoice in a transaction label must not be filed as an invoice. The precedence is stated rather than smuggled into an ordering.
columns and roles - what a column holds, and what it is
truecopy/columns · truecopy/roles
Count what each column contains once, then deduce what it is from that. Recognising a header label only works on issuers you have already seen.
pattern - domain knowledge as data
truecopy/pattern
Everything that varies by market, by issuer or by document family should be a value, not a branch. And a pattern off the wire is untrusted input applied to untrusted input.