CAD CLI v2.0 - Model Package Architecture
August 28, 2026 · View on GitHub
AI-Native CAD Command Line Tool with Model Packages (.456d)
What's New in v2.0
Key Improvements
- Model Packages (.456d) - Self-contained package structure replacing
.caddirectories - STEP Artifacts - Reliable STEP files instead of unstable pickle caching
- JSON Metadata - Render outputs include camera parameters and timestamps
- JSONL History - Efficient commit history in JSONL format
- Artifact Management - Configurable cleanup policies for managing storage
- Assembly Packages -
kind=assembly, multi-solid validation, aggregate metrics, and component-aware headless PNGs - Optional Standard Parts - Progressive
cadpartscatalog queries and reusable assembly proxies - Model-Directed Review Drawings - Optional dimensions, callouts, hidden lines, and cutaway views without changing the model
Migration from v1.0
v1.0 has been archived to src/cad_cli/v1/. No automatic migration is provided - start fresh with v2.0.
Installation
Codex plugin
codex plugin marketplace add liwuzhan/cad-tool --ref main
codex plugin add cad-tool@cad-tool
Start a new Codex session after installation. The plugin itself has no install hook; on the first real CAD request it checks the local runtime and asks before creating the isolated dependency environment.
DSH plugin package
The self-contained package carries the 16 Host tools, browser result cards, and the complete Python CLI in one tarball. The plugin is not yet listed in the DSH marketplace, so install the newest GitHub Release directly:
# macOS / Linux
curl -fL https://github.com/liwuzhan/cad-tool/releases/latest/download/dsh-cad-studio.tgz \
-o dsh-cad-studio.tgz
dsh plugin --profile <profile> add ./dsh-cad-studio.tgz
# Windows PowerShell
Invoke-WebRequest `
-Uri https://github.com/liwuzhan/cad-tool/releases/latest/download/dsh-cad-studio.tgz `
-OutFile dsh-cad-studio.tgz
dsh plugin --profile <profile> add ./dsh-cad-studio.tgz
The latest URL always follows the newest published package. After the
marketplace entry is accepted, CAD Studio can also be installed from the
DSH plugin marketplace. The package source remains at
packages/dsh-cad-studio.
Headless Linux automatically uses a process-safe Matplotlib renderer and colors
assembly solids separately. On unstable Windows remote/screen-off sessions, set
CAD_RENDER_BACKEND=matplotlib. Use CAD_SKIP_RENDER=1 only when automation
should omit PNGs completely; geometry checks, STEP, metrics, and history remain active.
One-line install
git clone https://github.com/liwuzhan/cad-tool
cd cad-tool
bash install.sh # macOS / Linux
# Windows: powershell -ExecutionPolicy Bypass -File install.ps1
The script needs Python 3.11–3.14, creates an isolated .venv inside the repo
(~300 MB download: build123d + OCP + pyvista), verifies the install with a smoke
test, and never touches your global site-packages.
Optional: clone the cad-parts
parametric standard-parts library next to this repo — install.sh (and the DSH
plugin's cad_env_bootstrap) auto-detects and installs it as a soft dependency
(CAD_PARTS_ROOT=/path to override). Everything works without it; with it,
model scripts can directly from cadparts import gear, deep_groove_bearing, ...
and query the catalog via the cadparts CLI.
AI-assisted install
Paste this prompt to any coding agent (Claude Code, DSH, Cursor, ...) — it can finish the install on its own by reading this README:
Install the CAD CLI tool:
1. git clone https://github.com/liwuzhan/cad-tool && cd cad-tool
2. macOS/Linux: run bash install.sh
Windows: run powershell -ExecutionPolicy Bypass -File install.ps1
(Requires Python 3.11-3.14. The script builds an isolated .venv; do NOT
pip-install into the global environment.)
3. Verify: .venv/bin/cad --help (Windows: .venv\Scripts\cad.exe --help)
then smoke-test the CLI by creating and running a throwaway package:
cad init /tmp/smoke.456d --name=smoke && cd /tmp/smoke.456d && cad run
4. Report the installed versions and the smoke-test result.
If install.sh fails, follow its printed hints (Python version, pip mirror)
and retry; do not give up after one attempt.
Manual install
# Using conda
conda create -n cad-cli python=3.12
conda activate cad-cli
conda install -c conda-forge build123d pyvista
pip install -e .
# Or plain pip inside a venv
python3.12 -m venv .venv && source .venv/bin/activate
pip install -e .
Quick Start
1. Create a Model Package
cad init my_gear --name="Spur Gear"
cd my_gear.456d
For an assembly, choose the assembly template explicitly:
cad init bearing_block --name="Bearing block assembly" --kind assembly
The assembly workflow keeps components as labeled Compound children and allows
multiple valid solids. See docs/assembly_workflow.md
for coordinate, interface, standard-parts, validation, and review conventions.
If an ordinary multi-view review reveals an ambiguous area, use the optional
annotated drawing input described in
docs/review_drawing.md. It generates evidence only;
it is not a mandatory gate or an automatic design verdict.
This creates:
my_gear.456d/
├── manifest.json # Package metadata
├── src/
│ └── main.py # Your CAD script
├── vcs/
│ └── commits.jsonl # Commit history
├── artifacts/ # Build artifacts
└── runlog/ # Execution logs
2. Write Your Model
Edit src/main.py:
from build123d import *
# Create your model
result = Box(100, 50, 20)
3. Run and Test
# Execute script (in-memory, no artifacts)
cad run
# Validate geometry
cad validate
# Inspect properties
cad inspect --prop=volume
cad inspect --prop=bounds
For an issue that cannot be localized from the ordinary views, ask for selected dimensions, callouts, or a cutaway without changing the source model:
cad review --commit <hash> --drawing-spec review-request.json
The request format and neutral measurement output are documented in
docs/review_drawing.md.
4. Commit Your Work
# Full build workflow: execute + validate + STEP + thumbnails + metrics
cad commit -m "Initial gear design"
This creates artifacts at artifacts/<hash>/:
model.step- STEP file (persistent)thumb_*.png- Thumbnail rendersthumb_*.json- Render metadatametrics.json- Geometry metricsvalidate.json- Validation results
5. Version Control
# Show commit history
cad log
# Check current status
cad status
# Checkout previous version (loads STEP)
cad checkout abc123
# Export to file
cad export --format=step --output=gear_v1.step
6. Manage Artifacts
# List all artifacts and sizes
cad artifacts list
# Clean up old artifacts (uses manifest policy)
cad artifacts clean
Command Reference
Project Management
cad init <path> --name=<name>- Create new model packagecad status- Show repository statuscad log [--limit=N]- Show commit history
Modeling Workflow
cad run [script]- Execute script (in-memory only)cad build [script]- Build workflow without commitcad commit -m "msg" [script]- Full build + commitcad validate [script]- Validate geometrycad checkout <hash>- Load commit's STEP artifact
Inspection
cad inspect --prop=<property>- Query geometry property- Properties:
volume,area,bounds,faces,edges,vertices
- Properties:
cad inspect --list-targets- List all topology targetscad inspect --target=face[0] --target-prop=center- Query specific target
Output
cad render [--views=top,front,iso]- Generate renderscad export --format=<step|stl> --output=<path>- Export model
Artifact Management
cad artifacts list- List artifacts and sizescad artifacts clean [--policy=<policy>]- Clean up artifacts- Policies:
all_commits,latest_per_branch,releases_only
- Policies:
Branch Management
cad branch list- List all branchescad branch create <name>- Create a new branchcad branch switch <name>- Switch to a branch (restores STEP + script)cad branch delete <name>- Delete a branch
Model Package Structure
<model_name>.456d/
├── manifest.json # Package metadata
│ ├── name, version
│ ├── head (current commit)
│ ├── branches
│ ├── artifact_policy
│ └── render settings
│
├── src/
│ └── main.py # Main script
│
├── vcs/
│ └── commits.jsonl # Linear commit history
│
├── artifacts/
│ └── <commit_hash>/
│ ├── model.step # STEP artifact
│ ├── thumb_*.png # Thumbnails
│ ├── thumb_*.json # Render metadata
│ ├── metrics.json # Geometry metrics
│ └── validate.json # Validation results
│
└── runlog/
└── <run_id>.jsonl # Execution logs
Configuration
Edit manifest.json to configure:
{
"name": "My Model",
"unit": "mm",
"timeout_seconds": 60,
"artifact_policy": "latest_per_branch",
"render": {
"default_views": ["top", "front", "right", "iso"],
"resolution": [800, 600],
"image_format": "png"
}
}
Output Format
All commands output JSONL (JSON Lines):
{"event": "run_start", "ts": "2026-01-31T10:30:00", "payload": {"script": "src/main.py"}}
{"event": "run_success", "ts": "2026-01-31T10:30:01", "payload": {"metrics": {...}}}
Script Convention
Scripts must assign the final shape to a result variable:
from build123d import *
# Create geometry
box = Box(100, 50, 20)
cylinder = Cylinder(30, 100)
# Assign to result
result = box - cylinder
Feature-Level Checkpoints
Checkpoints are the reliable way to detect boolean operation failures. Add checkpoints after each feature operation:
from build123d import *
from cad_cli.feedback import Checkpoint
Checkpoint.reset()
with BuildPart() as part:
Cylinder(30, 10)
Checkpoint(part, "base").expect_volume(28274, tolerance=100).expect_solids(1).verify()
Cylinder(10, 10, mode=Mode.SUBTRACT)
Checkpoint(part, "hole").expect_volume_decreased().expect_solids(1).verify()
result = part.part
Checkpoint Methods
| Method | Description |
|---|---|
.expect_volume(value, tolerance=1.0) | Assert specific volume |
.expect_volume_decreased() | Assert volume decreased from previous checkpoint |
.expect_volume_increased() | Assert volume increased from previous checkpoint |
.expect_solids(count) | Assert number of solids (always verify = 1) |
.expect_faces(count) | Assert face count |
.expect_bbox_size(x, y, z, tolerance=1.0) | Assert bounding box dimensions |
.verify() | Execute all checks, raise exception on failure |
Checkpoint results appear in JSONL output as checkpoint_passed or checkpoint_failed events.
Testing
Run the test suite:
pytest # All tests
pytest --cov=cad_cli # With coverage
pytest test/test_package.py -v # Specific test
Architecture Highlights
v2.0 vs v1.0
| Feature | v1.0 | v2.0 |
|---|---|---|
| Project structure | .cad/ directory | .456d package |
| Shape caching | Pickle (unreliable) | STEP artifacts |
| Commit storage | Individual JSON files | Single JSONL file |
| Render metadata | None | JSON with camera params |
| Artifact cleanup | Manual | Policy-based |
| Complex models | Fails >150 faces | Reliable with STEP |
Error Codes
E-SYNTAX- Python syntax errorE-RUNTIME- Runtime errorE-CONSTRAINT- Constraint violationE-BREP- BRep validation failureE-RENDER- Rendering errorE-IO- File I/O error
Development
pip install -e ".[dev]" # Install dev dependencies
pytest # Run tests
black src/ test/ # Format code
mypy src/ # Type check
Requirements
- Python 3.11+
- build123d 0.5.0+
- cadquery-ocp 7.7.0+
- pyvista 0.43.0+
- click 8.1.0+
- numpy 1.24.0+
License
MIT
Troubleshooting
"No model package found"
Make sure you're inside a .456d directory or run cad init first.
"STEP artifact not found"
The commit may have been cleaned up. Check cad artifacts list.
Render failures
Ensure pyvista is installed: pip install pyvista
Import errors
Make sure build123d is installed: conda install -c conda-forge build123d