doc-router
Rust tool that asks Jev which PDF pages actually need OCR, extracting text pages locally and sending only the rest to your OCR provider.
# doc-router **Don't pay to OCR a page that already has text on it.** Most PDFs are not all-scan or all-text. A contract has two signature pages scanned in the middle. A report's appendix was photocopied. An invoice batch has every third document off a flatbed. Hand the whole file to a hosted OCR model and you pay for every page — including the ones you could have read for free, instantly, with no network call. `doc-router` looks at a PDF **page by page**, decides which pages have a usable text layer and which genuinely need OCR, then acts on that: text pages are extracted locally in-process, only the rest go to your OCR provider, and the two halves merge back into one page-ordered result. It's Rust, and the core library never touches a network. --- ## What it bought us Measured 2026-09-17 on 19 documents / 155 pages, `mistral-ocr-latest` through a live LiteLLM gateway, 3 runs per document: | | OCR every page | routed | |---|---|---| | pages billed | 155 | 87 | | API requests | 19 | 13 | | wall clock | 35,578 ms | 20,666 ms — **1.72x faster** | | bill at $2.00/1k pages | $0.3100 | $0.1783 — **1.74x cheaper** | | pages that needed OCR and didn't get it | 0 | 9 — vs **28** for a rules-based judge | The judge costs **2.5% of the OCR bill it authorises**. Note that a cheaper bill is not automatically a better result: the rules-based judge is cheaper still and misses three times as many pages. [docs/GUIDE.md](docs/GUIDE.md) has the method and the per-document numbers. ## What's under the hood - **[Jev](https://docs.typesafe.ai)** (TypeSafe System One) — the page judge. Given the evidence for a page, it answers one question: does this page need OCR? It catches what rules can't — a scan carrying a bad pre-existing OCR layer, a page whose only text is a watermar