Text to CAD

Use when the user provides a natural language description of a 3D object or mechanical part and wants to generate a CAD model. Converts the description into CadQuery Python code, automatically detects or sets up the CadQuery environment, executes the script, and produces STL and STEP output files.

Best use case

Text to CAD is best used when you need a repeatable AI agent workflow instead of a one-off prompt.

Use when the user provides a natural language description of a 3D object or mechanical part and wants to generate a CAD model. Converts the description into CadQuery Python code, automatically detects or sets up the CadQuery environment, executes the script, and produces STL and STEP output files.

Teams using Text to CAD should expect a more consistent output, faster repeated execution, less prompt rewriting.

When to use this skill

  • You want a reusable workflow that can be run more than once with consistent structure.

When not to use this skill

  • You only need a quick one-off answer and do not need a reusable workflow.
  • You cannot install or maintain the underlying files, dependencies, or repository context.

Installation

Claude Code / Cursor / Codex

$curl -o ~/.claude/skills/text2cad/SKILL.md --create-dirs "https://raw.githubusercontent.com/SpectrAI-Initiative/InnoClaw/main/.claude/skills/text2cad/SKILL.md"

Manual Installation

  1. Download SKILL.md from GitHub
  2. Place it in .claude/skills/text2cad/SKILL.md inside your project
  3. Restart your AI agent — it will auto-discover the skill

How Text to CAD Compares

Feature / AgentText to CADStandard Approach
Platform SupportNot specifiedLimited / Varies
Context Awareness High Baseline
Installation ComplexityUnknownN/A

Frequently Asked Questions

What does this skill do?

Use when the user provides a natural language description of a 3D object or mechanical part and wants to generate a CAD model. Converts the description into CadQuery Python code, automatically detects or sets up the CadQuery environment, executes the script, and produces STL and STEP output files.

Where can I find the source code?

You can find the source code on GitHub using the link provided at the top of the page.

SKILL.md Source

# Text to CAD (CadQuery)

This skill converts a natural language description of a 3D object into a fully functional CadQuery Python script, executes it, and delivers STL + STEP files. The workflow is designed to handle everything from simple primitives ("a cube with rounded edges") to complex mechanical assemblies ("a flanged bearing housing with bolt holes").

## Phase 0: Environment Detection & Setup

Before generating any model, **automatically detect a working CadQuery environment**. Follow this sequence -- stop at the first success:

1. **Check if `cadquery` is already importable**:
   ```bash
   python -c "import cadquery; print(cadquery.__version__)"
   ```
   If this succeeds, use `python` directly as the interpreter.

2. **Search for conda/mamba environments that have cadquery**:
   ```bash
   conda env list
   ```
   For each environment found, test:
   ```bash
   conda run -n <env_name> python -c "import cadquery; print(cadquery.__version__)"
   ```
   If one succeeds, use `conda run -n <env_name> python` as the interpreter.

3. **Search for virtual environments in the working directory or common locations** (`.venv`, `venv`, `env`):
   ```bash
   # Linux/macOS
   .venv/bin/python -c "import cadquery; print(cadquery.__version__)"
   # Windows
   .venv/Scripts/python -c "import cadquery; print(cadquery.__version__)"
   ```

4. **If no environment found, install cadquery**:
   - Preferred: `pip install cadquery` (in current Python)
   - Fallback: `conda install -c conda-forge cadquery` (if conda is available)
   - Confirm installation succeeded before proceeding.

5. **Cache the result**: Once a working interpreter command is found, reuse it for all subsequent executions in this session. Store it as `CADQUERY_PYTHON` (e.g., `python`, `conda run -n myenv python`, `.venv/bin/python`).

If all attempts fail, inform the user and provide manual installation instructions:
```
pip install cadquery
# or
conda install -c conda-forge cadquery
```

---

## Phase 1: Requirement Analysis & Clarification

When the user provides a natural language description:

1. **Parse the description** to extract:
   - **Geometry type**: primitive (box, cylinder, sphere), composite, or assembly
   - **Dimensions**: explicit measurements (mm by default) or relative sizing
   - **Features**: holes, fillets, chamfers, patterns, text, threads, etc.
   - **Spatial relationships**: positions, alignments, symmetry
   - **Material/functional hints**: load-bearing, aesthetic, printable, etc.

2. **Fill in missing details intelligently**:
   - If no units specified -> assume millimeters (mm)
   - If no dimensions specified -> infer reasonable engineering defaults based on the object type
   - If ambiguous geometry -> choose the most common/standard engineering interpretation
   - If "printable" mentioned -> ensure manifold geometry, add appropriate tolerances

3. **Confirm understanding** (brief, 2-3 sentences):
   - Summarize what you will model
   - State key dimensions and features
   - Note any assumptions made
   - Ask the user to confirm or adjust before proceeding

---

## Phase 2: Code Generation

Generate a complete, self-contained CadQuery Python script following these **mandatory rules**:

### Code Structure Template

```python
"""
CadQuery Model: {model_name}
Description: {user_description}
Generated dimensions: {key_dimensions}
Units: millimeters (mm)
"""

import cadquery as cq
import os

# ============================================================
# Parameters (easy to modify)
# ============================================================
# Group all dimensional parameters at the top for easy tweaking
PARAM_NAME = value  # description, unit

# ============================================================
# Output Configuration
# ============================================================
# Output to an "output" folder relative to this script's location.
# The user can override OUTPUT_DIR if they prefer a different path.
OUTPUT_DIR = os.path.join(os.path.dirname(os.path.abspath(__file__)), "output")
MODEL_NAME = "{model_name}"

os.makedirs(OUTPUT_DIR, exist_ok=True)

# ============================================================
# Model Construction
# ============================================================
# Build the model step by step with comments explaining each operation

result = (
    cq.Workplane("XY")
    .box(...)
    # ... operations ...
)

# ============================================================
# Export
# ============================================================
step_path = os.path.join(OUTPUT_DIR, f"{MODEL_NAME}.step")
stl_path = os.path.join(OUTPUT_DIR, f"{MODEL_NAME}.stl")

cq.exporters.export(result, step_path)
cq.exporters.export(result, stl_path)

print(f"Model '{MODEL_NAME}' generated successfully!")
print(f"   STEP: {step_path}")
print(f"   STL:  {stl_path}")

# Print bounding box for verification
bb = result.val().BoundingBox()
print(f"   Bounding Box: {bb.xlen:.2f} x {bb.ylen:.2f} x {bb.zlen:.2f} mm")
```

### CadQuery API Best Practices

**Primitives & Basic Shapes:**
- `cq.Workplane("XY").box(length, width, height)` -- centered box
- `cq.Workplane("XY").cylinder(height, radius)` -- centered cylinder
- `cq.Workplane("XY").sphere(radius)` -- sphere
- `cq.Workplane("XY").wedge(dx, dy, dz, xmin, zmin, xmax, zmax)` -- wedge/prism

**2D Sketch -> 3D Extrusion (most versatile pattern):**
```python
result = (
    cq.Workplane("XY")
    .moveTo(x, y).lineTo(...).lineTo(...).close()  # sketch profile
    .extrude(height)  # or .revolve(angleDegrees, axisStart, axisEnd)
)
```

**Feature Operations:**
- `.fillet(radius)` -- round all edges (use with `.edges("|Z")` etc. for selective)
- `.chamfer(distance)` -- chamfer edges
- `.hole(diameter, depth=None)` -- through or blind hole at center
- `.cboreHole(diameter, cboreDiameter, cboreDepth)` -- counterbore hole
- `.cskHole(diameter, cskDiameter, cskAngle)` -- countersink hole
- `.shell(thickness)` -- hollow out (negative = inward)

**Face/Edge Selection (critical for targeted operations):**
- `.faces(">Z")` -- topmost face in Z
- `.faces("<Z")` -- bottommost face in Z
- `.edges("|Z")` -- edges parallel to Z
- `.edges(">Z")` -- topmost edges in Z
- `.edges("%Circle")` -- circular edges
- `.faces("+Z")` -- faces with normal pointing in +Z direction

**Boolean Operations:**
- `.cut(other_shape)` -- subtract
- `.union(other_shape)` -- add
- `.intersect(other_shape)` -- intersection

**Patterns & Arrays:**
- `.pushPoints([(x1,y1), (x2,y2), ...])` -- place features at points
- `.rarray(xSpacing, ySpacing, xCount, yCount)` -- rectangular array
- `.polarArray(radius, startAngle, angle, count)` -- circular array

**Advanced:**
- `.sweep(path)` -- sweep a profile along a path
- `.loft()` -- loft between profiles
- `.twistExtrude(height, angleDegrees)` -- helical extrusion
- `.text("text", fontsize, distance)` -- embossed/engraved text
- `.mirror("XY")` -- mirror about a plane
- `.translate((x, y, z))` -- move
- `.rotate((0,0,0), (0,0,1), angleDeg)` -- rotate

**Multi-body / Assembly Pattern:**
```python
part_a = cq.Workplane("XY").box(10, 10, 10)
part_b = cq.Workplane("XY").transformed(offset=(20, 0, 0)).cylinder(10, 5)
result = part_a.union(part_b)
```

### Code Quality Rules

1. **All parameters at the top** -- no magic numbers in the modeling section
2. **Descriptive variable names** -- `flange_diameter`, not `d1`
3. **Step-by-step comments** -- explain what each operation does in context
4. **Build incrementally** -- complex models should be built in logical stages
5. **Selective fillet/chamfer** -- use face/edge selectors, not blanket `.fillet()` which often fails
6. **Error-safe ordering**: fillet/chamfer operations MUST come AFTER all boolean cuts/unions. Fillets on edges that get modified by later booleans will crash
7. **Manifold geometry** -- ensure the result is a valid solid (no self-intersections)
8. **Reasonable tolerances** -- if parts need to fit together, add 0.1-0.2mm clearance

### Common Pitfalls to AVOID

- `.fillet()` with radius >= smallest edge length -> crash. Always use conservative radii.
- `.shell()` on complex geometry with thin walls -> often fails. Keep wall thickness reasonable.
- Chaining too many operations without `.clean()` -> geometry corruption. Add `.clean()` after complex booleans.
- Forgetting that `.box()` and `.cylinder()` are centered by default.
- Using `.faces(">Z").fillet()` when there are multiple faces at the same Z height -> ambiguous selection.
- Applying `.fillet()` before `.cut()` -- fillet edges may be destroyed by the cut.

---

## Phase 3: Execution

1. **Determine the working directory**: Use the user's current working directory (or a temporary directory) to write the script. Write the script to `{working_dir}/{model_name}.py`.
2. **Execute** using the interpreter found in Phase 0:
   ```bash
   {CADQUERY_PYTHON} {working_dir}/{model_name}.py
   ```
   Where `{CADQUERY_PYTHON}` is the cached interpreter command from environment detection.
3. **Set timeout** to 60 seconds (complex models may take time)

---

## Phase 4: Auto-Debug (up to 5 attempts)

If execution fails, follow this diagnostic protocol:

| Error Type | Diagnosis | Fix Strategy |
|---|---|---|
| `Standard_ConstructionError` | Fillet/chamfer radius too large | Reduce radius to 50% of smallest adjacent edge |
| `BRep_API: not done` | Boolean operation failed | Add `.clean()` before boolean; simplify geometry |
| `StdFail_NotDone` | Impossible geometric operation | Re-order operations; split into sub-steps |
| `ValueError: No wire found` | Unclosed sketch profile | Ensure `.close()` is called; check `.lineTo()` endpoints |
| `Selector found no objects` | Face/edge selector matched nothing | Use simpler selectors; print available faces/edges for debugging |
| `ModuleNotFoundError` | Missing package | Install via `pip install {package}` using the detected interpreter's environment, then retry. If cadquery itself is missing, re-run Phase 0 |
| `MemoryError` or timeout | Model too complex | Reduce polygon count; simplify fillets |

**Debug approach:**
1. Read the full traceback
2. Identify the exact failing CadQuery operation
3. Apply the targeted fix from the table above
4. If unclear, add diagnostic prints: `print(result.faces().vals())` to inspect geometry state
5. Rebuild and re-execute

---

## Phase 5: Result Verification & Delivery

After successful execution:

1. **Verify output files exist** and have non-zero size
2. **Report to user**:
   - Confirmation of success
   - Bounding box dimensions (X x Y x Z mm)
   - File paths (STEP and STL)
   - Brief description of modeling approach
   - Suggestions for modifications (optional parameters to tweak)

3. **Offer follow-up options**:
   - "Want me to adjust any dimensions?"
   - "Need additional features (holes, fillets, text)?"
   - "Want to generate a variant or assembly?"
   - "Need the code explained step by step?"

---

## Phase 6: Iterative Refinement

If the user requests changes:
1. **Read the existing script** to understand current state
2. **Apply targeted modifications** -- don't regenerate from scratch unless major restructuring is needed
3. **Re-execute and verify** with the same pipeline
4. **Show diff** -- briefly describe what changed

---

## Mechanical Parts Library (reference patterns)

**Bolt/Screw:**
```python
head = cq.Workplane("XY").cylinder(head_height, head_radius)
shaft = cq.Workplane("XY").workplane(offset=-head_height).cylinder(shaft_length, shaft_radius)
result = head.union(shaft)
```

**Gear (simplified profile):**
```python
result = (
    cq.Workplane("XY")
    .circle(outer_radius)
    .extrude(thickness)
    .faces(">Z")
    .workplane()
    .hole(bore_diameter)
    .faces(">Z")
    .workplane()
    .polarArray(pitch_radius, 0, 360, num_teeth)
    .rect(tooth_width, tooth_height)
    .cutThruAll()
)
```

**Enclosure/Box with lid:**
```python
body = cq.Workplane("XY").box(L, W, H).edges("|Z").fillet(corner_r).shell(-wall)
lid = cq.Workplane("XY").workplane(offset=H/2).box(L, W, lid_h).edges("|Z").fillet(corner_r)
```

**Pipe/Tube:**
```python
result = (
    cq.Workplane("XY")
    .circle(outer_radius)
    .circle(inner_radius)  # concentric circle creates annular profile
    .extrude(length)
)
```

**Flange:**
```python
result = (
    cq.Workplane("XY")
    .circle(flange_radius).extrude(flange_thickness)
    .faces(">Z").workplane()
    .circle(pipe_radius).extrude(pipe_length)
    .faces("<Z").workplane()
    .pushPoints(bolt_hole_positions)
    .hole(bolt_hole_diameter)
    .faces("<Z").workplane()
    .hole(bore_diameter)
)
```

---

## Quality Checklist (verify before delivering)

- [ ] Script runs without errors
- [ ] Both STL and STEP files generated with non-zero size
- [ ] Bounding box matches expected dimensions (within 1%)
- [ ] All user-specified features present
- [ ] Parameters are clearly labeled and at the top of the script
- [ ] Code is well-commented and readable
- [ ] Fillets/chamfers applied AFTER all boolean operations
- [ ] No magic numbers in modeling section

---

## Response Language

Always respond in the **same language as the user's message**. If the user writes in Chinese, respond in Chinese. If in English, respond in English.

Related Skills

Researcher Context Audit

370
from SpectrAI-Initiative/InnoClaw

Use when the Researcher starts, resumes, or reaches a major decision point. Build a context inventory from workstation materials, prior messages, existing artifacts, requirements, and unfinished work.

wind-site-assessment

370
from SpectrAI-Initiative/InnoClaw

Assess wind energy potential and perform site analysis using atmospheric science calculations.

web_literature_mining

370
from SpectrAI-Initiative/InnoClaw

Scientific Literature Mining - Mine scientific literature: PubMed search, arXiv search, web search, and Tavily deep search. Use this skill for scientific informatics tasks involving pubmed search search literature search web tavily search. Combines 4 tools from 2 SCP server(s).

virus_genomics

370
from SpectrAI-Initiative/InnoClaw

Virus Genomics Analysis - Analyze virus genomics: NCBI virus dataset, annotation, taxonomy, and literature search. Use this skill for virology tasks involving get virus dataset report get virus annotation report get taxonomy search literature. Combines 4 tools from 2 SCP server(s).

virtual_screening

370
from SpectrAI-Initiative/InnoClaw

Virtual Screening Pipeline - Virtual screening: search PubChem by substructure, compute similarity, filter by drug-likeness, and predict binding affinity. Use this skill for drug discovery tasks involving search pubchem by smiles calculate smiles similarity calculate mol drug chemistry boltz binding affinity. Combines 4 tools from 3 SCP server(s).

variant_pathogenicity

370
from SpectrAI-Initiative/InnoClaw

Variant Pathogenicity Assessment - Assess variant pathogenicity: Ensembl VEP prediction, ClinVar lookup, variation details, and gene phenotype associations. Use this skill for clinical genetics tasks involving get vep hgvs clinvar search get variation get phenotype gene. Combines 4 tools from 2 SCP server(s).

variant-population-frequency

370
from SpectrAI-Initiative/InnoClaw

Query gnomAD for variant allele frequency across populations. Uses FAVOR to convert rsID→variant_id first, then queries gnomAD.

variant-pharmacogenomics

370
from SpectrAI-Initiative/InnoClaw

Query PharmGKB (clinPGx) for pharmacogenomic clinical annotations — how a variant affects drug response, dosing, and adverse reactions.

variant-gwas-associations

370
from SpectrAI-Initiative/InnoClaw

Query EBI GWAS Catalog for GWAS statistical associations (p-value, effect size, risk allele) between a variant and traits/diseases.

variant-genomic-location

370
from SpectrAI-Initiative/InnoClaw

Query dbSNP + NCBI Gene to get variant genomic position (chromosome, coordinates, ref/alt alleles, mutation type) and associated gene coordinates.

variant-functional-prediction

370
from SpectrAI-Initiative/InnoClaw

Query FAVOR API for variant functional prediction scores (CADD, SIFT, PolyPhen, REVEL, etc.) and gene annotation.

variant-cross-database-ids

370
from SpectrAI-Initiative/InnoClaw

Query ClinGen Allele Registry to map variant rsID to identifiers in other databases (ClinVar, gnomAD, COSMIC, UniProtKB, OMIM, etc.).