Skip to main content
Pre-release

This release is a pre-release and may not be stable for production use.

SimpleCADAPI repository cover

SimpleCADAPI

中文说明

Update Notes (2.0.4b1)

Beta release: Review generated CAD documents before using this version in production.

SimpleCADAPI 2.0.4b1 adds semantic, product-oriented FreeCAD model trees and more reliable assembly occurrences and joints. It also hardens face-touching boolean unions with glue fallback diagnostics, adds fused standard bearings, and migrates the integrated BLDC actuator to the standard bearing factory. See the full English update notes for implementation details, limitations, and verification coverage.


CADDesigner Research Artifact

This repository is an artifact of

CADDesigner: Conceptual CAD Model Generation with a General-Purpose Agent

Accepted by Computer-Aided Design, 2026


SimpleCADAPI is an OCP-native Python SDK for building CAD models with clear, functional operations and replayable model graphs. It wraps OpenCascade geometry in a compact public API for creating solids, applying features, tagging semantic intent, querying topology, exporting manufacturing files, and translating recorded models into FreeCAD workflows.

Current beta release: simplecadapi==2.0.4b1.

What It Provides

  • OCP-native shape types: Vertex, Edge, Wire, Face, and Solid.
  • Functional modeling operations for primitives, profiles, extrude, revolve, loft, sweep, booleans, transforms, patterns, fillets, chamfers, and shells.
  • Replayable modeling with @model, ModelResult, capture_result(...), import_model_json(...), and replay_model_json(...).
  • Expression parameters with var(...), arithmetic expressions, and serialized expression graphs.
  • Physical units with automatic dimension inference, canonical CAD conversion, and manufacturing tolerance-chain validation.
  • QL selectors for geometry grounding, topology queries, and stable feature selections.
  • Semantic tags through apply_tag(shape=..., tag=...) and list_tags(shape=...).
  • STEP/STL export and FreeCAD translation helpers for script or .FCStd output.

Install

pip install simplecadapi

With uv:

uv add simplecadapi

For local development from this repository:

uv sync --group dev

Quick Start

from pathlib import Path

import simplecadapi as scad

out = Path("out")
out.mkdir(exist_ok=True)

base = scad.make_box_rsolid(
    width=60.0, height=36.0, depth=8.0, bottom_face_center=(0.0, 0.0, 0.0)
)
hole = scad.make_cylinder_rsolid(
    radius=5.0, height=14.0, bottom_face_center=(0.0, 0.0, -3.0)
)
slot = scad.make_box_rsolid(
    width=18.0, height=8.0, depth=14.0, bottom_face_center=(14.0, 0.0, -3.0)
)

part = scad.cut_rsolid(base, hole, slot)
boss = scad.make_cylinder_rsolid(
    radius=8.0, height=7.0, bottom_face_center=(-18.0, 0.0, 8.0)
)
part = scad.union_rsolid(part, boss)
part = scad.apply_tag(shape=part, tag="role.demo.bracket")

print("volume", round(part.get_volume(), 3))
print("faces", len(part.get_faces()))
print("tags", scad.list_tags(shape=part))

scad.export_step(shapes=part, filename=str(out / "bracket.step"))
scad.export_stl(shapes=part, filename=str(out / "bracket.stl"))

Replayable Modeling

Use one @scad.model entry point when a model should be inspectable, serializable, replayable, or translated into another CAD environment. The decorated function owns its GraphSession and returns a ModelResult.

import simplecadapi as scad
from simplecadapi import ql as Q

@scad.model(graph_id="chamfered_block")
def build_model():
    body = scad.make_box_rsolid(
        width=40.0, height=24.0, depth=10.0,
        bottom_face_center=(0.0, 0.0, 0.0),
    )
    cutter = scad.make_cylinder_rsolid(
        radius=4.0, height=16.0, bottom_face_center=(0.0, 0.0, -3.0)
    )
    drilled = scad.cut_rsolid(body, cutter)

    bottom_circle = (
        Q.edges()
        .where(Q.curve_type(kind="circle"))
        .order_by(Q.center_axis(axis="z"))
        .take(1)
        .exactly(1)
    )
    final = scad.chamfer_rsolid(solid=drilled, edges=bottom_circle, distance=0.6)
    scad.capture_result(value=final)
    return final

result = build_model()
model_json = result.model_json
rebuilt = result.replay()

print("recorded_nodes", result.session.graph.node_count)
print("replayed_outputs", len(rebuilt))

Pass export_dir=... to @scad.model when the invocation should also write one self-contained <graph_id>.scene.zip. The package contains scene.json, model/model.json, the complete project-relative Python files referenced by operation source mappings under sources/, and the GLB/entity assets required by the Viewer. Automatic export does not write adjacent model/session JSON, STEP, STL, or FCStd files; those explicit export APIs remain available. The package path is result.artifact_paths["scene"]. Without export_dir, model execution remains in memory.

Physical Units And Tolerances

Declare nominal and manufacturing-tolerance units at the variable boundary. SimpleCAD evaluates lengths in millimeters and angles in degrees while preserving the declaration units in model JSON:

import simplecadapi as scad

width = scad.var(
    "width",
    1.0,
    unit="in",
    tolerance=0.1,
    tolerance_unit="mm",
)
height = scad.var("height", 40.0, unit="mm", tolerance=0.2)
diagonal = scad.sqrt(width**2 + height**2)

analysis = scad.analyze_tolerance(diagonal)
check = scad.check_tolerance(diagonal, 0.3, tolerance_unit="mm")

print(analysis.dimension.name, analysis.unit.symbol)
print(analysis.nominal, analysis.lower_bound, analysis.upper_bound)
print("passes", check.passed)

Addition and subtraction require matching dimensions. Multiplication, division, integer powers, and square root derive dimensions. Trigonometric functions require angle or dimensionless inputs as appropriate. Legacy variables without unit remain supported, but cannot be mixed with unit-declared variables in one expression.

Modeling Mental Model

  • Start from design intent: reference axes, critical profiles, and the features that produce the final solid.
  • Build from lower-dimensional geometry to higher-dimensional geometry: profile wires/faces first, then solid features such as extrude, revolve, loft, and sweep.
  • Keep operations functional. Create new values with public functions such as make_rectangle_rface(...), extrude_rsolid(...), cut_rsolid(...), and fillet_rsolid(...).
  • Use tags for semantic intent and selection anchors, for example role.mounting.surface, anchor.datum.primary, or group.fasteners.
  • Store numeric and geometric facts in metadata or graph payloads, not in tags.
  • Use QL to ground selections by geometry facts rather than relying on topology iteration order.
  • When an indexed topology pick is intentional, pass the index to the plural child-geometry getter, such as get_edges(index), get_faces(index), get_wires(index), or get_vertices(index), so replayable graph workflows preserve the pick as a geo select node.
  • Use model JSON as the interchange boundary for replay, tests, and FreeCAD translation.

FreeCAD Translation

Recorded model JSON can be translated into a FreeCAD Python script:

script = scad.translator.freecad_translator.translate_model_json_to_freecad_script(model_json)

If FreeCAD or FreeCADCmd is available, the same model JSON can be written as an .FCStd file:

scad.translator.freecad_translator.translate_model_json_to_fcstd(model_json, "bracket.FCStd")

Part/Assembly models are written as editable FreeCAD assembly structure: parts are App::Part, assemblies are Assembly::AssemblyObject, and components are links. Explicit compound projections remain available for geometry-only STEP export.

Examples

Run examples from the source checkout:

uv run python examples/04_dimension_tolerance_chain.py
uv run python examples/08_constrained_sketch.py
uv run python examples/09_naca0016_blade_freecad.py
uv run python examples/10_part_assembly.py
uv run python examples/16_compact_two_stage_planetary_reducer/main.py
uv run python examples/20_integrated_bldc_joint_actuator/main.py

Documentation

Releasing the Agent Skill

The repository includes a thin Agent Skill under skills/simplecadapi/. It contains generated API and modeling references, but does not bundle the SDK source code.

From a clean checkout, update the project version and documentation, then build and validate the release artifacts:

uv sync --group dev
uv run skill-pack --refresh-docs --archive
uv run python -m pytest test/test_skill_pack.py

The command refreshes the generated docs, rewrites skills/simplecadapi/, and creates skills/simplecadapi.tar.gz. Review the generated SKILL.md and references before release:

git diff -- skills/simplecadapi docs
tar -tzf skills/simplecadapi.tar.gz

Commit the generated skills/simplecadapi/ directory and refreshed docs/ with the release. The archive is intentionally ignored by Git; attach skills/simplecadapi.tar.gz to the corresponding GitHub release or distribute it through the target Agent Skills registry.

Development

uv sync --group dev
uv run python -m pytest test tests
python3 -m compileall src/simplecadapi

License

AGPL-3.0, see LICENSE.

Community

The group chat currently has too many members for direct QR-code joining. Scan the QR code below to add Teacher Du Peng on WeChat, then ask him for an invitation to the CADDesigner technical community:

Teacher Du Peng's personal WeChat QR code

Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

simplecadapi-2.0.4b1.tar.gz (710.1 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

simplecadapi-2.0.4b1-py3-none-any.whl (872.9 kB view details)

Uploaded Python 3

File details

Details for the file simplecadapi-2.0.4b1.tar.gz.

File metadata

  • Download URL: simplecadapi-2.0.4b1.tar.gz
  • Upload date:
  • Size: 710.1 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.1.0 CPython/3.10.19

File hashes

Hashes for simplecadapi-2.0.4b1.tar.gz
Algorithm Hash digest
SHA256 e0ae3af92a2c371c7f5c631710a1a5c31492fd8c4f54b4fe23a4f9f0f42738a6
MD5 685c5923f70e227bb22bbbb9a3cdd437
BLAKE2b-256 86a4b8109386edaf9bd494825672a13a80112e73e85d08a0427a54172eafdf13

See more details on using hashes here.

File details

Details for the file simplecadapi-2.0.4b1-py3-none-any.whl.

File metadata

  • Download URL: simplecadapi-2.0.4b1-py3-none-any.whl
  • Upload date:
  • Size: 872.9 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.1.0 CPython/3.10.19

File hashes

Hashes for simplecadapi-2.0.4b1-py3-none-any.whl
Algorithm Hash digest
SHA256 e5c86c4f29be44dcd6b711e24d0ed874d5b3fd101dde9dd663d5a3ed12647a5d
MD5 aab2f7fbd7dea8b2d128e509e1fb91a3
BLAKE2b-256 d07fc08c94270b76ae905f3675285b88933e0adc65a9f460857f10adf10f1ae5

See more details on using hashes here.

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page