> built 2026-10-14 02:29 UTC from 4de5796 (main) · ocracy 0.1.13. Details: build_info.json

# index.html.md

<!-- generated by epythet -->

# ocracy

One façade over many OCR engines — plus a **ledger** to help you choose between them.

OCR (“read the text in this image”) is solved a dozen ways: local engines
(Tesseract, EasyOCR, PaddleOCR), cloud APIs (Google Vision, AWS Textract, Azure),
and VLM readers — each with its own install, API, pricing, and language coverage.
`ocracy` gives you a uniform call, a browsable catalog of every option, and the
tools to wrap any of them.

```python
import ocracy

text = ocracy.read_text("scan.png")  # just the text, default backend
result = ocracy.ocr("scan.png")  # full result: text + word boxes + confidence
print(result)  # -> the recognized text
for word in result.words:
    print(word.text, word.bbox.as_tuple, word.confidence)
```

## Install

`import ocracy` is dependency-free. Install only the backends you use, via extras:

```bash
pip install "ocracy[tesseract]"     # local, free (also needs the system `tesseract` binary)
pip install "ocracy[easyocr]"       # local, pip-only
pip install "ocracy[google-vision]" # cloud API
pip install "ocracy[table]"         # pandas, for catalog.to_dataframe()
```

## Backends that ship today

The **Blocks** column is the one people get caught by: each backend reports exactly
one granularity, so `result.words` is empty on a line-level backend and
`result.lines` is empty on a word-level one — an empty list, not an error. See
*Granularity* just below.

| Backend                     | `backend=` id                 | Local / Remote   | Cost                 | Install                                    | Blocks      | Notable                                                                                          |
|-----------------------------|-------------------------------|------------------|----------------------|--------------------------------------------|-------------|--------------------------------------------------------------------------------------------------|
| Tesseract                   | `tesseract`                   | local            | free                 | `ocracy[tesseract]` (+ system `tesseract`) | **word**    | 100+ language baseline                                                                           |
| EasyOCR                     | `easyocr`                     | local            | free                 | `ocracy[easyocr]`                          | **line**    | 80+ languages, scene text                                                                        |
| RapidOCR                    | `rapidocr`                    | local            | free                 | `ocracy[rapidocr]`                         | **line**    | same PP-OCR models as Paddle, light CPU/ONNX — **recommended default for local plain text**      |
| PaddleOCR                   | `paddleocr`                   | local            | free                 | `ocracy[paddleocr]`                        | **line**    | the platform: server models, GPU, on-ramp to tables/layout (PP-Structure) & VL — heavier install |
| ocrmac (Apple Vision)       | `ocrmac`                      | local (macOS)    | free                 | `ocracy[ocrmac]`                           | **line**    | on-device, handwriting                                                                           |
| pix2tex (LaTeX-OCR)         | `pix2tex-latex-ocr`           | local            | free                 | `ocracy[pix2tex]`                          | *text only* | one printed equation → LaTeX, offline                                                            |
| TrOCR (handwritten)         | `trocr-handwritten`           | local            | free                 | `ocracy[trocr]`                            | *text only* | one pre-segmented handwritten line, MIT weights                                                  |
| OCR.space                   | `ocr-space`                   | remote           | free tier            | `ocracy[ocr-space]`                        | **word**    | zero-install REST                                                                                |
| Google Cloud Vision         | `google-vision`               | remote           | paid (+free tier)    | `ocracy[google-vision]`                    | **word**    | high accuracy, handwriting, structure                                                            |
| AWS Textract                | `aws-textract`                | remote           | paid (+free tier)    | `ocracy[aws-textract]`                     | **word**    | business docs, handwriting (forms/tables in analyze mode)                                        |
| Azure Document Intelligence | `azure-document-intelligence` | remote           | paid (+free tier)    | `ocracy[azure]`                            | **word**    | layout/tables/handwriting, on-prem container option                                              |
| Mistral OCR                 | `mistral-ocr`                 | remote           | paid (pay-as-you-go) | `ocracy[mistral]`                          | *text only* | cheap VLM → clean Markdown + math/tables                                                         |
| Mathpix                     | `mathpix`                     | remote           | paid (+free tier)    | `ocracy[mathpix]`                          | *text only* | math/handwriting → LaTeX & Markdown                                                              |
| Claude Vision               | `claude-vision`               | remote           | paid                 | `ocracy[anthropic]`                        | *text only* | prompt-driven “read + reason” over messy/mixed documents                                         |
| GPT-4o Vision               | `gpt-4o-vision`               | remote           | paid                 | `ocracy[openai]`                           | *text only* | same, via OpenAI; schema-constrained JSON output                                                 |

…plus **49 more** engines/services catalogued in the ledger that you can turn into
a working façade with one command (see *Add a backend* below).

### Granularity: which backends fill `.words`, which fill `.lines`

Every backend emits **exactly one** granularity level. Nothing promotes words into
lines or splits lines into words, and `result.words` / `result.lines` are just
filters over the one flat `blocks` list — so **asking for the level a backend does
not produce returns `[]`, silently**:

```python
r = ocracy.ocr("scan.png", backend="rapidocr")
r.lines  # populated
r.words  # [] — rapidocr reports lines, and nothing raises

r = ocracy.ocr("scan.png", backend="tesseract")
r.words  # populated
r.lines  # [] — tesseract reports words
```

- **word-level** (`.words` populated, `.lines` empty): `tesseract`, `google-vision`,
  `aws-textract`, `azure-document-intelligence`, `ocr-space`.
- **line-level** (`.lines` populated, `.words` empty): `easyocr`, `rapidocr`,
  `paddleocr`, `ocrmac`.
- **text only** (`blocks == []`, so *both* are empty and `mean_confidence` is `None`):
  `claude-vision`, `gpt-4o-vision`, `mathpix`, `mistral-ocr`, `pix2tex-latex-ocr`,
  `trocr-handwritten`. Use `result.text` / `result.markdown`.

Iterating a result (`for block in result:`) yields whatever units that engine gave
you, at its own level — it is not “lines by default”.

**The ledger’s `bounding_boxes` flag describes the engine, not ocracy’s adapter.**
`claude-vision`, `mathpix` and `mistral-ocr` are all `bounding_boxes: true` (their
APIs can return geometry) while ocracy’s façades for them return text only. Treat
`ocracy.find(bounding_boxes=True)` as “engines worth wrapping for geometry”, and
the list above as what you get today. If your code needs a level, assert it:

```python
result = ocracy.ocr(img, backend=chosen)
if not result.words:
    raise ValueError(f"{chosen} does not report word-level boxes")
```

### Getting a backend running

Some backends need more than `pip install` (Tesseract’s *system* binary, Paddle’s
framework, GPU wheels, first-run model weights, or an API key). ocracy turns that
into structured, OS-aware guidance — handy for humans and AI agents alike:

```python
ocracy.doctor()  # what's usable now vs what each missing one needs
ocracy.check("paddleocr")  # -> True/False (usable right now?)
print(
    ocracy.requirements("paddleocr").instructions()
)  # exact plan: pip + system deps + GPU + weights
ocracy.install(
    "rapidocr", yes=True
)  # run the pip install + verify (yes=False = dry run)
```

```bash
ocracy doctor · ocracy requirements paddleocr --gpu · ocracy install rapidocr --yes
```

`requirements()` even suggests a *lighter alternative* when one exists (e.g.
PaddleOCR → RapidOCR). The `ocracy-install-backend` skill drives all of this.

## Three tiers of access

From simplest to most powerful — reach for the next tier only when you need it:

```python
ocracy.ocr(img)  # 1. facade, default (installed) backend
ocracy.ocr(img, backend="easyocr", languages=["en", "fr"])
ocracy.services.tesseract.read(img, psm=6)  # 2. pick a backend explicitly
ocracy.services.tesseract.adapter  # 3. the raw engine adapter, full control
```

Every backend returns the same `OcrResult`, so your code doesn’t change when you
switch engines: `result.text`, `result.words` / `result.lines`, each block’s
`.bbox` and `.confidence` (normalized to 0..1), `result.mean_confidence`,
`result.markdown` (when a backend produces it), and `result.raw` (the untouched
engine output).

The *shape* is uniform; the *granularity* is not. Each engine fills either
`.words` or `.lines` (or neither), and the other is an empty list rather than an
error — see [Granularity]()
before writing code that depends on one.

## Command line

Install the CLI extra (`pip install "ocracy[cli]"`) for an `ocracy` command:

```bash
ocracy read scan.png                          # print recognized text
ocracy read scan.png --backend easyocr --languages en,fr
ocracy read scan.png --output json            # text + blocks (boxes, confidence)
ocracy backends                               # backends you can run now
ocracy backends --capability math
ocracy status                                 # readiness table: all / implemented / set-up / tested
ocracy status --level set_up --names          # one level + the "Name (website)" lists
ocracy status --run-tests                     # also OCR-test set-up backends (real calls for remotes)
ocracy find --local --free --handwriting      # browse/filter the ledger
ocracy info google-vision                     # a backend's full record
ocracy scaffold surya                          # start a new façade from the ledger
ocracy validate tesseract                      # smoke-test a backend
```

Everything is also reachable as `python -m ocracy <command>`. [`cw`](https://github.com/thorwhalen/cw)
builds the parser from the function signatures in `ocracy/tools.py`; `argcomplete` gives
tab completion when activated.

## The ledger — choose a backend with eyes open

`ocracy` ships a curated, data-driven catalog of **every** engine we researched —
not only the ones with a working façade — so you can compare on the axes that
matter (local vs remote, price, accuracy, languages, handwriting, math, tables,
privacy). The data lives in `ocracy/data/backends.json`, separate from code.

```python
ocracy.catalog  # <Catalog … backends … implemented …>
ocracy.catalog["google-vision"]  # one backend's full record
ocracy.find(is_local=True, open_source=True)  # filter the ledger
ocracy.find(handwriting="yes", is_remote=True)
ocracy.catalog.can("math")  # engines that read formulas
ocracy.catalog.supports_language("Arabic")
ocracy.find(implemented=True)  # only what ocracy can run today
ocracy.catalog.to_dataframe()  # browse as a pandas table
ocracy.catalog.compare(["tesseract", "google-vision", "mathpix"])
```

`implemented` is computed live from the code, so the ledger never lies about what
actually runs. See `ocracy/data/SCHEMA.md` for every field. The full cited research
report behind the ledger is in [`misc/docs/ocr_landscape_research.md`]().

## Getting API keys (remote backends)

Remote backends need a credential in an environment variable. ocracy tells you
exactly which one — **with a link to get it** — the moment it’s missing:

```python
>>> ocracy.ocr("receipt.png", backend="ocr-space")
MissingCredentialError: No credential found for ocr-space (set one of: OCR_SPACE_API_KEY).
How to get a credential for ocr-space: Register a free API key by email; free tier
allows 25,000 requests/month. Get a key: https://ocr.space/ocrapi/freekey
```

| Backend                       | Environment variable(s)                                                    | Where to get a key                                                                                                                                                                                                     |
|-------------------------------|----------------------------------------------------------------------------|------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| `ocr-space`                   | `OCR_SPACE_API_KEY`                                                        | [https://ocr.space/ocrapi/freekey](https://ocr.space/ocrapi/freekey) (free, 25k/month)                                                                                                                                 |
| `google-vision`               | `GOOGLE_APPLICATION_CREDENTIALS` (service-account JSON path)               | [https://cloud.google.com/vision/docs/setup](https://cloud.google.com/vision/docs/setup)                                                                                                                               |
| `aws-textract`                | `AWS_ACCESS_KEY_ID` + `AWS_SECRET_ACCESS_KEY` + `AWS_DEFAULT_REGION`       | [https://docs.aws.amazon.com/textract/latest/dg/getting-started.html](https://docs.aws.amazon.com/textract/latest/dg/getting-started.html)                                                                             |
| `azure-document-intelligence` | `AZURE_DOCUMENT_INTELLIGENCE_KEY` + `AZURE_DOCUMENT_INTELLIGENCE_ENDPOINT` | [https://learn.microsoft.com/azure/ai-services/document-intelligence/create-document-intelligence-resource](https://learn.microsoft.com/azure/ai-services/document-intelligence/create-document-intelligence-resource) |
| `mistral-ocr`                 | `MISTRAL_API_KEY`                                                          | [https://console.mistral.ai/api-keys](https://console.mistral.ai/api-keys)                                                                                                                                             |
| `mathpix`                     | `MATHPIX_APP_ID` + `MATHPIX_APP_KEY`                                       | [https://mathpix.com/ocr-api](https://mathpix.com/ocr-api)                                                                                                                                                             |

The same guidance (and links for AWS, Azure, Mistral, OpenAI, Anthropic, Gemini)
lives in `ocracy.credentials.CREDENTIAL_GUIDANCE`, and powers the dynamic errors.
Tip: drop the variables in a `.env` file — ocracy soft-loads it via `python-dotenv`
if that package is installed.

## Add a backend (wrap any engine in minutes)

The catalog is large; `ocracy` ships façades for a curated subset and gives you
the machinery to add any other one. Scaffold a backend straight from its ledger
entry, fill in the adapter, and validate it:

```python
from ocracy.make_backend import scaffold_backend, validate_adapter

scaffold_backend(
    "mathpix"
)  # creates ocracy/backends/mathpix/ prefilled from the ledger
# ... implement adapter.py's _read (call the engine, return an OcrResult) ...
validate_adapter("mathpix")  # smoke-test it end to end
```

The full, step-by-step process — including the adapter contract, input/output
normalization helpers, credential handling, and packaging — is captured as an
agent **skill** at `ocracy/data/skills/ocracy-add-backend/SKILL.md`. The
`ocracy/backends/tesseract/` package is a complete worked example.

## Agent skills (Claude Code & other AI agents)

ocracy ships four Anthropic-style **skills** (under `ocracy/data/skills/`,
installed with the package) so AI coding agents can both *use* and *extend* it:

| Skill                    | Audience       | What it helps with                                                          |
|--------------------------|----------------|-----------------------------------------------------------------------------|
| `ocracy`                 | users          | OCR an image/PDF, choose & install a backend, read the result               |
| `ocracy-choose-backend`  | users          | filter & compare the 64-backend ledger to pick the right engine             |
| `ocracy-install-backend` | users / agents | get a backend running — heavy installs, system deps, GPU, weights, keys     |
| `ocracy-add-backend`     | developers     | wrap a new engine behind ocracy’s interface (scaffold → adapter → validate) |

In a repo using Claude Code they’re discoverable via the `.claude/skills/`
symlink bridge; they also travel with `pip install ocracy` under
`ocracy/data/skills/`.

## How it works

- `ocracy/base.py` — the normalized types (`OcrResult`, `TextBlock`, `BBox`).
- `ocracy/catalog.py` — the ledger reader/filter (`ocracy/data/backends.json`).
- `ocracy/registry.py` — lazy backend discovery + default selection.
- `ocracy/services.py` — the three-tier service layer.
- `ocracy/make_backend.py` — the façade-building toolkit (`BaseOcrAdapter`,
  `make_block`, `scaffold_backend`, `validate_adapter`).
- `ocracy/backends/<id>/` — one subpackage per engine (`config.py` + `adapter.py`).
- `ocracy/credentials.py` — credential resolution for remote backends.
- `ocracy/kit/` — the facade kit: the param_map translator, the credential chain
  and install plans, stdlib-only and shared with other facades (see below).
- `ocracy/tools.py` + `ocracy/__main__.py` — the `ocracy` CLI (cw).

### The facade kit, for building other facades

The machinery under ocracy is not OCR-specific, and other facades (foley, falaw,
voxy, scribed) use it instead of copying it:

```python
from ocracy.kit import make_translator, resolve_credential, using_credentials

translate = make_translator(
    {"languages": {"native_name": "lang", "coerce": "+".join}, "dpi": None},
    backend="tess",
    on_unsupported="note",
    always_raise=("seed",),
)
t = translate({"languages": ["eng", "fra"], "dpi": 300})
# t.kwargs == {"lang": "eng+fra"}; t.notes == ["dpi=300 is not supported by tess; dropped"]

key = resolve_credential("acme", env_var="ACME_API_KEY")  # explicit -> bound -> env
with using_credentials(acme=request_key):  # per-request BYO key
    ...
```

`ocracy.kit` imports only the standard library; the design is in
`docs/adr/0001-facade-kit.md`.

The architecture mirrors the sibling façade packages
[`denote`](https://github.com/thorwhalen/denote) (audio→symbol) and
[`aix`](https://github.com/thorwhalen/aix) (LLM providers).

<p class="epythet-aggregates">This documentation as a single file: <a href="ocracy.md">ocracy.md</a> (Markdown, for agents).</p>


# _autosummary/ocracy.backends.aws_textract.adapter.html.md

# ocracy.backends.aws_textract.adapter

Adapter for AWS Textract — image -> text + word boxes via detect_document_text.

Textract reports geometry as fractions of the page (0..1), so this adapter scales
boxes to pixels using the decoded image size. LINE blocks build the reading-order
text; WORD blocks carry boxes + confidence (rescaled 0..100 -> 0..1).

### Classes

| [`Adapter`](_autosummary/ocracy.backends.aws_textract.adapter.html.md#ocracy.backends.aws_textract.adapter.Adapter)(config)   | AWS Textract adapter.   |
|--------------------------------------------------------------------|-------------------------|

### *class* ocracy.backends.aws_textract.adapter.Adapter(config)

Bases: [`BaseOcrAdapter`](_autosummary/ocracy.make_backend.html.md#ocracy.make_backend.BaseOcrAdapter)

AWS Textract adapter.


# _autosummary/ocracy.backends.aws_textract.config.html.md

# ocracy.backends.aws_textract.config

Configuration for the AWS Textract backend.

This façade wraps Textract’s `detect_document_text` (text + word boxes +
confidence; handwriting included). Forms/tables/queries (`analyze_document`) are
a richer, pricier mode left for a future extension. Credentials use the standard
AWS chain (env vars, `~/.aws/credentials`, or an IAM role); set a region via
`region` or `AWS_DEFAULT_REGION`.


# _autosummary/ocracy.backends.aws_textract.html.md

# ocracy.backends.aws_textract

AWS Textract backend for ocracy (cloud OCR + forms/tables).

### Modules

| [`adapter`](_autosummary/ocracy.backends.aws_textract.adapter.html.md#module-ocracy.backends.aws_textract.adapter)   | Adapter for AWS Textract — image -> text + word boxes via detect_document_text.   |
|--------------------------------------------------------------------------------------------------------|-----------------------------------------------------------------------------------|
| [`config`](_autosummary/ocracy.backends.aws_textract.config.html.md#module-ocracy.backends.aws_textract.config)     | Configuration for the AWS Textract backend.                                       |


# _autosummary/ocracy.backends.azure_document_intelligence.adapter.html.md

# ocracy.backends.azure_document_intelligence.adapter

Adapter for Azure AI Document Intelligence — image -> text + word polygons.

Uses the analyze-document API; `result.content` is the full text and each
page’s words carry a polygon and confidence. Requires a key and an endpoint.

### Classes

| [`Adapter`](_autosummary/ocracy.backends.azure_document_intelligence.adapter.html.md#ocracy.backends.azure_document_intelligence.adapter.Adapter)(config)   | Azure Document Intelligence adapter.   |
|--------------------------------------------------------------------|----------------------------------------|

### *class* ocracy.backends.azure_document_intelligence.adapter.Adapter(config)

Bases: [`BaseOcrAdapter`](_autosummary/ocracy.make_backend.html.md#ocracy.make_backend.BaseOcrAdapter)

Azure Document Intelligence adapter.


# _autosummary/ocracy.backends.azure_document_intelligence.config.html.md

# ocracy.backends.azure_document_intelligence.config

Configuration for the Azure AI Document Intelligence backend.

`model` selects the analysis model: `prebuilt-read` (default; text + words +
handwriting) or `prebuilt-layout` (adds reading order, tables, and structure).
Needs both a key (`AZURE_DOCUMENT_INTELLIGENCE_KEY`) and an endpoint
(`AZURE_DOCUMENT_INTELLIGENCE_ENDPOINT`, or pass `endpoint=`).


# _autosummary/ocracy.backends.azure_document_intelligence.html.md

# ocracy.backends.azure_document_intelligence

Azure AI Document Intelligence backend for ocracy (cloud read/layout).

### Modules

| [`adapter`](_autosummary/ocracy.backends.azure_document_intelligence.adapter.html.md#module-ocracy.backends.azure_document_intelligence.adapter)   | Adapter for Azure AI Document Intelligence — image -> text + word polygons.   |
|-----------------------------------------------------------------------------------------------------------------------|-------------------------------------------------------------------------------|
| [`config`](_autosummary/ocracy.backends.azure_document_intelligence.config.html.md#module-ocracy.backends.azure_document_intelligence.config)     | Configuration for the Azure AI Document Intelligence backend.                 |


# _autosummary/ocracy.backends.claude_vision.adapter.html.md

# ocracy.backends.claude_vision.adapter

Adapter for Claude vision — image -> transcribed text via the Anthropic SDK.

VLM OCR is text-oriented (no per-word boxes/confidence): the model’s transcription
becomes `result.text`. Pass a custom `prompt` to do structured extraction
instead of plain transcription. Uses the official `anthropic` SDK and the
base64 image content-block format.

### Classes

| [`Adapter`](_autosummary/ocracy.backends.claude_vision.adapter.html.md#ocracy.backends.claude_vision.adapter.Adapter)(config)   | Anthropic Claude vision adapter.   |
|--------------------------------------------------------------------|------------------------------------|

### *class* ocracy.backends.claude_vision.adapter.Adapter(config)

Bases: [`BaseOcrAdapter`](_autosummary/ocracy.make_backend.html.md#ocracy.make_backend.BaseOcrAdapter)

Anthropic Claude vision adapter.


# _autosummary/ocracy.backends.claude_vision.config.html.md

# ocracy.backends.claude_vision.config

Configuration for the Claude (Anthropic) vision backend.

A vision-language-model OCR: send the image to Claude and ask it to transcribe.
Excels at messy, handwritten, and structured content (it can also follow a custom
`prompt` to extract fields), but returns plain text/Markdown with no bounding
boxes or confidences. Needs `ANTHROPIC_API_KEY`.

`model` defaults to `claude-opus-4-8` (most capable); override with a cheaper
vision model such as `claude-haiku-4-5` for high-volume, cost-sensitive OCR.


# _autosummary/ocracy.backends.claude_vision.html.md

# ocracy.backends.claude_vision

Claude (Anthropic) vision backend for ocracy — VLM ‘read + reason’ OCR.

### Modules

| [`adapter`](_autosummary/ocracy.backends.claude_vision.adapter.html.md#module-ocracy.backends.claude_vision.adapter)   | Adapter for Claude vision — image -> transcribed text via the Anthropic SDK.   |
|---------------------------------------------------------------------------------------------------------|--------------------------------------------------------------------------------|
| [`config`](_autosummary/ocracy.backends.claude_vision.config.html.md#module-ocracy.backends.claude_vision.config)     | Configuration for the Claude (Anthropic) vision backend.                       |


# _autosummary/ocracy.backends.easyocr.adapter.html.md

# ocracy.backends.easyocr.adapter

Adapter for EasyOCR — image -> text + polygon boxes via easyocr.Reader.

### Classes

| [`Adapter`](_autosummary/ocracy.backends.easyocr.adapter.html.md#ocracy.backends.easyocr.adapter.Adapter)(config)   | EasyOCR adapter (caches one Reader per language-set + gpu flag).   |
|--------------------------------------------------------------------|--------------------------------------------------------------------|

### *class* ocracy.backends.easyocr.adapter.Adapter(config)

Bases: [`BaseOcrAdapter`](_autosummary/ocracy.make_backend.html.md#ocracy.make_backend.BaseOcrAdapter)

EasyOCR adapter (caches one Reader per language-set + gpu flag).


# _autosummary/ocracy.backends.easyocr.config.html.md

# ocracy.backends.easyocr.config

Configuration for the EasyOCR backend.

`languages` (a list of ISO-639-1 codes) is coerced to EasyOCR’s `lang_list`
(mostly the same codes; Chinese maps to `ch_sim` / `ch_tra`). `gpu` toggles
CUDA use. EasyOCR readers are expensive to build, so the adapter caches one per
(language-set, gpu) combination.


# _autosummary/ocracy.backends.easyocr.html.md

# ocracy.backends.easyocr

EasyOCR backend for ocracy.

### Modules

| [`adapter`](_autosummary/ocracy.backends.easyocr.adapter.html.md#module-ocracy.backends.easyocr.adapter)   | Adapter for EasyOCR — image -> text + polygon boxes via easyocr.Reader.   |
|---------------------------------------------------------------------------------------------------|---------------------------------------------------------------------------|
| [`config`](_autosummary/ocracy.backends.easyocr.config.html.md#module-ocracy.backends.easyocr.config)     | Configuration for the EasyOCR backend.                                    |


# _autosummary/ocracy.backends.google_vision.adapter.html.md

# ocracy.backends.google_vision.adapter

Adapter for Google Cloud Vision — image -> text + word boxes + confidence.

### Classes

| [`Adapter`](_autosummary/ocracy.backends.google_vision.adapter.html.md#ocracy.backends.google_vision.adapter.Adapter)(config)   | Google Cloud Vision adapter (caches the client).   |
|--------------------------------------------------------------------|----------------------------------------------------|

### *class* ocracy.backends.google_vision.adapter.Adapter(config)

Bases: [`BaseOcrAdapter`](_autosummary/ocracy.make_backend.html.md#ocracy.make_backend.BaseOcrAdapter)

Google Cloud Vision adapter (caches the client).


# _autosummary/ocracy.backends.google_vision.config.html.md

# ocracy.backends.google_vision.config

Configuration for the Google Cloud Vision backend.

`languages` (ISO-639-1) maps to Vision `language_hints`. `document=True`
(default) uses DOCUMENT_TEXT_DETECTION (dense text + handwriting + structure);
`document=False` uses TEXT_DETECTION (sparse/scene text). Auth is Google ADC —
set `GOOGLE_APPLICATION_CREDENTIALS` to a service-account JSON
([https://cloud.google.com/vision/docs/setup](https://cloud.google.com/vision/docs/setup)).


# _autosummary/ocracy.backends.google_vision.html.md

# ocracy.backends.google_vision

Google Cloud Vision API (TEXT_DETECTION & DOCUMENT_TEXT_DETECTION) backend for ocracy.

### Modules

| [`adapter`](_autosummary/ocracy.backends.google_vision.adapter.html.md#module-ocracy.backends.google_vision.adapter)   | Adapter for Google Cloud Vision — image -> text + word boxes + confidence.   |
|---------------------------------------------------------------------------------------------------------|------------------------------------------------------------------------------|
| [`config`](_autosummary/ocracy.backends.google_vision.config.html.md#module-ocracy.backends.google_vision.config)     | Configuration for the Google Cloud Vision backend.                           |


# _autosummary/ocracy.backends.gpt_4o_vision.adapter.html.md

# ocracy.backends.gpt_4o_vision.adapter

Adapter for OpenAI GPT-4o vision — image -> transcribed text via the openai SDK.

VLM OCR is text-oriented (no per-word boxes/confidence): the model’s transcription
becomes `result.text`. Pass a custom `prompt` for structured extraction. Uses
the official `openai` SDK’s chat-completions image-input format.

### Classes

| [`Adapter`](_autosummary/ocracy.backends.gpt_4o_vision.adapter.html.md#ocracy.backends.gpt_4o_vision.adapter.Adapter)(config)   | OpenAI GPT-4o vision adapter.   |
|--------------------------------------------------------------------|---------------------------------|

### *class* ocracy.backends.gpt_4o_vision.adapter.Adapter(config)

Bases: [`BaseOcrAdapter`](_autosummary/ocracy.make_backend.html.md#ocracy.make_backend.BaseOcrAdapter)

OpenAI GPT-4o vision adapter.


# _autosummary/ocracy.backends.gpt_4o_vision.config.html.md

# ocracy.backends.gpt_4o_vision.config

Configuration for the OpenAI GPT-4o vision backend.

A vision-language-model OCR via OpenAI’s chat completions with image input.
Like other VLM OCR: great at messy/handwritten/structured content and
prompt-driven extraction, but no bounding boxes or confidences. Needs
`OPENAI_API_KEY`. `model` defaults to `gpt-4o` (override e.g. `gpt-4o-mini`).


# _autosummary/ocracy.backends.gpt_4o_vision.html.md

# ocracy.backends.gpt_4o_vision

OpenAI GPT-4o vision backend for ocracy — VLM ‘read + reason’ OCR.

### Modules

| [`adapter`](_autosummary/ocracy.backends.gpt_4o_vision.adapter.html.md#module-ocracy.backends.gpt_4o_vision.adapter)   | Adapter for OpenAI GPT-4o vision — image -> transcribed text via the openai SDK.   |
|---------------------------------------------------------------------------------------------------------|------------------------------------------------------------------------------------|
| [`config`](_autosummary/ocracy.backends.gpt_4o_vision.config.html.md#module-ocracy.backends.gpt_4o_vision.config)     | Configuration for the OpenAI GPT-4o vision backend.                                |


# _autosummary/ocracy.backends.html.md

# ocracy.backends

Implemented OCR backends.

Each real backend is a subpackage with a `config.py` (`BACKEND_CONFIG`) and an
`adapter.py` (`Adapter` with a `read` method). The registry
([`ocracy.registry`](_autosummary/ocracy.registry.html.md#module-ocracy.registry)) discovers them automatically. Subpackages whose name
starts with `_` (e.g. `ocracy.backends._template`) are scaffolding
helpers, not real backends, and are skipped by discovery.

To add a backend, scaffold one from the template:

```default
from ocracy.make_backend import scaffold_backend
scaffold_backend("easyocr")   # creates ocracy/backends/easyocr/ from the template
```

### Modules

| [`aws_textract`](_autosummary/ocracy.backends.aws_textract.html.md#module-ocracy.backends.aws_textract)                               | AWS Textract backend for ocracy (cloud OCR + forms/tables).                            |
|---------------------------------------------------------------------------------------------------------------------------------|----------------------------------------------------------------------------------------|
| [`azure_document_intelligence`](_autosummary/ocracy.backends.azure_document_intelligence.html.md#module-ocracy.backends.azure_document_intelligence) | Azure AI Document Intelligence backend for ocracy (cloud read/layout).                 |
| [`claude_vision`](_autosummary/ocracy.backends.claude_vision.html.md#module-ocracy.backends.claude_vision)                             | Claude (Anthropic) vision backend for ocracy — VLM 'read + reason' OCR.                |
| [`easyocr`](_autosummary/ocracy.backends.easyocr.html.md#module-ocracy.backends.easyocr)                                         | EasyOCR backend for ocracy.                                                            |
| [`google_vision`](_autosummary/ocracy.backends.google_vision.html.md#module-ocracy.backends.google_vision)                             | Google Cloud Vision API (TEXT_DETECTION & DOCUMENT_TEXT_DETECTION) backend for ocracy. |
| [`gpt_4o_vision`](_autosummary/ocracy.backends.gpt_4o_vision.html.md#module-ocracy.backends.gpt_4o_vision)                             | OpenAI GPT-4o vision backend for ocracy — VLM 'read + reason' OCR.                     |
| [`mathpix`](_autosummary/ocracy.backends.mathpix.html.md#module-ocracy.backends.mathpix)                                         | Mathpix (Snip + Convert API) backend for ocracy.                                       |
| [`mistral_ocr`](_autosummary/ocracy.backends.mistral_ocr.html.md#module-ocracy.backends.mistral_ocr)                                 | Mistral OCR backend for ocracy (VLM document OCR via the Mistral API).                 |
| [`ocr_space`](_autosummary/ocracy.backends.ocr_space.html.md#module-ocracy.backends.ocr_space)                                     | OCR.space OCR API backend for ocracy.                                                  |
| [`ocrmac`](_autosummary/ocracy.backends.ocrmac.html.md#module-ocracy.backends.ocrmac)                                           | ocrmac (Apple Vision) backend for ocracy.                                              |
| [`paddleocr`](_autosummary/ocracy.backends.paddleocr.html.md#module-ocracy.backends.paddleocr)                                     | PaddleOCR backend for ocracy (PP-OCR text recognition).                                |
| [`pix2tex_latex_ocr`](_autosummary/ocracy.backends.pix2tex_latex_ocr.html.md#module-ocracy.backends.pix2tex_latex_ocr)                     | pix2tex (LaTeX-OCR) backend for ocracy — local math image -> LaTeX.                    |
| [`rapidocr`](_autosummary/ocracy.backends.rapidocr.html.md#module-ocracy.backends.rapidocr)                                       | RapidOCR backend for ocracy.                                                           |
| [`tesseract`](_autosummary/ocracy.backends.tesseract.html.md#module-ocracy.backends.tesseract)                                     | Tesseract backend for ocracy (via pytesseract).                                        |
| [`trocr_handwritten`](_autosummary/ocracy.backends.trocr_handwritten.html.md#module-ocracy.backends.trocr_handwritten)                     | TrOCR (handwritten) backend for ocracy — local handwriting recognition.                |


# _autosummary/ocracy.backends.mathpix.adapter.html.md

# ocracy.backends.mathpix.adapter

Adapter for Mathpix — image -> Mathpix-Markdown / LaTeX via the Convert API.

Mathpix is a text-oriented (not box-oriented) engine: the primary payload is a
Markdown/LaTeX string, surfaced as `result.text` and `result.markdown`; the
LaTeX form and confidence are kept in `result.meta` and the raw JSON in
`result.raw`.

### Classes

| [`Adapter`](_autosummary/ocracy.backends.mathpix.adapter.html.md#ocracy.backends.mathpix.adapter.Adapter)(config)   | Mathpix Convert API adapter.   |
|--------------------------------------------------------------------|--------------------------------|

### *class* ocracy.backends.mathpix.adapter.Adapter(config)

Bases: [`BaseOcrAdapter`](_autosummary/ocracy.make_backend.html.md#ocracy.make_backend.BaseOcrAdapter)

Mathpix Convert API adapter.


# _autosummary/ocracy.backends.mathpix.config.html.md

# ocracy.backends.mathpix.config

Configuration for the Mathpix backend (Convert API).

The standard for STEM OCR: printed/handwritten math, chemistry, and tables into
LaTeX / Mathpix-Markdown. `formats` selects output formats. Needs BOTH
`MATHPIX_APP_ID` and `MATHPIX_APP_KEY` ([https://mathpix.com/ocr-api](https://mathpix.com/ocr-api)).


# _autosummary/ocracy.backends.mathpix.html.md

# ocracy.backends.mathpix

Mathpix (Snip + Convert API) backend for ocracy.

### Modules

| [`adapter`](_autosummary/ocracy.backends.mathpix.adapter.html.md#module-ocracy.backends.mathpix.adapter)   | Adapter for Mathpix — image -> Mathpix-Markdown / LaTeX via the Convert API.   |
|---------------------------------------------------------------------------------------------------|--------------------------------------------------------------------------------|
| [`config`](_autosummary/ocracy.backends.mathpix.config.html.md#module-ocracy.backends.mathpix.config)     | Configuration for the Mathpix backend (Convert API).                           |


# _autosummary/ocracy.backends.mistral_ocr.adapter.html.md

# ocracy.backends.mistral_ocr.adapter

Adapter for Mistral OCR — image -> Markdown via the Mistral OCR API.

Mistral OCR is text/markdown-oriented (no per-word boxes or confidence): the
payload is per-page Markdown, joined into `result.text` and `result.markdown`,
with the raw SDK response in `result.raw`.

### Classes

| [`Adapter`](_autosummary/ocracy.backends.mistral_ocr.adapter.html.md#ocracy.backends.mistral_ocr.adapter.Adapter)(config)   | Mistral OCR API adapter.   |
|--------------------------------------------------------------------|----------------------------|

### *class* ocracy.backends.mistral_ocr.adapter.Adapter(config)

Bases: [`BaseOcrAdapter`](_autosummary/ocracy.make_backend.html.md#ocracy.make_backend.BaseOcrAdapter)

Mistral OCR API adapter.


# _autosummary/ocracy.backends.mistral_ocr.config.html.md

# ocracy.backends.mistral_ocr.config

Configuration for the Mistral OCR backend (cloud VLM document OCR).

A modern, cheap (~$1–2 / 1,000 pages) VLM OCR that returns clean Markdown with
structure, math, and tables. Text-oriented (no per-word boxes/confidence). Needs a
`MISTRAL_API_KEY` ([https://console.mistral.ai/api-keys](https://console.mistral.ai/api-keys)).


# _autosummary/ocracy.backends.mistral_ocr.html.md

# ocracy.backends.mistral_ocr

Mistral OCR backend for ocracy (VLM document OCR via the Mistral API).

### Modules

| [`adapter`](_autosummary/ocracy.backends.mistral_ocr.adapter.html.md#module-ocracy.backends.mistral_ocr.adapter)   | Adapter for Mistral OCR — image -> Markdown via the Mistral OCR API.   |
|-------------------------------------------------------------------------------------------------------|------------------------------------------------------------------------|
| [`config`](_autosummary/ocracy.backends.mistral_ocr.config.html.md#module-ocracy.backends.mistral_ocr.config)     | Configuration for the Mistral OCR backend (cloud VLM document OCR).    |


# _autosummary/ocracy.backends.ocr_space.adapter.html.md

# ocracy.backends.ocr_space.adapter

Adapter for OCR.space — image -> text + word boxes via its REST API.

### Classes

| [`Adapter`](_autosummary/ocracy.backends.ocr_space.adapter.html.md#ocracy.backends.ocr_space.adapter.Adapter)(config)   | OCR.space REST adapter.   |
|--------------------------------------------------------------------|---------------------------|

### *class* ocracy.backends.ocr_space.adapter.Adapter(config)

Bases: [`BaseOcrAdapter`](_autosummary/ocracy.make_backend.html.md#ocracy.make_backend.BaseOcrAdapter)

OCR.space REST adapter.


# _autosummary/ocracy.backends.ocr_space.config.html.md

# ocracy.backends.ocr_space.config

Configuration for the OCR.space backend (REST API).

A zero-install cloud OCR with a generous free tier. `languages` (ISO-639-1) is
coerced to OCR.space’s 3-letter codes (`en` -> `eng`). `ocr_engine` selects
engine 1/2/3 (2 is the multilingual default). Needs an `OCR_SPACE_API_KEY`
(free key at [https://ocr.space/ocrapi/freekey](https://ocr.space/ocrapi/freekey)).


# _autosummary/ocracy.backends.ocr_space.html.md

# ocracy.backends.ocr_space

OCR.space OCR API backend for ocracy.

### Modules

| [`adapter`](_autosummary/ocracy.backends.ocr_space.adapter.html.md#module-ocracy.backends.ocr_space.adapter)   | Adapter for OCR.space — image -> text + word boxes via its REST API.   |
|-----------------------------------------------------------------------------------------------------|------------------------------------------------------------------------|
| [`config`](_autosummary/ocracy.backends.ocr_space.config.html.md#module-ocracy.backends.ocr_space.config)     | Configuration for the OCR.space backend (REST API).                    |


# _autosummary/ocracy.backends.ocrmac.adapter.html.md

# ocracy.backends.ocrmac.adapter

Adapter for ocrmac — image -> text via the macOS Vision framework.

Vision reports bounding boxes as normalized `(x, y, w, h)` with a bottom-left
origin; this adapter converts them to ocracy’s pixel, top-left convention using
the image’s pixel size.

### Classes

| [`Adapter`](_autosummary/ocracy.backends.ocrmac.adapter.html.md#ocracy.backends.ocrmac.adapter.Adapter)(config)   | Apple Vision adapter (macOS only).   |
|--------------------------------------------------------------------|--------------------------------------|

### *class* ocracy.backends.ocrmac.adapter.Adapter(config)

Bases: [`BaseOcrAdapter`](_autosummary/ocracy.make_backend.html.md#ocracy.make_backend.BaseOcrAdapter)

Apple Vision adapter (macOS only).


# _autosummary/ocracy.backends.ocrmac.config.html.md

# ocracy.backends.ocrmac.config

Configuration for the ocrmac backend (Apple Vision, macOS-only).

Wraps the on-device macOS Vision OCR. `languages` (ISO-639-1) is coerced to
Vision’s BCP-47 preference codes (`en` -> `en-US`). `recognition_level`
trades speed for accuracy (`"fast"` / `"accurate"`). Handwriting works
automatically. macOS only.


# _autosummary/ocracy.backends.ocrmac.html.md

# ocracy.backends.ocrmac

ocrmac (Apple Vision) backend for ocracy.

### Modules

| [`adapter`](_autosummary/ocracy.backends.ocrmac.adapter.html.md#module-ocracy.backends.ocrmac.adapter)   | Adapter for ocrmac — image -> text via the macOS Vision framework.   |
|--------------------------------------------------------------------------------------------------|----------------------------------------------------------------------|
| [`config`](_autosummary/ocracy.backends.ocrmac.config.html.md#module-ocracy.backends.ocrmac.config)     | Configuration for the ocrmac backend (Apple Vision, macOS-only).     |


# _autosummary/ocracy.backends.paddleocr.adapter.html.md

# ocracy.backends.paddleocr.adapter

Adapter for PaddleOCR — image -> text + quad boxes via PP-OCR.

PaddleOCR’s constructor and `ocr()` signatures have shifted across major versions
(`use_angle_cls`/`cls` in 2.x vs `use_textline_orientation` in 3.x), so this
adapter probes a couple of signatures defensively and parses the classic
`[[ [box, (text, score)], ... ]]` result. Engines are cached per language.

### Classes

| [`Adapter`](_autosummary/ocracy.backends.paddleocr.adapter.html.md#ocracy.backends.paddleocr.adapter.Adapter)(config)   | PaddleOCR adapter (caches one engine per language).   |
|--------------------------------------------------------------------|-------------------------------------------------------|

### *class* ocracy.backends.paddleocr.adapter.Adapter(config)

Bases: [`BaseOcrAdapter`](_autosummary/ocracy.make_backend.html.md#ocracy.make_backend.BaseOcrAdapter)

PaddleOCR adapter (caches one engine per language).


# _autosummary/ocracy.backends.paddleocr.config.html.md

# ocracy.backends.paddleocr.config

Configuration for the PaddleOCR backend.

PaddleOCR’s PP-OCR models are among the most accurate open engines, especially for
CJK, across 100+ languages. `languages` (ISO-639-1) is coerced to PaddleOCR’s own
`lang` codes (`fr` -> `french`, `zh` -> `ch`, …). The adapter caches one
engine per language. (Table/layout extraction is PP-StructureV3 — a separate ledger
entry, `paddleocr-ppstructure`; this façade wraps the text OCR.)


# _autosummary/ocracy.backends.paddleocr.html.md

# ocracy.backends.paddleocr

PaddleOCR backend for ocracy (PP-OCR text recognition).

### Modules

| [`adapter`](_autosummary/ocracy.backends.paddleocr.adapter.html.md#module-ocracy.backends.paddleocr.adapter)   | Adapter for PaddleOCR — image -> text + quad boxes via PP-OCR.   |
|-----------------------------------------------------------------------------------------------------|------------------------------------------------------------------|
| [`config`](_autosummary/ocracy.backends.paddleocr.config.html.md#module-ocracy.backends.paddleocr.config)     | Configuration for the PaddleOCR backend.                         |


# _autosummary/ocracy.backends.pix2tex_latex_ocr.adapter.html.md

# ocracy.backends.pix2tex_latex_ocr.adapter

Adapter for pix2tex — image of an equation -> LaTeX, locally.

Math OCR is text-oriented: the LaTeX string is `result.text`, also surfaced as
`result.markdown` (`$$…$$`) and `result.meta['latex']`. The model is heavy to
construct, so it is built once and cached.

### Classes

| [`Adapter`](_autosummary/ocracy.backends.pix2tex_latex_ocr.adapter.html.md#ocracy.backends.pix2tex_latex_ocr.adapter.Adapter)(config)   | pix2tex (LaTeX-OCR) adapter (caches the model).   |
|--------------------------------------------------------------------|---------------------------------------------------|

### *class* ocracy.backends.pix2tex_latex_ocr.adapter.Adapter(config)

Bases: [`BaseOcrAdapter`](_autosummary/ocracy.make_backend.html.md#ocracy.make_backend.BaseOcrAdapter)

pix2tex (LaTeX-OCR) adapter (caches the model).


# _autosummary/ocracy.backends.pix2tex_latex_ocr.config.html.md

# ocracy.backends.pix2tex_latex_ocr.config

Configuration for the pix2tex (LaTeX-OCR) backend.

Local, offline math OCR: turns an image of a (typically single) printed equation
into LaTeX — the free, self-hosted counterpart to Mathpix. The LaTeX string is
returned as `result.text` and also wrapped as `result.markdown` (`$$…$$`).
Heavy (PyTorch); first run downloads model weights.


# _autosummary/ocracy.backends.pix2tex_latex_ocr.html.md

# ocracy.backends.pix2tex_latex_ocr

pix2tex (LaTeX-OCR) backend for ocracy — local math image -> LaTeX.

### Modules

| [`adapter`](_autosummary/ocracy.backends.pix2tex_latex_ocr.adapter.html.md#module-ocracy.backends.pix2tex_latex_ocr.adapter)   | Adapter for pix2tex — image of an equation -> LaTeX, locally.   |
|-------------------------------------------------------------------------------------------------------------|-----------------------------------------------------------------|
| [`config`](_autosummary/ocracy.backends.pix2tex_latex_ocr.config.html.md#module-ocracy.backends.pix2tex_latex_ocr.config)     | Configuration for the pix2tex (LaTeX-OCR) backend.              |


# _autosummary/ocracy.backends.rapidocr.adapter.html.md

# ocracy.backends.rapidocr.adapter

Adapter for RapidOCR — image -> text + quad boxes via ONNXRuntime PP-OCR.

### Classes

| [`Adapter`](_autosummary/ocracy.backends.rapidocr.adapter.html.md#ocracy.backends.rapidocr.adapter.Adapter)(config)   | RapidOCR adapter (lazily builds and caches one engine).   |
|--------------------------------------------------------------------|-----------------------------------------------------------|

### *class* ocracy.backends.rapidocr.adapter.Adapter(config)

Bases: [`BaseOcrAdapter`](_autosummary/ocracy.make_backend.html.md#ocracy.make_backend.BaseOcrAdapter)

RapidOCR adapter (lazily builds and caches one engine).


# _autosummary/ocracy.backends.rapidocr.config.html.md

# ocracy.backends.rapidocr.config

Configuration for the RapidOCR backend (ONNXRuntime).

RapidOCR runs the PP-OCR models via ONNXRuntime — PaddleOCR-grade accuracy with a
light, framework-free install and fast CPU inference. It bundles multilingual
models and selects scripts internally, so there is no per-call `languages`
parameter; callers can still tune detection/recognition via `**kwargs`.


# _autosummary/ocracy.backends.rapidocr.html.md

# ocracy.backends.rapidocr

RapidOCR backend for ocracy.

### Modules

| [`adapter`](_autosummary/ocracy.backends.rapidocr.adapter.html.md#module-ocracy.backends.rapidocr.adapter)   | Adapter for RapidOCR — image -> text + quad boxes via ONNXRuntime PP-OCR.   |
|----------------------------------------------------------------------------------------------------|-----------------------------------------------------------------------------|
| [`config`](_autosummary/ocracy.backends.rapidocr.config.html.md#module-ocracy.backends.rapidocr.config)     | Configuration for the RapidOCR backend (ONNXRuntime).                       |


# _autosummary/ocracy.backends.tesseract.adapter.html.md

# ocracy.backends.tesseract.adapter

Adapter for Tesseract — image -> text+word-boxes via pytesseract.

A worked example of the adapter contract:

1. Normalize the input to a PIL image (`ocracy.util.to_pil`).
2. Call the engine *inside* `_read` (lazy import of `pytesseract`).
3. Map Tesseract’s TSV-style word rows into normalized `TextBlock``s (boxes +
   confidence rescaled 0..100 -> 0..1) and assemble reading-order text, keeping
   the raw dict in ``raw=`.

### Classes

| [`Adapter`](_autosummary/ocracy.backends.tesseract.adapter.html.md#ocracy.backends.tesseract.adapter.Adapter)(config)   | Tesseract adapter.   |
|--------------------------------------------------------------------|----------------------|

### *class* ocracy.backends.tesseract.adapter.Adapter(config)

Bases: [`BaseOcrAdapter`](_autosummary/ocracy.make_backend.html.md#ocracy.make_backend.BaseOcrAdapter)

Tesseract adapter.


# _autosummary/ocracy.backends.tesseract.config.html.md

# ocracy.backends.tesseract.config

Configuration for the Tesseract backend.

Demonstrates the `param_map` pattern: ocracy’s normalized `languages` (a list
of ISO-639-1 codes like `["en", "fr"]`) is coerced to Tesseract’s native
`lang` string (`"eng+fra"`). `psm` / `oem` / `config` are passed through
and assembled into a Tesseract config string by the adapter.


# _autosummary/ocracy.backends.tesseract.html.md

# ocracy.backends.tesseract

Tesseract backend for ocracy (via pytesseract).

The canonical local, free, offline OCR engine. Requires the system `tesseract`
binary plus the `pytesseract` Python wrapper.

### Modules

| [`adapter`](_autosummary/ocracy.backends.tesseract.adapter.html.md#module-ocracy.backends.tesseract.adapter)   | Adapter for Tesseract — image -> text+word-boxes via pytesseract.   |
|-----------------------------------------------------------------------------------------------------|---------------------------------------------------------------------|
| [`config`](_autosummary/ocracy.backends.tesseract.config.html.md#module-ocracy.backends.tesseract.config)     | Configuration for the Tesseract backend.                            |


# _autosummary/ocracy.backends.trocr_handwritten.adapter.html.md

# ocracy.backends.trocr_handwritten.adapter

Adapter for TrOCR (handwritten) — image of a text line -> text, locally.

Loads a HuggingFace `VisionEncoderDecoderModel` + `TrOCRProcessor` (cached per
checkpoint) and decodes one line of (hand)written text. TrOCR is line-level: the
recognized line is `result.text`.

### Classes

| [`Adapter`](_autosummary/ocracy.backends.trocr_handwritten.adapter.html.md#ocracy.backends.trocr_handwritten.adapter.Adapter)(config)   | TrOCR adapter (caches the processor + model per checkpoint).   |
|--------------------------------------------------------------------|----------------------------------------------------------------|

### *class* ocracy.backends.trocr_handwritten.adapter.Adapter(config)

Bases: [`BaseOcrAdapter`](_autosummary/ocracy.make_backend.html.md#ocracy.make_backend.BaseOcrAdapter)

TrOCR adapter (caches the processor + model per checkpoint).


# _autosummary/ocracy.backends.trocr_handwritten.config.html.md

# ocracy.backends.trocr_handwritten.config

Configuration for the TrOCR (handwritten) backend.

Local, offline handwriting recognition via HuggingFace TrOCR transformer models.

#### NOTE
TrOCR recognizes a single text line per image — for full pages, segment into
line crops upstream and call once per line. Heavy (PyTorch + transformers); first
run downloads the model. `model_name` selects the checkpoint.


# _autosummary/ocracy.backends.trocr_handwritten.html.md

# ocracy.backends.trocr_handwritten

TrOCR (handwritten) backend for ocracy — local handwriting recognition.

### Modules

| [`adapter`](_autosummary/ocracy.backends.trocr_handwritten.adapter.html.md#module-ocracy.backends.trocr_handwritten.adapter)   | Adapter for TrOCR (handwritten) — image of a text line -> text, locally.   |
|-------------------------------------------------------------------------------------------------------------|----------------------------------------------------------------------------|
| [`config`](_autosummary/ocracy.backends.trocr_handwritten.config.html.md#module-ocracy.backends.trocr_handwritten.config)     | Configuration for the TrOCR (handwritten) backend.                         |


# _autosummary/ocracy.base.html.md

# ocracy.base

Core types and normalized result objects for ocracy.

OCR engines disagree wildly on what they return: Tesseract emits TSV rows of
words with pixel boxes and confidences; cloud APIs return nested JSON of
pages/blocks/paragraphs/words; VLM-based engines often return just a Markdown
string. ocracy normalizes all of that into a small, stable set of dataclasses so
that callers get the *same shape* regardless of which backend produced the text:

- [`OcrResult`](_autosummary/ocracy.base.html.md#ocracy.base.OcrResult) — the full result of reading an image: a concatenated
  `text` (in reading order) plus a list of structured `blocks` carrying
  bounding boxes and confidences, plus the untouched `raw` backend output for
  power users who need engine-specific detail.
- [`TextBlock`](_autosummary/ocracy.base.html.md#ocracy.base.TextBlock) — one recognized unit of text (word/line/paragraph/block)
  with an optional [`BBox`](_autosummary/ocracy.base.html.md#ocracy.base.BBox) and `confidence`.
- [`BBox`](_autosummary/ocracy.base.html.md#ocracy.base.BBox) — an axis-aligned bounding box, with an optional `polygon` for
  rotated or quadrilateral regions (common in scene-text engines).

The input side is normalized too: every facade function accepts an
`ImageInput` — a path, URL, `bytes`, PIL image, or numpy array. Concrete
decoding happens lazily in [`ocracy.util`](_autosummary/ocracy.util.html.md#module-ocracy.util), so importing ocracy never
requires Pillow or numpy.

The design goal is *progressive disclosure*: `str(result)` gives you the text,
`result.text` is the same string, iterating the result yields its lines, and
`result.blocks` / `result.raw` are there when you need structure.

### Classes

| [`BBox`](_autosummary/ocracy.base.html.md#ocracy.base.BBox)(x0, y0, x1, y1[, polygon])                 | An axis-aligned bounding box in pixel coordinates (origin = top-left).   |
|--------------------------------------------------------------------------------------------------|--------------------------------------------------------------------------|
| [`OcrResult`](_autosummary/ocracy.base.html.md#ocracy.base.OcrResult)(text[, blocks, backend, raw, meta])   | The normalized result of reading an image with any backend.              |
| [`TextBlock`](_autosummary/ocracy.base.html.md#ocracy.base.TextBlock)(text[, bbox, confidence, level, ...]) | One recognized unit of text.                                             |

### *class* ocracy.base.BBox(x0, y0, x1, y1, polygon=None)

Bases: [`object`](https://docs.python.org/3/builtins/functions.html#object)

An axis-aligned bounding box in pixel coordinates (origin = top-left).

`polygon` optionally carries the original (possibly rotated) vertices as a
sequence of `(x, y)` points; the axis-aligned `x0/y0/x1/y1` are always
populated (derived from the polygon if a backend only gives one).

#### *property* as_tuple *: [Tuple](https://docs.python.org/3/library/typing.html#typing.Tuple)[[float](https://docs.python.org/3/builtins/functions.html#float), [float](https://docs.python.org/3/builtins/functions.html#float), [float](https://docs.python.org/3/builtins/functions.html#float), [float](https://docs.python.org/3/builtins/functions.html#float)]*

`(x0, y0, x1, y1)` — the convention PIL’s `crop` expects.

#### *classmethod* from_polygon(points)

Build a box from polygon vertices `[(x, y), ...]`.

The axis-aligned extent is computed from the vertices and the original
polygon is preserved for callers that care about rotation.

* **Return type:**
  [`BBox`](_autosummary/ocracy.base.html.md#ocracy.base.BBox)

#### *property* xywh *: [Tuple](https://docs.python.org/3/library/typing.html#typing.Tuple)[[float](https://docs.python.org/3/builtins/functions.html#float), [float](https://docs.python.org/3/builtins/functions.html#float), [float](https://docs.python.org/3/builtins/functions.html#float), [float](https://docs.python.org/3/builtins/functions.html#float)]*

`(x, y, width, height)` — the convention many drawing libs expect.

### *class* ocracy.base.OcrResult(text, blocks=<factory>, backend='', raw=None, meta=<factory>)

Bases: [`object`](https://docs.python.org/3/builtins/functions.html#object)

The normalized result of reading an image with any backend.

`text` is the headline payload: the full recognized text in reading order.
`blocks` carries the structured units (with boxes/confidences) when the
backend provides them. `raw` is the untouched backend output. `meta`
holds cross-cutting extras (languages, page count, a Markdown rendering,
timing, …).

Progressive disclosure:

```default
result = ocracy.ocr("scan.png")
print(result)              # -> the text
result.text                # -> the same string
for line in result:        # -> iterate TextBlocks (lines by default)
    print(line.text, line.confidence)
result.words               # -> only word-level blocks
result.mean_confidence     # -> average confidence, if available
result.raw                 # -> engine-specific structure
```

#### at_level(level)

Blocks at a given granularity (`"word"`, `"line"`, …).

* **Return type:**
  [`List`](https://docs.python.org/3/library/typing.html#typing.List)[[`TextBlock`](_autosummary/ocracy.base.html.md#ocracy.base.TextBlock)]

#### filter_confidence(min_confidence)

Return a copy keeping only blocks at or above `min_confidence`.

Blocks without a confidence are dropped. `text` is rebuilt from the
surviving blocks (joined by newline).

* **Return type:**
  [`OcrResult`](_autosummary/ocracy.base.html.md#ocracy.base.OcrResult)

#### *classmethod* from_blocks(blocks, , backend='', raw=None, text=None, joiner='\\\\n', \*\*meta)

Build a result from structured blocks.

If `text` is not given it is synthesized by joining the blocks’ text in
their given order with `joiner` (callers should pass blocks already in
reading order, or pre-join and pass `text` explicitly).

* **Return type:**
  [`OcrResult`](_autosummary/ocracy.base.html.md#ocracy.base.OcrResult)

#### *classmethod* from_text(text, , backend='', raw=None, \*\*meta)

Build a minimal result from just a text string (no geometry).

* **Return type:**
  [`OcrResult`](_autosummary/ocracy.base.html.md#ocracy.base.OcrResult)

#### *property* markdown *: [str](https://docs.python.org/3/builtins/stdtypes.html#str) | [None](https://docs.python.org/3/builtins/constants.html#None)*

Markdown rendering if the backend produced one (else `None`).

#### *property* mean_confidence *: [float](https://docs.python.org/3/builtins/functions.html#float) | [None](https://docs.python.org/3/builtins/constants.html#None)*

Mean confidence over blocks that report one, or `None`.

### *class* ocracy.base.TextBlock(text, bbox=None, confidence=None, level='line', language=None, meta=<factory>)

Bases: [`object`](https://docs.python.org/3/builtins/functions.html#object)

One recognized unit of text.

#### text

The recognized string for this unit.

#### bbox

Where it was found (pixel coordinates), if the backend reports it.

#### confidence

Recognition confidence in `[0, 1]` (normalized by ocracy
from whatever scale the backend used), if available.

#### level

Granularity — one of `ocracy.base.LEVELS` (“word”, “line”, …).

#### language

Detected/declared language code for this unit, if any.

#### meta

Backend-specific extras (font size, style, page index, …).


# _autosummary/ocracy.catalog.html.md

# ocracy.catalog

### ocracy.catalog *= <Catalog 64 backends | 15 implemented | 40 local, 38 remote>*

A filterable, dict-like collection of [`BackendInfo`](_autosummary/ocracy.html.md#ocracy.BackendInfo), keyed by id.

Loaded lazily from `DEFAULT_LEDGER_PATH` (override via the `path`
argument or the `OCRACY_LEDGER` environment variable). `filter()`
returns a *new* `Catalog` over the matching subset, so filters compose:

```default
catalog.filter(is_remote=True).filter(pricing_model="free_tier_then_paid")
```


# _autosummary/ocracy.credentials.html.md

# ocracy.credentials

Credential resolution for remote OCR backends.

Remote engines need an API key (or a path to a service-account JSON). This module
holds ocracy’s *data* – which env vars each OCR provider uses and where to get a
key – and binds it to the facade kit’s chain ([`ocracy.kit.credentials`](_autosummary/ocracy.kit.credentials.html.md#module-ocracy.kit.credentials)):

1. an explicit value passed by the caller (`api_key=...`),
2. a key bound for the provider with [`using_credentials()`](_autosummary/ocracy.credentials.html.md#ocracy.credentials.using_credentials) (bring-your-own-key),
3. the backend’s declared environment variable(s), then the provider’s defaults,
4. (soft) a project `.env` found from the current directory, if `python-dotenv`
   is installed,
5. (optional) an interactive prompt, only in a terminal and only if asked.

A backend declares its variable(s) in `BACKEND_CONFIG['api_env_var']` (a string
or list).

### Module Attributes

| [`PROVIDER_ENV_VARS`](_autosummary/ocracy.credentials.html.md#ocracy.credentials.PROVIDER_ENV_VARS)   | Friendly provider -> canonical env-var name(s) for well-known services.                               |
|----------------------------------------------------------------------|-------------------------------------------------------------------------------------------------------|
| [`CREDENTIAL_GUIDANCE`](_autosummary/ocracy.credentials.html.md#ocracy.credentials.CREDENTIAL_GUIDANCE) | Where/how to get a key, per provider — powers the dynamic "missing credential" errors AND the README. |

### Functions

| [`resolve_credential`](_autosummary/ocracy.credentials.html.md#ocracy.credentials.resolve_credential)([provider, api_key, ...])   | Resolve a credential for a remote backend.                                                                                |
|-------------------------------------------------------------------------------------------------|---------------------------------------------------------------------------------------------------------------------------|
| [`credential_help`](_autosummary/ocracy.credentials.html.md#ocracy.credentials.credential_help)(provider)                      | A short, link-bearing 'how to get a key' message for `provider` (or '').                                                  |
| [`using_credentials`](_autosummary/ocracy.credentials.html.md#ocracy.credentials.using_credentials)([keys])                      | Bind provider keys for the `with` block (overlaying any outer binding).                                                   |
| [`current_credentials`](_autosummary/ocracy.credentials.html.md#ocracy.credentials.current_credentials)()                          | The provider keys bound in this context by [`using_credentials()`](_autosummary/ocracy.credentials.html.md#ocracy.credentials.using_credentials) (a copy). |

### Exceptions

| [`MissingCredentialError`](_autosummary/ocracy.credentials.html.md#ocracy.credentials.MissingCredentialError)([message, provider, ...])   | A required credential could not be resolved; the message says how to get one.   |
|-----------------------------------------------------------------------------------------------------|---------------------------------------------------------------------------------|

### ocracy.credentials.CREDENTIAL_GUIDANCE *= {'anthropic': {'env_var': 'ANTHROPIC_API_KEY', 'get_key_url': 'https://console.anthropic.com/settings/keys', 'note': 'Create an API key in the Anthropic console.'}, 'aws-textract': {'env_var': 'AWS_ACCESS_KEY_ID (plus AWS_SECRET_ACCESS_KEY, AWS_DEFAULT_REGION)', 'get_key_url': 'https://docs.aws.amazon.com/textract/latest/dg/getting-started.html', 'note': 'Create AWS credentials (IAM user/role) with Textract permissions.'}, 'azure-document-intelligence': {'env_var': 'AZURE_DOCUMENT_INTELLIGENCE_KEY (plus AZURE_DOCUMENT_INTELLIGENCE_ENDPOINT)', 'get_key_url': 'https://learn.microsoft.com/azure/ai-services/document-intelligence/create-document-intelligence-resource', 'note': 'Create a Document Intelligence resource in the Azure portal; copy its key and endpoint.'}, 'gemini': {'env_var': 'GOOGLE_API_KEY (or GEMINI_API_KEY)', 'get_key_url': 'https://aistudio.google.com/app/apikey', 'note': 'Create an API key in Google AI Studio.'}, 'google-vision': {'env_var': 'GOOGLE_APPLICATION_CREDENTIALS', 'get_key_url': 'https://cloud.google.com/vision/docs/setup', 'note': 'Create a Google Cloud project, enable the Cloud Vision API, create a service account, download its JSON key, and point GOOGLE_APPLICATION_CREDENTIALS at that file. Free tier: 1,000 units/month.'}, 'mathpix': {'env_var': 'MATHPIX_APP_KEY (plus MATHPIX_APP_ID)', 'get_key_url': 'https://mathpix.com/ocr-api', 'note': 'Create a Mathpix account, then copy your app_id and app_key from the Mathpix console; set MATHPIX_APP_ID and MATHPIX_APP_KEY.'}, 'mistral-ocr': {'env_var': 'MISTRAL_API_KEY', 'get_key_url': 'https://console.mistral.ai/api-keys', 'note': 'Create an API key in the Mistral console (La Plateforme).'}, 'ocr-space': {'env_var': 'OCR_SPACE_API_KEY', 'get_key_url': 'https://ocr.space/ocrapi/freekey', 'note': 'Register a free API key by email; free tier allows 25,000 requests/month.'}, 'openai': {'env_var': 'OPENAI_API_KEY', 'get_key_url': 'https://platform.openai.com/api-keys', 'note': 'Create an API key in the OpenAI platform dashboard.'}}*

Where/how to get a key, per provider — powers the dynamic “missing credential”
errors AND the README. Keep links current; these are user-facing.

### *exception* ocracy.credentials.MissingCredentialError(message='', , provider=None, env_vars=(), get_key_url=None)

Bases: [`RuntimeError`](https://docs.python.org/3/builtins/exceptions.html#RuntimeError)

A required credential could not be resolved; the message says how to get one.

#### provider

The provider id asked for (or `None`).

#### env_vars

The env vars that were checked, in order.

#### get_key_url

Where to get a key, when the guidance table knows.

### ocracy.credentials.PROVIDER_ENV_VARS *= {'anthropic': ['ANTHROPIC_API_KEY'], 'aws-textract': ['AWS_ACCESS_KEY_ID'], 'azure-document-intelligence': ['AZURE_DOCUMENT_INTELLIGENCE_KEY'], 'azure-vision': ['AZURE_VISION_KEY', 'AZURE_COMPUTER_VISION_KEY'], 'gemini': ['GOOGLE_API_KEY', 'GEMINI_API_KEY'], 'google-document-ai': ['GOOGLE_APPLICATION_CREDENTIALS'], 'google-vision': ['GOOGLE_APPLICATION_CREDENTIALS', 'GOOGLE_API_KEY'], 'mathpix': ['MATHPIX_APP_KEY'], 'mistral-ocr': ['MISTRAL_API_KEY'], 'ocr-space': ['OCR_SPACE_API_KEY'], 'openai': ['OPENAI_API_KEY']}*

Friendly provider -> canonical env-var name(s) for well-known services.

### ocracy.credentials.credential_help(provider)

A short, link-bearing ‘how to get a key’ message for `provider` (or ‘’).

* **Return type:**
  [`str`](https://docs.python.org/3/builtins/stdtypes.html#str)

### ocracy.credentials.current_credentials()

The provider keys bound in this context by [`using_credentials()`](_autosummary/ocracy.credentials.html.md#ocracy.credentials.using_credentials) (a copy).

* **Return type:**
  [`dict`](https://docs.python.org/3/builtins/stdtypes.html#dict)

### ocracy.credentials.resolve_credential(provider=None, , api_key=None, env_var=None, required=True, prompt_if_missing=False)

Resolve a credential for a remote backend.

* **Parameters:**
  * **provider** ([`Optional`](https://docs.python.org/3/library/typing.html#typing.Optional)[[`str`](https://docs.python.org/3/builtins/stdtypes.html#str)]) – A known provider id (see [`PROVIDER_ENV_VARS`](_autosummary/ocracy.credentials.html.md#ocracy.credentials.PROVIDER_ENV_VARS)) used to
    infer default env-var names, and the key for [`using_credentials()`](_autosummary/ocracy.credentials.html.md#ocracy.credentials.using_credentials).
  * **api_key** ([`Optional`](https://docs.python.org/3/library/typing.html#typing.Optional)[[`str`](https://docs.python.org/3/builtins/stdtypes.html#str)]) – An explicit value; if given, it wins and is returned as-is.
  * **env_var** (`Union`[[`str`](https://docs.python.org/3/builtins/stdtypes.html#str), [`Sequence`](https://docs.python.org/3/library/typing.html#typing.Sequence)[[`str`](https://docs.python.org/3/builtins/stdtypes.html#str)], [`None`](https://docs.python.org/3/builtins/constants.html#None)]) – Extra env-var name(s) to check (checked before provider defaults).
  * **required** ([`bool`](https://docs.python.org/3/builtins/functions.html#bool)) – If True (default), raise [`MissingCredentialError`](_autosummary/ocracy.credentials.html.md#ocracy.credentials.MissingCredentialError) when
    nothing resolves; if False, return `None`.
  * **prompt_if_missing** ([`bool`](https://docs.python.org/3/builtins/functions.html#bool)) – If True and running interactively, prompt the user
    (via `getpass`) as a last resort.
* **Return type:**
  [`Optional`](https://docs.python.org/3/library/typing.html#typing.Optional)[[`str`](https://docs.python.org/3/builtins/stdtypes.html#str)]
* **Returns:**
  The resolved secret, or `None` when `required=False` and nothing was
  found.

### ocracy.credentials.using_credentials(keys=None, , \*\*provider_keys)

Bind provider keys for the `with` block (overlaying any outer binding).

Pass a mapping for provider ids that are not identifiers (`"google-vision"`)
or keywords for the rest. Falsy values are ignored, so an optional request
header can be passed straight through.

* **Return type:**
  [`Iterator`](https://docs.python.org/3/library/typing.html#typing.Iterator)[[`dict`](https://docs.python.org/3/builtins/stdtypes.html#dict)]

```pycon
>>> with using_credentials(acme="outer"):
...     with using_credentials({"acme": "inner", "other": None}):
...         inner = current_credentials()
...     outer = current_credentials()
>>> inner, outer
({'acme': 'inner'}, {'acme': 'outer'})
```


# _autosummary/ocracy.html.md

# ocracy

ocracy — one facade over many OCR engines, plus a ledger to choose between them.

OCR (“read the text in this image”) is solved a dozen different ways: local
engines (Tesseract, EasyOCR, PaddleOCR), cloud APIs (Google Vision, AWS
Textract, Azure), and VLM-based readers — each with its own install, API,
pricing, language coverage, and quirks. ocracy gives you:

1. **A uniform facade.** Call [`ocr()`](_autosummary/ocracy.html.md#ocracy.ocr) and get the same [`OcrResult`](_autosummary/ocracy.base.html.md#ocracy.base.OcrResult)
   back no matter which backend ran:
   ```default
   import ocracy
   result = ocracy.ocr("scan.png")          # default (first installed) backend
   print(result)                            # -> the recognized text
   result = ocracy.ocr("scan.png", backend="easyocr", languages=["en", "fr"])
   ```

   Convenience: [`read_text()`](_autosummary/ocracy.html.md#ocracy.read_text) returns just the string.
2. **A ledger / gallery** of *every* engine we researched — not only the ones
   with a working facade — so you can choose with eyes open:
   ```default
   ocracy.catalog                                   # the whole ledger
   ocracy.find(is_local=True, open_source=True)     # filter it
   ocracy.find(handwriting="yes", is_remote=True)
   ocracy.catalog.to_dataframe()                    # browse as a table
   ```

   The ledger lives in data (`ocracy/data/backends.json`), not code.
3. **Tools to build new facades.** The catalog is large; ocracy ships a facade
   for a curated subset and gives you the machinery (and a SKILL) to add any
   other one in minutes:
   ```default
   from ocracy.make_backend import scaffold_backend, validate_adapter
   scaffold_backend("mathpix")    # generate a backend package from the ledger
   validate_adapter("tesseract")  # smoke-test an adapter end to end
   ```

Three tiers of access, from simplest to most powerful:

```default
ocracy.ocr(img)                                # facade, default backend
ocracy.services.tesseract.read(img, lang="fra")  # pick a backend
ocracy.services.tesseract.adapter              # raw engine adapter
```

### Functions

| [`ocr`](_autosummary/ocracy.html.md#ocracy.ocr)(image, \*[, backend])                        | Read text from an image with any backend, returning a normalized result.                                  |
|---------------------------------------------------------------------------------------------------|-----------------------------------------------------------------------------------------------------------|
| [`read_text`](_autosummary/ocracy.html.md#ocracy.read_text)(image, \*[, backend])                  | Like [`ocr()`](_autosummary/ocracy.html.md#ocracy.ocr) but returns just the recognized text string.  |
| [`find`](_autosummary/ocracy.html.md#ocracy.find)(\*\*criteria)                               | Filter the ledger; shorthand for `ocracy.catalog.Catalog.filter()`.                                       |
| [`list_backends`](_autosummary/ocracy.html.md#ocracy.list_backends)([capability])                      | Sorted ids of implemented backends, optionally filtered by capability.                                    |
| [`register_backend`](_autosummary/ocracy.html.md#ocracy.register_backend)(backend_id, config[, adapter])  | Register a backend at runtime (for third-party plugins).                                                  |
| [`get_default_backend`](_autosummary/ocracy.html.md#ocracy.get_default_backend)([capability, ...])           | Pick a sensible default backend id for a capability.                                                      |
| [`get_config`](_autosummary/ocracy.html.md#ocracy.get_config)(backend_id)                           | A backend's `BACKEND_CONFIG` without loading its adapter.                                                 |
| [`make_block`](_autosummary/ocracy.html.md#ocracy.make_block)(text, \*[, bbox, confidence, ...])    | Build a normalized [`TextBlock`](_autosummary/ocracy.base.html.md#ocracy.base.TextBlock).      |
| [`scaffold_backend`](_autosummary/ocracy.html.md#ocracy.scaffold_backend)(backend_id, \*[, dest, ...])    | Create a new `ocracy/backends/<id>/` package from the template.                                           |
| [`validate_adapter`](_autosummary/ocracy.html.md#ocracy.validate_adapter)(backend_id, \*[, image, ...])   | Smoke-test a backend adapter end to end, returning a report dict.                                         |
| [`requirements`](_autosummary/ocracy.html.md#ocracy.requirements)(backend_id, \*[, gpu])              | Return structured install [`Requirements`](_autosummary/ocracy.html.md#ocracy.Requirements) for `backend_id`. |
| [`check`](_autosummary/ocracy.html.md#ocracy.check)(backend_id)                                | Is `backend_id` importable / usable right now? (no install, no network).                                  |
| [`doctor`](_autosummary/ocracy.html.md#ocracy.doctor)()                                         | Report which implemented backends are usable now and what the rest need.                                  |
| [`install`](_autosummary/ocracy.html.md#ocracy.install)(backend_id, \*[, yes, gpu, verify, ...]) | Plan (and optionally run) the pip install for a backend.                                                  |
| [`available_backends`](_autosummary/ocracy.html.md#ocracy.available_backends)()                             | Implemented backends whose dependency is importable right now.                                            |
| [`backend_ids`](_autosummary/ocracy.html.md#ocracy.backend_ids)([level, info, test_image])           | Sorted backend ids at a readiness `level` (one of `LEVELS`).                                              |
| [`backend_info`](_autosummary/ocracy.html.md#ocracy.backend_info)([ids, run_tests, test_image])       | Per-backend status: every ledger field plus `implemented`/`set_up`/`tested`.                              |
| [`status_table`](_autosummary/ocracy.html.md#ocracy.status_table)([ids, info, columns, ...])          | Render an aligned Markdown table of backend status (also plain-text readable).                            |
| [`names_with_sites`](_autosummary/ocracy.html.md#ocracy.names_with_sites)(ids, \*[, info])                | `"Name (website), Name2 (website2), ..."` for `ids` (name, not id).                                       |
| [`is_set_up`](_autosummary/ocracy.html.md#ocracy.is_set_up)(backend_id)                            | Ready to run here & now.                                                                                  |
| [`is_tested`](_autosummary/ocracy.html.md#ocracy.is_tested)(backend_id, \*[, image])               | Actually run OCR on `image` (a generated one if None); True iff it worked.                                |

### Classes

| [`OcrResult`](_autosummary/ocracy.html.md#ocracy.OcrResult)(text[, blocks, backend, raw, meta])     | The normalized result of reading an image with any backend.                                                      |
|----------------------------------------------------------------------------------------------------|------------------------------------------------------------------------------------------------------------------|
| [`TextBlock`](_autosummary/ocracy.html.md#ocracy.TextBlock)(text[, bbox, confidence, level, ...])   | One recognized unit of text.                                                                                     |
| [`BBox`](_autosummary/ocracy.html.md#ocracy.BBox)(x0, y0, x1, y1[, polygon])                   | An axis-aligned bounding box in pixel coordinates (origin = top-left).                                           |
| [`BackendInfo`](_autosummary/ocracy.html.md#ocracy.BackendInfo)(record, \*[, implemented])            | One backend's ledger entry — a read-only, attribute-and-dict accessible record.                                  |
| [`Catalog`](_autosummary/ocracy.html.md#ocracy.Catalog)([path, \_records])                        | A filterable, dict-like collection of [`BackendInfo`](_autosummary/ocracy.html.md#ocracy.BackendInfo), keyed by id. |
| [`ServiceCollection`](_autosummary/ocracy.html.md#ocracy.ServiceCollection)()                               | Lazy mapping of backend ids -> `ServiceHandle`.                                                                  |
| [`BaseOcrAdapter`](_autosummary/ocracy.html.md#ocracy.BaseOcrAdapter)(config)                            | Optional base class for backend adapters.                                                                        |
| [`Requirements`](_autosummary/ocracy.html.md#ocracy.Requirements)(backend_id, implemented, ...[, ...]) | What a backend needs to run, structured for an agent to act on.                                                  |

### *class* ocracy.BBox(x0, y0, x1, y1, polygon=None)

Bases: [`object`](https://docs.python.org/3/builtins/functions.html#object)

An axis-aligned bounding box in pixel coordinates (origin = top-left).

`polygon` optionally carries the original (possibly rotated) vertices as a
sequence of `(x, y)` points; the axis-aligned `x0/y0/x1/y1` are always
populated (derived from the polygon if a backend only gives one).

#### *property* as_tuple *: [Tuple](https://docs.python.org/3/library/typing.html#typing.Tuple)[[float](https://docs.python.org/3/builtins/functions.html#float), [float](https://docs.python.org/3/builtins/functions.html#float), [float](https://docs.python.org/3/builtins/functions.html#float), [float](https://docs.python.org/3/builtins/functions.html#float)]*

`(x0, y0, x1, y1)` — the convention PIL’s `crop` expects.

#### *classmethod* from_polygon(points)

Build a box from polygon vertices `[(x, y), ...]`.

The axis-aligned extent is computed from the vertices and the original
polygon is preserved for callers that care about rotation.

* **Return type:**
  [`BBox`](_autosummary/ocracy.base.html.md#ocracy.base.BBox)

#### *property* xywh *: [Tuple](https://docs.python.org/3/library/typing.html#typing.Tuple)[[float](https://docs.python.org/3/builtins/functions.html#float), [float](https://docs.python.org/3/builtins/functions.html#float), [float](https://docs.python.org/3/builtins/functions.html#float), [float](https://docs.python.org/3/builtins/functions.html#float)]*

`(x, y, width, height)` — the convention many drawing libs expect.

### *class* ocracy.BackendInfo(record, , implemented=False)

Bases: [`Mapping`](https://docs.python.org/3/library/collections.abc.html#collections.abc.Mapping)

One backend’s ledger entry — a read-only, attribute-and-dict accessible record.

Wraps the raw record dict so that new fields added to the JSON are available
immediately (via attribute or key access) without code changes, while a few
commonly used fields get typed properties for convenience and discoverability.

### *class* ocracy.BaseOcrAdapter(config)

Bases: [`object`](https://docs.python.org/3/builtins/functions.html#object)

Optional base class for backend adapters.

Stores the config, builds a kwarg translator from `config['param_map']`,
and implements `read` as: translate normalized kwargs -> native kwargs ->
`_read()`. Subclasses implement `_read()` and return an
[`OcrResult`](_autosummary/ocracy.base.html.md#ocracy.base.OcrResult).

Adapters are not *required* to subclass this — the registry only needs an
`Adapter` class with a `read(image, **kwargs)` method — but doing so
removes the boilerplate.

#### ADAPTER_KWARGS *= ('api_key', 'app_key', 'app_id')*

Keyword arguments a *remote* adapter reads itself (credentials), passed
through untranslated: no `param_map` declares them, and they must never be
dropped. On a local backend they are dropped with a (redacted) note.

#### read(image, \*\*kwargs)

Translate `kwargs`, run `_read()`, and put any drop notes on the result.

A parameter the backend cannot honour is warned about and dropped, and the
drop is recorded in `result.meta["notes"]` so it is visible after the
warning is gone (or filtered).

* **Return type:**
  [`OcrResult`](_autosummary/ocracy.base.html.md#ocracy.base.OcrResult)

### *class* ocracy.Catalog(path=None, , \_records=None)

Bases: [`Mapping`](https://docs.python.org/3/library/collections.abc.html#collections.abc.Mapping)

A filterable, dict-like collection of [`BackendInfo`](_autosummary/ocracy.html.md#ocracy.BackendInfo), keyed by id.

Loaded lazily from `DEFAULT_LEDGER_PATH` (override via the `path`
argument or the `OCRACY_LEDGER` environment variable). [`filter()`](_autosummary/ocracy.html.md#ocracy.Catalog.filter)
returns a *new* `Catalog` over the matching subset, so filters compose:

```default
catalog.filter(is_remote=True).filter(pricing_model="free_tier_then_paid")
```

#### can(capability)

Backends with a non-plain-text `capability` (e.g. `"math"`, `"tables"`).

Matches either the `beyond_text` list or a `<capability>` field set
to `"yes"` (e.g. `handwriting`, `tables`, `math_formula`).

* **Return type:**
  [`Catalog`](_autosummary/ocracy.html.md#ocracy.Catalog)

#### compare(ids=None, , fields=('name', 'is_local', 'is_remote', 'open_source', 'pricing_model', 'price_note', 'accuracy_tier', 'languages_count', 'handwriting', 'math_formula', 'tables', 'best_for'))

A trimmed, side-by-side view of selected backends and fields.

* **Return type:**
  [`List`](https://docs.python.org/3/library/typing.html#typing.List)[[`dict`](https://docs.python.org/3/builtins/stdtypes.html#dict)]

#### filter(, predicate=None, implemented=None, \*\*criteria)

Return a new `Catalog` of backends matching every criterion.

* **Parameters:**
  * **predicate** ([`Optional`](https://docs.python.org/3/library/typing.html#typing.Optional)[[`Callable`](https://docs.python.org/3/library/typing.html#typing.Callable)[[[`BackendInfo`](_autosummary/ocracy.html.md#ocracy.BackendInfo)], [`bool`](https://docs.python.org/3/builtins/functions.html#bool)]]) – An arbitrary `BackendInfo -> bool` callable.
  * **implemented** ([`Optional`](https://docs.python.org/3/library/typing.html#typing.Optional)[[`bool`](https://docs.python.org/3/builtins/functions.html#bool)]) – If set, keep only (un)implemented backends.
  * **\*\*criteria** ([`Any`](https://docs.python.org/3/library/typing.html#typing.Any)) – `field=value` constraints. `value` may be a
    set/list/tuple meaning “one of”. Free-text fields
    (`languages_note`, `beyond_text`, `output_formats`) use a
    case-insensitive substring match.
* **Return type:**
  [`Catalog`](_autosummary/ocracy.html.md#ocracy.Catalog)

Example:

```default
catalog.filter(is_local=True, open_source=True, handwriting="yes")
```

#### supports_language(language)

Backends whose `languages_note` mentions `language` (name or code).

* **Return type:**
  [`Catalog`](_autosummary/ocracy.html.md#ocracy.Catalog)

#### to_dataframe(, columns=None)

Return a pandas DataFrame of the catalog (pandas imported lazily).

### *class* ocracy.OcrResult(text, blocks=<factory>, backend='', raw=None, meta=<factory>)

Bases: [`object`](https://docs.python.org/3/builtins/functions.html#object)

The normalized result of reading an image with any backend.

`text` is the headline payload: the full recognized text in reading order.
`blocks` carries the structured units (with boxes/confidences) when the
backend provides them. `raw` is the untouched backend output. `meta`
holds cross-cutting extras (languages, page count, a Markdown rendering,
timing, …).

Progressive disclosure:

```default
result = ocracy.ocr("scan.png")
print(result)              # -> the text
result.text                # -> the same string
for line in result:        # -> iterate TextBlocks (lines by default)
    print(line.text, line.confidence)
result.words               # -> only word-level blocks
result.mean_confidence     # -> average confidence, if available
result.raw                 # -> engine-specific structure
```

#### at_level(level)

Blocks at a given granularity (`"word"`, `"line"`, …).

* **Return type:**
  [`List`](https://docs.python.org/3/library/typing.html#typing.List)[[`TextBlock`](_autosummary/ocracy.base.html.md#ocracy.base.TextBlock)]

#### filter_confidence(min_confidence)

Return a copy keeping only blocks at or above `min_confidence`.

Blocks without a confidence are dropped. `text` is rebuilt from the
surviving blocks (joined by newline).

* **Return type:**
  [`OcrResult`](_autosummary/ocracy.base.html.md#ocracy.base.OcrResult)

#### *classmethod* from_blocks(blocks, , backend='', raw=None, text=None, joiner='\\\\n', \*\*meta)

Build a result from structured blocks.

If `text` is not given it is synthesized by joining the blocks’ text in
their given order with `joiner` (callers should pass blocks already in
reading order, or pre-join and pass `text` explicitly).

* **Return type:**
  [`OcrResult`](_autosummary/ocracy.base.html.md#ocracy.base.OcrResult)

#### *classmethod* from_text(text, , backend='', raw=None, \*\*meta)

Build a minimal result from just a text string (no geometry).

* **Return type:**
  [`OcrResult`](_autosummary/ocracy.base.html.md#ocracy.base.OcrResult)

#### *property* markdown *: [str](https://docs.python.org/3/builtins/stdtypes.html#str) | [None](https://docs.python.org/3/builtins/constants.html#None)*

Markdown rendering if the backend produced one (else `None`).

#### *property* mean_confidence *: [float](https://docs.python.org/3/builtins/functions.html#float) | [None](https://docs.python.org/3/builtins/constants.html#None)*

Mean confidence over blocks that report one, or `None`.

### *class* ocracy.Requirements(backend_id, implemented, available, is_local, is_remote, pip_command, extra=None, system=<factory>, system_note=None, gpu=None, weights=None, heavy=False, alternative=None, credentials=<factory>, notes=<factory>, verify_command=None, alternative_label='Lighter alternative')

Bases: [`object`](https://docs.python.org/3/builtins/functions.html#object)

What a backend needs to run, structured for an agent to act on.

#### instructions()

An agent- and human-readable, copy-pasteable install plan.

* **Return type:**
  [`str`](https://docs.python.org/3/builtins/stdtypes.html#str)

### *class* ocracy.ServiceCollection

Bases: [`Mapping`](https://docs.python.org/3/library/collections.abc.html#collections.abc.Mapping)

Lazy mapping of backend ids -> `ServiceHandle`.

Supports dict-style (`services['tesseract']`) and attribute-style
(`services.tesseract`) access.

### *class* ocracy.TextBlock(text, bbox=None, confidence=None, level='line', language=None, meta=<factory>)

Bases: [`object`](https://docs.python.org/3/builtins/functions.html#object)

One recognized unit of text.

#### text

The recognized string for this unit.

#### bbox

Where it was found (pixel coordinates), if the backend reports it.

#### confidence

Recognition confidence in `[0, 1]` (normalized by ocracy
from whatever scale the backend used), if available.

#### level

Granularity — one of `ocracy.base.LEVELS` (“word”, “line”, …).

#### language

Detected/declared language code for this unit, if any.

#### meta

Backend-specific extras (font size, style, page index, …).

### ocracy.available_backends()

Implemented backends whose dependency is importable right now.

* **Return type:**
  [`List`](https://docs.python.org/3/library/typing.html#typing.List)[[`str`](https://docs.python.org/3/builtins/stdtypes.html#str)]

### ocracy.backend_ids(level='all', , info=None, test_image=None)

Sorted backend ids at a readiness `level` (one of `LEVELS`).

Pass a precomputed `info` (from [`backend_info()`](_autosummary/ocracy.html.md#ocracy.backend_info)) to avoid recomputation
— important for `"tested"`, which otherwise re-runs OCR.

* **Return type:**
  [`List`](https://docs.python.org/3/library/typing.html#typing.List)[[`str`](https://docs.python.org/3/builtins/stdtypes.html#str)]

### ocracy.backend_info(ids=None, , run_tests=False, test_image=None)

Per-backend status: every ledger field plus `implemented`/`set_up`/`tested`.

* **Parameters:**
  * **ids** ([`Optional`](https://docs.python.org/3/library/typing.html#typing.Optional)[[`Iterable`](https://docs.python.org/3/library/typing.html#typing.Iterable)[[`str`](https://docs.python.org/3/builtins/stdtypes.html#str)]]) – Which backends (default: every ledger id).
  * **run_tests** – Which set-up backends to actually OCR-test. `True` = all
    set-up (real API calls for remotes!); `False` = none (`tested` is
    `None`); or an iterable of ids to limit testing to those.
  * **test_image** ([`Any`](https://docs.python.org/3/library/typing.html#typing.Any)) – Image to test with (default: a generated one, shared across all).
* **Return type:**
  [`Dict`](https://docs.python.org/3/library/typing.html#typing.Dict)[[`str`](https://docs.python.org/3/builtins/stdtypes.html#str), [`dict`](https://docs.python.org/3/builtins/stdtypes.html#dict)]
* **Returns:**
  `{id: {..., "name", "website", "implemented", "set_up", "tested"}}` where
  `tested` is `True`/`False`/`None` (None = not attempted).

### ocracy.check(backend_id)

Is `backend_id` importable / usable right now? (no install, no network).

* **Return type:**
  [`bool`](https://docs.python.org/3/builtins/functions.html#bool)

### ocracy.doctor()

Report which implemented backends are usable now and what the rest need.

Returns `{"available": [...], "missing": {id: one-line install hint}}`.

* **Return type:**
  [`dict`](https://docs.python.org/3/builtins/stdtypes.html#dict)

### ocracy.find(\*\*criteria)

Filter the ledger; shorthand for `ocracy.catalog.Catalog.filter()`.

Example:

```default
ocracy.find(is_local=True, open_source=True, handwriting="yes")
ocracy.find(implemented=True)        # only backends ocracy can run now
```

* **Return type:**
  [`Catalog`](_autosummary/ocracy.html.md#ocracy.Catalog)

### ocracy.get_config(backend_id)

A backend’s `BACKEND_CONFIG` without loading its adapter.

* **Return type:**
  [`dict`](https://docs.python.org/3/builtins/stdtypes.html#dict)

### ocracy.get_default_backend(capability='read', , require_available=True)

Pick a sensible default backend id for a capability.

Strategy (OCR-tuned): prefer a backend explicitly flagged `default_for` the
capability *and* whose dependency is importable; then any importable backend
for the capability; then — if `require_available` is False or nothing is
installed — the first registered candidate (using it will raise a helpful
install error).

* **Return type:**
  [`str`](https://docs.python.org/3/builtins/stdtypes.html#str)

### ocracy.install(backend_id, , yes=False, gpu=False, verify=True, upgrade=False)

Plan (and optionally run) the pip install for a backend.

With `yes=False` (default) this is a **dry run**: it returns the plan
without changing anything — call `result['requirements'].instructions()` to
show it. With `yes=True` it runs `pip install` for the backend’s extra in
the current interpreter, then (if `verify`) checks importability.

System dependencies and GPU wheels are *surfaced*, never run automatically
(they need sudo/brew or an environment-specific CUDA choice) — run those
yourself from `result['requirements'].system` / `.gpu`.

* **Return type:**
  [`dict`](https://docs.python.org/3/builtins/stdtypes.html#dict)

### ocracy.is_set_up(backend_id)

Ready to run here & now.

Requires the engine/client to be importable (local *and* remote), and — for a
remote backend — its (primary) credential env var to resolve. So a remote
whose key is set but whose client library isn’t installed is *not* set up
(it couldn’t actually run). Returns False for ledger-only backends.

* **Return type:**
  [`bool`](https://docs.python.org/3/builtins/functions.html#bool)

### ocracy.is_tested(backend_id, , image=None)

Actually run OCR on `image` (a generated one if None); True iff it worked.

For remote backends this performs a real API call. Returns False if the
backend isn’t set up or the run fails.

* **Return type:**
  [`bool`](https://docs.python.org/3/builtins/functions.html#bool)

### ocracy.list_backends(capability=None)

Sorted ids of implemented backends, optionally filtered by capability.

A backend matches `capability` if it appears in the backend’s
`capabilities` list (the primary `"read"` is implied for all).

* **Return type:**
  [`List`](https://docs.python.org/3/library/typing.html#typing.List)[[`str`](https://docs.python.org/3/builtins/stdtypes.html#str)]

### ocracy.make_block(text, , bbox=None, confidence=None, conf_scale=1.0, level='word', language=None, \*\*meta)

Build a normalized [`TextBlock`](_autosummary/ocracy.base.html.md#ocracy.base.TextBlock).

`bbox` may be any shape accepted by `as_bbox()`. `confidence` is
normalized to `[0, 1]` via `conf_scale` (e.g. `conf_scale=100` for
percent-scale engines).

* **Return type:**
  [`TextBlock`](_autosummary/ocracy.base.html.md#ocracy.base.TextBlock)

### ocracy.names_with_sites(ids, , info=None)

`"Name (website), Name2 (website2), ..."` for `ids` (name, not id).

* **Return type:**
  [`str`](https://docs.python.org/3/builtins/stdtypes.html#str)

### ocracy.ocr(image, , backend=None, \*\*kwargs)

Read text from an image with any backend, returning a normalized result.

* **Parameters:**
  * **image** (ImageInput) – A path, `http(s)` URL, `bytes`, PIL image, or numpy array.
  * **backend** ([`str`](https://docs.python.org/3/builtins/stdtypes.html#str)) – Backend id (see [`list_backends()`](_autosummary/ocracy.html.md#ocracy.list_backends)). Defaults to the first
    *installed* implemented backend (see [`get_default_backend()`](_autosummary/ocracy.html.md#ocracy.get_default_backend)).
  * **\*\*kwargs** – Normalized, backend-translated options (e.g. `languages`).
    Unknown options for the chosen backend are warned about and dropped.
* **Return type:**
  OcrResult
* **Returns:**
  An [`OcrResult`](_autosummary/ocracy.base.html.md#ocracy.base.OcrResult) (`str(result)` is the text).

### ocracy.read_text(image, , backend=None, \*\*kwargs)

Like [`ocr()`](_autosummary/ocracy.html.md#ocracy.ocr) but returns just the recognized text string.

* **Return type:**
  [`str`](https://docs.python.org/3/builtins/stdtypes.html#str)

### ocracy.register_backend(backend_id, config, adapter=None)

Register a backend at runtime (for third-party plugins).

* **Parameters:**
  * **backend_id** ([`str`](https://docs.python.org/3/builtins/stdtypes.html#str)) – Unique identifier.
  * **config** ([`dict`](https://docs.python.org/3/builtins/stdtypes.html#dict)) – `BACKEND_CONFIG`-shaped dict (needs at least `name`).
  * **adapter** ([`Any`](https://docs.python.org/3/library/typing.html#typing.Any)) – Optional pre-instantiated adapter; else loaded lazily from
    `config['module_path']` when first used.
* **Return type:**
  [`None`](https://docs.python.org/3/builtins/constants.html#None)

### ocracy.requirements(backend_id, , gpu=False)

Return structured install [`Requirements`](_autosummary/ocracy.html.md#ocracy.Requirements) for `backend_id`.

Works for both implemented backends (uses the `ocracy[extra]` install and
the recipe) and ledger-only backends (falls back to the ledger’s
`python_install` string). A recipe’s GPU guidance is always included;
`gpu` is accepted for compatibility and changes nothing.

* **Return type:**
  [`Requirements`](_autosummary/ocracy.kit.install.html.md#ocracy.kit.install.Requirements)

### ocracy.scaffold_backend(backend_id, , dest=None, overwrite=False, ledger=None, extra_overrides=None)

Create a new `ocracy/backends/<id>/` package from the template.

Pre-fills `config.py` from the backend’s ledger entry (if any) so you only
have to flesh out `param_map` and implement `adapter.py`’s `_read`.

* **Parameters:**
  * **backend_id** ([`str`](https://docs.python.org/3/builtins/stdtypes.html#str)) – The ledger id (e.g. `"easyocr"`, `"google-vision"`). The
    on-disk module name uses underscores; the config `id` keeps the id
    verbatim.
  * **dest** (`Union`[[`str`](https://docs.python.org/3/builtins/stdtypes.html#str), [`Path`](https://docs.python.org/3/library/pathlib.html#pathlib.Path), [`None`](https://docs.python.org/3/builtins/constants.html#None)]) – Target directory (defaults to `ocracy/backends/<id_underscored>`).
  * **overwrite** ([`bool`](https://docs.python.org/3/builtins/functions.html#bool)) – Allow writing into an existing non-empty directory.
  * **ledger** ([`Any`](https://docs.python.org/3/library/typing.html#typing.Any)) – A [`Catalog`](_autosummary/ocracy.html.md#ocracy.Catalog) to read the record from
    (defaults to the shipped catalog).
  * **extra_overrides** ([`Optional`](https://docs.python.org/3/library/typing.html#typing.Optional)[[`dict`](https://docs.python.org/3/builtins/stdtypes.html#dict)]) – Extra config-key overrides applied on top of the record.
* **Return type:**
  [`Path`](https://docs.python.org/3/library/pathlib.html#pathlib.Path)
* **Returns:**
  The path to the created backend package.

### ocracy.status_table(ids=None, , info=None, columns=None, run_tests=False, test_image=None)

Render an aligned Markdown table of backend status (also plain-text readable).

Rows are ordered tested → set-up → implemented → listed, then by name, so the
“live” backends float to the top. Pass a precomputed `info` to avoid re-running
tests; otherwise `run_tests` controls which set-up backends get OCR-tested.

* **Return type:**
  [`str`](https://docs.python.org/3/builtins/stdtypes.html#str)

### ocracy.validate_adapter(backend_id, , image=None, expect_text=None)

Smoke-test a backend adapter end to end, returning a report dict.

Loads the adapter (reporting unavailability instead of raising), runs
`read` on a generated (or supplied) image, and checks the contract: an
[`OcrResult`](_autosummary/ocracy.base.html.md#ocracy.base.OcrResult) came back with text and/or blocks. Never
raises on a *recognition* mismatch — it returns what happened so callers can
decide.

* **Return type:**
  [`dict`](https://docs.python.org/3/builtins/stdtypes.html#dict)

### Modules

| [`backends`](_autosummary/ocracy.backends.html.md#module-ocracy.backends)         | Implemented OCR backends.                                                                                        |
|------------------------------------------------------------------------------------------|------------------------------------------------------------------------------------------------------------------|
| [`base`](_autosummary/ocracy.base.html.md#module-ocracy.base)                 | Core types and normalized result objects for ocracy.                                                             |
| [`catalog`](_autosummary/ocracy.catalog.html.md#ocracy.catalog)                  | A filterable, dict-like collection of [`BackendInfo`](_autosummary/ocracy.html.md#ocracy.BackendInfo), keyed by id. |
| [`credentials`](_autosummary/ocracy.credentials.html.md#module-ocracy.credentials)   | Credential resolution for remote OCR backends.                                                                   |
| [`kit`](_autosummary/ocracy.kit.html.md#module-ocracy.kit)                   | The facade kit: the three helpers every fleet facade used to copy by hand.                                       |
| [`make_backend`](_autosummary/ocracy.make_backend.html.md#module-ocracy.make_backend) | Abstraction tools for *building* OCR facades.                                                                    |
| [`registry`](_autosummary/ocracy.registry.html.md#module-ocracy.registry)         | Backend discovery, registration, and lazy loading.                                                               |
| [`services`](_autosummary/ocracy.services.html.md#ocracy.services)                | Lazy mapping of backend ids -> `ServiceHandle`.                                                                  |
| [`status`](_autosummary/ocracy.status.html.md#module-ocracy.status)             | Backend readiness status — four nested levels, info dicts, and a Markdown table.                                 |
| [`tools`](_autosummary/ocracy.tools.html.md#module-ocracy.tools)               | Command-line tools for ocracy (dispatched via `cw` in `__main__`).                                               |
| [`translation`](_autosummary/ocracy.translation.html.md#module-ocracy.translation)   | Parameter translation between ocracy's normalized kwargs and native engines.                                     |
| [`util`](_autosummary/ocracy.util.html.md#module-ocracy.util)                 | Image-input normalization and small shared helpers.                                                              |


# _autosummary/ocracy.kit.credentials.html.md

# ocracy.kit.credentials

One credential chain for every facade: explicit -> bound -> env -> store -> prompt.

[`resolve_credential()`](_autosummary/ocracy.kit.credentials.html.md#ocracy.kit.credentials.resolve_credential) looks for a provider’s secret in this order and stops at
the first non-empty value:

1. `api_key=` passed by the caller (an empty string counts as not given);
2. a key bound for this provider in the current context with
   [`using_credentials()`](_autosummary/ocracy.kit.credentials.html.md#ocracy.kit.credentials.using_credentials) – the bring-your-own-key seam a server uses without
   > threading a key through every call;
3. the environment: `env_var` first, then the provider’s row of
   `provider_env_vars`, in order, without duplicates (with `dotenv=True` a
   project `.env`, found from the current directory, is loaded on a miss and the
   environment checked again; it never overrides a variable that is already set,
   and like any `.env` loader it writes to `os.environ`, so every later reader
   sees it);
4. `store`: any mapping keyed by env-var name (a `config2py` store, a dict);
   only a missing key moves on, any other error propagates;
5. with `prompt_if_missing=True` and an interactive terminal, `getpass`; the
   answer is written to `store` when it is a `MutableMapping`, else to the
   process environment.

When nothing resolves and `required=True`, it raises `error` (default
[`MissingCredentialError`](_autosummary/ocracy.kit.credentials.html.md#ocracy.kit.credentials.MissingCredentialError)) with a message naming every env var it tried and,
from `guidance`, where to get a key:

```default
>>> resolve_credential("acme", api_key="explicit")
'explicit'
>>> with using_credentials(acme="bound"):
...     resolve_credential("acme")
'bound'
>>> resolve_credential("acme", env_var="ACME_SURELY_UNSET_KEY", required=False) is None
True
```

Two properties of the binding (step 2) that a server must know:

- **It is shared by provider id across every package using the kit.** A key bound
  as `openai` reaches ocracy, aix and any other facade calling OpenAI in that
  context. That is the point of a bring-your-own-key binding, so pick provider ids
  that name the *account* (`openai`, `fal`, `elevenlabs`), not the facade.
- **It is a** [`ContextVar`](https://docs.python.org/3/library/contextvars.html#contextvars.ContextVar) **binding**, so it follows the
  context: `asyncio` tasks and `asyncio.to_thread` see it, but a bare
  `threading.Thread`, `ThreadPoolExecutor.submit` or `loop.run_in_executor`
  start from an empty context and fall through to the environment (the operator’s
  key). Submit `contextvars.copy_context().run` to keep the binding.

A package binds its own tables once, with [`functools.partial()`](https://docs.python.org/3/library/functools.html#functools.partial) or a thin
wrapper, and keeps its public names; ocracy’s [`ocracy.credentials`](_autosummary/ocracy.credentials.html.md#module-ocracy.credentials) is the
worked example. Stdlib only; imports nothing else from ocracy.

### Functions

| [`resolve_credential`](_autosummary/ocracy.kit.credentials.html.md#ocracy.kit.credentials.resolve_credential)([provider, api_key, ...])   | Resolve a provider's credential through the chain in the module docstring.                                                |
|-------------------------------------------------------------------------------------------------|---------------------------------------------------------------------------------------------------------------------------|
| [`env_var_names`](_autosummary/ocracy.kit.credentials.html.md#ocracy.kit.credentials.env_var_names)([provider, env_var, ...])        | The env vars the chain checks: `env_var` first, then the provider's row.                                                  |
| [`credential_help`](_autosummary/ocracy.kit.credentials.html.md#ocracy.kit.credentials.credential_help)(provider, \*[, guidance])      | A short, link-bearing "how to get a key" line for `provider` (or `''`).                                                   |
| [`credential_lines`](_autosummary/ocracy.kit.credentials.html.md#ocracy.kit.credentials.credential_lines)(env_var, provider, \*[, ...]) | `export VAR  (get a key: URL)` lines for an install plan (empty if no var).                                               |
| [`using_credentials`](_autosummary/ocracy.kit.credentials.html.md#ocracy.kit.credentials.using_credentials)([keys])                      | Bind provider keys for the `with` block (overlaying any outer binding).                                                   |
| [`current_credentials`](_autosummary/ocracy.kit.credentials.html.md#ocracy.kit.credentials.current_credentials)()                          | The provider keys bound in this context by [`using_credentials()`](_autosummary/ocracy.kit.credentials.html.md#ocracy.kit.credentials.using_credentials) (a copy). |

### Exceptions

| [`MissingCredentialError`](_autosummary/ocracy.kit.credentials.html.md#ocracy.kit.credentials.MissingCredentialError)([message, provider, ...])   | A required credential could not be resolved; the message says how to get one.   |
|-----------------------------------------------------------------------------------------------------|---------------------------------------------------------------------------------|

### *exception* ocracy.kit.credentials.MissingCredentialError(message='', , provider=None, env_vars=(), get_key_url=None)

Bases: [`RuntimeError`](https://docs.python.org/3/builtins/exceptions.html#RuntimeError)

A required credential could not be resolved; the message says how to get one.

#### provider

The provider id asked for (or `None`).

#### env_vars

The env vars that were checked, in order.

#### get_key_url

Where to get a key, when the guidance table knows.

### ocracy.kit.credentials.credential_help(provider, , guidance=None)

A short, link-bearing “how to get a key” line for `provider` (or `''`).

`guidance[provider]` may carry `note` and `get_key_url`.

* **Return type:**
  [`str`](https://docs.python.org/3/builtins/stdtypes.html#str)

### ocracy.kit.credentials.credential_lines(env_var, provider, , guidance=None)

`export VAR  (get a key: URL)` lines for an install plan (empty if no var).

Several env vars (alternatives) are shown as `A / B`.

* **Return type:**
  [`list`](https://docs.python.org/3/builtins/stdtypes.html#list)

### ocracy.kit.credentials.current_credentials()

The provider keys bound in this context by [`using_credentials()`](_autosummary/ocracy.kit.credentials.html.md#ocracy.kit.credentials.using_credentials) (a copy).

* **Return type:**
  [`dict`](https://docs.python.org/3/builtins/stdtypes.html#dict)

### ocracy.kit.credentials.env_var_names(provider=None, , env_var=None, provider_env_vars=None)

The env vars the chain checks: `env_var` first, then the provider’s row.

* **Return type:**
  [`list`](https://docs.python.org/3/builtins/stdtypes.html#list)

### ocracy.kit.credentials.resolve_credential(provider=None, \*, api_key=None, env_var=None, provider_env_vars=None, guidance=None, store=None, dotenv=False, prompt_if_missing=False, required=True, error=<class 'ocracy.kit.credentials.MissingCredentialError'>, hint='')

Resolve a provider’s credential through the chain in the module docstring.

* **Parameters:**
  * **provider** ([`Optional`](https://docs.python.org/3/library/typing.html#typing.Optional)[[`str`](https://docs.python.org/3/builtins/stdtypes.html#str)]) – The provider id, used for bindings, table rows and messages.
  * **api_key** ([`Optional`](https://docs.python.org/3/library/typing.html#typing.Optional)[[`str`](https://docs.python.org/3/builtins/stdtypes.html#str)]) – An explicit value; wins when non-empty.
  * **env_var** (`Union`[[`str`](https://docs.python.org/3/builtins/stdtypes.html#str), [`Sequence`](https://docs.python.org/3/library/typing.html#typing.Sequence)[[`str`](https://docs.python.org/3/builtins/stdtypes.html#str)], [`None`](https://docs.python.org/3/builtins/constants.html#None)]) – Env var name(s) checked before the provider’s table row.
  * **provider_env_vars** ([`Optional`](https://docs.python.org/3/library/typing.html#typing.Optional)[[`Mapping`](https://docs.python.org/3/library/typing.html#typing.Mapping)[[`str`](https://docs.python.org/3/builtins/stdtypes.html#str), `Union`[[`str`](https://docs.python.org/3/builtins/stdtypes.html#str), [`Sequence`](https://docs.python.org/3/library/typing.html#typing.Sequence)[[`str`](https://docs.python.org/3/builtins/stdtypes.html#str)], [`None`](https://docs.python.org/3/builtins/constants.html#None)]]]) – The package’s provider -> env var(s) table.
  * **guidance** ([`Optional`](https://docs.python.org/3/library/typing.html#typing.Optional)[[`Mapping`](https://docs.python.org/3/library/typing.html#typing.Mapping)]) – The package’s provider -> `{note, get_key_url}` table.
  * **store** ([`Optional`](https://docs.python.org/3/library/typing.html#typing.Optional)[[`Mapping`](https://docs.python.org/3/library/typing.html#typing.Mapping)[[`str`](https://docs.python.org/3/builtins/stdtypes.html#str), [`str`](https://docs.python.org/3/builtins/stdtypes.html#str)]]) – A mapping keyed by env-var name, read after the environment.
  * **dotenv** ([`bool`](https://docs.python.org/3/builtins/functions.html#bool)) – On an environment miss, load a project `.env` (searched from the
    current directory, never overriding) and look again.
  * **prompt_if_missing** ([`bool`](https://docs.python.org/3/builtins/functions.html#bool)) – Ask with `getpass` when interactive (last resort).
  * **required** ([`bool`](https://docs.python.org/3/builtins/functions.html#bool)) – Raise when nothing resolves; else return `None`.
  * **error** ([`Callable`](https://docs.python.org/3/library/typing.html#typing.Callable)[[[`str`](https://docs.python.org/3/builtins/stdtypes.html#str)], [`BaseException`](https://docs.python.org/3/builtins/exceptions.html#BaseException)]) – The exception to raise, called with the message. When it builds a
    [`MissingCredentialError`](_autosummary/ocracy.kit.credentials.html.md#ocracy.kit.credentials.MissingCredentialError) (or subclass), its `provider`,
    `env_vars` and `get_key_url` attributes are filled in.
  * **hint** ([`str`](https://docs.python.org/3/builtins/stdtypes.html#str)) – An extra sentence for the error message (why this key is needed).
* **Return type:**
  [`Optional`](https://docs.python.org/3/library/typing.html#typing.Optional)[[`str`](https://docs.python.org/3/builtins/stdtypes.html#str)]
* **Returns:**
  The secret, or `None` when `required=False` and nothing resolved.

### ocracy.kit.credentials.using_credentials(keys=None, , \*\*provider_keys)

Bind provider keys for the `with` block (overlaying any outer binding).

Pass a mapping for provider ids that are not identifiers (`"google-vision"`)
or keywords for the rest. Falsy values are ignored, so an optional request
header can be passed straight through.

* **Return type:**
  [`Iterator`](https://docs.python.org/3/library/typing.html#typing.Iterator)[[`dict`](https://docs.python.org/3/builtins/stdtypes.html#dict)]

```pycon
>>> with using_credentials(acme="outer"):
...     with using_credentials({"acme": "inner", "other": None}):
...         inner = current_credentials()
...     outer = current_credentials()
>>> inner, outer
({'acme': 'inner'}, {'acme': 'outer'})
```


# _autosummary/ocracy.kit.html.md

# ocracy.kit

The facade kit: the three helpers every fleet facade used to copy by hand.

One interface over many backends needs the same three mechanisms whatever the
backends do, and until this kit each facade (ocracy, scribed, denote, arioso,
illustration, aix, foley, falaw, voxy) carried its own drifting copy:

- [`translation`](_autosummary/ocracy.kit.translation.html.md#module-ocracy.kit.translation) – canonical kwargs -> native kwargs from a
  declared `param_map`, with an unsupported-parameter policy that never drops
  silently (every drop and clamp comes back as a note);
- [`credentials`](_autosummary/ocracy.kit.credentials.html.md#module-ocracy.kit.credentials) – the key chain (explicit -> bound in context ->
  env -> store -> prompt), whose error names the env vars and where to get a key;
- [`install`](_autosummary/ocracy.kit.install.html.md#module-ocracy.kit.install) – per-OS install plans an agent can act on.

Usage:

```default
from ocracy.kit import make_translator, resolve_credential, using_credentials

translate = make_translator(BACKEND_CONFIG["param_map"], backend="acme",
                            on_unsupported="note", always_raise=("seed",))
t = translate(canonical_kwargs)        # t.kwargs, t.notes, t.dropped
key = resolve_credential("acme", env_var="ACME_API_KEY", api_key=api_key)
```

Every module here is stdlib-only and imports nothing from ocracy outside
`ocracy.kit`, so the kit can move to its own distribution without a rewrite.
The decisions behind its shape are in `docs/adr/0001-facade-kit.md`.

### Functions

| [`make_translator`](_autosummary/ocracy.kit.html.md#ocracy.kit.make_translator)(param_map, \*[, backend, ...])   | Build `translate(kwargs, *, on_unsupported=None) -> Translation` from a map.                                              |
|---------------------------------------------------------------------------------------------------|---------------------------------------------------------------------------------------------------------------------------|
| [`check_range`](_autosummary/ocracy.kit.html.md#ocracy.kit.check_range)(name, value, spec)                   | Raise `ValueError` unless `value` fits `spec`'s `min`/`max`/`choices`.                                                    |
| [`resolve_credential`](_autosummary/ocracy.kit.html.md#ocracy.kit.resolve_credential)([provider, api_key, ...])     | Resolve a provider's credential through the chain in the module docstring.                                                |
| [`using_credentials`](_autosummary/ocracy.kit.html.md#ocracy.kit.using_credentials)([keys])                        | Bind provider keys for the `with` block (overlaying any outer binding).                                                   |
| [`current_credentials`](_autosummary/ocracy.kit.html.md#ocracy.kit.current_credentials)()                            | The provider keys bound in this context by [`using_credentials()`](_autosummary/ocracy.kit.html.md#ocracy.kit.using_credentials) (a copy). |
| [`env_var_names`](_autosummary/ocracy.kit.html.md#ocracy.kit.env_var_names)([provider, env_var, ...])          | The env vars the chain checks: `env_var` first, then the provider's row.                                                  |
| [`credential_help`](_autosummary/ocracy.kit.html.md#ocracy.kit.credential_help)(provider, \*[, guidance])        | A short, link-bearing "how to get a key" line for `provider` (or `''`).                                                   |
| [`credential_lines`](_autosummary/ocracy.kit.html.md#ocracy.kit.credential_lines)(env_var, provider, \*[, ...])   | `export VAR  (get a key: URL)` lines for an install plan (empty if no var).                                               |
| [`build_requirements`](_autosummary/ocracy.kit.html.md#ocracy.kit.build_requirements)(backend_id, \*, package, ...) | Build [`Requirements`](_autosummary/ocracy.kit.html.md#ocracy.kit.Requirements) for `backend_id` from its recipe and known facts.     |
| [`run_install`](_autosummary/ocracy.kit.html.md#ocracy.kit.run_install)(req, \*, package[, yes, ...])        | Plan (default) or run (`yes=True`) the pip install that `req` describes.                                                  |
| [`current_platform`](_autosummary/ocracy.kit.html.md#ocracy.kit.current_platform)()                               | `'darwin'`, `'linux'`, `'windows'`, or `sys.platform` for anything else.                                                  |

### Classes

| [`Translation`](_autosummary/ocracy.kit.html.md#ocracy.kit.Translation)([kwargs, notes, dropped])             | What a translator produced: the native kwargs, and every change it made.   |
|----------------------------------------------------------------------------------------------------|----------------------------------------------------------------------------|
| [`Requirements`](_autosummary/ocracy.kit.html.md#ocracy.kit.Requirements)(backend_id, implemented, ...[, ...]) | What a backend needs to run, structured for an agent to act on.            |

### Exceptions

| [`UnsupportedParameter`](_autosummary/ocracy.kit.html.md#ocracy.kit.UnsupportedParameter)                             | A backend cannot honour a parameter, and the policy says not to drop it.      |
|---------------------------------------------------------------------------------------------------|-------------------------------------------------------------------------------|
| [`MissingCredentialError`](_autosummary/ocracy.kit.html.md#ocracy.kit.MissingCredentialError)([message, provider, ...]) | A required credential could not be resolved; the message says how to get one. |

### *exception* ocracy.kit.MissingCredentialError(message='', , provider=None, env_vars=(), get_key_url=None)

Bases: [`RuntimeError`](https://docs.python.org/3/builtins/exceptions.html#RuntimeError)

A required credential could not be resolved; the message says how to get one.

#### provider

The provider id asked for (or `None`).

#### env_vars

The env vars that were checked, in order.

#### get_key_url

Where to get a key, when the guidance table knows.

### *class* ocracy.kit.Requirements(backend_id, implemented, available, is_local, is_remote, pip_command, extra=None, system=<factory>, system_note=None, gpu=None, weights=None, heavy=False, alternative=None, credentials=<factory>, notes=<factory>, verify_command=None, alternative_label='Lighter alternative')

Bases: [`object`](https://docs.python.org/3/builtins/functions.html#object)

What a backend needs to run, structured for an agent to act on.

#### instructions()

An agent- and human-readable, copy-pasteable install plan.

* **Return type:**
  [`str`](https://docs.python.org/3/builtins/stdtypes.html#str)

### *class* ocracy.kit.Translation(kwargs=<factory>, notes=<factory>, dropped=<factory>)

Bases: [`object`](https://docs.python.org/3/builtins/functions.html#object)

What a translator produced: the native kwargs, and every change it made.

#### kwargs

The native kwargs to pass to the backend.

#### notes

One human-readable line per drop or clamp, for the facade’s result.

#### dropped

The canonical names that were dropped.

### *exception* ocracy.kit.UnsupportedParameter

Bases: [`ValueError`](https://docs.python.org/3/builtins/exceptions.html#ValueError)

A backend cannot honour a parameter, and the policy says not to drop it.

### ocracy.kit.build_requirements(backend_id, , package, implemented, available, recipe=None, is_local=False, is_remote=False, ledger_pip='', credentials=(), platform=None, verify_command=None, unimplemented_note=None, alternative_label='Lighter alternative')

Build [`Requirements`](_autosummary/ocracy.kit.html.md#ocracy.kit.Requirements) for `backend_id` from its recipe and known facts.

* **Parameters:**
  * **backend_id** ([`str`](https://docs.python.org/3/builtins/stdtypes.html#str)) – The backend’s id.
  * **package** ([`str`](https://docs.python.org/3/builtins/stdtypes.html#str)) – The distribution whose extra installs it (`pip install "pkg[x]"`).
  * **implemented** ([`bool`](https://docs.python.org/3/builtins/functions.html#bool)) – Whether the package ships a facade for it.
  * **available** ([`bool`](https://docs.python.org/3/builtins/functions.html#bool)) – Whether it is usable right now (the package’s own probe).
  * **recipe** ([`Optional`](https://docs.python.org/3/library/typing.html#typing.Optional)[[`Mapping`](https://docs.python.org/3/library/typing.html#typing.Mapping)]) – Its row of the package’s recipes table (see the module docstring).
  * **is_remote** ([`bool`](https://docs.python.org/3/builtins/functions.html#bool)) – From the backend’s config or ledger record.
  * **ledger_pip** ([`str`](https://docs.python.org/3/builtins/stdtypes.html#str)) – The ledger’s install line, used for a backend not implemented.
  * **credentials** ([`Iterable`](https://docs.python.org/3/library/typing.html#typing.Iterable)[[`str`](https://docs.python.org/3/builtins/stdtypes.html#str)]) – `export` lines (see [`credential_lines()`](_autosummary/ocracy.kit.credentials.html.md#ocracy.kit.credentials.credential_lines)).
  * **platform** ([`Optional`](https://docs.python.org/3/library/typing.html#typing.Optional)[[`str`](https://docs.python.org/3/builtins/stdtypes.html#str)]) – Override [`current_platform()`](_autosummary/ocracy.kit.html.md#ocracy.kit.current_platform) (for tests and docs).
  * **verify_command** ([`Optional`](https://docs.python.org/3/library/typing.html#typing.Optional)[[`str`](https://docs.python.org/3/builtins/stdtypes.html#str)]) – The shell line shown as `Verify:`.
  * **unimplemented_note** ([`Optional`](https://docs.python.org/3/library/typing.html#typing.Optional)[[`str`](https://docs.python.org/3/builtins/stdtypes.html#str)]) – Appended to `notes` when not implemented.
  * **alternative_label** ([`str`](https://docs.python.org/3/builtins/stdtypes.html#str)) – The wording before `alt` in the instructions.
* **Return type:**
  [`Requirements`](_autosummary/ocracy.kit.install.html.md#ocracy.kit.install.Requirements)

### ocracy.kit.check_range(name, value, spec)

Raise `ValueError` unless `value` fits `spec`’s `min`/`max`/`choices`.

The standalone form of the translator’s `out_of_range='raise'` check; returns
`value` unchanged. `None` is “unset” and always fits.

* **Return type:**
  [`Any`](https://docs.python.org/3/library/typing.html#typing.Any)

### ocracy.kit.credential_help(provider, , guidance=None)

A short, link-bearing “how to get a key” line for `provider` (or `''`).

`guidance[provider]` may carry `note` and `get_key_url`.

* **Return type:**
  [`str`](https://docs.python.org/3/builtins/stdtypes.html#str)

### ocracy.kit.credential_lines(env_var, provider, , guidance=None)

`export VAR  (get a key: URL)` lines for an install plan (empty if no var).

Several env vars (alternatives) are shown as `A / B`.

* **Return type:**
  [`list`](https://docs.python.org/3/builtins/stdtypes.html#list)

### ocracy.kit.current_credentials()

The provider keys bound in this context by [`using_credentials()`](_autosummary/ocracy.kit.html.md#ocracy.kit.using_credentials) (a copy).

* **Return type:**
  [`dict`](https://docs.python.org/3/builtins/stdtypes.html#dict)

### ocracy.kit.current_platform()

`'darwin'`, `'linux'`, `'windows'`, or `sys.platform` for anything else.

* **Return type:**
  [`str`](https://docs.python.org/3/builtins/stdtypes.html#str)

### ocracy.kit.env_var_names(provider=None, , env_var=None, provider_env_vars=None)

The env vars the chain checks: `env_var` first, then the provider’s row.

* **Return type:**
  [`list`](https://docs.python.org/3/builtins/stdtypes.html#list)

### ocracy.kit.make_translator(param_map, , backend='', on_unsupported='warn', always_raise=(), vocabulary=None, passthrough=(), skip_none=False, out_of_range='raise', stacklevel=2)

Build `translate(kwargs, *, on_unsupported=None) -> Translation` from a map.

* **Parameters:**
  * **param_map** ([`Mapping`](https://docs.python.org/3/library/typing.html#typing.Mapping)[[`str`](https://docs.python.org/3/builtins/stdtypes.html#str), [`Any`](https://docs.python.org/3/library/typing.html#typing.Any)]) – Canonical name -> spec (see the module docstring). Specs are
    validated here, so a malformed map fails when the backend loads, not on
    the first call that happens to use the bad entry.
  * **backend** ([`str`](https://docs.python.org/3/builtins/stdtypes.html#str)) – The backend’s name, used in notes and errors.
  * **on_unsupported** ([`str`](https://docs.python.org/3/builtins/stdtypes.html#str)) – The backend’s policy (one of `POLICIES`).
  * **always_raise** ([`Iterable`](https://docs.python.org/3/library/typing.html#typing.Iterable)[[`str`](https://docs.python.org/3/builtins/stdtypes.html#str)]) – Canonical names that raise under the backend’s policy because
    dropping them changes what the caller gets.
  * **vocabulary** ([`Optional`](https://docs.python.org/3/library/typing.html#typing.Optional)[[`Mapping`](https://docs.python.org/3/library/typing.html#typing.Mapping)[[`str`](https://docs.python.org/3/builtins/stdtypes.html#str), [`Any`](https://docs.python.org/3/library/typing.html#typing.Any)]]) – The facade’s canonical names -> their default values. Enables
    “not asked for” detection and “not a parameter of” wording.
  * **passthrough** ([`Iterable`](https://docs.python.org/3/library/typing.html#typing.Iterable)[[`str`](https://docs.python.org/3/builtins/stdtypes.html#str)]) – Names passed through untranslated and unreported.
  * **skip_none** ([`bool`](https://docs.python.org/3/builtins/functions.html#bool)) – Treat a `None` value as unset: never sent, never reported.
  * **out_of_range** ([`str`](https://docs.python.org/3/builtins/stdtypes.html#str)) – The default for specs that do not set their own.
  * **stacklevel** ([`int`](https://docs.python.org/3/builtins/functions.html#int)) – The frame a `'warn'` points at, counted from the code that
    calls `translate` (1 = that code, 2 = its caller).
* **Return type:**
  [`Callable`](https://docs.python.org/3/library/typing.html#typing.Callable)[[`...`](https://docs.python.org/3/builtins/constants.html#Ellipsis), [`Translation`](_autosummary/ocracy.kit.translation.html.md#ocracy.kit.translation.Translation)]
* **Returns:**
  `translate`. Its optional `on_unsupported=` is the *caller’s* policy for
  this one call; when given it replaces both the backend’s policy and
  `always_raise`.

### ocracy.kit.resolve_credential(provider=None, \*, api_key=None, env_var=None, provider_env_vars=None, guidance=None, store=None, dotenv=False, prompt_if_missing=False, required=True, error=<class 'ocracy.kit.credentials.MissingCredentialError'>, hint='')

Resolve a provider’s credential through the chain in the module docstring.

* **Parameters:**
  * **provider** ([`Optional`](https://docs.python.org/3/library/typing.html#typing.Optional)[[`str`](https://docs.python.org/3/builtins/stdtypes.html#str)]) – The provider id, used for bindings, table rows and messages.
  * **api_key** ([`Optional`](https://docs.python.org/3/library/typing.html#typing.Optional)[[`str`](https://docs.python.org/3/builtins/stdtypes.html#str)]) – An explicit value; wins when non-empty.
  * **env_var** (`Union`[[`str`](https://docs.python.org/3/builtins/stdtypes.html#str), [`Sequence`](https://docs.python.org/3/library/typing.html#typing.Sequence)[[`str`](https://docs.python.org/3/builtins/stdtypes.html#str)], [`None`](https://docs.python.org/3/builtins/constants.html#None)]) – Env var name(s) checked before the provider’s table row.
  * **provider_env_vars** ([`Optional`](https://docs.python.org/3/library/typing.html#typing.Optional)[[`Mapping`](https://docs.python.org/3/library/typing.html#typing.Mapping)[[`str`](https://docs.python.org/3/builtins/stdtypes.html#str), `Union`[[`str`](https://docs.python.org/3/builtins/stdtypes.html#str), [`Sequence`](https://docs.python.org/3/library/typing.html#typing.Sequence)[[`str`](https://docs.python.org/3/builtins/stdtypes.html#str)], [`None`](https://docs.python.org/3/builtins/constants.html#None)]]]) – The package’s provider -> env var(s) table.
  * **guidance** ([`Optional`](https://docs.python.org/3/library/typing.html#typing.Optional)[[`Mapping`](https://docs.python.org/3/library/typing.html#typing.Mapping)]) – The package’s provider -> `{note, get_key_url}` table.
  * **store** ([`Optional`](https://docs.python.org/3/library/typing.html#typing.Optional)[[`Mapping`](https://docs.python.org/3/library/typing.html#typing.Mapping)[[`str`](https://docs.python.org/3/builtins/stdtypes.html#str), [`str`](https://docs.python.org/3/builtins/stdtypes.html#str)]]) – A mapping keyed by env-var name, read after the environment.
  * **dotenv** ([`bool`](https://docs.python.org/3/builtins/functions.html#bool)) – On an environment miss, load a project `.env` (searched from the
    current directory, never overriding) and look again.
  * **prompt_if_missing** ([`bool`](https://docs.python.org/3/builtins/functions.html#bool)) – Ask with `getpass` when interactive (last resort).
  * **required** ([`bool`](https://docs.python.org/3/builtins/functions.html#bool)) – Raise when nothing resolves; else return `None`.
  * **error** ([`Callable`](https://docs.python.org/3/library/typing.html#typing.Callable)[[[`str`](https://docs.python.org/3/builtins/stdtypes.html#str)], [`BaseException`](https://docs.python.org/3/builtins/exceptions.html#BaseException)]) – The exception to raise, called with the message. When it builds a
    [`MissingCredentialError`](_autosummary/ocracy.kit.html.md#ocracy.kit.MissingCredentialError) (or subclass), its `provider`,
    `env_vars` and `get_key_url` attributes are filled in.
  * **hint** ([`str`](https://docs.python.org/3/builtins/stdtypes.html#str)) – An extra sentence for the error message (why this key is needed).
* **Return type:**
  [`Optional`](https://docs.python.org/3/library/typing.html#typing.Optional)[[`str`](https://docs.python.org/3/builtins/stdtypes.html#str)]
* **Returns:**
  The secret, or `None` when `required=False` and nothing resolved.

### ocracy.kit.run_install(req, , package, yes=False, verify_code=None, upgrade=False)

Plan (default) or run (`yes=True`) the pip install that `req` describes.

* **Parameters:**
  * **req** ([`Requirements`](_autosummary/ocracy.kit.install.html.md#ocracy.kit.install.Requirements)) – The plan, from [`build_requirements()`](_autosummary/ocracy.kit.html.md#ocracy.kit.build_requirements).
  * **package** ([`str`](https://docs.python.org/3/builtins/stdtypes.html#str)) – The distribution whose extra to install.
  * **yes** ([`bool`](https://docs.python.org/3/builtins/functions.html#bool)) – Actually run pip; otherwise a dry run that changes nothing.
  * **verify_code** ([`Optional`](https://docs.python.org/3/library/typing.html#typing.Optional)[[`str`](https://docs.python.org/3/builtins/stdtypes.html#str)]) – Python source run in a fresh interpreter after a successful
    install; `available_after` is whether it printed `True`.
  * **upgrade** ([`bool`](https://docs.python.org/3/builtins/functions.html#bool)) – Pass `--upgrade` to pip.
* **Return type:**
  [`dict`](https://docs.python.org/3/builtins/stdtypes.html#dict)
* **Returns:**
  `{backend, requirements, ran, available_before, message?, pip_argv?,
  returncode?, stdout_tail?, stderr_tail?, available_after?, system_todo?}`.

### ocracy.kit.using_credentials(keys=None, , \*\*provider_keys)

Bind provider keys for the `with` block (overlaying any outer binding).

Pass a mapping for provider ids that are not identifiers (`"google-vision"`)
or keywords for the rest. Falsy values are ignored, so an optional request
header can be passed straight through.

* **Return type:**
  [`Iterator`](https://docs.python.org/3/library/typing.html#typing.Iterator)[[`dict`](https://docs.python.org/3/builtins/stdtypes.html#dict)]

```pycon
>>> with using_credentials(acme="outer"):
...     with using_credentials({"acme": "inner", "other": None}):
...         inner = current_credentials()
...     outer = current_credentials()
>>> inner, outer
({'acme': 'inner'}, {'acme': 'outer'})
```

### Modules

| [`credentials`](_autosummary/ocracy.kit.credentials.html.md#module-ocracy.kit.credentials)   | One credential chain for every facade: explicit -> bound -> env -> store -> prompt.   |
|----------------------------------------------------------------------------------------------|---------------------------------------------------------------------------------------|
| [`install`](_autosummary/ocracy.kit.install.html.md#module-ocracy.kit.install)           | Install plans: what a backend needs on *this* OS, as data an agent can act on.        |
| [`translation`](_autosummary/ocracy.kit.translation.html.md#module-ocracy.kit.translation)   | Canonical -> native keyword translation, with an honest unsupported-parameter policy. |


# _autosummary/ocracy.kit.install.html.md

# ocracy.kit.install

Install plans: what a backend needs on *this* OS, as data an agent can act on.

Many backends are not one `pip install` away: a system binary (`brew install
tesseract`), a GPU wheel, first-run model weights, a credential. A package keeps
that knowledge as a `recipes` table (backend id -> recipe) and this module turns
one recipe into a [`Requirements`](_autosummary/ocracy.kit.install.html.md#ocracy.kit.install.Requirements) whose [`instructions()`](_autosummary/ocracy.kit.install.html.md#ocracy.kit.install.Requirements.instructions) is a
copy-pasteable plan:

```default
>>> req = build_requirements(
...     "tess", package="ocracy", implemented=True, available=False,
...     recipe={"system": {"linux": ["apt-get install tesseract-ocr"]}},
...     platform="linux",
... )
>>> req.pip_command
'pip install "ocracy[tess]"'
>>> req.system
['apt-get install tesseract-ocr']
```

A recipe needs only the fields that differ from the trivial
`pip install "<package>[<id>]"`: `extra` (the pyproject extra, when it differs
from the id), `system` (platform -> shell commands), `system_note`, `gpu` (an
alternative pip line), `weights` (first-run downloads), `heavy`, `alt` (a
lighter backend) and `notes`.

[`run_install()`](_autosummary/ocracy.kit.install.html.md#ocracy.kit.install.run_install) executes the pip part of a plan (`yes=True` only) and verifies
it in a fresh interpreter. System commands and GPU wheels are surfaced, never run:
they need sudo, brew, or a CUDA choice only the user can make.

The registry and ledger lookups stay in the package (they are the package’s
knowledge); [`ocracy.install`](_autosummary/ocracy.html.md#ocracy.install) is the worked example. Stdlib only; imports
nothing else from ocracy.

### Functions

| [`current_platform`](_autosummary/ocracy.kit.install.html.md#ocracy.kit.install.current_platform)()                               | `'darwin'`, `'linux'`, `'windows'`, or `sys.platform` for anything else.                                              |
|---------------------------------------------------------------------------------------------------|-----------------------------------------------------------------------------------------------------------------------|
| [`build_requirements`](_autosummary/ocracy.kit.install.html.md#ocracy.kit.install.build_requirements)(backend_id, \*, package, ...) | Build [`Requirements`](_autosummary/ocracy.kit.install.html.md#ocracy.kit.install.Requirements) for `backend_id` from its recipe and known facts. |
| [`run_install`](_autosummary/ocracy.kit.install.html.md#ocracy.kit.install.run_install)(req, \*, package[, yes, ...])        | Plan (default) or run (`yes=True`) the pip install that `req` describes.                                              |

### Classes

| [`Requirements`](_autosummary/ocracy.kit.install.html.md#ocracy.kit.install.Requirements)(backend_id, implemented, ...[, ...])   | What a backend needs to run, structured for an agent to act on.   |
|------------------------------------------------------------------------------------------------------|-------------------------------------------------------------------|

### *class* ocracy.kit.install.Requirements(backend_id, implemented, available, is_local, is_remote, pip_command, extra=None, system=<factory>, system_note=None, gpu=None, weights=None, heavy=False, alternative=None, credentials=<factory>, notes=<factory>, verify_command=None, alternative_label='Lighter alternative')

Bases: [`object`](https://docs.python.org/3/builtins/functions.html#object)

What a backend needs to run, structured for an agent to act on.

#### instructions()

An agent- and human-readable, copy-pasteable install plan.

* **Return type:**
  [`str`](https://docs.python.org/3/builtins/stdtypes.html#str)

### ocracy.kit.install.build_requirements(backend_id, , package, implemented, available, recipe=None, is_local=False, is_remote=False, ledger_pip='', credentials=(), platform=None, verify_command=None, unimplemented_note=None, alternative_label='Lighter alternative')

Build [`Requirements`](_autosummary/ocracy.kit.install.html.md#ocracy.kit.install.Requirements) for `backend_id` from its recipe and known facts.

* **Parameters:**
  * **backend_id** ([`str`](https://docs.python.org/3/builtins/stdtypes.html#str)) – The backend’s id.
  * **package** ([`str`](https://docs.python.org/3/builtins/stdtypes.html#str)) – The distribution whose extra installs it (`pip install "pkg[x]"`).
  * **implemented** ([`bool`](https://docs.python.org/3/builtins/functions.html#bool)) – Whether the package ships a facade for it.
  * **available** ([`bool`](https://docs.python.org/3/builtins/functions.html#bool)) – Whether it is usable right now (the package’s own probe).
  * **recipe** ([`Optional`](https://docs.python.org/3/library/typing.html#typing.Optional)[[`Mapping`](https://docs.python.org/3/library/typing.html#typing.Mapping)]) – Its row of the package’s recipes table (see the module docstring).
  * **is_remote** ([`bool`](https://docs.python.org/3/builtins/functions.html#bool)) – From the backend’s config or ledger record.
  * **ledger_pip** ([`str`](https://docs.python.org/3/builtins/stdtypes.html#str)) – The ledger’s install line, used for a backend not implemented.
  * **credentials** ([`Iterable`](https://docs.python.org/3/library/typing.html#typing.Iterable)[[`str`](https://docs.python.org/3/builtins/stdtypes.html#str)]) – `export` lines (see [`credential_lines()`](_autosummary/ocracy.kit.credentials.html.md#ocracy.kit.credentials.credential_lines)).
  * **platform** ([`Optional`](https://docs.python.org/3/library/typing.html#typing.Optional)[[`str`](https://docs.python.org/3/builtins/stdtypes.html#str)]) – Override [`current_platform()`](_autosummary/ocracy.kit.install.html.md#ocracy.kit.install.current_platform) (for tests and docs).
  * **verify_command** ([`Optional`](https://docs.python.org/3/library/typing.html#typing.Optional)[[`str`](https://docs.python.org/3/builtins/stdtypes.html#str)]) – The shell line shown as `Verify:`.
  * **unimplemented_note** ([`Optional`](https://docs.python.org/3/library/typing.html#typing.Optional)[[`str`](https://docs.python.org/3/builtins/stdtypes.html#str)]) – Appended to `notes` when not implemented.
  * **alternative_label** ([`str`](https://docs.python.org/3/builtins/stdtypes.html#str)) – The wording before `alt` in the instructions.
* **Return type:**
  [`Requirements`](_autosummary/ocracy.kit.install.html.md#ocracy.kit.install.Requirements)

### ocracy.kit.install.current_platform()

`'darwin'`, `'linux'`, `'windows'`, or `sys.platform` for anything else.

* **Return type:**
  [`str`](https://docs.python.org/3/builtins/stdtypes.html#str)

### ocracy.kit.install.run_install(req, , package, yes=False, verify_code=None, upgrade=False)

Plan (default) or run (`yes=True`) the pip install that `req` describes.

* **Parameters:**
  * **req** ([`Requirements`](_autosummary/ocracy.kit.install.html.md#ocracy.kit.install.Requirements)) – The plan, from [`build_requirements()`](_autosummary/ocracy.kit.install.html.md#ocracy.kit.install.build_requirements).
  * **package** ([`str`](https://docs.python.org/3/builtins/stdtypes.html#str)) – The distribution whose extra to install.
  * **yes** ([`bool`](https://docs.python.org/3/builtins/functions.html#bool)) – Actually run pip; otherwise a dry run that changes nothing.
  * **verify_code** ([`Optional`](https://docs.python.org/3/library/typing.html#typing.Optional)[[`str`](https://docs.python.org/3/builtins/stdtypes.html#str)]) – Python source run in a fresh interpreter after a successful
    install; `available_after` is whether it printed `True`.
  * **upgrade** ([`bool`](https://docs.python.org/3/builtins/functions.html#bool)) – Pass `--upgrade` to pip.
* **Return type:**
  [`dict`](https://docs.python.org/3/builtins/stdtypes.html#dict)
* **Returns:**
  `{backend, requirements, ran, available_before, message?, pip_argv?,
  returncode?, stdout_tail?, stderr_tail?, available_after?, system_todo?}`.


# _autosummary/ocracy.kit.translation.html.md

# ocracy.kit.translation

Canonical -> native keyword translation, with an honest unsupported-parameter policy.

A facade speaks one vocabulary (`languages`, `duration`, `seed`); each backend
speaks its own (`lang`, `audio_length_s`, `random_seed`). A backend declares a
`param_map` from canonical names to *specs*, and [`make_translator()`](_autosummary/ocracy.kit.translation.html.md#ocracy.kit.translation.make_translator) turns it
into a function that rewrites the caller’s canonical kwargs into native ones and
**reports every change** it made:

```default
>>> translate = make_translator(
...     {"languages": {"native_name": "lang", "coerce": "+".join},
...      "dpi": None},                       # known, explicitly unsupported
...     backend="tess", on_unsupported="note",
... )
>>> t = translate({"languages": ["eng", "fra"], "dpi": 300})
>>> t.kwargs
{'lang': 'eng+fra'}
>>> t.notes
['dpi=300 is not supported by tess; dropped']
>>> t.dropped
['dpi']
```

A spec is one of:

- `None` – the backend explicitly does not support the parameter;
- a `str` – a plain rename to that native name;
- a callable – coerce the value, keep the canonical name;
- a mapping with any of: `native_name` (`name` is accepted as an alias),
  `coerce`, `default` (injected when the caller omits the parameter),
  `choices` / `min` / `max` (checked on the *canonical* value), and
  `out_of_range` – `'raise'`, `'clamp'` (`min`/`max` only, with a note) or
  `'drop'` (handled like an unsupported parameter); the translator’s
  `out_of_range=` is the default – plus `unit` (shown in the clamp note).
  `native_name: None` means unsupported, exactly like a bare `None`.
  `adapter_handled: True` passes the value through under its canonical name, for
  the adapter to handle (whatever `native_name` says). Other keys
  (`description`…) are ignored.

The policy for a parameter the backend cannot honour is one of [`POLICIES`](_autosummary/ocracy.kit.translation.html.md#ocracy.kit.translation.POLICIES):
`'raise'` ([`UnsupportedParameter`](_autosummary/ocracy.kit.translation.html.md#ocracy.kit.translation.UnsupportedParameter)), `'warn'` (drop, note it, and
[`warnings.warn()`](https://docs.python.org/3/library/warnings.html#warnings.warn)), `'note'` (drop and note it), or `'ignore'` (an alias of
`'note'`: kept for the copies that used it, and still never silent – the drop is
always in [`Translation.notes`](_autosummary/ocracy.kit.translation.html.md#ocracy.kit.translation.Translation.notes) and [`Translation.dropped`](_autosummary/ocracy.kit.translation.html.md#ocracy.kit.translation.Translation.dropped)).

Notes, warnings and errors show the dropped value, shortened, so a reader knows what
was lost – but never a secret, because notes end up in results that get stored and
logged. A parameter or mapping key named like one ([`is_secret_name()`](_autosummary/ocracy.kit.translation.html.md#ocracy.kit.translation.is_secret_name):
`api_key`, `x-api-key`, `accessToken`, `client_secret`…) or a string shaped
like one (`Bearer ...`, `https://user:pw@host`, `?key=...`) is shown as
`<redacted>`, and anything that is not plain data (an object, bytes) is shown only
as its type. This is best-effort by name and shape: a secret passed under an
innocent name, with no recognisable shape, can still show – so credentials belong
in parameters named for them.

Several choices are declared once, when the translator is made, and each was a real
divergence between the fleet’s copies (see `docs/adr/0001-facade-kit.md`):

- `always_raise` – parameters that *carry meaning* (`lyrics`, `seed`,
  `negative_prompt`): dropping them changes what the caller gets, so they raise
  under the backend’s policy. A caller who passes `on_unsupported=` to the
  translator call has chosen explicitly, and that choice wins.
- `vocabulary` – the facade’s canonical names mapped to their defaults. With it,
  an unsupported parameter left at its default (or `None`) was never asked for, so
  it is skipped rather than reported as dropped, and an unknown name is worded
  “not a parameter of” rather than “not supported by”.
- `skip_none` / `passthrough` – a `None` value means “unset” and is never sent;
  named adapter-only parameters (credentials, clients) go through untranslated.
- `stacklevel` – which frame a `'warn'` points at, counted from the code that
  calls the translator (1 = that code, 2 = its caller…).

Stdlib only; imports nothing else from ocracy.

### Module Attributes

| [`POLICIES`](_autosummary/ocracy.kit.translation.html.md#ocracy.kit.translation.POLICIES)        | How a parameter the backend cannot honour is handled.                                                                                                                                                      |
|------------------------------------------------------------------|------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| [`OUT_OF_RANGE`](_autosummary/ocracy.kit.translation.html.md#ocracy.kit.translation.OUT_OF_RANGE)    | How a value outside a spec's `choices` / `min` / `max` is handled.                                                                                                                                         |
| [`SECRET_SEGMENTS`](_autosummary/ocracy.kit.translation.html.md#ocracy.kit.translation.SECRET_SEGMENTS) | Name segments (split on `_ - .`, spaces and camelCase, case-insensitive) that make a value secret wherever they appear: `api_key`, `x-api-key`, `aws_access_key_id`, `accessToken`, `client_secret_value`. |
| [`SECRET_VALUE`](_autosummary/ocracy.kit.translation.html.md#ocracy.kit.translation.SECRET_VALUE)    | an auth scheme (`Bearer ...`), a URL carrying a user:password or a key-like query.                                                                                                                         |

### Functions

| [`make_translator`](_autosummary/ocracy.kit.translation.html.md#ocracy.kit.translation.make_translator)(param_map, \*[, backend, ...])   | Build `translate(kwargs, *, on_unsupported=None) -> Translation` from a map.   |
|---------------------------------------------------------------------------------------------------|--------------------------------------------------------------------------------|
| [`check_range`](_autosummary/ocracy.kit.translation.html.md#ocracy.kit.translation.check_range)(name, value, spec)                   | Raise `ValueError` unless `value` fits `spec`'s `min`/`max`/`choices`.         |
| [`is_secret_name`](_autosummary/ocracy.kit.translation.html.md#ocracy.kit.translation.is_secret_name)(name)                             | Whether a parameter (or mapping key) named `name` may hold a secret.           |

### Classes

| [`Translation`](_autosummary/ocracy.kit.translation.html.md#ocracy.kit.translation.Translation)([kwargs, notes, dropped])   | What a translator produced: the native kwargs, and every change it made.   |
|------------------------------------------------------------------------------------------|----------------------------------------------------------------------------|

### Exceptions

| [`UnsupportedParameter`](_autosummary/ocracy.kit.translation.html.md#ocracy.kit.translation.UnsupportedParameter)   | A backend cannot honour a parameter, and the policy says not to drop it.   |
|-------------------------------------------------------------------------|----------------------------------------------------------------------------|

### ocracy.kit.translation.OUT_OF_RANGE *= ('raise', 'clamp', 'drop')*

How a value outside a spec’s `choices` / `min` / `max` is handled.

### ocracy.kit.translation.POLICIES *= ('raise', 'warn', 'note', 'ignore')*

How a parameter the backend cannot honour is handled.

### ocracy.kit.translation.SECRET_SEGMENTS *= frozenset({'apikey', 'auth', 'authorization', 'bearer', 'cookie', 'credential', 'credentials', 'key', 'passphrase', 'passwd', 'password', 'private', 'pwd', 'secret', 'session', 'sig', 'signature', 'token'})*

Name segments (split on `_ - .`, spaces and camelCase, case-insensitive) that
make a value secret wherever they appear: `api_key`, `x-api-key`,
`aws_access_key_id`, `accessToken`, `client_secret_value`. The rule errs
toward hiding: `key_frames` or a musical `key` are hidden too, which costs a
drop note its value and nothing else.

### ocracy.kit.translation.SECRET_VALUE *= re.compile('^\\\\s\*(bearer|basic|token)\\\\s+\\\\S|://[^/\\\\s:@]+:[^/\\\\s@]+@|[?&#](api_?key|key|token|access_token|auth|sig|signature|password)=', re.IGNORECASE)*

an auth
scheme (`Bearer ...`), a URL carrying a user:password or a key-like query.

* **Type:**
  String values that are credentials whatever the parameter is called

### *class* ocracy.kit.translation.Translation(kwargs=<factory>, notes=<factory>, dropped=<factory>)

Bases: [`object`](https://docs.python.org/3/builtins/functions.html#object)

What a translator produced: the native kwargs, and every change it made.

#### kwargs

The native kwargs to pass to the backend.

#### notes

One human-readable line per drop or clamp, for the facade’s result.

#### dropped

The canonical names that were dropped.

### *exception* ocracy.kit.translation.UnsupportedParameter

Bases: [`ValueError`](https://docs.python.org/3/builtins/exceptions.html#ValueError)

A backend cannot honour a parameter, and the policy says not to drop it.

### ocracy.kit.translation.check_range(name, value, spec)

Raise `ValueError` unless `value` fits `spec`’s `min`/`max`/`choices`.

The standalone form of the translator’s `out_of_range='raise'` check; returns
`value` unchanged. `None` is “unset” and always fits.

* **Return type:**
  [`Any`](https://docs.python.org/3/library/typing.html#typing.Any)

### ocracy.kit.translation.is_secret_name(name)

Whether a parameter (or mapping key) named `name` may hold a secret.

* **Return type:**
  [`bool`](https://docs.python.org/3/builtins/functions.html#bool)

### ocracy.kit.translation.make_translator(param_map, , backend='', on_unsupported='warn', always_raise=(), vocabulary=None, passthrough=(), skip_none=False, out_of_range='raise', stacklevel=2)

Build `translate(kwargs, *, on_unsupported=None) -> Translation` from a map.

* **Parameters:**
  * **param_map** ([`Mapping`](https://docs.python.org/3/library/typing.html#typing.Mapping)[[`str`](https://docs.python.org/3/builtins/stdtypes.html#str), [`Any`](https://docs.python.org/3/library/typing.html#typing.Any)]) – Canonical name -> spec (see the module docstring). Specs are
    validated here, so a malformed map fails when the backend loads, not on
    the first call that happens to use the bad entry.
  * **backend** ([`str`](https://docs.python.org/3/builtins/stdtypes.html#str)) – The backend’s name, used in notes and errors.
  * **on_unsupported** ([`str`](https://docs.python.org/3/builtins/stdtypes.html#str)) – The backend’s policy (one of [`POLICIES`](_autosummary/ocracy.kit.translation.html.md#ocracy.kit.translation.POLICIES)).
  * **always_raise** ([`Iterable`](https://docs.python.org/3/library/typing.html#typing.Iterable)[[`str`](https://docs.python.org/3/builtins/stdtypes.html#str)]) – Canonical names that raise under the backend’s policy because
    dropping them changes what the caller gets.
  * **vocabulary** ([`Optional`](https://docs.python.org/3/library/typing.html#typing.Optional)[[`Mapping`](https://docs.python.org/3/library/typing.html#typing.Mapping)[[`str`](https://docs.python.org/3/builtins/stdtypes.html#str), [`Any`](https://docs.python.org/3/library/typing.html#typing.Any)]]) – The facade’s canonical names -> their default values. Enables
    “not asked for” detection and “not a parameter of” wording.
  * **passthrough** ([`Iterable`](https://docs.python.org/3/library/typing.html#typing.Iterable)[[`str`](https://docs.python.org/3/builtins/stdtypes.html#str)]) – Names passed through untranslated and unreported.
  * **skip_none** ([`bool`](https://docs.python.org/3/builtins/functions.html#bool)) – Treat a `None` value as unset: never sent, never reported.
  * **out_of_range** ([`str`](https://docs.python.org/3/builtins/stdtypes.html#str)) – The default for specs that do not set their own.
  * **stacklevel** ([`int`](https://docs.python.org/3/builtins/functions.html#int)) – The frame a `'warn'` points at, counted from the code that
    calls `translate` (1 = that code, 2 = its caller).
* **Return type:**
  [`Callable`](https://docs.python.org/3/library/typing.html#typing.Callable)[[`...`](https://docs.python.org/3/builtins/constants.html#Ellipsis), [`Translation`](_autosummary/ocracy.kit.translation.html.md#ocracy.kit.translation.Translation)]
* **Returns:**
  `translate`. Its optional `on_unsupported=` is the *caller’s* policy for
  this one call; when given it replaces both the backend’s policy and
  `always_raise`.


# _autosummary/ocracy.make_backend.html.md

# ocracy.make_backend

Abstraction tools for *building* OCR facades.

Writing a new backend should be mostly declarative. This module supplies the
reusable machinery so an adapter is just “call the engine, return normalized
blocks”:

- [`BaseOcrAdapter`](_autosummary/ocracy.make_backend.html.md#ocracy.make_backend.BaseOcrAdapter) — subclass it and implement `_read()`;
  kwarg translation (via the backend’s `param_map`) is handled for you.
- [`make_block()`](_autosummary/ocracy.make_backend.html.md#ocracy.make_backend.make_block) / [`as_bbox()`](_autosummary/ocracy.make_backend.html.md#ocracy.make_backend.as_bbox) — build normalized [`TextBlock`](_autosummary/ocracy.base.html.md#ocracy.base.TextBlock)
  / [`BBox`](_autosummary/ocracy.base.html.md#ocracy.base.BBox) from whatever shape the engine returned, including
  confidence-scale normalization (e.g. Tesseract’s `0..100` -> `0..1`).
- [`scaffold_backend()`](_autosummary/ocracy.make_backend.html.md#ocracy.make_backend.scaffold_backend) — generate a new `ocracy/backends/<id>/` package from
  the template, pre-filled from the ledger entry. This is the one-command way to
  start a facade for any backend in the catalog.
- [`make_test_image()`](_autosummary/ocracy.make_backend.html.md#ocracy.make_backend.make_test_image) / [`validate_adapter()`](_autosummary/ocracy.make_backend.html.md#ocracy.make_backend.validate_adapter) — smoke-test an adapter end
  to end so you know a new facade actually works.

These are the “abstraction tools and skills that know the process” — the
companion `SKILL.md` walks an agent (or human) through using them.

### Functions

| [`make_block`](_autosummary/ocracy.make_backend.html.md#ocracy.make_backend.make_block)(text, \*[, bbox, confidence, ...])   | Build a normalized [`TextBlock`](_autosummary/ocracy.base.html.md#ocracy.base.TextBlock).     |
|--------------------------------------------------------------------------------------------------|----------------------------------------------------------------------------------------------------------|
| [`as_bbox`](_autosummary/ocracy.make_backend.html.md#ocracy.make_backend.as_bbox)(obj)                                    | Coerce common bbox shapes into a [`BBox`](_autosummary/ocracy.base.html.md#ocracy.base.BBox). |
| [`normalize_confidence`](_autosummary/ocracy.make_backend.html.md#ocracy.make_backend.normalize_confidence)(value, \*[, scale])        | Normalize a raw confidence to `[0, 1]` (dividing by `scale`).                                            |
| [`scaffold_backend`](_autosummary/ocracy.make_backend.html.md#ocracy.make_backend.scaffold_backend)(backend_id, \*[, dest, ...])   | Create a new `ocracy/backends/<id>/` package from the template.                                          |
| [`make_test_image`](_autosummary/ocracy.make_backend.html.md#ocracy.make_backend.make_test_image)([text, size, font_size])        | Render a black-on-white test image with `text` (needs Pillow).                                           |
| [`validate_adapter`](_autosummary/ocracy.make_backend.html.md#ocracy.make_backend.validate_adapter)(backend_id, \*[, image, ...])  | Smoke-test a backend adapter end to end, returning a report dict.                                        |

### Classes

| [`BaseOcrAdapter`](_autosummary/ocracy.make_backend.html.md#ocracy.make_backend.BaseOcrAdapter)(config)   | Optional base class for backend adapters.   |
|---------------------------------------------------------------------------|---------------------------------------------|

### *class* ocracy.make_backend.BaseOcrAdapter(config)

Bases: [`object`](https://docs.python.org/3/builtins/functions.html#object)

Optional base class for backend adapters.

Stores the config, builds a kwarg translator from `config['param_map']`,
and implements `read` as: translate normalized kwargs -> native kwargs ->
`_read()`. Subclasses implement `_read()` and return an
[`OcrResult`](_autosummary/ocracy.base.html.md#ocracy.base.OcrResult).

Adapters are not *required* to subclass this — the registry only needs an
`Adapter` class with a `read(image, **kwargs)` method — but doing so
removes the boilerplate.

#### ADAPTER_KWARGS *= ('api_key', 'app_key', 'app_id')*

Keyword arguments a *remote* adapter reads itself (credentials), passed
through untranslated: no `param_map` declares them, and they must never be
dropped. On a local backend they are dropped with a (redacted) note.

#### read(image, \*\*kwargs)

Translate `kwargs`, run `_read()`, and put any drop notes on the result.

A parameter the backend cannot honour is warned about and dropped, and the
drop is recorded in `result.meta["notes"]` so it is visible after the
warning is gone (or filtered).

* **Return type:**
  [`OcrResult`](_autosummary/ocracy.base.html.md#ocracy.base.OcrResult)

### ocracy.make_backend.as_bbox(obj)

Coerce common bbox shapes into a [`BBox`](_autosummary/ocracy.base.html.md#ocracy.base.BBox).

Accepts a `BBox` (returned as-is), a 4-tuple `(x0, y0, x1, y1)`, or a
polygon `[(x, y), ...]` (4+ points). `None` passes through.

* **Return type:**
  [`Optional`](https://docs.python.org/3/library/typing.html#typing.Optional)[[`BBox`](_autosummary/ocracy.base.html.md#ocracy.base.BBox)]

### ocracy.make_backend.make_block(text, , bbox=None, confidence=None, conf_scale=1.0, level='word', language=None, \*\*meta)

Build a normalized [`TextBlock`](_autosummary/ocracy.base.html.md#ocracy.base.TextBlock).

`bbox` may be any shape accepted by [`as_bbox()`](_autosummary/ocracy.make_backend.html.md#ocracy.make_backend.as_bbox). `confidence` is
normalized to `[0, 1]` via `conf_scale` (e.g. `conf_scale=100` for
percent-scale engines).

* **Return type:**
  [`TextBlock`](_autosummary/ocracy.base.html.md#ocracy.base.TextBlock)

### ocracy.make_backend.make_test_image(text='OCR test 123', , size=(640, 140), font_size=48)

Render a black-on-white test image with `text` (needs Pillow).

Uses a real TrueType font (DejaVuSans, then Pillow’s sized default) at a
legible size so OCR engines can actually read it — important for
[`validate_adapter()`](_autosummary/ocracy.make_backend.html.md#ocracy.make_backend.validate_adapter) to be a meaningful smoke test.

### ocracy.make_backend.normalize_confidence(value, , scale=1.0)

Normalize a raw confidence to `[0, 1]` (dividing by `scale`).

`None` passes through. Use `scale=100` for engines that report `0..100`.

* **Return type:**
  [`Optional`](https://docs.python.org/3/library/typing.html#typing.Optional)[[`float`](https://docs.python.org/3/builtins/functions.html#float)]

### ocracy.make_backend.scaffold_backend(backend_id, , dest=None, overwrite=False, ledger=None, extra_overrides=None)

Create a new `ocracy/backends/<id>/` package from the template.

Pre-fills `config.py` from the backend’s ledger entry (if any) so you only
have to flesh out `param_map` and implement `adapter.py`’s `_read`.

* **Parameters:**
  * **backend_id** ([`str`](https://docs.python.org/3/builtins/stdtypes.html#str)) – The ledger id (e.g. `"easyocr"`, `"google-vision"`). The
    on-disk module name uses underscores; the config `id` keeps the id
    verbatim.
  * **dest** (`Union`[[`str`](https://docs.python.org/3/builtins/stdtypes.html#str), [`Path`](https://docs.python.org/3/library/pathlib.html#pathlib.Path), [`None`](https://docs.python.org/3/builtins/constants.html#None)]) – Target directory (defaults to `ocracy/backends/<id_underscored>`).
  * **overwrite** ([`bool`](https://docs.python.org/3/builtins/functions.html#bool)) – Allow writing into an existing non-empty directory.
  * **ledger** ([`Any`](https://docs.python.org/3/library/typing.html#typing.Any)) – A [`Catalog`](_autosummary/ocracy.html.md#ocracy.Catalog) to read the record from
    (defaults to the shipped catalog).
  * **extra_overrides** ([`Optional`](https://docs.python.org/3/library/typing.html#typing.Optional)[[`dict`](https://docs.python.org/3/builtins/stdtypes.html#dict)]) – Extra config-key overrides applied on top of the record.
* **Return type:**
  [`Path`](https://docs.python.org/3/library/pathlib.html#pathlib.Path)
* **Returns:**
  The path to the created backend package.

### ocracy.make_backend.validate_adapter(backend_id, , image=None, expect_text=None)

Smoke-test a backend adapter end to end, returning a report dict.

Loads the adapter (reporting unavailability instead of raising), runs
`read` on a generated (or supplied) image, and checks the contract: an
[`OcrResult`](_autosummary/ocracy.base.html.md#ocracy.base.OcrResult) came back with text and/or blocks. Never
raises on a *recognition* mismatch — it returns what happened so callers can
decide.

* **Return type:**
  [`dict`](https://docs.python.org/3/builtins/stdtypes.html#dict)


# _autosummary/ocracy.registry.html.md

# ocracy.registry

Backend discovery, registration, and lazy loading.

An *implemented* backend is a subpackage of [`ocracy.backends`](_autosummary/ocracy.backends.html.md#module-ocracy.backends) that ships
two things:

- `config.py` defining a `BACKEND_CONFIG` dict (id, pip_install, capabilities,
  `param_map`, …), and
- `adapter.py` defining an `Adapter` class whose `read(image, **kwargs)`
  returns an [`ocracy.base.OcrResult`](_autosummary/ocracy.base.html.md#ocracy.base.OcrResult).

This registry scans for those at first use, loads each adapter *lazily* (so
importing ocracy never imports heavy engine SDKs), and raises a friendly
`pip install` error if a backend’s dependency is missing. Third parties can
register their own backends at runtime via [`register_backend()`](_autosummary/ocracy.registry.html.md#ocracy.registry.register_backend).

The design mirrors the sibling `denote` facade, adapted for OCR: the primary
capability is `"read"` (image -> text+layout), with optional extra capabilities
(`"tables"`, `"math"`, …) declared per backend.

### Module Attributes

| [`PRIMARY_CAPABILITY`](_autosummary/ocracy.registry.html.md#ocracy.registry.PRIMARY_CAPABILITY)   | The capability every general OCR backend provides.   |
|-----------------------------------------------------------------------|------------------------------------------------------|

### Functions

| [`clear_registry`](_autosummary/ocracy.registry.html.md#ocracy.registry.clear_registry)()                                | Clear all registered backends (useful for tests).                      |
|--------------------------------------------------------------------------------------------------|------------------------------------------------------------------------|
| [`get_backend`](_autosummary/ocracy.registry.html.md#ocracy.registry.get_backend)(backend_id)                         | Config + lazily-loaded adapter for a backend (raises on missing deps). |
| [`get_config`](_autosummary/ocracy.registry.html.md#ocracy.registry.get_config)(backend_id)                          | A backend's `BACKEND_CONFIG` without loading its adapter.              |
| [`get_default_backend`](_autosummary/ocracy.registry.html.md#ocracy.registry.get_default_backend)([capability, ...])          | Pick a sensible default backend id for a capability.                   |
| [`list_backends`](_autosummary/ocracy.registry.html.md#ocracy.registry.list_backends)([capability])                     | Sorted ids of implemented backends, optionally filtered by capability. |
| [`register_backend`](_autosummary/ocracy.registry.html.md#ocracy.registry.register_backend)(backend_id, config[, adapter]) | Register a backend at runtime (for third-party plugins).               |

### ocracy.registry.PRIMARY_CAPABILITY *= 'read'*

The capability every general OCR backend provides.

### ocracy.registry.clear_registry()

Clear all registered backends (useful for tests).

* **Return type:**
  [`None`](https://docs.python.org/3/builtins/constants.html#None)

### ocracy.registry.get_backend(backend_id)

Config + lazily-loaded adapter for a backend (raises on missing deps).

* **Return type:**
  [`dict`](https://docs.python.org/3/builtins/stdtypes.html#dict)

### ocracy.registry.get_config(backend_id)

A backend’s `BACKEND_CONFIG` without loading its adapter.

* **Return type:**
  [`dict`](https://docs.python.org/3/builtins/stdtypes.html#dict)

### ocracy.registry.get_default_backend(capability='read', , require_available=True)

Pick a sensible default backend id for a capability.

Strategy (OCR-tuned): prefer a backend explicitly flagged `default_for` the
capability *and* whose dependency is importable; then any importable backend
for the capability; then — if `require_available` is False or nothing is
installed — the first registered candidate (using it will raise a helpful
install error).

* **Return type:**
  [`str`](https://docs.python.org/3/builtins/stdtypes.html#str)

### ocracy.registry.list_backends(capability=None)

Sorted ids of implemented backends, optionally filtered by capability.

A backend matches `capability` if it appears in the backend’s
`capabilities` list (the primary `"read"` is implied for all).

* **Return type:**
  [`List`](https://docs.python.org/3/library/typing.html#typing.List)[[`str`](https://docs.python.org/3/builtins/stdtypes.html#str)]

### ocracy.registry.register_backend(backend_id, config, adapter=None)

Register a backend at runtime (for third-party plugins).

* **Parameters:**
  * **backend_id** ([`str`](https://docs.python.org/3/builtins/stdtypes.html#str)) – Unique identifier.
  * **config** ([`dict`](https://docs.python.org/3/builtins/stdtypes.html#dict)) – `BACKEND_CONFIG`-shaped dict (needs at least `name`).
  * **adapter** ([`Any`](https://docs.python.org/3/library/typing.html#typing.Any)) – Optional pre-instantiated adapter; else loaded lazily from
    `config['module_path']` when first used.
* **Return type:**
  [`None`](https://docs.python.org/3/builtins/constants.html#None)


# _autosummary/ocracy.services.html.md

# ocracy.services

### ocracy.services *: [ServiceCollection](_autosummary/ocracy.html.md#ocracy.ServiceCollection)* *= <ServiceCollection backends=['aws-textract', 'azure-document-intelligence', 'claude-vision', 'easyocr', 'google-vision', 'gpt-4o-vision', 'mathpix', 'mistral-ocr', 'ocr-space', 'ocrmac', 'paddleocr', 'pix2tex-latex-ocr', 'rapidocr', 'tesseract', 'trocr-handwritten']>*

Lazy mapping of backend ids -> `ServiceHandle`.

Supports dict-style (`services['tesseract']`) and attribute-style
(`services.tesseract`) access.


# _autosummary/ocracy.status.html.md

# ocracy.status

Backend readiness status — four nested levels, info dicts, and a Markdown table.

ocracy describes far more OCR engines than any one machine has ready to run, so it
helps to know, at a glance, where each one stands. Four **nested** levels:

1. **all** — every engine in the ledger (`ocracy/data/backends.json`).
2. **implemented** — ocracy ships a working facade for it (`⊆ all`).
3. **set_up** — ready to run *here, now*: the engine/client library is importable
   and, for a remote backend, its credential env var is present (`⊆ implemented`).
4. **tested** — actually produced text from a small image on this machine (`⊆ set_up`).

`all ⊇ implemented ⊇ set_up ⊇ tested`.

API:

- [`backend_ids()`](_autosummary/ocracy.status.html.md#ocracy.status.backend_ids) — the id list at a level.
- [`backend_info()`](_autosummary/ocracy.status.html.md#ocracy.status.backend_info) — `{id: {...all ledger fields..., implemented, set_up, tested}}`.
- [`status_table()`](_autosummary/ocracy.status.html.md#ocracy.status.status_table) — an aligned Markdown table (also readable as plain text).
- [`names_with_sites()`](_autosummary/ocracy.status.html.md#ocracy.status.names_with_sites) — `"Name (website), ..."` for a set of ids.

#### NOTE
computing **tested** runs real OCR — for *remote* backends that means a real
(possibly billed) API call. Use the `run_tests` argument to control exactly which
backends get called.

### Functions

| [`is_set_up`](_autosummary/ocracy.status.html.md#ocracy.status.is_set_up)(backend_id)                      | Ready to run here & now.                                                       |
|---------------------------------------------------------------------------------------------|--------------------------------------------------------------------------------|
| [`is_tested`](_autosummary/ocracy.status.html.md#ocracy.status.is_tested)(backend_id, \*[, image])         | Actually run OCR on `image` (a generated one if None); True iff it worked.     |
| [`backend_ids`](_autosummary/ocracy.status.html.md#ocracy.status.backend_ids)([level, info, test_image])     | Sorted backend ids at a readiness `level` (one of `LEVELS`).                   |
| [`backend_info`](_autosummary/ocracy.status.html.md#ocracy.status.backend_info)([ids, run_tests, test_image]) | Per-backend status: every ledger field plus `implemented`/`set_up`/`tested`.   |
| [`status_table`](_autosummary/ocracy.status.html.md#ocracy.status.status_table)([ids, info, columns, ...])    | Render an aligned Markdown table of backend status (also plain-text readable). |
| [`names_with_sites`](_autosummary/ocracy.status.html.md#ocracy.status.names_with_sites)(ids, \*[, info])          | `"Name (website), Name2 (website2), ..."` for `ids` (name, not id).            |

### ocracy.status.backend_ids(level='all', , info=None, test_image=None)

Sorted backend ids at a readiness `level` (one of `LEVELS`).

Pass a precomputed `info` (from [`backend_info()`](_autosummary/ocracy.status.html.md#ocracy.status.backend_info)) to avoid recomputation
— important for `"tested"`, which otherwise re-runs OCR.

* **Return type:**
  [`List`](https://docs.python.org/3/library/typing.html#typing.List)[[`str`](https://docs.python.org/3/builtins/stdtypes.html#str)]

### ocracy.status.backend_info(ids=None, , run_tests=False, test_image=None)

Per-backend status: every ledger field plus `implemented`/`set_up`/`tested`.

* **Parameters:**
  * **ids** ([`Optional`](https://docs.python.org/3/library/typing.html#typing.Optional)[[`Iterable`](https://docs.python.org/3/library/typing.html#typing.Iterable)[[`str`](https://docs.python.org/3/builtins/stdtypes.html#str)]]) – Which backends (default: every ledger id).
  * **run_tests** – Which set-up backends to actually OCR-test. `True` = all
    set-up (real API calls for remotes!); `False` = none (`tested` is
    `None`); or an iterable of ids to limit testing to those.
  * **test_image** ([`Any`](https://docs.python.org/3/library/typing.html#typing.Any)) – Image to test with (default: a generated one, shared across all).
* **Return type:**
  [`Dict`](https://docs.python.org/3/library/typing.html#typing.Dict)[[`str`](https://docs.python.org/3/builtins/stdtypes.html#str), [`dict`](https://docs.python.org/3/builtins/stdtypes.html#dict)]
* **Returns:**
  `{id: {..., "name", "website", "implemented", "set_up", "tested"}}` where
  `tested` is `True`/`False`/`None` (None = not attempted).

### ocracy.status.is_set_up(backend_id)

Ready to run here & now.

Requires the engine/client to be importable (local *and* remote), and — for a
remote backend — its (primary) credential env var to resolve. So a remote
whose key is set but whose client library isn’t installed is *not* set up
(it couldn’t actually run). Returns False for ledger-only backends.

* **Return type:**
  [`bool`](https://docs.python.org/3/builtins/functions.html#bool)

### ocracy.status.is_tested(backend_id, , image=None)

Actually run OCR on `image` (a generated one if None); True iff it worked.

For remote backends this performs a real API call. Returns False if the
backend isn’t set up or the run fails.

* **Return type:**
  [`bool`](https://docs.python.org/3/builtins/functions.html#bool)

### ocracy.status.names_with_sites(ids, , info=None)

`"Name (website), Name2 (website2), ..."` for `ids` (name, not id).

* **Return type:**
  [`str`](https://docs.python.org/3/builtins/stdtypes.html#str)

### ocracy.status.status_table(ids=None, , info=None, columns=None, run_tests=False, test_image=None)

Render an aligned Markdown table of backend status (also plain-text readable).

Rows are ordered tested → set-up → implemented → listed, then by name, so the
“live” backends float to the top. Pass a precomputed `info` to avoid re-running
tests; otherwise `run_tests` controls which set-up backends get OCR-tested.

* **Return type:**
  [`str`](https://docs.python.org/3/builtins/stdtypes.html#str)


# _autosummary/ocracy.tools.html.md

# ocracy.tools

Command-line tools for ocracy (dispatched via `cw` in `__main__`).

Each function here is a thin, CLI-friendly wrapper over the Python API; `cw`
turns their signatures into subcommands and options. Run `ocracy <command>
--help` (after `pip install 'ocracy[cli]'`) or `python -m ocracy <command>`.

### Functions

| [`read`](_autosummary/ocracy.tools.html.md#ocracy.tools.read)(image, \*[, backend, languages, output])     | OCR an image and print the result.                                                  |
|----------------------------------------------------------------------------------------------------|-------------------------------------------------------------------------------------|
| [`backends`](_autosummary/ocracy.tools.html.md#ocracy.tools.backends)(\*[, capability])                        | List the backends ocracy can run right now (optionally by capability).              |
| [`info`](_autosummary/ocracy.tools.html.md#ocracy.tools.info)(backend_id)                                  | Print a backend's full ledger record as JSON.                                       |
| [`find`](_autosummary/ocracy.tools.html.md#ocracy.tools.find)(\*[, local, remote, free, implemented, ...]) | Filter the ledger and print matching backends (id, where, pricing, best-for).       |
| [`scaffold`](_autosummary/ocracy.tools.html.md#ocracy.tools.scaffold)(backend_id, \*[, dest])                  | Generate a new backend package from its ledger entry.                               |
| [`validate`](_autosummary/ocracy.tools.html.md#ocracy.tools.validate)(backend_id)                              | Smoke-test a backend adapter end to end and print the report.                       |
| [`requirements`](_autosummary/ocracy.tools.html.md#ocracy.tools.requirements)(backend_id, \*[, gpu])               | Show what a backend needs to run (pip, system deps, GPU, weights, creds).           |
| [`doctor`](_autosummary/ocracy.tools.html.md#ocracy.tools.doctor)()                                          | Report which backends are usable now, and how to install the rest.                  |
| [`install`](_autosummary/ocracy.tools.html.md#ocracy.tools.install)(backend_id, \*[, gpu, yes])               | Plan (default) or run (`--yes`) the pip install for a backend.                      |
| [`status`](_autosummary/ocracy.tools.html.md#ocracy.tools.status)(\*[, level, run_tests, names])             | Print an OCR-backend readiness table (levels: all ⊇ implemented ⊇ set_up ⊇ tested). |

### ocracy.tools.backends(, capability=None)

List the backends ocracy can run right now (optionally by capability).

* **Parameters:**
  **capability** ([`Optional`](https://docs.python.org/3/library/typing.html#typing.Optional)[[`str`](https://docs.python.org/3/builtins/stdtypes.html#str)]) – Filter to a capability, e.g. `math`, `tables`, `handwriting`.

### ocracy.tools.doctor()

Report which backends are usable now, and how to install the rest.

### ocracy.tools.find(, local=False, remote=False, free=False, implemented=False, handwriting=False, math=False, tables=False, language=None)

Filter the ledger and print matching backends (id, where, pricing, best-for).

Flags compose (AND). Example: `ocracy find --local --free --handwriting`.

* **Parameters:**
  * **local** ([`bool`](https://docs.python.org/3/builtins/functions.html#bool)) – Keep only backends that run locally.
  * **remote** ([`bool`](https://docs.python.org/3/builtins/functions.html#bool)) – Keep only hosted/remote backends.
  * **free** ([`bool`](https://docs.python.org/3/builtins/functions.html#bool)) – Keep only free / open-source backends.
  * **implemented** ([`bool`](https://docs.python.org/3/builtins/functions.html#bool)) – Keep only backends ocracy can run today.
  * **handwriting** ([`bool`](https://docs.python.org/3/builtins/functions.html#bool)) – Keep only backends that read handwriting.
  * **math** ([`bool`](https://docs.python.org/3/builtins/functions.html#bool)) – Keep only backends that read math/formulas.
  * **tables** ([`bool`](https://docs.python.org/3/builtins/functions.html#bool)) – Keep only backends that extract tables.
  * **language** ([`Optional`](https://docs.python.org/3/library/typing.html#typing.Optional)[[`str`](https://docs.python.org/3/builtins/stdtypes.html#str)]) – Keep only backends whose languages mention this name/code.

### ocracy.tools.info(backend_id)

Print a backend’s full ledger record as JSON.

* **Parameters:**
  **backend_id** ([`str`](https://docs.python.org/3/builtins/stdtypes.html#str)) – A ledger id, e.g. `google-vision` (see `ocracy find`).

### ocracy.tools.install(backend_id, , gpu=False, yes=False)

Plan (default) or run (`--yes`) the pip install for a backend.

Without `--yes` it prints the plan and changes nothing. System deps and GPU
wheels are surfaced, not run automatically.

* **Parameters:**
  * **backend_id** ([`str`](https://docs.python.org/3/builtins/stdtypes.html#str)) – Backend id to install, e.g. `rapidocr`.
  * **gpu** ([`bool`](https://docs.python.org/3/builtins/functions.html#bool)) – Surface GPU-wheel guidance.
  * **yes** ([`bool`](https://docs.python.org/3/builtins/functions.html#bool)) – Actually run `pip install` (otherwise just print the plan).

### ocracy.tools.read(image, , backend=None, languages=None, output='text')

OCR an image and print the result.

* **Parameters:**
  * **image** ([`str`](https://docs.python.org/3/builtins/stdtypes.html#str)) – Path or http(s) URL to the image.
  * **backend** ([`Optional`](https://docs.python.org/3/library/typing.html#typing.Optional)[[`str`](https://docs.python.org/3/builtins/stdtypes.html#str)]) – Backend id (default: first installed). See `ocracy backends`.
  * **languages** ([`Optional`](https://docs.python.org/3/library/typing.html#typing.Optional)[[`str`](https://docs.python.org/3/builtins/stdtypes.html#str)]) – Comma-separated language codes, e.g. `en,fr`.
  * **output** ([`str`](https://docs.python.org/3/builtins/stdtypes.html#str)) – `text` (default), `json` (text + blocks), or `markdown`.

### ocracy.tools.requirements(backend_id, , gpu=False)

Show what a backend needs to run (pip, system deps, GPU, weights, creds).

* **Parameters:**
  * **backend_id** ([`str`](https://docs.python.org/3/builtins/stdtypes.html#str)) – Backend id, e.g. `paddleocr`.
  * **gpu** ([`bool`](https://docs.python.org/3/builtins/functions.html#bool)) – Include GPU-wheel guidance.

### ocracy.tools.scaffold(backend_id, , dest=None)

Generate a new backend package from its ledger entry.

* **Parameters:**
  * **backend_id** ([`str`](https://docs.python.org/3/builtins/stdtypes.html#str)) – The ledger id to scaffold (e.g. `surya`).
  * **dest** ([`Optional`](https://docs.python.org/3/library/typing.html#typing.Optional)[[`str`](https://docs.python.org/3/builtins/stdtypes.html#str)]) – Optional destination directory.

### ocracy.tools.status(, level='all', run_tests=False, names=False)

Print an OCR-backend readiness table (levels: all ⊇ implemented ⊇ set_up ⊇ tested).

* **Parameters:**
  * **level** ([`str`](https://docs.python.org/3/builtins/stdtypes.html#str)) – Restrict rows to a level: `all` | `implemented` | `set_up` | `tested`.
  * **run_tests** ([`bool`](https://docs.python.org/3/builtins/functions.html#bool)) – Actually OCR-test the set-up backends — makes real API calls for
    set-up remotes (off by default, so a plain `ocracy status` never bills you).
  * **names** ([`bool`](https://docs.python.org/3/builtins/functions.html#bool)) – Also print, per level, a comma-separated `Name (website)` list.

### ocracy.tools.validate(backend_id)

Smoke-test a backend adapter end to end and print the report.

* **Parameters:**
  **backend_id** ([`str`](https://docs.python.org/3/builtins/stdtypes.html#str)) – The backend id to validate (e.g. `tesseract`).


# _autosummary/ocracy.translation.html.md

# ocracy.translation

Parameter translation between ocracy’s normalized kwargs and native engines.

Every backend exposes its own parameter names and scales (`lang` vs
`languages` vs `language_hints`; thresholds in `0..1` vs `0..100`; pixel
vs point units). A backend declares a `param_map` in its `BACKEND_CONFIG`
mapping *normalized* names to native ones, and [`make_kwargs_translator()`](_autosummary/ocracy.translation.html.md#ocracy.translation.make_kwargs_translator)
turns that declaration into a function that rewrites caller kwargs into the
shape the engine wants.

The machinery lives in the facade kit ([`ocracy.kit.translation`](_autosummary/ocracy.kit.translation.html.md#module-ocracy.kit.translation)), shared
with the fleet’s other facades; this module keeps ocracy’s original
`translate(**kwargs) -> dict` shape for existing callers. New code that wants
the drops and clamps as notes uses [`ocracy.kit.make_translator()`](_autosummary/ocracy.kit.html.md#ocracy.kit.make_translator) directly,
as [`BaseOcrAdapter`](_autosummary/ocracy.make_backend.html.md#ocracy.make_backend.BaseOcrAdapter) does.

### Functions

| [`make_kwargs_translator`](_autosummary/ocracy.translation.html.md#ocracy.translation.make_kwargs_translator)(param_map, \*[, ...])   | Create a function that translates normalized kwargs to native kwargs.   |
|-------------------------------------------------------------------------------------------------|-------------------------------------------------------------------------|
| [`validate_param`](_autosummary/ocracy.translation.html.md#ocracy.translation.validate_param)(name, value, config)            | Validate a single parameter against `min`/`max`/`choices` in config.    |

### ocracy.translation.make_kwargs_translator(param_map, , on_unsupported='warn')

Create a function that translates normalized kwargs to native kwargs.

* **Parameters:**
  * **param_map** ([`Dict`](https://docs.python.org/3/library/typing.html#typing.Dict)[[`str`](https://docs.python.org/3/builtins/stdtypes.html#str), [`Optional`](https://docs.python.org/3/library/typing.html#typing.Optional)[[`dict`](https://docs.python.org/3/builtins/stdtypes.html#dict)]]) – Mapping of `normalized_name -> spec`; see
    [`ocracy.kit.translation`](_autosummary/ocracy.kit.translation.html.md#module-ocracy.kit.translation) for every spec form (`None` means the
    backend does not support the parameter).
  * **on_unsupported** ([`str`](https://docs.python.org/3/builtins/stdtypes.html#str)) – `"warn"` (default), `"raise"`, `"note"` or
    `"ignore"`. The notes are discarded by this dict-returning form.
* **Return type:**
  [`Callable`](https://docs.python.org/3/library/typing.html#typing.Callable)[[`...`](https://docs.python.org/3/builtins/constants.html#Ellipsis), [`dict`](https://docs.python.org/3/builtins/stdtypes.html#dict)]
* **Returns:**
  A `translate(**kwargs) -> dict` function.

### ocracy.translation.validate_param(name, value, config)

Validate a single parameter against `min`/`max`/`choices` in config.

* **Return type:**
  [`Any`](https://docs.python.org/3/library/typing.html#typing.Any)


# _autosummary/ocracy.util.html.md

# ocracy.util

Image-input normalization and small shared helpers.

Different OCR backends want their input in different forms: a filesystem path
(Tesseract, PaddleOCR), raw `bytes` (most cloud REST APIs), a PIL image, or a
numpy array (deep-learning engines). Callers, meanwhile, want to pass whatever
they have — a path, an `http(s)` URL, bytes, a PIL image, or an array. This
module bridges the two with a handful of converters that **lazily** import
Pillow / numpy / urllib only when actually exercised, so `import ocracy` stays
dependency-free.

The key converters:

- [`load_image_bytes()`](_autosummary/ocracy.util.html.md#ocracy.util.load_image_bytes) — anything -> encoded image `bytes` (for REST APIs).
- [`ensure_file_path()`](_autosummary/ocracy.util.html.md#ocracy.util.ensure_file_path) — anything -> a path on disk (writing a temp file for
  in-memory inputs); pair with [`cleanup_temp()`](_autosummary/ocracy.util.html.md#ocracy.util.cleanup_temp) or use [`image_path()`](_autosummary/ocracy.util.html.md#ocracy.util.image_path).
- [`image_path()`](_autosummary/ocracy.util.html.md#ocracy.util.image_path) — a context manager yielding a path and cleaning up.
- [`to_pil()`](_autosummary/ocracy.util.html.md#ocracy.util.to_pil) / [`to_numpy()`](_autosummary/ocracy.util.html.md#ocracy.util.to_numpy) — anything -> a PIL image / numpy array.

### Functions

| [`classify_input`](_autosummary/ocracy.util.html.md#ocracy.util.classify_input)(image)                              | Classify an image input as `url`/`path`/`bytes`/`pil`/`numpy`.                                                          |
|-----------------------------------------------------------------------------------------------------|-------------------------------------------------------------------------------------------------------------------------|
| [`is_url`](_autosummary/ocracy.util.html.md#ocracy.util.is_url)(x)                                          | True if `x` is a string that looks like an http(s) URL.                                                                 |
| [`load_image_bytes`](_autosummary/ocracy.util.html.md#ocracy.util.load_image_bytes)(image, \*[, fmt])                 | Return encoded image `bytes` for any supported input.                                                                   |
| [`ensure_file_path`](_autosummary/ocracy.util.html.md#ocracy.util.ensure_file_path)(image, \*[, suffix])              | Return `(path, is_temp)` for any supported input.                                                                       |
| [`cleanup_temp`](_autosummary/ocracy.util.html.md#ocracy.util.cleanup_temp)(path, is_temp)                        | Delete `path` iff `is_temp` (the flag returned by [`ensure_file_path()`](_autosummary/ocracy.util.html.md#ocracy.util.ensure_file_path)). |
| [`image_path`](_autosummary/ocracy.util.html.md#ocracy.util.image_path)(image, \*[, suffix])                    | Context manager yielding a filesystem path for `image`, cleaning up temps.                                              |
| [`to_pil`](_autosummary/ocracy.util.html.md#ocracy.util.to_pil)(image)                                      | Convert any supported input into a PIL `Image` (lazy import).                                                           |
| [`to_numpy`](_autosummary/ocracy.util.html.md#ocracy.util.to_numpy)(image)                                    | Convert any supported input into a numpy array (lazy import).                                                           |
| [`check_import`](_autosummary/ocracy.util.html.md#ocracy.util.check_import)(module_name, \*, install_hint[, ...]) | Import `module_name` or raise a friendly, actionable ImportError.                                                       |

### ocracy.util.check_import(module_name, , install_hint, feature='this')

Import `module_name` or raise a friendly, actionable ImportError.

Centralizes the “you need to `pip install X`” guidance so adapters and
converters don’t each hand-roll it.

### ocracy.util.classify_input(image)

Classify an image input as `url`/`path`/`bytes`/`pil`/`numpy`.

Decided structurally (and via duck typing for PIL/numpy) so we never import
Pillow or numpy just to look at the input.

* **Return type:**
  str

### ocracy.util.cleanup_temp(path, is_temp)

Delete `path` iff `is_temp` (the flag returned by [`ensure_file_path()`](_autosummary/ocracy.util.html.md#ocracy.util.ensure_file_path)).

* **Return type:**
  [`None`](https://docs.python.org/3/builtins/constants.html#None)

### ocracy.util.ensure_file_path(image, , suffix='.png')

Return `(path, is_temp)` for any supported input.

Existing on-disk paths are returned untouched (`is_temp=False`). In-memory
inputs (bytes/URL/PIL/numpy) are written to a temp file (`is_temp=True`);
the caller is responsible for cleanup (use [`cleanup_temp()`](_autosummary/ocracy.util.html.md#ocracy.util.cleanup_temp), or prefer
the [`image_path()`](_autosummary/ocracy.util.html.md#ocracy.util.image_path) context manager).

* **Return type:**
  Tuple[str, bool]

### ocracy.util.image_path(image, , suffix='.png')

Context manager yielding a filesystem path for `image`, cleaning up temps.

Example:

```default
with image_path(pil_image) as p:
    text = pytesseract.image_to_string(p)
```

* **Return type:**
  Iterator[str]

### ocracy.util.is_url(x)

True if `x` is a string that looks like an http(s) URL.

* **Return type:**
  [`bool`](https://docs.python.org/3/builtins/functions.html#bool)

### ocracy.util.load_image_bytes(image, , fmt='PNG')

Return encoded image `bytes` for any supported input.

Pass-through for `bytes`; reads files; fetches URLs; encodes PIL/numpy
inputs as `fmt` (PNG by default — lossless and universally accepted).

* **Return type:**
  bytes

### ocracy.util.to_numpy(image)

Convert any supported input into a numpy array (lazy import).

### ocracy.util.to_pil(image)

Convert any supported input into a PIL `Image` (lazy import).


# about-this-build.html.md

<!-- generated by epythet -->

# About this build

This documentation was built on **2026-10-14 02:29 UTC** from commit <a href="https://github.com/thorwhalen/ocracy/commit/4de579644780e1348cc516ef3beabd72fbed418a"><code>4de5796</code></a> on branch <code>main</code>, for **ocracy 0.1.13** (from <code>pyproject.toml</code>).

#### WARNING
The documentation and the package may be misaligned:

- The documented version (0.1.13) is behind the latest release on PyPI (0.1.14): `pip install ocracy` gives newer code than these docs describe.

## Source

|                     |                                                                                                                                                          |
|---------------------|----------------------------------------------------------------------------------------------------------------------------------------------------------|
| Commit              | <a href="https://github.com/thorwhalen/ocracy/commit/4de579644780e1348cc516ef3beabd72fbed418a"><code>4de579644780e1348cc516ef3beabd72fbed418a</code></a> |
| Branch              | <code>main</code>                                                                                                                                        |
| Tags at this commit | none                                                                                                                                                     |
| Working tree        | clean                                                                                                                                                    |
| Remote              | <code>https://github.com/thorwhalen/ocracy</code>                                                                                                        |

## Continuous integration

|              |                                                                                            |
|--------------|--------------------------------------------------------------------------------------------|
| Repository   | <code>thorwhalen/ocracy</code>                                                             |
| Run          | <a href="https://github.com/thorwhalen/ocracy/actions/runs/38501134999">38501134999</a>    |
| Ref          | <code>refs/heads/main</code>                                                               |
| Event commit | <code>4de579644780e1348cc516ef3beabd72fbed418a</code> (in the history of the built commit) |

## Tools

|          |         |
|----------|---------|
| epythet  | 0.2.17  |
| Sphinx   | 9.1.0   |
| docutils | 0.22.4  |
| Python   | 3.12.15 |

## Configuration as resolved

|               |                                                                   |
|---------------|-------------------------------------------------------------------|
| theme         | <code>auto</code> (Sphinx theme <code>pydata_sphinx_theme</code>) |
| accent        | <code>#7a3a80</code>                                              |
| api_generator | <code>autosummary</code>                                          |
| ignore        | <code>tests/</code>, <code>scrap/</code>, <code>examples/</code>  |
| agent_outputs | <code>true</code>                                                 |
| aggregates    | <code>md</code>                                                   |
| ai_artifacts  | <code>true</code>                                                 |

## Package on PyPI

Latest release: <a href="https://pypi.org/project/ocracy/0.1.14/">0.1.14</a>, newer than the documented version (0.1.13).

## Reproduce

```bash
git clone https://github.com/thorwhalen/ocracy && cd ocracy
git checkout 4de579644780e1348cc516ef3beabd72fbed418a
pip install "epythet==0.2.17"
epythet quickstart . --ignore tests/ scrap/ examples/
```

The same data, for machines: <a href="build_info.json"><code>build_info.json</code></a> (schema version 1).


# ai-agents.html.md

<!-- generated by epythet -->

# For AI agents

`ocracy` ships artifacts for coding agents alongside its code. This page lists
them, says where each lives in the repository, and points at the
machine-readable copies of this documentation.

## Skills

Skills are folders holding a `SKILL.md` (the [Agent Skills](https://agentskills.io) format): a description that tells an agent when to use it and a body with the procedure. Install one into your agent with `gh skill` (any host: `--agent claude-code`, `copilot`, `cursor`, `codex`, `gemini`), or use the copy bundled in the wheel.

### `ocracy`

Extract text from images, scans, screenshots, photos, or PDFs using the `ocracy` package — one uniform interface over many OCR engines (Tesseract, EasyOCR, PaddleOCR, Apple Vision, Google Vision, AWS Textract, Azure, Mathpix, Claude/GPT vision, …). Use when the user wants to “extract/read/get the text from this image/scan/screenshot/photo/PDF”, “OCR this”, “image to text”, “transcribe handwriting”, “pull the text out of a picture”, “read a receipt/ form/document”, or “turn an equation image into LaTeX”. Covers the one-line call, choosing/installing a backend, reading the result (text + boxes + confidence), languages, and the `ocracy` CLI. For *picking* the best engine for a need, see ocracy-choose-backend; for *adding* a new engine, see ocracy-add-backend.

```bash
gh skill install thorwhalen/ocracy ocracy --agent claude-code
```

Source: [`ocracy/data/skills/ocracy`](https://github.com/thorwhalen/ocracy/tree/HEAD/ocracy/data/skills/ocracy) (bundled with the pip package).

### `ocracy-add-backend`

Build a new OCR backend façade for the ocracy package — wrap any engine or service (Tesseract, EasyOCR, PaddleOCR, Google Vision, AWS Textract, Mathpix, a VLM, …) behind ocracy’s uniform `ocr()` interface. Use when the user wants to “add a backend to ocracy”, “wrap <engine> in ocracy”, “implement an OCR façade”, “make ocracy support <service>”, pick a backend from the ledger and make it real, or extend ocracy’s engine coverage. Walks through scaffolding from the ledger, filling the config/param_map, implementing the adapter’s `_read`, normalizing output to `OcrResult`, handling credentials, packaging the extra, and validating end to end.

```bash
gh skill install thorwhalen/ocracy ocracy-add-backend --agent claude-code
```

Source: [`ocracy/data/skills/ocracy-add-backend`](https://github.com/thorwhalen/ocracy/tree/HEAD/ocracy/data/skills/ocracy-add-backend) (bundled with the pip package).

### `ocracy-choose-backend`

Choose or compare OCR engines/services using ocracy’s data-driven ledger (64 researched backends). Use when the user asks “which OCR should I use”, “what’s the best OCR for <language / handwriting / math / tables / receipts>”, “compare OCR engines/services”, “local vs cloud OCR”, “cheapest OCR API”, “free offline OCR”, “OCR options”, or wants to weigh accuracy / price / privacy / language coverage before committing to a backend. Filters the ledger by feature and explains the trade-offs. For actually running OCR see ocracy; for adding a new engine see ocracy-add-backend.

```bash
gh skill install thorwhalen/ocracy ocracy-choose-backend --agent claude-code
```

Source: [`ocracy/data/skills/ocracy-choose-backend`](https://github.com/thorwhalen/ocracy/tree/HEAD/ocracy/data/skills/ocracy-choose-backend) (bundled with the pip package).

### `ocracy-install-backend`

Install / set up an ocracy OCR backend that isn’t available yet — handle the heavy or awkward installs (PaddleOCR’s framework, Torch-based EasyOCR/TrOCR/ pix2tex, Tesseract’s *system* binary, GPU vs CPU wheels, first-run model-weight downloads, remote-API credentials). Use when ocracy raises “Backend X requires: pip install …”, an `ImportError` for an OCR engine, when the user says “install <engine> for ocracy”, “set up paddleocr/easyocr/tesseract”, “make this OCR backend work”, “ocracy backend not installed”, or “which OCR backends do I have installed”. Drives `ocracy.requirements()`, `ocracy.check()`, `ocracy.doctor()`, and `ocracy.install()`. To *pick* a backend first see ocracy-choose-backend; to *use* one see ocracy.

```bash
gh skill install thorwhalen/ocracy ocracy-install-backend --agent claude-code
```

Source: [`ocracy/data/skills/ocracy-install-backend`](https://github.com/thorwhalen/ocracy/tree/HEAD/ocracy/data/skills/ocracy-install-backend) (bundled with the pip package).

The bundled skills are also on disk after `pip install ocracy`, under the package’s `data/skills/` directory; link them into an agent without network access with `skill link-skills <that directory>`.

## Instruction files

Files agents read before working in this repository.

- [`CLAUDE.md`](https://github.com/thorwhalen/ocracy/tree/HEAD/CLAUDE.md): read by Claude Code

## Machine-readable documentation

This site publishes the same documentation in forms that fit an agent’s context window:

- [`llms.txt`](https://thorwhalen.github.io/ocracy/llms.txt): an index of every page with a one-line description ([llms.txt](https://llmstxt.org) format)
- [`ocracy.md`](https://thorwhalen.github.io/ocracy/ocracy.md): the whole documentation as one Markdown file
- `<page>.html.md`: a rendered Markdown twin of every page, advertised from each page’s `<head>` with `<link rel="alternate" type="text/markdown">`
- [`objects.inv`](https://thorwhalen.github.io/ocracy/objects.inv): the Sphinx inventory: a symbol-to-URL index (`sphobjinv convert plain objects.inv -`)


# api.html.md

# API reference

| [`ocracy`](_autosummary/ocracy.html.md#module-ocracy)   | ocracy — one facade over many OCR engines, plus a ledger to choose between them.   |
|-------------------------------------------------------------------------|------------------------------------------------------------------------------------|


