Skip to main content

LocalContextRouter

Decide locally how each page of a document should reach a multimodal model: as extracted text, on-device OCR, or a rendered image. That keeps you from paying for vision tokens on pages that are only text.

A multimodal model reads a PDF by pulling its text and rendering every page to an image, then billing for both. On a text page that image runs roughly 1,300 to 4,800 tokens while the same page as plain text is 400 to 800. For a text-dominant document that is several times the cost for nothing extra. LocalContextRouter does the cheap work on your machine first and tells you what each page actually needs.

It does not call a model. It returns a per-page decision and the text to send; your application still makes the call.

How it decides

For each page:

  • A usable text layer that is mostly prose: use the extracted text.
  • A text layer dominated by a table, chart, or diagram: send the page as an image, where the layout carries the meaning.
  • No usable text, such as a scan or a photo: recognize it on-device with Apple's Vision framework.

The result also reports how many tokens you saved against sending every page as an image.

Install

pip install localcontextrouter

macOS only. The wheel bundles a universal (Apple Silicon and Intel) OCR binary, so text recognition works with no extra setup.

Command line

localctx invoice.pdf
localctx invoice.pdf --json
localctx scan.png

localctx invoice.pdf prints each page, the source chosen for it, and the tokens saved:

Document: invoice.pdf (3 pages)
Tokens saved vs sending every page as an image: 3085

Page 1 [text]
ACME Corp, Invoice #4471 ...

Page 2 [vision]
Quarterly results by segment ...

Page 3 [ocr]
SCANNED RECEIPT TOTAL 42.00

Add --vision-dir DIR to render the pages that should go to the model as images into DIR; their paths are then listed in the output and the JSON.

In code

from localcontextrouter import route_pdf, Source

result = route_pdf("invoice.pdf")
for page in result.pages:
    if page.source is Source.VISION:
        send_image(page.index)     # the page's meaning is visual
    else:
        send_text(page.text)       # extracted or recognized text

print(result.tokens_saved)

Every page also carries an estimate of its cost both ways, as page.tokens.text_tokens and page.tokens.image_tokens.

As an agent skill

local-context-router is an Agent Skill in the open SKILL.md format, so it works in Claude Code and other compatible agents. It lives in this repository under .claude/skills/local-context-router; copy that folder into your agent's skills directory:

cp -r .claude/skills/local-context-router ~/.claude/skills/

With the package installed, the agent runs the preflight on any PDF or image you share, then uses the text for the cheap pages and attaches images only for the visual ones.

Requirements and scope

  • macOS 11 or newer. Recognition uses the Apple Vision framework and needs a normal macOS graphics environment; it will not run inside a headless sandbox that lacks one.
  • Python 3.10 or newer.
  • The scope is per-page routing, on-device OCR, and a token estimate. Retrieval over very large documents is out of scope.

License

MIT. See LICENSE.

Metadata

Release files for localcontextrouter 0.1.0

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for localcontextrouter 0.1.0
File Size Uploaded
localcontextrouter-0.1.0.tar.gz 26.4 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for localcontextrouter 0.1.0
File Interpreter ABI Platform
localcontextrouter-0.1.0-py3-none-macosx_11_0_universal2.whl Python 3 none macOS 11.0+ universal2 (ARM64, x86-64) Details

Total release size: 139.3 kB

Release files / localcontextrouter-0.1.0.tar.gz

Download URL localcontextrouter-0.1.0.tar.gz
Size 26.4 kB
Tags Source
SHA-256 checksum
How to use checksums
1ef1e6d6fcedeab7c6b811d1c5fac3bc4462c28f7e3a9156e77904574d920541
BLAKE2b-256 checksum
How to use checksums
6f645291963fb63c02a11cf3c7587aebc2aadef05689bb019d84f1459fb30f83
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/6.1.0 CPython/3.13.12

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Jun 23, 2026.

Transparency log

Release files / localcontextrouter-0.1.0-py3-none-macosx_11_0_universal2.whl

Download URL localcontextrouter-0.1.0-py3-none-macosx_11_0_universal2.whl
Size 112.9 kB
Tags Python 3 macOS 11.0+ universal2 (ARM64, x86-64)
SHA-256 checksum
How to use checksums
c38fb5e92bb958135ef82edac46fa079c1e976887bd546c2b928698dda4a7848
BLAKE2b-256 checksum
How to use checksums
dd6a99f150f73db1b784c2b7d0c33746c6787d771028c03b8ac38d990238ee3a
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/6.1.0 CPython/3.13.12

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Jun 23, 2026.

Transparency log

Release history Release notifications | RSS feed

This release

0.1.0 This release

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page