# How the cadgen Package Handles Model Execution in Text-to-CAD

> Learn how the cadgen package executes CAD models through a reproducible Python pipeline, discover source definitions, and submit jobs to backends.

- Repository: [earthtojake/text-to-cad](https://github.com/earthtojake/text-to-cad)
- Tags: internals
- Published: 2026-09-11

---

**The cadgen package executes CAD models by transforming Python functions decorated with `@step`, `@dxf`, or mesh decorators into a reproducible build pipeline that discovers source definitions, selects generation targets, and submits jobs to either a warm daemon or transient subprocess backend.**

When working with the earthtojake/text-to-cad repository, understanding how the cadgen package handles model execution is essential for optimizing build performance and debugging generation workflows. The execution flow begins when you run `python model.py` and triggers a sophisticated orchestration system involving argument parsing, source discovery, and event-driven backend processing.

## The Model Execution Pipeline

The cadgen package implements a multi-stage pipeline that transforms a simple script execution into a deterministic CAD build process.

### Entry Point and Argument Parsing

Execution begins in `cadgen.authoring`, which calls the internal runner `cadgen.cli._run_model.run_model_argv`. This function builds an argument parser via `_build_parser` that recognizes flags including `--model`, `--force`, `--json`, and mesh tolerance parameters.

In [`cli/_run_model.py`](https://github.com/earthtojake/text-to-cad/blob/main/cli/_run_model.py), the parser processes command-line arguments and normalizes mesh-related values using `cadgen.metadata.normalize_mesh_numeric` (lines 73-77). These normalized values feed into `StepImportOptions` used during generation.

### Model Discovery and Target Resolution

The `catalog.source_from_path` function (defined in [`catalog.py`](https://github.com/earthtojake/text-to-cad/blob/main/catalog.py) line 71) reads the target script and extracts the decorated function, creating a `Source` object that describes the model's artifacts. If the source defines only a DXF export (`source.dxf_path` set with empty `source.step_path`), the pipeline selects the DXF generation route; otherwise, it defaults to the full STEP pipeline (see [`_run_model.py`](https://github.com/earthtojake/text-to-cad/blob/main/_run_model.py) lines 91-100).

### Generation and Caching

The public façade functions `generate_step_targets` and `generate_dxf_targets` (exposed in [`generation.py`](https://github.com/earthtojake/text-to-cad/blob/main/generation.py)) drive the actual build process. These functions consult the internal store cache to skip up-to-date work when `force=False`, handle mesh-resolution parameters, and manage incremental file writes. The generation engine lives in `cadgen._internal.generation` and coordinates the entire artifact creation process.

## Execution Backends: Daemon vs. Transient Mode

The cadgen package supports two distinct execution strategies selected by `cadgen.daemon.executors.submit`.

### Daemon Mode (Default)

By default, execution requests route through `cadgen.daemon.executors.submit` to a long-running warm daemon. The daemon client ([`daemon/client.py`](https://github.com/earthtojake/text-to-cad/blob/main/daemon/client.py)) forwards jobs to worker threads managed by [`daemon/server.py`](https://github.com/earthtojake/text-to-cad/blob/main/daemon/server.py), maintaining state between builds for faster subsequent executions. This mode provides real-time event streaming and is ideal for iterative development.

### Transient Mode

When `CADGEN_DAEMON=0` is set or the platform cannot support the daemon, the executor spawns a short-lived subprocess. Despite the different runtime characteristics, both backends use identical pipeline code, guaranteeing deterministic artifacts regardless of execution mode. You can verify the backend selection through environment variables or platform capability detection in [`daemon/executors.py`](https://github.com/earthtojake/text-to-cad/blob/main/daemon/executors.py) line 62.

## Event-Driven Build Reporting

During execution, the system emits `model_event` events via `executors.emit_event` (line 106) to provide real-time progress updates. These events flow to either a UI tree renderer for interactive sessions or a line-based sink for transient workers. The event stream includes `submitted`, `running`, `succeeded`, and `failed` states, enabling hierarchical build-tree visualization in CAD Viewer interfaces.

When the `--json` flag is present, the CLI outputs structured JSON lines; otherwise, it prints human-readable summaries. Error handling occurs through `cadgen._internal.cli_errors.report_cli_error`, which catches exceptions and presents clean error messages rather than raw tracebacks (see [`_run_model.py`](https://github.com/earthtojake/text-to-cad/blob/main/_run_model.py) lines 118-122).

## Practical Code Examples

### Running a Simple STEP Model

```python

# model.py

from cadgen import step, box

@step
def model():
    # Build a 10 mm cube

    return box(10)

```

Execute the model:

```bash
$ python model.py

```

This triggers `cadgen.authoring`, which resolves to `generate_step_targets([ "model.py" ])`.

### Selecting Specific Models in Multi-Definition Files

```python

# multi.py

from cadgen import step, cylinder

@step
def small():
    return cylinder(radius=5, height=20)

@step
def large():
    return cylinder(radius=10, height=40)

```

Target a specific function:

```bash
$ python multi.py --model large

```

The CLI constructs the target string `"multi.py::large"` and passes it to the generation engine.

### Forcing Rebuilds with Custom Mesh Tolerances

```bash
$ python model.py --force --mesh-tolerance 0.01 --mesh-angular-tolerance 0.5

```

These parameters are normalized and injected into `StepImportOptions` for the generation backend.

### Explicit Daemon Management

```bash

# Start the warm daemon (once per session)

$ cadgen daemon start

# Submit a model to the daemon

$ python model.py

```

The `executors.submit` function creates a `Job` instance and forwards the request through the daemon client, with the worker thread handling the actual build and event emission.

## Core Architecture Components

The execution flow relies on specific modules within the cadgen package:

- **[`cli/_run_model.py`](https://github.com/earthtojake/text-to-cad/blob/main/cli/_run_model.py)** – Internal runner handling argument parsing, model resolution, and pipeline invocation.
- **[`generation.py`](https://github.com/earthtojake/text-to-cad/blob/main/generation.py)** – Public façade exposing `generate_step_targets` and `generate_dxf_targets` to orchestration tools.
- **[`daemon/executors.py`](https://github.com/earthtojake/text-to-cad/blob/main/daemon/executors.py)** – Decision logic for backend selection (daemon vs. transient), job submission, and event emission.
- **[`daemon/client.py`](https://github.com/earthtojake/text-to-cad/blob/main/daemon/client.py)** and **[`daemon/server.py`](https://github.com/earthtojake/text-to-cad/blob/main/daemon/server.py)** – Communication layer managing the warm daemon's job queues and worker threads.
- **[`authoring.py`](https://github.com/earthtojake/text-to-cad/blob/main/authoring.py)** – Entry point module referenced by model scripts' `__main__` blocks.
- **[`catalog.py`](https://github.com/earthtojake/text-to-cad/blob/main/catalog.py)** and **[`metadata.py`](https://github.com/earthtojake/text-to-cad/blob/main/metadata.py)** – Source resolution and mesh parameter normalization.
- **[`store/index.py`](https://github.com/earthtojake/text-to-cad/blob/main/store/index.py)** – Persistent index mapping `script::function` references to stable model IDs and tracking closure states.

## Summary

- The cadgen package transforms decorated Python functions into executable CAD models through `cadgen.cli._run_model.run_model_argv`.
- Model discovery uses `catalog.source_from_path` to resolve script paths into `Source` objects describing STEP or DXF targets.
- Generation occurs through `generate_step_targets` or `generate_dxf_targets` in [`generation.py`](https://github.com/earthtojake/text-to-cad/blob/main/generation.py), with built-in caching for incremental builds.
- Execution modes include a warm daemon (default) for performance or transient subprocesses when `CADGEN_DAEMON=0` is set, both handled by [`daemon/executors.py`](https://github.com/earthtojake/text-to-cad/blob/main/daemon/executors.py).
- Real-time progress reporting uses event emission (`model_event`) to support both CLI JSON output and interactive UI tree rendering.
- Error handling routes through `report_cli_error` to provide user-friendly diagnostics instead of stack traces.

## Frequently Asked Questions

### What triggers the cadgen model execution pipeline?

Running a Python script containing cadgen decorators (`@step`, `@dxf`, `@stl`, etc.) triggers the pipeline through the script's `__main__` block, which imports `cadgen.authoring`. This module forwards execution to `cadgen.cli._run_model.run_model_argv`, initiating argument parsing and model discovery.

### How does cadgen choose between daemon and transient execution?

The `cadgen.daemon.executors.submit` function checks the `CADGEN_DAEMON` environment variable and platform capabilities. If the daemon is available and enabled (default), jobs route to the warm daemon via [`daemon/client.py`](https://github.com/earthtojake/text-to-cad/blob/main/daemon/client.py). If `CADGEN_DAEMON=0` or the platform lacks daemon support, the system spawns a transient subprocess.

### Can I force a rebuild without clearing the entire cache?

Yes. Pass the `--force` flag when running your model script. This bypasses the cache check in `generate_step_targets`, forcing the generation engine to rebuild artifacts regardless of existing cached states.

### How does cadgen handle errors during model generation?

Errors are caught and processed by `cadgen._internal.cli_errors.report_cli_error`, which formats exceptions into clean, user-readable messages. This prevents raw Python tracebacks from cluttering the CLI output while preserving diagnostic information for debugging.