# build123d: a Python BREP CAD library built on Open Cascade

> build123d is a parametric boundary representation modeling framework for 2D and 3D CAD, written in Python on top of the Open Cascade kernel. It suits engineers who want CAD as code, and it assumes you are comfortable with Python and with BREP thinking.

**gumyr/build123d** — A python CAD programming library

- Repository: https://github.com/gumyr/build123d
- Stars: 3,268 · Forks: 290
- Language: Python
- License: Apache-2.0
- Published: 2026-09-24 · Updated: 2026-09-24 · Language: en
- Canonical page: https://hysenlabs.com/projects/gumyr-build123d

## What build123d solves, and who it is actually for

Most CAD work happens in a graphical application. You sketch, you constrain, you extrude, and the history tree lives inside a proprietary file. That model breaks down when the geometry is generated rather than drawn: a bracket whose hole spacing comes from a spreadsheet, a panel with a hundred laser-cut slots, a part family where the same script produces fifty variants.

build123d targets that case. The README describes it as a Python-based, parametric boundary representation (BREP) modeling framework for 2D and 3D CAD, built on the Open Cascade geometric kernel, and says it is aimed at models suitable for 3D printing, CNC machining, laser cutting and other manufacturing processes. The audience is therefore narrow and specific: programmers who need real solids, not mesh approximations, and who are willing to learn a geometry API instead of a toolbar.

The repository carries the topics 3d-printing, brep, cad, cadquery and opencascade, which is an accurate summary of the neighbourhood it lives in. If you have never written code to make a part, this is not the entry point. If you already script geometry and find your current tool's abstractions leaking, the design decisions below are the ones worth reading.

## Algebra mode and builder mode: the two ways to write the same part

The README builds its example in what it calls algebra mode, and the shape of that code is the library's main idea. Objects compose with operators. A line is created from two points, extended with an arc and a polar line, closed into a face with make_hull, cut with a positioned circle, and extruded into a solid:

```py
from build123d import *

line = Line((0, -3), (6, -3))
line += JernArc(line @ 1, line % 1, radius=3, arc_size=180)
line += PolarLine(line @ 1, 6, direction=line % 1)
sketch = make_hull(line.edges())
sketch -= Pos(6, 0, 0) * Circle(2)
part = extrude(sketch, amount=2)
```

The `@` and `%` operators are worth pausing on. The README states that they reference a position along a line and its tangent at that position, which is how you anchor new geometry to existing geometry without computing coordinates by hand. That is the feature that separates this from a thin wrapper over raw kernel calls.

Placement uses Location objects. `Pos` translates, `Rot` rotates, and `Plane.YZ * RectangleRounded(...)` orients a sketch onto a plane before extrusion. Selection is the other half. Calling `.faces()` returns a ShapeList, and the README shows grouping by area, sorting along an axis, and taking a list slice to pick one face:

```py
plate_face = plate.faces().group_by(Face.area)[-1].sort_by(Axis.X)[-1]
plate -= Plane(plate_face) * GridLocations(13, 3, 2, 2) * CounterSinkHole(.5, 1, 2)
part += plate
```

Filtering by geometry type and by a predicate on a property appears in the same README section: `part.edges().filter_by(lambda e: e.length == 2).filter_by(Axis.Z)`, then `part.faces().filter_by(GeomType.CYLINDER).filter_by(lambda f: f.radius == 2)`, feeding fillet and chamfer. The README also states that a second construction path exists, builder mode, and that the earlier construction is done through algebra mode. Both modes ship; the docs cover both.

## Installing build123d and making a first part

The package is on PyPI under the name build123d, and pyproject.toml declares requires-python as >= 3.11, < 3.15. The README badge lists Python 3.11, 3.12, 3.13 and 3.14. A virtual environment is the sane starting point because the dependency list is long and includes the Open Cascade bindings.

```bash
pip install build123d
```

After installation, importing the package should return silently. If it fails, the likely cause is the kernel binding: pyproject.toml pins `cadquery-ocp-novtk >= 8.0, < 8.1`, and that wheel has to exist for your platform and Python version.

The README notes that wildcard imports are generally bad practice but that build123d scripts are usually self contained, so `from build123d import *` is the common convention. The README's own opening sequence creates a line, extends it with an arc and a polar line, closes it into a face with make_hull, subtracts a positioned circle, and extrudes the result:

```py
from build123d import *

line = Line((0, -3), (6, -3))
line += JernArc(line @ 1, line % 1, radius=3, arc_size=180)
line += PolarLine(line @ 1, 6, direction=line % 1)
sketch = make_hull(line.edges())
sketch -= Pos(6, 0, 0) * Circle(2)
part = extrude(sketch, amount= 2)
```

Run that and you have a solid in memory. The repository's examples/ directory is the better next stop than the README: it contains files such as examples/benchy.py, examples/din_rail.py, examples/clock.py, examples/circuit_board.py and examples/extrude.py, several of which have an `_algebra` counterpart showing the same model written in the other mode. Reading one pair side by side is the fastest way to decide which mode your team should standardise on. The project also publishes a cheat sheet alongside the main documentation.

## The dependency surface is the real cost of adoption

build123d does not vendor a geometry kernel. It depends on cadquery-ocp-novtk, the Open Cascade Python bindings, and that single pin shapes most deployment problems. The distribution has to have a wheel for your operating system, architecture and Python version. pyproject.toml already shows the project working around this: lib3mf is installed from the standard package on most platforms, but on Linux aarch64 it switches to py-lib3mf. That is a maintainer-visible sign that platform coverage is not uniform.

The rest of the dependency list is broad: numpy, sympy, scipy, scikit-learn, ezdxf, fonttools, svgpathtools, anytree, ocpsvg, ocp_gordon, trianglesolver, webcolors, requests, bd_materials and threejs-materials. That is a large install for a CAD library, and it means version conflicts are more likely than with a smaller package. The upper bounds in pyproject.toml (`numpy >= 2, < 3`, `ezdxf >= 1.1.0, < 2`, and so on) limit how far a resolver can wander, but they also mean you may have to pin numpy down if another library in the same environment wants a different major version.

The second limitation is conceptual rather than technical. BREP modeling with selectors is a different mental model from sketch-and-constrain CAD. Picking the right face with `group_by(Face.area)[-1].sort_by(Axis.X)[-1]` is compact, but it is positional logic. Change the model enough and that expression can select a different face without raising an error. The library gives you the tools to write precise selectors; it does not stop you from writing fragile ones. If your parts are one-off and visual, a graphical CAD tool will be faster and you should not be here.

## build123d compared with CadQuery and OpenSCAD

CadQuery is the closest neighbour, and the repository's own keyword list includes cadquery, so the comparison is invited. Both are Python and both sit on Open Cascade, which means the kernel behaviour, the STEP and STL story, and the BREP precision are shared ground. The difference is the API surface. CadQuery's fluent chain style builds a model by chaining method calls on a workplane. build123d instead offers the algebra mode shown above, where shapes are values and operators (`+=`, `-=`, `*`) combine them, plus a builder mode. The README's feature list makes the intent explicit: minimal or no internal state depending on mode, explicit 1D, 2D and 3D geometry classes, and extensibility through subclassing and functional composition rather than monkey patching. If you have found CadQuery's implicit workplane state hard to reason about in large scripts, that is the specific itch build123d is scratching.

OpenSCAD is the other common comparison and the difference is more fundamental. OpenSCAD is a declarative language that compiles to meshes; build123d produces BREP solids through Open Cascade. For a part destined for a 3D printer, both can work. For CNC toolpaths or any downstream step that needs true curved surfaces rather than tessellation, the BREP route is the one that keeps precision. The trade-off runs the other way too: OpenSCAD's language is small enough to learn in an afternoon, while build123d asks you to learn Python, a geometry API, and selector semantics. The README also notes export to FreeCAD and SolidWorks formats, which matters if your output has to land in someone else's CAD seat.

## Maintenance, licensing and what an upgrade actually costs

The repository is not archived, and the last push was on 2026-09-23. The release history shows v0.13.0 on 2026-09-21, v0.12.0 on 2026-09-18 and v0.11.1 on 2026-07-02. Two releases three days apart in September is a fast cadence, and the version numbers are still in the 0.x range. That combination is the practical picture: the project moves, and it has not declared a stable API yet.

The upgrade cost follows from that. A 0.x library can change method names, argument names or operator behaviour between minor versions, and nothing published promises otherwise. The mitigation is cheap: pin the version in your requirements file, keep your models in scripts under version control, and re-run the examples/ files after an upgrade to see whether anything shifted. The tests/ directory and the CI badges for tests, pylint, mypy and codecov in the README indicate that the maintainers do run that check themselves, which raises the odds that a break shows up in the changelog rather than in your part.

The licence is Apache-2.0, declared in pyproject.toml and in the LICENSE file, with a NOTICE file present at the repository root. Apache-2.0 is permissive and includes an explicit patent grant, which is generally the friendlier option for commercial use than a copyleft licence. One thing to check yourself rather than assume: the Open Cascade bindings arrive as a separate package with their own licence terms, and the repository does not state what those are. If you are shipping a product built on this stack, read that licence directly. Nothing here is legal advice.

## Conclusion

Adopt build123d if your parts are parametric, your team already writes Python, and you need BREP solids rather than meshes. Do not adopt it if you need a GUI, a mouse-driven assembly workflow, or a kernel you can support commercially without reading the Open Cascade bindings. Before committing, verify two things: that cadquery-ocp-novtk installs cleanly on your platform, and that the difference between the algebra and builder modes in the documentation matches how your team thinks about geometry.

## FAQ

### What is build123d?

It is a Python-based, parametric boundary representation (BREP) modeling framework for 2D and 3D CAD, built on the Open Cascade geometric kernel. The README describes it as a clean, fully Pythonic interface for creating precise models suitable for 3D printing, CNC machining and laser cutting.

### How do I install build123d?

Install it from PyPI with pip install build123d. It requires Python >= 3.11 and < 3.15, and it pulls in the cadquery-ocp-novtk Open Cascade bindings, so a virtual environment is worth using.

### What are the differences between CadQuery and build123d?

Both are Python libraries on Open Cascade, so the kernel and BREP precision are shared. build123d offers algebra mode, where shapes are values combined with operators like += and -=, plus a builder mode, and its README lists minimal internal state and extensibility through subclassing rather than monkey patching as design goals.

### What are the key differences between build123d and OpenSCAD?

OpenSCAD is a declarative language that produces meshes, while build123d produces BREP solids through the Open Cascade kernel. That distinction matters when downstream work needs true curved surfaces rather than a tessellated approximation.

## Sources

- [gumyr/build123d on GitHub](https://github.com/gumyr/build123d)
- [Issues](https://github.com/gumyr/build123d/issues)
- [License: Apache-2.0](https://github.com/gumyr/build123d/blob/dev/LICENSE)
- [README](https://github.com/gumyr/build123d/blob/dev/README.md)
- [Releases](https://github.com/gumyr/build123d/releases)

---

Hysen Labs editorial analysis, written from the project's own repository and release notes. Cite the canonical page: https://hysenlabs.com/projects/gumyr-build123d
