# How to Generate STEP Files from Natural Language Using Text-to-CAD

> Learn how to generate STEP files from natural language with Text-to-CAD. This powerful tool uses LLMs and Python to create production-ready CAD models from simple text descriptions.

- Repository: [earthtojake/text-to-cad](https://github.com/earthtojake/text-to-cad)
- Tags: how-to-guide
- Published: 2026-07-31

---

**Text-to-CAD converts plain English descriptions into production-ready STEP files by using an LLM to generate Python scripts that describe geometry via the build123d API, then exports the result through a specialized CLI pipeline.**

The text-to-cad open-source repository provides an end-to-end pipeline to generate STEP files from natural language descriptions. By chaining a large language model (LLM) with a robust CAD generation engine, the system transforms simple prompts like "a 100 mm cylinder with a 20 mm hole" into valid, manufacturable geometry. This guide explains the three-layer architecture and demonstrates how to use the CLI and Python API to convert text into STEP format.

## The Three-Layer Architecture

The pipeline operates through three distinct layers that handle the transformation from natural language to final CAD output.

### Layer 1: Natural Language to Python Script

The **cad** skill uses an LLM (configured in [`skills/cad/agents/openai.yaml`](https://github.com/earthtojake/text-to-cad/blob/main/skills/cad/agents/openai.yaml)) to parse user prompts and emit Python modules. These generated scripts define a `gen_step()` function (or `gen_assembly()` for assemblies) that uses the **build123d** API provided by the **cadpy** package to describe geometry.

For example, the prompt "a rectangular block 100 mm × 50 mm × 20 mm with a 10 mm hole through the short side" generates a script like:

```python
from build123d import *

def gen_step():
    # rectangular block

    block = Box(100, 50, 20)
    # hole through the short side

    hole = Cylinder(r=5, h=50).rotate((0, 0, 90))
    result = block - hole
    return result

```

The script is saved to a file (e.g., [`parts/block.py`](https://github.com/earthtojake/text-to-cad/blob/main/parts/block.py)) and passed to the generation layer.

### Layer 2: CLI to Generation Engine

The `scripts/step` CLI in [`skills/cad/scripts/step/cli.py`](https://github.com/earthtojake/text-to-cad/blob/main/skills/cad/scripts/step/cli.py) parses command-line arguments and forwards requests to the core generation engine. The entry point `cli.main` builds an `argparse.ArgumentParser` (`_add_step_arguments`), normalizes numeric flags (`_normalize_cli_numeric`), and calls `cadpy.generation.generate_step_targets` at line 2183.

Users invoke the pipeline via:

```bash
python -m scripts.step parts/block.py            # generates block.step

python -m scripts.step parts/block.py -o out.step --stl out.stl

```

### Layer 3: Engine to STEP Export

The generation engine (`cadpy.generation._generate_step_outputs` at line 1823) loads the user script, executes `gen_step()`, and builds the geometry. It then:

1. Creates a hidden GLB topology artifact for the CAD Viewer via [`step_scene.py`](https://github.com/earthtojake/text-to-cad/blob/main/step_scene.py)
2. Exports the geometry to a STEP file using `cadpy.step_export.write_step` at line 338, which wraps the OCP STEPCAFControl_Writer
3. Optionally writes side-car files (`.stl`, `.3mf`, `.glb`) using shared mesh data to avoid duplicate calculations

The engine validates successful writes and raises `RuntimeError` if the STEP writer fails.

## Generating STEP Files from the Command Line

You can generate STEP files directly from natural language using the text-to-cad CLI.

### Basic One-Liner Usage

Pipe a natural language description directly into the step generator:

```bash
text-to-cad "a 100 mm cylinder with a 20 mm hole through the middle" \
  | python -m scripts.step -

```

Behind the scenes, this writes a temporary `tmp_*.py` file containing the LLM-generated geometry code, which the CLI imports and passes to `generate_step_targets`.

### Explicit Script Generation with Side-Cars

For reproducible builds, save the generated Python script and explicitly define output formats:

```python

# parts/gear.py  (generated by the LLM)

from build123d import *

def gen_step():
    gear = Gear(tooth_count=20, module=2)
    return gear

```

```bash
python -m scripts.step parts/gear.py \
    --stl gear.stl \
    --3mf gear.3mf \
    --glb gear.glb \
    --mesh-tolerance 0.05 \
    --mesh-angular-tolerance 0.1

```

This produces:
- `gear.step` – the canonical STEP model
- `gear.stl`, `gear.3mf`, `gear.glb` – mesh side-cars sharing the same tolerance settings

## Using the Python API Directly

Embed the generation pipeline in your own Python tooling by importing from `cadpy`:

```python
from cadpy.generation import generate_step_targets
from cadpy.catalog import StepImportOptions

targets = ["parts/gear.py"]
options = StepImportOptions(
    stl="gear.stl",
    three_mf="gear.3mf",
    glb="gear.glb",
    mesh_tolerance=0.05,
    mesh_angular_tolerance=0.1,
)

generate_step_targets(
    targets,
    direct_step_kind="part",
    step_options=options,
    output="gear.step",
    skip_step_write=False,
    force=False,
    verbose=True,
)

```

This mirrors the CLI flow but integrates seamlessly with Jupyter notebooks or automated build systems.

## Caching and Reproducibility

The system computes a deterministic hash of the source script and its imports ([`source_hash.py`](https://github.com/earthtojake/text-to-cad/blob/main/source_hash.py)) to deduplicate work. This guarantees that rerunning the same script produces identical STEP output, enabling incremental builds and CI verification as implemented in [`tests/python/skills/cad/step/test_cli.py`](https://github.com/earthtojake/text-to-cad/blob/main/tests/python/skills/cad/step/test_cli.py).

## Summary

- **Text-to-CAD** bridges natural language and industrial CAD formats through an LLM-driven pipeline.
- The architecture consists of three layers: prompt-to-Python generation, CLI dispatch, and geometry export.
- **Key files** include [`skills/cad/scripts/step/cli.py`](https://github.com/earthtojake/text-to-cad/blob/main/skills/cad/scripts/step/cli.py) for argument parsing, `cadpy.generation.generate_step_targets` for orchestration, and `cadpy.step_export.write_step` for final STEP serialization.
- Users can invoke the system via one-liner pipes, explicit CLI commands with side-car generation, or direct Python API calls.
- Deterministic hashing ensures reproducible builds and efficient caching across multiple runs.

## Frequently Asked Questions

### What CAD kernel does text-to-cad use for STEP export?

Text-to-CAD uses the **OCP** (Open CASCADE Python) STEPCAFControl_Writer, wrapped by `cadpy.step_export.write_step` at line 338 of [`packages/cadpy/src/cadpy/step_export.py`](https://github.com/earthtojake/text-to-cad/blob/main/packages/cadpy/src/cadpy/step_export.py). This industrial-grade kernel ensures compatibility with major CAD platforms like SolidWorks, CATIA, and Fusion 360.

### Can I generate assembly files or just single parts?

The system supports both. Define `gen_step()` for single parts or `gen_assembly()` for multi-component assemblies. The generation engine in `cadpy.generation` handles both function signatures and exports them to a single STEP file containing the complete assembly structure.

### How does the system handle mesh quality for exported side-cars?

The `StepImportOptions` dataclass in [`step_targets.py`](https://github.com/earthtojake/text-to-cad/blob/main/step_targets.py) accepts `mesh_tolerance` and `mesh_angular_tolerance` parameters. These values control the tessellation density for STL, 3MF, and GLB outputs. The engine shares the computed mesh across all side-car formats to ensure consistency and avoid redundant calculations.

### Is there a way to preview the geometry before exporting the STEP file?

Yes. The generation engine automatically creates a hidden GLB topology artifact via [`step_scene.py`](https://github.com/earthtojake/text-to-cad/blob/main/step_scene.py) that the integrated CAD Viewer uses for visualization. This allows you to inspect the geometry mesh without parsing the STEP file directly, providing immediate visual feedback on the generated model.