How the text-to-CAD Model Works: Inside the Decorator-Driven Pipeline

The text-to-CAD model transforms Python functions into CAD files using decorators like @step() that register geometry definitions in a global registry, later executed via a thread-local build context and exported through a generation engine.

The earthtojake/text-to-cad library provides a declarative workflow for converting Python scripts into industry-standard CAD formats such as STEP and DXF. By leveraging lightweight decorators and a thread-local build context, the pipeline enables incremental compilation, caching, and live preview capabilities without boilerplate configuration.

Core Architecture of the text-to-CAD Pipeline

The library operates on a decorator-driven registration pattern that separates model declaration from execution. This architecture allows functions to be defined as CAD models while deferring geometry construction until the build phase.

Model Declaration via Decorators

Decorators such as @step(), @dxf(), @stl(), @glb(), and @threemf() mark Python functions as CAD model definitions. These decorators do not execute geometry code immediately; instead, they register the function for later invocation. In packages/cadgen/src/cadgen/authoring.py, lines 4-13 illustrate this registration pattern where the decorator captures the callable without building geometry.

When applied, these decorators create a ModelDef instance that stores:

  • The target output format (STEP, DXF, etc.)
  • The callable geometry function
  • Output path resolution logic
  • Mesh tolerance settings and kinematic metadata

The ModelDef Registry

Registered models are stored as immutable ModelDef objects in a global registry keyed by the model's script::function reference. According to the source code in packages/cadgen/src/cadgen/authoring.py (lines 70-78), this registry maintains the mapping between function references and their execution parameters, enabling the CLI to resolve and dispatch the correct pipeline for any given model.

The Build Execution Flow

When you run python model.py, the text-to-CAD pipeline activates through several coordinated stages that handle parsing, context management, and file generation.

CLI Entry Point and Argument Parsing

The entry point run_model_argv in packages/cadgen/src/cadgen/cli/_run_model.py (lines 44-66) parses command-line arguments, resolves the script-function pair into a model reference, and dispatches to the appropriate generation function. This module handles flags such as --verbose, --force, and mesh tolerance overrides before invoking the build process.

The Thread-Local Building Context

Actual geometry construction occurs within a building() context manager that creates a thread-local BuildFrame. As implemented in packages/cadgen/src/cadgen/authoring.py (lines 81-90), this context tracks:

  • Invoked child models and their resulting tree hashes
  • A unique root identifier for event streaming
  • Build state isolation for incremental updates

This design enables snapshot isolation and incremental builds, where only modified geometry triggers recompilation.

Generation Engine and Export

The generation logic resides in packages/cadgen/src/cadgen/generation.py, which re-exports generate_step_targets and generate_dxf_targets. These functions drive the full pipeline including:

  • Freshness gate checking for cache validation
  • Incremental package compilation
  • OCP kernel integration for geometry operations
  • Final export to STEP, DXF, STL, GLB, or 3MF formats

The internal implementation in packages/cadgen/src/cadgen/_internal/generation.py handles the heavy lifting of compiling models and writing output files next to the source script (or to user-specified paths as defined by ModelDef.output_path at lines 86-90 in authoring.py).

Optional Warm Daemon for Parallel Execution

When the environment variable CADGEN_EVENTS=1 is set, the pipeline supports a warm daemon process managed through packages/cadgen/src/cadgen/daemon/executors.py. As shown in packages/cadgen/src/cadgen/cli/_run_model.py (lines 63-65), this daemon receives build events over a line-sink, enabling parallel builds and live-preview updates in the CAD Viewer without cold-start penalties.

Practical text-to-CAD Examples

A minimal model declares geometry using the build123d API and the @step() decorator:


# demo_bracket.py

from cadgen import build123d as bd
from cadgen import step

@step()
def bracket():
    """A simple rectangular bracket."""
    return bd.Box(40, 10, 10)

Running the model creates demo_bracket.step beside the script:

python demo_bracket.py

Explicit CLI usage with flags:

python demo_bracket.py --verbose --force --mesh-tolerance 0.01

For 2D DXF output instead of 3D STEP:

from cadgen import dxf

@dxf()
def my_drawing():
    # 2D geometry construction

    pass
python my_drawing.py  # Produces my_drawing.dxf

Summary

  • Decorator registration: Functions become CAD models via @step(), @dxf(), and similar decorators that store definitions in a global registry without immediate execution.
  • Lazy evaluation: Geometry building is deferred until script execution, managed by a thread-local BuildFrame context that tracks dependencies and enables incremental compilation.
  • CLI dispatch: The run_model_argv function in _run_model.py parses arguments and routes to generate_step_targets or generate_dxf_targets based on the model type.
  • Multi-format export: The generation engine exports to STEP, DXF, STL, GLB, and 3MF formats with configurable mesh tolerances.
  • Optional daemon: Setting CADGEN_EVENTS=1 enables a warm daemon for parallel builds and live preview capabilities.

Frequently Asked Questions

What file formats does the text-to-CAD model support?

The text-to-CAD pipeline supports STEP and DXF as primary CAD formats, plus STL, GLB, and 3MF for mesh-based exports. You specify the output format by choosing the appropriate decorator: @step() for STEP files, @dxf() for 2D drawings, and @stl(), @glb(), or @threemf() for mesh formats.

How does the warm daemon improve text-to-CAD performance?

When CADGEN_EVENTS=1 is set, the warm daemon process receives build events over a line-sink and maintains a hot OCP kernel instance. This eliminates cold-start latency for subsequent builds and enables parallel execution for batch processing, significantly reducing build times for complex model trees.

Can I customize mesh export tolerances in text-to-CAD?

Yes. The ModelDef class stores mesh tolerance parameters that you can override via CLI flags. Pass --mesh-tolerance and --mesh-angular-tolerance to python model.py to control tessellation quality for STL, GLB, and 3MF exports without modifying the source code.

What is the difference between @step() and @dxf() decorators?

Both decorators register functions as CAD models, but @step() configures the pipeline to generate 3D STEP files (CAD industry standard for solids), while @dxf() targets 2D DXF drawings. The decorator determines which generation function the CLI invokes—generate_step_targets or generate_dxf_targets—and sets the appropriate file extension and export logic in the ModelDef registry.

Have a question about this repo?

These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →