How to Add New Export Formats to the CAD Skill in text-to-cad: A Complete 8-Step Workflow
Adding a new export format to the CAD skill requires implementing an exporter function in the cadpy package, extending the StepImportOptions data class, exposing the format through the CLI in scripts/step/cli.py, and wiring the exporter into the generation orchestration in generation.py.
The earthtojake/text-to-cad repository generates primary STEP files alongside optional side-car mesh formats like STL, 3MF, and GLB. When extending the system to support additional formats such as OBJ or PLY, developers must follow a predictable four-layer pipeline that ensures consistent CLI exposure, generation orchestration, and documentation. Mastering this workflow for adding new export formats to the CAD skill enables clean integration with the existing side-car processing loop.
Core Implementation
Step 1: Create the Exporter Function
Create a new module under skills/cad/scripts/packages/cadpy/src/cadpy/ (for example, obj.py). The function signature must mirror the existing exporters like stl.py:
from pathlib import Path
from cadpy.types import LoadedStepScene
def export_part_obj_from_scene(
step_path: Path,
scene: LoadedStepScene,
*,
target_path: Path | None = None,
) -> Path:
"""Export the supplied `scene` as an OBJ file.
* `step_path` – the original STEP file (used for error messages).
* `scene` – the fully-loaded step scene produced by `load_step_scene`.
* `target_path` – optional explicit output location; if omitted a path is
derived from the STEP file name.
"""
# Use a geometry library (e.g., trimesh, pywavefront) to write OBJ
return target_path
The STL exporter at skills/cad/scripts/packages/cadpy/src/cadpy/stl.py serves as the reference implementation for error handling and path derivation logic.
Step 2: Extend the Configuration Data Class
The StepImportOptions dataclass in skills/cad/scripts/packages/cadpy/src/cadpy/catalog.py carries side-car flags from the CLI to the generation engine. Add a new field for your format:
from dataclasses import dataclass
from typing import Optional
@dataclass
class StepImportOptions:
stl: Optional[str] = None
three_mf: Optional[str] = None
glb: Optional[str] = None
obj: Optional[str] = None # ← NEW FIELD
mesh_tolerance: Optional[float] = None
mesh_angular_tolerance: Optional[float] = None
This dataclass acts as the configuration contract between the CLI layer and the generation pipeline.
Interface Integration
Step 3: Add CLI Arguments
Edit skills/cad/scripts/step/cli.py to expose the new option. Existing STL, 3MF, and GLB flags are defined around lines 48-62:
parser.add_argument(
"--obj",
metavar="OUTPUT",
help="Export an OBJ side-car to this relative .obj path.",
)
Update the _step_import_options_from_args function to populate the field:
return StepImportOptions(
stl=args.stl,
three_mf=args.three_mf,
glb=args.glb,
obj=args.obj, # ← NEW
mesh_tolerance=args.mesh_tolerance,
mesh_angular_tolerance=args.mesh_angular_tolerance,
)
Step 4: Wire into the Generation Pipeline
Inside skills/cad/scripts/packages/cadpy/src/cadpy/generation.py, the generate_step_targets function builds a list of _ArtifactJob instances. Locate the side-car handling block around lines 1700-1800 and add your exporter:
if spec.obj_path:
jobs.append(_ArtifactJob(
name="OBJ",
func=lambda s=spec, sc=scene: export_part_obj_from_scene(
s.step_path, sc, target_path=Path(s.obj_path)
),
))
The lambda closure captures the spec and scene variables to ensure the exporter receives the correct paths when executed.
Documentation and Quality Assurance
Step 5: Update Export References
Document the new format in skills/cad/references/supported-exports.md:
## OBJ
Export a Wavefront OBJ file. Useful for downstream tools that require explicit vertex/face listings.
The CLI flag added in Step 3 automatically appears in the generated --help output.
Step 6: Add Automated Tests
Create a test case under tests/python/skills/cad/ following the pattern of existing format tests:
- Run
scripts/stepwith--objon a minimal sample model. - Assert the file is created with the expected
.objsuffix. - Validate the output contains proper OBJ syntax (vertex and face definitions).
Name the file test_step_obj.py to maintain consistency with test_step_stl.py.
Validation and Deployment
Step 7: Verify End-to-End
Run the complete generation workflow locally:
python scripts/step path/to/sample_model.py --obj meshes/sample.obj --verbose
Confirm that:
- The primary STEP file is produced.
- The OBJ side-car appears next to the STEP file.
scripts/inspectoperates on the STEP file without interference from the side-car.
Step 8: Continuous Integration Validation
Execute the CI test suite via scripts/test/test.sh to ensure the new Python tests pass and no regressions occur in existing STL, 3MF, or GLB export paths. The test matrix automatically validates all configured export formats.
Summary
- Implement the exporter function in
skills/cad/scripts/packages/cadpy/src/cadpy/using the signature pattern fromstl.py. - Extend
StepImportOptionsincadpy/catalog.pyto carry the new export path. - Expose the format via CLI flags in
skills/cad/scripts/step/cli.py. - Wire the exporter into
generate_step_targetsincadpy/generation.pyusing the_ArtifactJobpattern. - Document the format in
skills/cad/references/supported-exports.md. - Test locally with sample models before submitting to CI via
scripts/test/test.sh.
Frequently Asked Questions
What is the minimum code required to add a basic export format?
You must modify four files: create an exporter module in cadpy/, add a field to StepImportOptions in catalog.py, add a flag in step/cli.py, and append an _ArtifactJob in generation.py. No changes are required to the core STEP generation logic, as side-car exports run after the primary CAD file creation.
How does the _ArtifactJob pattern handle multiple simultaneous exports?
The generate_step_targets function appends each requested format to a jobs list as separate _ArtifactJob instances. These execute sequentially after the primary STEP generation, allowing users to request STL, 3MF, GLB, and your new format in a single command without interference between exporters.
Where should mesh tolerance settings be configured for new formats?
Mesh tolerances are stored in StepImportOptions alongside format-specific paths. Your exporter function receives the scene object already loaded, but should respect mesh_tolerance and mesh_angular_tolerance if performing additional tessellation. Access these values via the spec object passed to your lambda in the _ArtifactJob definition.
How do I ensure backward compatibility when adding CLI flags?
Use Optional[str] type hints with None defaults in both the CLI argument parser and the StepImportOptions dataclass. This ensures existing scripts that do not specify the new flag continue to function without raising AttributeError or KeyError exceptions during option parsing.
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:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →