Offline · no warehouse · CI-ready

Validate data against its contract, offline.

datapact parses an Open Data Contract Standard (ODCS) contract, lints it, and validates a CSV dataset against it. One command, no connection string, no upload. The contract is finally checked, not just filed.

bunx github:srivtx/datapact#main check --contract contract.yaml --data data.csv

datapact is not on npm; bunx github:srivtx/datapact#main runs the latest main with Bun. Install the datapact binary with the one-line script, or add it as a dev dependency.

datapact check
$ datapact check --contract contract.yaml --data data.csvdata.csv  rows:5  errors:16  warnings:0  info:1INFO   DP-202  discount_code  column "discount_code" is not declared in the contractERROR  DP-208  orders.order_id  row 2: value "ORD-2" does not match pattern ^ORD-[0-9]{6}$ERROR  DP-205  orders.order_id  row 4: duplicate value "ORD-000101" in unique column "order_id"ERROR  DP-210  orders.customer_email  row 3: value "not-an-email" is not a valid emailERROR  DP-204  orders.customer_email  row 4: required column "customer_email" is emptyERROR  DP-209  orders.status  row 3: value "refunded" is not in the enum for "status"ERROR  DP-203  orders.item_count  row 2: "three" is not a valid integerERROR  DP-206  orders.item_count  row 3: value "0" is below minimum 1ERROR  DP-201  orders.is_gift  required column "is_gift" is missing from the datasetERROR  DP-203  orders.order_date  row 3: "2026-13-40" is not a valid date… and 7 more errors.

Try it in your browser

Paste a contract and a CSV, then check one against the other. Both run in this tab; nothing is uploaded and there is no network call.

Runs entirely in your browser. Nothing is uploaded.

Nothing checked yet.

What it catches

The ways a dataset drifts from the contract that describes it, each with a stable code you can look up.

A missing required column
When a column the contract marks required is absent from the CSV header, the run fails before a single row is read.
An undeclared column
Data that has grown a column nobody agreed to. Reported as DP-202, an informational finding rather than a failure.
A value of the wrong type
Text where the contract says integer, number, boolean, date, or date-time.
An empty required value
A required cell that is blank. Empty cells in optional columns are skipped, which is what lets a sparse column validate cleanly.
A broken uniqueness rule
A value that repeats in a column the contract marks unique, compared as exact, case-sensitive text.
Bounds, patterns, enums, formats
Numbers outside minimum/maximum, text that misses a pattern, values outside an enum, and values that fail a format such as email, uuid, uri, or ipv4.

Quick start

Install once, then point it at a contract and a data file. The exit code is the CI gate.

quick start
# install the binary$ curl -fsSL https://raw.githubusercontent.com/srivtx/datapact/main/install.sh | sh# lint a contract on its own$ datapact lint --contract contract.yaml# validate a dataset against it$ datapact check --contract contract.yaml --data data.csv# fail CI on warnings too, and write SARIF$ datapact check --contract contract.yaml --data data.csv --fail-on warning --sarif datapact.sarif

Every flag, the exit codes, the library API, and the MCP server are in Usage.

Documentation

The landing page is the pitch. The details live on four short pages.

Rules
Every lint and validation code, the logical types, the formats, and the empty-value rule.
Usage
The CLI commands, exit codes, JSON output, the browser-safe library API, and the MCP server.
CI
SARIF 2.1.0 and GitHub code scanning, with a workflow you can paste.
FAQ
Scope, honest limits, CSV parsing, and how datapact relates to ODCS.