woodwright
A semantic CAD library for woodworking. You describe furniture the way a woodworker thinks about it: boards and rods with named sides, and the joints between them. woodwright works out the joinery, the cut sizes and where every part goes, and produces 3D models (STEP, STL), drawings (SVG) and cut lists.
It is built on build123d. This is an early alpha: the API will still change.
| A chair with mortise-and-tenon joints, assembled and exploded: projects.chair in the example library. Every tenon and mortise is derived from the joints between the parts. | |
Getting started without programming
You don't need to know Python to try woodwright: one small program, uv, installs it with everything it needs, and you then type a few commands.
-
Open a terminal: Terminal on macOS (in Applications / Utilities), PowerShell on Windows (from the Start menu), any terminal on Linux.
-
Install uv by pasting this line into it and pressing Enter.
- macOS and Linux:
curl -LsSf https://astral.sh/uv/install.sh | sh
- Windows:
powershell -ExecutionPolicy ByPass -c "irm https://astral.sh/uv/install.ps1 | iex"
Then close the terminal and open a new one.
- macOS and Linux:
-
List the examples, from single joints to whole projects (the first run downloads Python and woodwright, which takes a minute):
uvx --python 3.14 woodwright list
-
Export one, e.g. a small cabinet door:
uvx --python 3.14 woodwright export projects.cabinet_door
This makes a folder
output/projects/cabinet_doorin the folder the terminal is in (your home folder, unless you moved withcd). In it:cut_list.txt– each part with its size and its cuts (tenons, mortises, grooves...), a plain text file;.svgdrawings of the whole thing, an exploded view and each part – open them in a web browser;.stl3D models of the whole thing and each part – open them in any online STL viewer;assembled.step– the 3D model for CAD programs such as the free FreeCAD, which opens the.stlfiles too.
-
Make your own: in a plain text editor (TextEdit set to plain text, Notepad, ...) write a file
my_door.pywith the sizes you want:from woodwright.examples import projects door = projects.cabinet_door(height=700, width=450)
and export it, in the folder where you saved it:
uvx --python 3.14 woodwright export my_door.py
The results are in
output/my_door/door. What each example can change (sizes, stock thickness...) is listed at the top of its code in the example library; copying an example's code into your file is the way on to your own designs.
To update woodwright later, write woodwright@latest instead of woodwright
once. If you use an AI coding assistant (e.g. Claude Code), you can also ask
it to do all of this for you.
Installation
pip install woodwright # or: uv add woodwright
Requires Python 3.14. The woodwright command lists and exports the
examples and your own design files (woodwright --help). Source: https://github.com/bzamecnik/woodwright
Quickstart
A rail tenoned into a stile. You give the design dimensions and the joint; the tenon, the mortise, the rail's cut length and its placement are derived.
from pathlib import Path
import woodwright as ww
from woodwright.export import export_model
oak = ww.Stock.board(thickness=20, species="oak")
frame = ww.Assembly("corner", root_location=ww.orient(right_end=ww.UP, back_edge=ww.RIGHT))
stile = frame.add(ww.Board("stile", oak, length=600, width=60))
rail = frame.add(ww.Board("rail", oak, length=300, width=60)) # shoulder to shoulder
frame.join(ww.MortiseTenon(tenon=rail.left_end, mortise=stile.back_edge))
model = frame.resolve()
print(model.cut_list())
export_model(model, Path("output/corner")) # STEP, STL, SVG views, cut list
stile 600 x 60 x 20 mm oak
- mortise 50 x 8 mm, 42 deep, in stile.back_edge
rail 340 x 60 x 20 mm oak
- tenon 50 x 8 mm, 40 long, on rail.left_end
What's there so far:
- Stock: boards, and round rods (dowels, pegs, rungs, round legs).
- Cuts: grooves, dados and rabbets (through or stopped), mortises, slot mortises, tenons (haunched, mitred, chamfered, multiple side by side or across the thickness, wedged), tongues, dovetail tongues and laps, chamfers, mitres (across the face, the edge, or along the grain), tapers; holes (through, blind, counterbored, countersunk, tapered), round tenons (tapered, chamfered, with a kerf for a wedge), end chamfers, round tapers and flats on rods.
- Joints: butt (also turned at an angle); dado, rabbet, groove and tongue and groove housings (also stopped); mortise and tenon (blind, through, stub, haunched, mitred, with mitred shoulders, multiple, wedged, tusk, pinned, drawbored); loose tenons and loose tongues; bridles (L and T); half laps (plain, dovetailed, mitred), cross laps, mitred face tenons; box joints; sliding, through, half-blind, mitred-corner and blind mitred dovetails; mitre corners and splices; table-top buttons; round tenons and whole rods in holes (blind, through, tapered, wedged, into square or round stock); dowels; screws (clearance and pilot holes, countersunk or counterbored).
Example library
woodwright.examples holds over 130 examples, from single cuts through
joints to projects: a try square, a mallet, a bookshelf, a dovetailed drawer
with a bottom, a dining table, a side table, a chair, a stool and a step
stool on round legs wedged through their seats, a towel rail, a coat rack
with pegs, ledged and frame-and-panel doors, a small glazed cabinet door.
woodwright list
woodwright export projects.chair --out output
The design ideas are in docs/vision.md and docs/plan.md.
Development
Install the environment and dependencies:
uv sync
pre-commit install # ruff lint + format on commit
Optionally, for notebooks with an interactive 3D viewer:
uv sync --group notebook
uv run jupyter lab
Run the tests and the linters:
uv run pytest
uv run ruff format
uv run ruff check --fix
License
Credits
- Ideas and guidance: Bohumír Zámečník
- Most of the implementation: Claude Code (Opus 5.5)
Metadata
Release files for woodwright 0.4.0
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | Provenance | |
|---|---|---|---|---|
| woodwright-0.4.0.tar.gz | 168.8 kB | Without provenance | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| woodwright-0.4.0-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 270.4 kB
Release files / woodwright-0.4.0.tar.gz
| Download URL | woodwright-0.4.0.tar.gz |
|---|---|
| Size | 168.8 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
f77482073a3a5042241c56e72de4fd79ebaf895e5128418655c37088abc03029
|
|
BLAKE2b-256 checksum How to use checksums |
edf5ec6e38201e0dc8e91768f75e49f57dedffe9f7dec8e2e167806937f5b21e
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
uv/0.13.1 {"installer":{"name":"uv","version":"0.13.1","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"macOS","version":null,"id":null,"libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}
|
Release files / woodwright-0.4.0-py3-none-any.whl
| Download URL | woodwright-0.4.0-py3-none-any.whl |
|---|---|
| Size | 101.6 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
d1dbbd8fd0d8bf6437b3b57d5bdc141c4affcf36d5ad9d27bf4a977b716ce776
|
|
BLAKE2b-256 checksum How to use checksums |
72e26fc79bd656064921957f03c396f9d642e765f217f6070cbb2e04b56e9b29
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
uv/0.13.1 {"installer":{"name":"uv","version":"0.13.1","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"macOS","version":null,"id":null,"libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}
|
Security for woodwright 0.4.0
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
No provenance found
None of the files in this release were uploaded with provenance metadata.
A note on package security
PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.