- Dockerfile 76.2%
- Shell 23.8%
| Filename | Latest commit message | Latest commit date |
|---|---|---|
| .forgejo/workflows | ||
| examples | ||
| cad.sh | ||
| Dockerfile | ||
| README.md | ||
cad-runtime
A warm, shared container for text-to-cad /
cadgen — the local CAD runtime (build123d + OpenCASCADE) that agent skills
such as $cad, $dxf, $gcode and friends drive to generate STEP / STL / 3MF
/ GLB models.
Multiple agents (or several machines) can share one container instance: it runs
the CAD Viewer on a stable port and builds against any project directory you
mount. All the heavy per-machine pieces — Python 3.13, the OpenCASCADE kernel,
libGL, headless Chromium — are pre-installed, so first use is instant.
Pull
docker pull nidavellir.jriyuu.io/jriyuu-labs/cad-runtime:latest
Tags: latest and per-commit <sha>.
Run
As a shared viewer (the default)
docker run -d --name cad-runtime \
-p 3245:3245 \
-v /path/to/your/cad-projects:/work \
-v cadgen-cache:/root/.cache/cadgen \
nidavellir.jriyuu.io/jriyuu-labs/cad-runtime:latest
Then open http://<host>:3245/?file=/work/STEP/part.step in a browser.
The viewer is one long-running server for every file on the container.
The
cadgen-cachevolume is what makes builds fast and shareable: it holds the content-addressed geometry store. Keep it.
Build a model from its Python source
docker run --rm -v /path/to/project:/work -w /work \
nidavellir.jriyuu.io/jriyuu-labs/cad-runtime:latest \
cad python src/plate.py
cad is a wrapper around the pinned runtime
(uvx --no-config --managed-python --python 3.13 --from cadgen==0.7.17).
Two doors:
| Command | What it runs |
|---|---|
cad python <model>.py |
the pinned python — builds a model script |
cad <cadgen subcommand> [args] |
the pinned cadgen — everything else |
Examples:
# render a PNG snapshot of a STEP for visual review
docker run --rm -v $PWD:/work -w /work <image> cad step snapshot STEP/plate.step tmp/plate.png
# one-off mesh export
docker run --rm -v $PWD:/work -w /work <image> cad stl build STEP/plate.step STL/plate.stl
# start the viewer manually (detached, prints the URL)
docker run --rm -it -v $PWD:/work <image> cad viewer --host 0.0.0.0 --port 3245 --json --detach
Project layout conventions and the model contract (decorated functions,
out= paths relative to the script, one model per entrypoint) come from the
upstream cad skill —
install those skills in your agent of choice and point it at this container.
Updates
- Update
cadgen: change the pinned version (0.7.17) inDockerfileandcad.sh(both must match), push — CI rebuilds. Upstream releases: https://pypi.org/project/cadgen/. - The pinned version is deliberate. cadgen reaches into build123d's
internals (determinism shims, lazy stores); it is bounded to
build123d>=0.11.1,<0.12on purpose. Don't float.
Telemetry
cadgen ships with anonymous usage telemetry (PostHog) and a once-a-day
update check on by default. This image ships both off
(CADGEN_TELEMETRY=0, CADGEN_UPDATE_CHECK=0). Re-enable per-run with
CADGEN_TELEMETRY=1 if you want.
Building locally
docker build -t cad-runtime .
CI (Forgejo Actions) builds both linux/amd64 and linux/arm64 on every push
to main, then merges them into a multi-arch manifest, and pushes to the org
registry as latest + <sha> (plus latest-<arch> / <sha>-<arch>). The
arm64 build runs on the org's linux-arm64 self-hosted runner (Pi 5); if that
runner is offline the whole run fails — check runner status before pushing.
Pi 5 disk heads-up: the arm64 runner's SD card is only 58G and fills up with Docker build cache fast. If a run fails with the Pi at ~100%, prune it (
docker builder prune -af && docker image prune -afon the Pi) and push again to re-trigger.