The five steps
Inbox — put statements in and look at them. Nothing is read yet.
Categories — the chart of accounts the classifier is allowed to choose from.
Review — only the lines a person has to decide about, each beside the document it came from.
Reconciliation — the arithmetic behind every verdict.
Export — the workbook, its exceptions sheet, and the log of what happened.
What it does
Reads statements and activity exports from several institutions — text PDFs, scanned PDFs, phone photos and Excel exports — pulls out the transactions, checks the arithmetic against the document's own balances, classifies each line against your chart of accounts, and writes an Excel workbook with the exceptions separated out.
Where it runs
- Text extraction uses pdf.js in this browser tab.
- OCR runs tesseract compiled to WebAssembly, also in this tab. The model files are served from this site and cached.
- Classification is a rules table plus a small logistic-regression model trained on a labelled sample at startup. No model is downloaded and no text is sent anywhere.
- The Excel file is assembled in this tab and saved by your browser.
There is no server side. You can confirm that with the browser's network panel: after the page loads, nothing is requested.
What is synthetic
Every statement in the sample set is generated for this demo, including the account holder, the institutions and the merchants. No real account, person or transaction is represented. The 10 documents deliberately differ in layout, date format, column naming, currency and quality, and one carries an error on purpose.
What is limited, honestly
- The classifier is trained on invented labels. On real books it needs your own category history — that is the first thing worth doing together.
- OCR is good on clean high-resolution scans and degrades on skew, faxes and faint print. Lines it is unsure about are flagged rather than silently accepted.
- A statement with no running balance and no opening/closing totals cannot be verified at all; it is labelled unverifiable rather than assumed correct.
- Documents that are summaries rather than transaction tables are refused. Nothing is invented to fill a table.
About this demo
Load the sample statements and this fills in.
The same pipeline, locally
The container runs the identical extraction, reconciliation, classification and export code against a folder, with native OCR (tesseract, pdftoppm) instead of WebAssembly:
docker compose run --rm desk --batch /inbox --out /out