Burr / Overview
Burr
CAD linter.
Burr checks CAD intent and writes receipts.
For the full CAD source, CLI, receipt, and agent-loop explanation, see How Burr Works.
build123d source -> generated STEP -> burr-design-data.json -> burr check -> burr-receipt.json -> fix the CAD or the declared ruleInstall
Install the Rust CLI:
cargo install burr --version 0.29.0Install the optional build123d helper in a CAD project:
uv add burr-build123d==0.10.0The helper is only a way to emit burr-design-data.json while writing
build123d. Burr core still checks JSON receipts, so other CAD tools can adopt
the same contract later.
Quickstart
Create a starter part:
burr init my-partcd my-partuv syncuv run python design.pyburr check .burr explain .Expected files:
my-part/ design.py pyproject.toml actuator.step burr-design-data.json burr-receipt.jsonThe STEP and receipt are generated artifacts. Commit the source and design intent. Ignore bulky generated CAD outputs unless a release artifact needs them.
Annotate CAD
In build123d, the useful pattern is one call that both cuts the geometry and records the mechanical feature:
from burr_build123d import BurrDesignData, DESIGN_DATA_FILE, m3_clearance_hole
design = BurrDesignData( artifact_id="starter-actuator", artifact_version="0.1.0", artifact_type="actuator_mount", units="mm",)
m3_clearance_hole( design, part=plate, feature_id="m3_loaded_mount_left", center=(-18, 0), edge_distance_mm=3.2, intent="mechanical_interface", role="loaded_mount",)
design.write(DESIGN_DATA_FILE)Target metadata is small on purpose:
{ "schema_version": "burr.design-data.v1", "artifact_id": "starter-actuator", "artifact_type": "actuator_mount", "units": "mm", "features": [ { "id": "m3_loaded_mount_left", "kind": "m3_clearance_hole", "intent": "mechanical_interface", "edge_distance_mm": 3.2, "role": "loaded_mount" } ]}Burr does not judge every random hole. It judges declared features selected by the active rulepack. Cosmetic holes, routing holes, labels, and relief cuts should be declared as cosmetic or left out of the mechanical rulepack.
Read The Receipt
Run:
burr check .Passing output means Burr wrote a receipt:
PASS burr-design-data.json -> burr-receipt.jsonThe receipt contains measured facts and rule outcomes:
Receipt schema: burr.receipt.v1.
{ "status": "pass", "checks": [ { "status": "pass", "rule_id": "m3_loaded_mount_edge_distance", "feature_id": "m3_loaded_mount_left", "measured": { "edge_distance_mm": 3.2 }, "required": { "min_edge_distance_mm": 2.7 } } ]}Failing output is the useful part:
FAIL burr-design-data.json -> burr-receipt.jsonThen ask Burr for the fix context:
burr explain .Example failure:
Problem: an M3 loaded mount is too close to the part edge.Measured: edge distance 1.8 mmRequired: at least 2.7 mmFix: move the hole inward, grow the local boss, or lower the declared load class.That is the loop. The image tells you what it looks like. The receipt tells you what Burr actually checked.
Failure To Fix
Burr should be learned from a failure first.
In the starter part, the good M3 mount is safely away from the side edge. Move it too close by changing:
m3_hole_y = 20.0Then rerun:
uv run python design.pyburr check .burr explain .Expected shape:
FAIL burr-design-data.json -> burr-receipt.jsonProblem: the loaded M3 hole is too close to a free edge.Evidence: Measured center-to-edge = 4 mm.Evidence: Required center-to-edge = 10.2 mm.Fix: move the hole inward or make the surrounding part larger.Restore the original hole offset:
m3_hole_y = 12.0Then rerun:
uv run python design.pyburr check .Expected shape:
PASS burr-design-data.json -> burr-receipt.jsonWebsite Proof
Fray displays Burr release artifacts at the Burr gallery.
The website does not regenerate CAD. It downloads a Burr release zip, validates the manifest, and renders PNG previews beside receipts and design data.
For a Fray website update, run:
cd fray-repos/fray-webnpm run burr-release:checknpm run buildThe release guard checks:
burrexists on crates.io at the documented version;burr-build123dexists on PyPI at the documented version;- the configured GitHub gallery zip downloads and validates;
- the Fray site page points at the same release asset.
Fray consumes Burr repair action source hints from the configured gallery
release. Each repair_actions[] entry includes a source_hint with exact
before_text and after_text, plus edit_kind, selector,
source_file_path, value_path, confidence, and before/after values. Fray
validates and renders those fields; Burr owns the source-repair proof.
The slower clean-user proof belongs in the Burr repo:
cd repos/burrnpm run check:fresh-installThat Burr-owned gate proves the published install path plus the failure-to-fix loop:
cargo install -> burr init -> uv sync -> uv run python design.py -> burr check passes -> move the M3 hole toward the side edge -> burr check fails -> burr explain gives the fix -> restore the hole -> burr check passesBoundary
Burr is a linter, not a guarantee that a part is good.
It can catch declared CAD mistakes such as bad edge distance, missing seats, missing capture, or out-of-range measured clearances. It does not replace engineering judgment, assembly checks, collision checks, FEA, slicer review, or real bench testing.