Algorithmic first - AI only when stuck

Business documents in. Clean rows out.
It knows when it can't.

Point terbium at any business document, a vendor catalogue, an invoice, a receipt, a resume, and get back a table of clean rows. Catalogues are the flagship: name, SKU, materials, and the product photo, extracted and named. Not markdown to re-parse, ready-to-use records. It rebuilds structure from raw geometry, scores its own confidence on every record, and only reaches for a Claude model when it is genuinely stuck. No key? It will not fail silently or burn tokens, it tells you what is missing, by name.

What one vendor PDF actually hides catalogue.pdf
192
Pages
964
Unique SKUs
505
Dimension rows
1157
Images
What it parses

Catalogues first. Not catalogues only.

The engine does not care what a document is called, it cares how the words are laid out. Four document families ship today. Catalogues are the flagship; the rest run on the same geometry, the same confidence scores, the same honesty.

CataloguesFlagship

Catalogues & lookbooks

Photo-anchored records: the product picture ties the name, SKU, and materials to the row. Picture-heavy pages are the headline strength, not the edge case.

TransactionsInvoices

Invoices, bills & receipts

Line items, quantities, unit prices, and totals, read from the layout of the page instead of a regex over flattened text.

HR techResumes

Resumes & CVs

Sections, experience, and skills, reconstructed from headings and alignment rather than keyword scraping.

TablesNative structure

Price lists & decks

Native tables from spreadsheets and slides, read straight from the file's own structure. Cheap and exact.

The flagship lane

Catalogue in. Product catalog out.

Each product photo anchors a row: terbium extracts the image, names it from the label beneath it, and mines the nearby text for the SKU and the materials. Then a CSV, ready for a PIM, Shopify, or a marketplace feed.

pythonbuild_catalog
import terbium

rows = terbium.build_catalog("vendor_catalogue.pdf", images_dir="images/")
terbium.to_catalog_csv(rows, "catalogue.csv")
# {"sku": "RG-1001", "name": "Anatolia Kilim",
#  "materials": "wool", "image": "Anatolia_Kilim.jpeg", "page": 12}
One CLI, every lane

Point it at a file. It tells you what it found.

The terbium command detects the document type, prints the extracted rows as a terminal table, and writes a spreadsheet or a self-contained HTML report when you ask for one.

terbium - universal cli
$ terbium invoice.pdf
detected: invoice · 3 line items · confidence 0.94

 description            qty    amount
 --------------------   ---    ------
 Studio desk lamp         2    178.00
 Linen shade              2     49.00
 Freight                  1     18.50

 total                        245.50

--csv out.csv    spreadsheet
--html out.html  self-contained report
Confidence, not guesswork

It asks for help by name.

Every run ends with a verdict, not a stack trace. When the layout carries the data, terbium finishes cold with zero tokens spent. When a catalogue buries its facts in photos or prose, it says exactly what is missing, where the data actually lives, and what to hand it next.

terbium - run summary
terbium: 8/121 products have a name, 0 a SKU, 9 materials/ingredients.
82 page(s) are image-only (1, 5, 6, 7, 8, ...) - the data lives in the photos, not the text.
-> set ANTHROPIC_API_KEY or pass ai=terbium.AI(...)   ·   recommended tier: Opus (vision)
File formats - the input lane

Every container, reduced to columns, rows, and matrices.

PDFGeometry engine

Word-level geometry

Reads the raw x/y position of every word and rebuilds the columns, rows, and 2-D matrices the page never labelled. This is where the full structural engine runs.

PPTXNative structure

Native slides, tables, images

Walks the real slide tree, pulling text frames, native tables, and embedded images straight from the deck's own structure.

XLSXNative structure

Cells, merged ranges, shape

Resolves merged ranges and detects whether a sheet is wide or long, so tables land in the right orientation without a guess.

CSVNative structure

Delimiter, encoding, types

Infers the delimiter, the encoding, and the type of each column before it reads a single row, so messy exports parse cleanly.

PDF gets the full geometry engine because a PDF throws its structure away, terbium has to rebuild it. PPTX, XLSX, and CSV already carry native structure, so terbium leans on it and parses them cleanly and cheaply.

The detector is content-agnostic. Any column-aligned table, a pricelist, a spec sheet, a size x finish matrix, an invoice's line items, reconstructs the same way, whatever the category. Schemas then map the columns to typed fields by header meaning: a bag gets capacity, a lamp gets wattage, an invoice gets a total, without a hand-written schema per category.

Not every PDF is a matrix. A lookbook, a grid of photos with a name under each, is reconstructed as a label grid: one record per product, grouped by collection. And when a page is image-only, terbium does not return nothing, it reports exactly which pages need the vision lane.

Not just the text

Pull out the product images, named by product.

terbium extracts every product photo losslessly and names each file after the product it sits beneath, dropping icons, thin banners, and logos that repeat across pages. One call, no AI key needed.

pythonexport_images
import terbium
manifest = terbium.export_images("lookbook.pdf", "out/")
# out/Kyoto_Bedside_Table.jpeg, out/Meadow_Bedside_Table.jpeg, ...

# or from the shell, with a manifest.csv alongside the photos
$ terbium lookbook.pdf --images out/

Per image: product, collection, page, format, pixel size, colorspace, effective dpi, dominant colour, and position, written to a manifest.csv.

Quickstart

Parse first. Add a key only when it asks.

Install, point it at a document, and read the table. Wire up an AI key when, and only when, terbium tells you the data lives somewhere the algorithm cannot reach.

shellpypi
pip install terbium-parse
terbium catalogue.pdf --csv out.csv                 # the product table + images/, no AI
terbium invoice.pdf --csv rows.csv --html report.html  # the universal CLI, any lane
pythonexample.py
import terbium

rows = terbium.build_catalog("catalogue.pdf", images_dir="images/")   # algorithmic only

rows = terbium.build_catalog("lookbook.pdf", images_dir="images/",
                             ai=terbium.AI(anthropic_key=...))       # vision fills the blanks

doc = terbium.parse("pricelist.xlsx", schema="product")              # raw records API
doc = terbium.parse("invoice.pdf")                                   # invoices, receipts, resumes too
When it does call AI, it routes

The hard page gets the strong model. Nothing else does.

terbium matches page difficulty to the cheapest tier that can solve it, across Claude (default), GPT, Kimi, Grok, and Gemini. You never pay Opus-class prices for a page Haiku could clear.

Trivial
Haiku tier
Claude Haiku GPT-4o mini Kimi Turbo Grok Mini

A stray label or an obvious cell. Cleared for pennies.

Moderate
Sonnet tier
Claude Sonnet GPT-4o Kimi K2 Grok 3 Mini

A table whose alignment is plausible but not certain.

Hard
Opus tier
Claude Opus o3-mini Kimi K2 Grok 3

Ambiguous matrices, orphan SKUs, image-only lookbook pages. The real work.

Images, material icons and finish swatches, are read by a vision model and folded back into the record.