FinePrint
Read the fine print of your metrics — a decompiler for your dashboards.
Source & issues · 中文文档 (Chinese docs)
FinePrint recovers, from your dbt project's compiled artifacts, the caliber a metric actually executes — its true definition, in the small print of the SQL.
It can tell you:
- how a metric's formula is computed;
- where the numerator and the denominator each come from;
- which filters, time windows and dedup rules shape the result;
- which upstream columns the metric depends on;
- whether a SQL change silently changed the metric's meaning.
FinePrint never connects to your database and never reads your business data.
Example
The dashboard says the refund rate is 30%. Finance computes 80%.
Walking the SQL chain reveals what the dashboard actually counts:
- only refunds issued within 14 days of payment;
- only the latest record of each refund;
- test orders excluded;
- paid orders only;
- attributed to the payment date, not the refund date.
FinePrint unfolds those conditions, buried across multiple layers of SQL, directly:
$ fineprint trace --project . dm_refund_rate_1d.refund_rate
◎ dm.dm_refund_rate_1d.refund_rate
│ formula: SUM(refund_amount) / SUM(amount)
│
├─ numerator
│ ├─ refunded_at <= paid_at + INTERVAL '14' DAY
│ └─ rn = 1
│
├─ denominator
│ └─ from stg_orders
│
└─ shared by both sides
├─ status = 'paid'
└─ is_test = 0
This caliber tree is derived from the SQL by a deterministic program — no LLM involved.
Try it yourself in 10 minutes with the bundled example project — pre-built dbt artifacts included, no dbt install and no database needed. No checkout needed either: pip install fineprint && fineprint init --demo.
On a dashboard, every metric card becomes a caliber entry — one click opens the full caliber card:
(Demo dashboard, Chinese sample data; an animated tour lives in the repository README.)
Core capabilities
Metric caliber tracing
Column-level lineage built on sqlglot, unfolding across models:
- the formula;
- numerator / denominator;
- filter conditions;
- time windows;
- column dependencies.
fineprint graph --project .
fineprint trace --project . model.column
Metric caliber cards
FinePrint runs two independent channels:
- a deterministic engine deriving technical facts from the SQL AST;
- an LLM reader producing a business-readable narrative.
The two are cross-validated before a traceable caliber card is published.
fineprint synth --project .
fineprint report --project .
synth sends the relevant compiled SQL and column documentation to the LLM
endpoint you configure; database credentials and warehouse data are never sent.
Every other command runs entirely locally.
Caliber drift detection
Detects:
- formula changes;
- filter changes;
- time-window changes;
- source-column and dependency changes;
- the downstream metrics affected.
fineprint drift --project .
--strict makes it a CI gate.
Accuracy
The deterministic engine has been probed exhaustively on:
- 5 public dbt projects;
- 3 SQL dialects;
- 1,364 models;
- 34,499 columns.
Provable cross-layer formula coverage: 99.73%. (Coverage measures formula provability — it is not the same thing as business-caliber accuracy.)
A hand-built suite of 14 classic caliber traps serves as regression: currently 14 / 14.
Install
Requires Python 3.10+.
pip install fineprint
Quick start
No dbt project handy? Start with the bundled example — no dbt, no database, no LLM key (a pre-built card batch ships with it):
fineprint init --demo && cd fineprint-quickstart
fineprint graph
fineprint trace dm_refund_rate_1d.refund_rate
fineprint report
On your own dbt project:
cd your-dbt-project
dbt compile
dbt docs generate
fineprint init --project .
fineprint graph --project .
fineprint columns --project .
fineprint trace --project . model.column
To generate caliber cards:
export FINEPRINT_LLM_BASE_URL=https://api.openai.com/v1
export FINEPRINT_LLM_API_KEY=sk-...
export FINEPRINT_LLM_MODEL=gpt-4.1-mini
fineprint synth --project .
fineprint report --project .
After changing SQL:
dbt compile
fineprint graph --project .
fineprint drift --project .
graph, trace and drift never call an LLM.
Python API
Since 0.9, a minimal public surface for notebooks, BI plugins and orchestration:
import fineprint
fineprint.build_graph("path/to/dbt_project")
print(fineprint.trace("path/to/dbt_project", "dm_refund_rate_1d.refund_rate"))
batch = fineprint.cards("path/to/dbt_project") # the card JSON is the contract (schema_version frozen)
Current boundaries
What FinePrint recovers is:
the caliber your code actually executes.
It cannot judge on its own whether the SQL matches the business's original intent.
The current stable release targets dbt projects.
Documentation
- Architecture — the two channels, the composer, the state machine
- Accuracy — the five-project probe and the trap suite, in full
- Privacy & data boundaries — what is read, what is sent, what never leaves
- Configuration reference — every key, variable and exit code
- Python API — the minimal public surface
- Known boundaries — what FinePrint knows it cannot do
- Stability policy — what is frozen, and when
License: Apache-2.0
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 fineprint-0.9.5.tar.gz.
File metadata
- Download URL: fineprint-0.9.5.tar.gz
- Upload date:
- Size: 188.0 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via:
twine/7.0.0 CPython/3.13.5
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
2f3431e491e02357bd1524c1bfe4f29a93471120ed477cb13d02d5e9c0566ff3
|
|
| MD5 |
b2f3278875318ed1ce805a5377a6786e
|
|
| BLAKE2b-256 |
1f409a7113bdf5bc9fe8faec9ef248d9a4cb2f3870db27e0e725cdac9560c710
|
File details
Details for the file fineprint-0.9.5-py3-none-any.whl.
File metadata
- Download URL: fineprint-0.9.5-py3-none-any.whl
- Upload date:
- Size: 214.0 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via:
twine/7.0.0 CPython/3.13.5
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
e7d8fafdc8a3bb057f153314d6665394be4d4fd50f0d6511bc69033dcc7aa295
|
|
| MD5 |
99c5424610cc098f91d0cc5f99e1e9ab
|
|
| BLAKE2b-256 |
e192664f15c539b5c98ca3495cc825573acae4dd2c30353cbe4b76ad0b728ed1
|