XL Marinade
Deterministic Excel formula-graph extraction to SQLite — with optional, bring-your-own-key LLM documentation.
Excel workbooks that drive real business decisions (actuarial models, pricing tools, finance workbooks) accumulate thousands of formulas across dozens of sheets, with no audit trail beyond "open it and trace the references by hand." XL Marinade parses a workbook once and writes its entire formula graph — every cell, every cross-sheet reference, every VBA-driven mutation — into a provenance-stamped SQLite database you can query, diff, and document like any other data asset.
What it does
- Formula graph extraction — every formula cell becomes a node; every reference
(same-sheet or cross-sheet) becomes an edge, so you can query "what feeds this cell"
or "what does this cell feed" with SQL instead of
Ctrl+[. - Cross-sheet dependency resolution — references across sheets and named ranges are resolved into the same graph, not left as opaque strings.
- Canonical formula families — structurally identical formulas repeated down a column or across a block (the common "one row per asset/policy" pattern) are grouped into a single family with a deterministic ID, instead of being treated as thousands of unrelated formulas.
- VBA edges — macro-driven mutations (e.g. paste-special /
.Value = .Valueoverwrites) are captured as edges in the same graph, so a value that "changes by magic" via a macro is still traceable. - Provenance-stamped SQLite output — the output database carries a schema version and per-edge provenance, so downstream tooling can rely on it as a versioned contract rather than reverse-engineering table shapes.
- Deterministic by default, LLM-optional — extraction, diffing, and baseline documentation are 100% deterministic and make no network calls. An optional bring-your-own-key LLM tier adds narrative documentation and VBA enrichment on top, and degrades gracefully to the deterministic output if no key is configured.
Install
pip install xl-marinade
For optional LLM-enriched documentation (bring your own API key):
pip install 'xl-marinade[llm]'
Requires Python 3.11+.
CLI quickstart
# Extract a workbook's formula graph to a SQLite database
marinade extract book.xlsx -o ir.db
# Generate deterministic documentation (documentation.md + model_spec.json)
marinade document ir.db -o out/
# Same, with optional LLM enrichment (requires xl-marinade[llm] + an API key;
# degrades to deterministic documentation if no key is configured)
marinade document ir.db -o out/ --enrich
# Diff two extracted databases, emitting a JSON changelist
marinade diff a.db b.db
Extraction and diffing are always deterministic and network-free. --enrich on
marinade document is the only opt-in network call in the tool.
Library API
import xl_marinade
# Deterministic extraction and diff
xl_marinade.extract("book.xlsx", "ir.db")
changelist = xl_marinade.diff("a.db", "b.db")
# Deterministic documentation (no network)
from xl_marinade.docs import document
document("ir.db", "out/")
# Optional LLM-enriched documentation (requires the [llm] extra)
from xl_marinade.llm import document as document_enriched
document_enriched("ir.db", "out/")
All library functions raise a typed error hierarchy (xl_marinade.errors.MarinadeError
and subclasses) rather than leaking internal exceptions.
LLM enrichment (optional, bring-your-own-key)
extract, diff, and document are fully deterministic and never touch the
network. The optional [llm] add-on layers LLM-generated narrative documentation
(and opt-in VBA enrichment) on top of that deterministic output, using a provider
and key you supply.
1. Install the extra:
pip install 'xl-marinade[llm]'
2. Set your API key — either variable works (LLM_API_KEY takes precedence):
export OPENAI_API_KEY="sk-..."
3. Enrich — add --enrich on the CLI, or call the xl_marinade.llm entry point:
marinade document ir.db -o out/ --enrich # LLM-written narrative documentation
marinade extract book.xlsx -o ir.db --enrich # opt-in LLM VBA enrichment
from xl_marinade.llm import document
document("ir.db", "out/") # uses the configured key
With the [llm] extra installed but no key configured, enrichment degrades to
deterministic documentation — it never raises or blocks. Enrichment is the only
network call in the tool, and your workbook data is sent only to the endpoint you
configure.
Configuration
All configuration is via environment variables — the key is read at call time and never stored:
| Variable | Purpose | Default |
|---|---|---|
LLM_API_KEY / OPENAI_API_KEY |
API key (required to enrich) | — |
OPENAI_MODEL |
Model name | gpt-5.2 |
LLM_BASE_URL |
OpenAI-compatible endpoint override | OpenAI's API |
LLM_PROVIDER |
Provider id, recorded in the audit log (openai, azure, openai_compatible) |
openai |
Azure, local, or proxied models
The add-on speaks to any OpenAI-compatible endpoint via LLM_BASE_URL — Azure
OpenAI, a local vLLM/Ollama server, or a LiteLLM proxy:
export LLM_API_KEY="..."
export LLM_BASE_URL="http://localhost:11434/v1" # e.g. a local Ollama server
export OPENAI_MODEL="llama3.1"
marinade document ir.db -o out/ --enrich
vs. alternatives
Tools like pycel, xlcalculator, formulas, and koala focus on re-executing Excel formulas in Python — useful when you want to run a workbook's calculations outside Excel.
XL Marinade solves a different problem: understanding and auditing the formula graph itself, without executing it. In particular it adds:
- a cross-sheet dependency graph as a first-class, queryable artifact — not an intermediate structure discarded after evaluation;
- canonical formula families, so a block of a thousand structurally identical formulas shows up as one family, not a thousand opaque nodes;
- VBA edges, capturing macro-driven mutations that pure-formula re-execution tools don't see at all;
- a provenance-stamped SQLite output designed to be a stable, versioned contract for downstream tooling, rather than an in-memory object graph.
License
Apache-2.0 — see LICENSE and NOTICE. Copyright 2026 Opio Inc. The deterministic Excel formula-graph extractor at the core of this project was originally authored by Klaas Stijnen — see AUTHORS.
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file xl_marinade-0.2.0.tar.gz.
File metadata
- Download URL: xl_marinade-0.2.0.tar.gz
- Upload date:
- Size: 741.1 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via:
twine/6.1.0 CPython/3.13.13
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
f7b36b79f6ae316405f8318d6f5be45d40144eb58afbf4168d0e4b70a32f103c
|
|
| MD5 |
f74d7de240b99c041dd5291410705e06
|
|
| BLAKE2b-256 |
91d9b94f6304c7e3f1b089e1eb4ff7306cfaa4dbd6a5da8b4e04e1344df49f47
|
Provenance
The following attestation bundles were made for xl_marinade-0.2.0.tar.gz:
Publisher:
release.yml on gaspatchio/xl-marinade
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
xl_marinade-0.2.0.tar.gz -
Subject digest:
f7b36b79f6ae316405f8318d6f5be45d40144eb58afbf4168d0e4b70a32f103c - Sigstore transparency entry: 2355748213
- Sigstore integration time:
-
Permalink:
gaspatchio/xl-marinade@00be7cd01cb68ebd11e9b7d786166b18d7405e43 -
Branch / Tag:
refs/tags/v0.2.0 - Owner: https://github.com/gaspatchio
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@00be7cd01cb68ebd11e9b7d786166b18d7405e43 -
Trigger Event:
push
-
Statement type:
File details
Details for the file xl_marinade-0.2.0-py3-none-any.whl.
File metadata
- Download URL: xl_marinade-0.2.0-py3-none-any.whl
- Upload date:
- Size: 612.6 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via:
twine/6.1.0 CPython/3.13.13
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
446560a59b77b35962e142c69c6d2963c330557b7d215f54f9cd2ab7ee0c2b36
|
|
| MD5 |
1c71cd3dd04883ebdbd1e6092d56280c
|
|
| BLAKE2b-256 |
7f419c0aaa388cc493b141a6e19f7e63daa988b275bf51b29e7c6bd66684ef78
|
Provenance
The following attestation bundles were made for xl_marinade-0.2.0-py3-none-any.whl:
Publisher:
release.yml on gaspatchio/xl-marinade
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
xl_marinade-0.2.0-py3-none-any.whl -
Subject digest:
446560a59b77b35962e142c69c6d2963c330557b7d215f54f9cd2ab7ee0c2b36 - Sigstore transparency entry: 2355748375
- Sigstore integration time:
-
Permalink:
gaspatchio/xl-marinade@00be7cd01cb68ebd11e9b7d786166b18d7405e43 -
Branch / Tag:
refs/tags/v0.2.0 - Owner: https://github.com/gaspatchio
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@00be7cd01cb68ebd11e9b7d786166b18d7405e43 -
Trigger Event:
push
-
Statement type: