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

  1. Model Packages (.456d) - Self-contained package structure replacing .cad directories
  2. STEP Artifacts - Reliable STEP files instead of unstable pickle caching
  3. JSON Metadata - Render outputs include camera parameters and timestamps
  4. JSONL History - Efficient commit history in JSONL format
  5. Artifact Management - Configurable cleanup policies for managing storage
  6. Assembly Packages - kind=assembly, multi-solid validation, aggregate metrics, and component-aware headless PNGs
  7. Optional Standard Parts - Progressive cadparts catalog queries and reusable assembly proxies
  8. 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 renders
  • thumb_*.json - Render metadata
  • metrics.json - Geometry metrics
  • validate.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 package
  • cad status - Show repository status
  • cad log [--limit=N] - Show commit history

Modeling Workflow

  • cad run [script] - Execute script (in-memory only)
  • cad build [script] - Build workflow without commit
  • cad commit -m "msg" [script] - Full build + commit
  • cad validate [script] - Validate geometry
  • cad checkout <hash> - Load commit's STEP artifact

Inspection

  • cad inspect --prop=<property> - Query geometry property
    • Properties: volume, area, bounds, faces, edges, vertices
  • cad inspect --list-targets - List all topology targets
  • cad inspect --target=face[0] --target-prop=center - Query specific target

Output

  • cad render [--views=top,front,iso] - Generate renders
  • cad export --format=<step|stl> --output=<path> - Export model

Artifact Management

  • cad artifacts list - List artifacts and sizes
  • cad artifacts clean [--policy=<policy>] - Clean up artifacts
    • Policies: all_commits, latest_per_branch, releases_only

Branch Management

  • cad branch list - List all branches
  • cad branch create <name> - Create a new branch
  • cad 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

MethodDescription
.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

Featurev1.0v2.0
Project structure.cad/ directory.456d package
Shape cachingPickle (unreliable)STEP artifacts
Commit storageIndividual JSON filesSingle JSONL file
Render metadataNoneJSON with camera params
Artifact cleanupManualPolicy-based
Complex modelsFails >150 facesReliable with STEP

Error Codes

  • E-SYNTAX - Python syntax error
  • E-RUNTIME - Runtime error
  • E-CONSTRAINT - Constraint violation
  • E-BREP - BRep validation failure
  • E-RENDER - Rendering error
  • E-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