The shape of a stack of paper is not something you discover in software. It is something you impose with your hands, before anything reaches the feeder.
This is part of the Paper Trail series: turning an entire family’s paperwork, from today’s invoices to court files and century-old records, into a system that reads itself. The map of the whole project is the first entry.
The hardware post ended with a machine on the network and a promise that paper would find its way in. This is the operating log of what that looks like in practice, and the surprise is where the work turned out to live. I assumed the interesting problem was building the thing that drives the scanner. The interesting problem was deciding what goes in the feeder, and it got solved on a desk rather than in a repository.
Push: the daily drip
Bills, invoices, the letter that showed up this morning. This material has no shape: it arrives one or two pieces at a time, from unrelated senders, in no order, forever.
So I handle each piece by hand, the moment it lands. Scanner on, page in the feeder, press the button on the device. The scanner writes to the network folder that paperless consumes, the document appears in the archive tagged INBOX, and I go back to whatever I was doing. A few seconds of my attention, no computer involved. There is no pile on the corner of the desk, because the pile is the thing that kills archives: once it exists, it grows, and then the archive is a project again instead of a habit.
The classification is the part I defer. Nothing gets a correspondent, a type, a title or a custom field at scan time. Documents accumulate under INBOX, and once enough of them have, I turn an LLM loose on the whole pile at once.
Note which half went to which worker. The human does the trivial physical act immediately; the tedious cognitive act is deferred and done in bulk by the model. That is backwards from how a person naturally works a stack of paper, and it is the right way around: the physical act does not get cheaper by batching it, and the classification does.
Pull: the mode I built, and the word I got wrong
The children’s medical records are the opposite problem, and the first real area from the map after the company paperwork. A large, finite body of paper that has been sitting in one place for years. It is not going to drip. It arrives all at once or never.
So the direction flips. I load the feeder and the computer initiates the scan, because a batch with a known shape lets me declare the rules up front. The load-bearing rule: each sheet is one document.
The word I got wrong was uniform. I had described that stack to myself as large, finite and uniform, and only the first two were ever true. Medical records are not ordered and they are not one thing: mostly single sheets printed on one side, a real minority printed on both, and threaded through all of it the referral folded into quarters, the lab slip the size of a receipt, the discharge summary that runs to four pages. A rule declared over that stack is a rule declared over an average that does not exist.
I did not know that yet, so I built for the average. Stock SANE drives the scanner without any of Brother’s software, and the pull is one command:
scanimage --source 'ADF Duplex' --batch=page_%04d.jpg
The feeder empties into a numbered sequence of images, fronts and backs interleaved, and because one sheet is one document, reassembly is arithmetic, not inference: images 1 and 2 are document one, 3 and 4 are document two, on down the stack. No separator pages, no barcode sheets, no model guessing where one report ends and the next begins.
There is a trap in that arithmetic. Every document scanner offers to skip blank pages, and here that helpful feature is poison: drop one blank back and the whole sequence shifts by one, so every later pair silently mismatches. Skip-blank stays off. Pair first by position, and discard blank backs inside the finished pair, where discarding them cannot move anything.
And one more, which cost ten minutes to find and would have cost years to notice: the OCR has to speak the right alphabet. My documents are Serbian in Latin script. The pipeline was configured for srp, which is Serbian in Cyrillic, so everything came back subtly wrong: Pavlovié for Pavlović, MikrobioloSkom for Mikrobiološkom. Nothing failed. No error, no warning, documents present and accounted for, and the text underneath them quietly useless for search. The language pack had been declared in the config the whole time and had simply never installed, because the language is called srp_latn with an underscore and the package is tesseract-ocr-srp-latn with a hyphen. A config that declares a language is not the same as a language you have.
One thing carries all of this and it is not code: an expensive, specialized document scanner. Dozens of sheets in one load, both sides in one pass. There are far more expensive machines, but this is not a cheap box, and nothing here works without it.
What actually went wrong
The intelligence was never the hard part. Any developer can wire up an LLM; that is an afternoon. The hard part is designing a workflow you do not get sick of. Not one failure here was an AI problem. All of them were plumbing.
The worst was the PDF writer that quietly ate seven sheets. A batch scanned straight to PDF looked like a clean run: the feeder emptied, 15 pages reported scanned, one PDF on disk with 15 pages in it. It contained 8 distinct images. Pages 9 through 15 were the same picture, repeated. No error, no warning, no non-zero exit; the tool reported success. Seven sheets had physically passed through the machine and left nothing behind, and the only reason I know is a size check that found eight files with byte-identical lengths. The failures that matter do not announce themselves. They just hand you a smaller archive than the one you scanned.
What fixed it was one sheet per invocation: scan a sheet, write one finished file, upload it immediately, then pull the next. Slower, and the loss mode disappears, because nothing is buffered inside a container that can be half-written. Each sheet reaches paperless the moment it exists, so a problem is visible after sheet one instead of after the stack. Build it so that when it breaks, you find out on sheet one.
Which is where the joke lands: a program that pulls one sheet, finishes it, files it.
I had reimplemented, in software, the button on the front of the machine. Sit with that. A device with a physical button, one that has worked flawlessly since the day it came out of the box, and I spent an afternoon writing a finger. The pipeline was never solving the paper problem. It was solving my discomfort at not having built anything.
The whole detour cost two or three hours. Building the wrong thing has got cheap enough that you can build it, run it into real paper and drop it inside an afternoon. At ten thousand sheets I would have finished it - at that volume you cannot pre-sort by hand and every hour of automation pays itself back. What follows is correct for a household, not a records department.
Three piles
What replaced the pipeline was sorting the paper.
Before anything reaches the feeder the stack gets split into three: one sheet, one side; one sheet, both sides; and everything else. The taxonomy is physical, not semantic - a lab slip and a discharge summary share a pile if they are the same shape.
The first two piles then go through the way the water bill does: feeder loaded, one press of the button on the machine. What comes back is one file of N pages, and the arithmetic moves to the end of the job instead of the front: the one-sided pile is N documents, the two-sided pile is N/2. I tell the model which pile it was, and it cuts the file.
One file is also far easier to check. A single PDF of N pages I can flip through by eye in seconds and see that every sheet landed, and landed straight - verification the pull mode never made easy. What is left for the machine is splitting by page count, a much smaller job than the one I had given it.
The rule one sheet is one document did not get smarter. It got true, because I made it true by hand before the paper moved.
The third pile gets no automation. Fragile paper, odd sizes, anything longer than one sheet. I stand at the machine and watch the whole run, and the delicate items go through in carrier sleeves. Under a minute per group.
Who presses the button
In a company I would insist on one protocol, declared up front. A company’s paper never stops arriving and the person feeding it changes, so a process that leans on someone’s judgement in the moment degrades the day that someone leaves.
A household archive is finite. Thousands of sheets, and then no more. Adapting pile by pile is not sloppiness, it is reading that constraint correctly.
So the question I opened with retires. Every scan here starts with a human pressing the button, water bill and medical records alike. The only thing that varies is how much sorting happened first.
Why there is no app
I build software for a living. I could obviously put a UI on this. I didn’t, and I am not going to dress that up as minimalism.
The agent already has everything an app would have needed. A shell, an HTTP client, file access, and the paperless API. Writing a front end would mean rebuilding, in a worse form, capabilities that are already sitting there, in service of a job I run occasionally. For a household system with exactly one user, the agent is the interface, and the app is ceremony.
Now the bill. Nothing here is discoverable by anyone but me: no screen to look at, no button to point a family member at, no path by which my wife could run the medical import while I am away. The whole apparatus lives in one person’s command history and one person’s head. That is a real cost, and it is the kind that only presents its invoice on the day you are unavailable.
What won was the least clever thing available. Scan a uniform stack as one PDF, tell the model to split it, upload the pieces back. Almost as fast as pushing documents into paperless one at a time, and it is the same flow the scanner already runs every day. The interesting part was never the intelligence. It was building something I will still be willing to use in a year.
The shape goes in with the paper, or it never goes in at all.
The Paper Trail series
- Paper Trail - the map of the whole project
- Paper Trail: Bootstrapping a Family Archive - the software bootstrap
- Paper Trail: Phone, Flatbed, or a Real Document Scanner - the hardware door
- Paper Trail: Push, Pull, and No App at All - this post, how the paper actually gets in