text-to-cad-harness
Compare original and translation side by side
🇺🇸
Original
English🇨🇳
Translation
Chinese⚙ Text-to-CAD Harness
⚙ 文本转CAD工具
Skill by ara.so — Daily 2026 Skills collection.
An open source harness that lets AI coding agents (Claude Code, Codex, Cursor, etc.) generate, export, and preview 3D CAD models from natural language descriptions. Models are written in Python using build123d on top of OpenCascade (OCP), exported to STEP/STL/DXF/GLB/URDF, and inspected in a local React/Vite CAD Explorer viewer.
How It Works
工作原理
User prompt → Agent edits models/*.py → Python skill regenerates artifacts → Viewer previews geometry- — Source-controlled Python CAD files (build123d scripts)
models/ - — Bundled CAD skill (STEP, STL, DXF, GLB, snapshots,
skills/cad/references)@cad[...] - — Bundled URDF skill (robot links, joints, validation)
skills/urdf/ - — Local React/Vite CAD Explorer (no backend required)
viewer/
用户提示 → Agent编辑models/*.py文件 → Python技能重新生成工件 → 查看器预览几何模型- — 受版本控制的Python CAD文件(build123d脚本)
models/ - — 集成的CAD技能(支持STEP、STL、DXF、GLB、快照、
skills/cad/引用)@cad[...] - — 集成的URDF技能(机器人连杆、关节、验证)
skills/urdf/ - — 本地React/Vite CAD Explorer查看器(无需后端)
viewer/
Installation
安装步骤
1. Clone the repo
1. 克隆仓库
bash
git clone https://github.com/earthtojake/text-to-cad.git
cd text-to-cadbash
git clone https://github.com/earthtojake/text-to-cad.git
cd text-to-cad2. Set up Python CAD environment
2. 设置Python CAD环境
bash
python3.11 -m venv .venv
./.venv/bin/python -m pip install --upgrade pip
./.venv/bin/pip install -r requirements-cad.txtRequires Python 3.11+. Thepins build123d, OCP, and all geometry dependencies.requirements-cad.txt
bash
python3.11 -m venv .venv
./.venv/bin/python -m pip install --upgrade pip
./.venv/bin/pip install -r requirements-cad.txt需要Python 3.11及以上版本。中固定了build123d、OCP及所有几何相关依赖的版本。requirements-cad.txt
3. Install viewer dependencies
3. 安装查看器依赖
bash
cd viewer
npm installbash
cd viewer
npm install4. Start the CAD Explorer
4. 启动CAD Explorer查看器
Project Structure
项目结构
text-to-cad/
├── models/ # Your CAD source files live here
│ └── my_part/
│ ├── part.py # build123d Python source
│ ├── part.step # Generated STEP export
│ ├── part.stl # Generated STL export
│ └── part.glb # Generated GLB for viewer
├── skills/
│ ├── cad/
│ │ ├── SKILL.md # CAD skill documentation
│ │ └── ...
│ └── urdf/
│ ├── SKILL.md # URDF skill documentation
│ └── ...
├── viewer/ # React/Vite local viewer
│ ├── package.json
│ └── src/
├── requirements-cad.txt # Python dependencies
└── assets/text-to-cad/
├── models/ # CAD源文件存放目录
│ └── my_part/
│ ├── part.py # build123d Python源文件
│ ├── part.step # 生成的STEP导出文件
│ ├── part.stl # 生成的STL导出文件
│ └── part.glb # 供查看器使用的GLB格式文件
├── skills/
│ ├── cad/
│ │ ├── SKILL.md # CAD技能文档
│ │ └── ...
│ └── urdf/
│ ├── SKILL.md # URDF技能文档
│ └── ...
├── viewer/ # React/Vite本地查看器
│ ├── package.json
│ └── src/
├── requirements-cad.txt # Python依赖文件
└── assets/Writing CAD Models (build123d)
编写CAD模型(build123d)
All models live under as Python scripts using build123d.
models/所有模型以Python脚本形式存放在目录下,使用build123d编写。
models/Basic Part Example
基础零件示例
python
undefinedpython
undefinedmodels/bracket/bracket.py
models/bracket/bracket.py
from build123d import *
with BuildPart() as bracket:
# Base plate
with BuildSketch(Plane.XY):
Rectangle(80, 60)
extrude(amount=5)
# Vertical wall
with BuildSketch(Plane.XZ.offset(30)):
Rectangle(80, 40)
extrude(amount=5)
# Fillets on all edges
fillet(bracket.edges(), radius=2)
# Mounting holes
with BuildSketch(bracket.faces().filter_by(Axis.Z).sort_by(Axis.Z)[-1]):
with Locations((-25, -15), (25, -15), (-25, 15), (25, 15)):
Circle(3.5)
extrude(amount=-5, mode=Mode.SUBTRACT)from build123d import *
with BuildPart() as bracket:
# 底座
with BuildSketch(Plane.XY):
Rectangle(80, 60)
extrude(amount=5)
# 垂直壁
with BuildSketch(Plane.XZ.offset(30)):
Rectangle(80, 40)
extrude(amount=5)
# 所有边倒圆角
fillet(bracket.edges(), radius=2)
# 安装孔
with BuildSketch(bracket.faces().filter_by(Axis.Z).sort_by(Axis.Z)[-1]):
with Locations((-25, -15), (25, -15), (-25, 15), (25, 15)):
Circle(3.5)
extrude(amount=-5, mode=Mode.SUBTRACT)Export
导出
export_step(bracket.part, "models/bracket/bracket.step")
export_stl(bracket.part, "models/bracket/bracket.stl")
undefinedexport_step(bracket.part, "models/bracket/bracket.step")
export_stl(bracket.part, "models/bracket/bracket.stl")
undefinedRunning a Model to Generate Artifacts
运行模型生成工件
bash
./.venv/bin/python models/bracket/bracket.pybash
./.venv/bin/python models/bracket/bracket.pyParametric Part with Variables
带变量的参数化零件
python
undefinedpython
undefinedmodels/hex_spacer/hex_spacer.py
models/hex_spacer/hex_spacer.py
from build123d import *
from build123d import *
Parameters — agent edits these values
参数 — Agent可编辑这些值
OUTER_DIAMETER = 12.0 # mm, across-flats
HEIGHT = 10.0 # mm
HOLE_DIAMETER = 5.0 # mm (M5 clearance)
WALL_THICKNESS = 2.0 # mm
with BuildPart() as spacer:
with BuildSketch(Plane.XY):
RegularPolygon(radius=OUTER_DIAMETER / 2, side_count=6)
extrude(amount=HEIGHT)
with BuildSketch(Plane.XY):
Circle(HOLE_DIAMETER / 2)
extrude(amount=HEIGHT, mode=Mode.SUBTRACT)
fillet(spacer.edges().filter_by(Axis.Z), radius=0.5)export_step(spacer.part, "models/hex_spacer/hex_spacer.step")
export_stl(spacer.part, "models/hex_spacer/hex_spacer.stl")
undefinedOUTER_DIAMETER = 12.0 # 毫米,对边距
HEIGHT = 10.0 # 毫米
HOLE_DIAMETER = 5.0 # 毫米(M5间隙孔)
WALL_THICKNESS = 2.0 # 毫米
with BuildPart() as spacer:
with BuildSketch(Plane.XY):
RegularPolygon(radius=OUTER_DIAMETER / 2, side_count=6)
extrude(amount=HEIGHT)
with BuildSketch(Plane.XY):
Circle(HOLE_DIAMETER / 2)
extrude(amount=HEIGHT, mode=Mode.SUBTRACT)
fillet(spacer.edges().filter_by(Axis.Z), radius=0.5)export_step(spacer.part, "models/hex_spacer/hex_spacer.step")
export_stl(spacer.part, "models/hex_spacer/hex_spacer.stl")
undefinedAssembly Example
装配体示例
python
undefinedpython
undefinedmodels/assembly/assembly.py
models/assembly/assembly.py
from build123d import *
from build123d import *
Base
底座
with BuildPart() as base:
with BuildSketch(Plane.XY):
Rectangle(100, 80)
extrude(amount=10)
with BuildPart() as base:
with BuildSketch(Plane.XY):
Rectangle(100, 80)
extrude(amount=10)
Post
立柱
with BuildPart() as post:
with BuildSketch(Plane.XY):
Circle(8)
extrude(amount=50)
with BuildPart() as post:
with BuildSketch(Plane.XY):
Circle(8)
extrude(amount=50)
Combine into assembly
组合成装配体
assembly = Compound(
children=[
base.part,
post.part.move(Location((0, 0, 10))),
]
)
export_step(assembly, "models/assembly/assembly.step")
export_stl(assembly, "models/assembly/assembly.stl")
---assembly = Compound(
children=[
base.part,
post.part.move(Location((0, 0, 10))),
]
)
export_step(assembly, "models/assembly/assembly.step")
export_stl(assembly, "models/assembly/assembly.stl")
---Exporting Formats
导出格式
From within any script, use build123d export functions:
models/*.pypython
from build123d import *在任意脚本中,可使用build123d的导出函数:
models/*.pypython
from build123d import *STEP — full geometry, use for CAD interchange
STEP — 完整几何模型,用于CAD数据交换
export_step(part, "models/my_part/my_part.step")
export_step(part, "models/my_part/my_part.step")
STL — mesh for 3D printing / simulation
STL — 网格模型,用于3D打印/仿真
export_stl(part, "models/my_part/my_part.stl")
export_stl(part, "models/my_part/my_part.stl")
DXF — 2D drawing / laser cutting
DXF — 2D图纸/激光切割
section = part.section(Plane.XY)
export_dxf(section, "models/my_part/my_part.dxf")
section = part.section(Plane.XY)
export_dxf(section, "models/my_part/my_part.dxf")
GLB — viewer-compatible 3D web format
GLB — 兼容查看器的Web 3D格式
export_gltf(part, "models/my_part/my_part.glb")
---export_gltf(part, "models/my_part/my_part.glb")
---URDF Robot Descriptions
URDF机器人描述
The bundled URDF skill generates robot description files. See for full docs.
skills/urdf/SKILL.md集成的URDF技能可生成机器人描述文件。完整文档请查看。
skills/urdf/SKILL.mdURDF Example Structure
URDF示例结构
models/my_robot/
├── robot.py # build123d geometry for each link
├── robot.urdf # Generated URDF XML
└── meshes/
├── base.stl
├── arm.stl
└── gripper.stlmodels/my_robot/
├── robot.py # 每个连杆的build123d几何模型
├── robot.urdf # 生成的URDF XML文件
└── meshes/
├── base.stl
├── arm.stl
└── gripper.stlMinimal URDF Output Pattern
最简URDF输出示例
xml
<!-- models/my_robot/robot.urdf (generated) -->
<?xml version="1.0"?>
<robot name="my_robot">
<link name="base_link">
<visual>
<geometry>
<mesh filename="meshes/base.stl"/>
</geometry>
</visual>
</link>
<link name="arm_link">
<visual>
<geometry>
<mesh filename="meshes/arm.stl"/>
</geometry>
</visual>
</link>
<joint name="base_to_arm" type="revolute">
<parent link="base_link"/>
<child link="arm_link"/>
<origin xyz="0 0 0.1" rpy="0 0 0"/>
<axis xyz="0 0 1"/>
<limit lower="-1.57" upper="1.57" effort="10" velocity="1"/>
</joint>
</robot>xml
<!-- models/my_robot/robot.urdf (generated) -->
<?xml version="1.0"?>
<robot name="my_robot">
<link name="base_link">
<visual>
<geometry>
<mesh filename="meshes/base.stl"/>
</geometry>
</visual>
</link>
<link name="arm_link">
<visual>
<geometry>
<mesh filename="meshes/arm.stl"/>
</geometry>
</visual>
</link>
<joint name="base_to_arm" type="revolute">
<parent link="base_link"/>
<child link="arm_link"/>
<origin xyz="0 0 0.1" rpy="0 0 0"/>
<axis xyz="0 0 1"/>
<limit lower="-1.57" upper="1.57" effort="10" velocity="1"/>
</joint>
</robot>CAD Explorer Viewer
CAD Explorer查看器
The local viewer reads exported files from and renders them in browser using WebAssembly (WASM).
models/本地查看器读取目录下的导出文件,通过WebAssembly(WASM)在浏览器中渲染模型。
models/Viewer Commands
查看器命令
bash
cd viewerbash
cd viewerStart dev server
启动开发服务器
npm run dev # → http://localhost:4178
npm run dev # → http://localhost:4178
Build for static hosting
构建用于静态托管的版本
npm run build
npm run build
Preview production build
预览生产构建版本
npm run preview
undefinednpm run preview
undefinedViewer Features
查看器功能
- Browse all models in directory
models/ - Inspect STEP/GLB geometry in 3D
- Copy geometry references for agent follow-up edits
@cad[...] - Quick snapshot renders for iteration review
- 浏览目录下的所有模型
models/ - 以3D形式查看STEP/GLB几何模型
- 复制几何引用,供Agent后续编辑使用
@cad[...] - 快速生成快照渲染图,用于迭代评审
@cad[...]
Geometry References
@cad[...]@cad[...]
几何引用
@cad[...]After generating a model, the viewer provides stable handles. Paste these into your agent prompt to give it geometry-aware context for precise edits.
@cad[...]undefined生成模型后,查看器会提供稳定的句柄。将其粘贴到Agent提示中,可为Agent提供几何感知上下文,实现精准编辑。
@cad[...]undefinedExample agent follow-up using a reference
使用引用进行Agent后续编辑的示例
@cad[models/bracket/bracket.step#face:top] — add a countersunk hole at center
---@cad[models/bracket/bracket.step#face:top] — 在中心添加一个沉头孔
---Agent Workflow (Step-by-Step)
Agent工作流程(分步说明)
Typical session with Claude Code or Codex
使用Claude Code或Codex的典型会话
1. User: "Create a parametric L-bracket with 4 mounting holes, 5mm thick"
2. Agent: creates models/l_bracket/l_bracket.py using build123d
3. Agent runs: ./.venv/bin/python models/l_bracket/l_bracket.py
→ generates l_bracket.step, l_bracket.stl, l_bracket.glb
4. User: opens http://localhost:4178, inspects the model
5. User copies @cad[...] reference from viewer
6. User: "Make the wall taller — @cad[models/l_bracket/l_bracket.step#face:wall]"
7. Agent edits WALL_HEIGHT parameter in l_bracket.py, reruns script
8. User commits models/l_bracket/ (source + artifacts together)1. 用户:“创建一个带4个安装孔、厚度5mm的参数化L型支架”
2. Agent:使用build123d创建models/l_bracket/l_bracket.py文件
3. Agent运行命令:./.venv/bin/python models/l_bracket/l_bracket.py
→ 生成l_bracket.step、l_bracket.stl、l_bracket.glb文件
4. 用户:打开http://localhost:4178,查看模型
5. 用户从查看器复制@cad[...]引用
6. 用户:“把壁加高 — @cad[models/l_bracket/l_bracket.step#face:wall]”
7. Agent编辑l_bracket.py中的WALL_HEIGHT参数,重新运行脚本
8. 用户提交models/l_bracket/目录(包含源文件和工件)Common Patterns
常用模式
Pattern: Slot / Cutout
模式:槽口/切口
python
with BuildPart() as panel:
with BuildSketch(Plane.XY):
Rectangle(100, 60)
extrude(amount=3)
# Horizontal slot
with BuildSketch(Plane.XY):
SlottedHole(length=30, radius=3, rotation=0, align=Align.CENTER)
extrude(amount=-3, mode=Mode.SUBTRACT)python
with BuildPart() as panel:
with BuildSketch(Plane.XY):
Rectangle(100, 60)
extrude(amount=3)
# 水平槽口
with BuildSketch(Plane.XY):
SlottedHole(length=30, radius=3, rotation=0, align=Align.CENTER)
extrude(amount=-3, mode=Mode.SUBTRACT)Pattern: Mirrored Geometry
模式:镜像几何
python
with BuildPart() as symmetric_part:
with BuildSketch(Plane.XY):
Rectangle(40, 20)
extrude(amount=10)
mirror(about=Plane.YZ)python
with BuildPart() as symmetric_part:
with BuildSketch(Plane.XY):
Rectangle(40, 20)
extrude(amount=10)
mirror(about=Plane.YZ)Pattern: Shelling a Solid
模式:实体抽壳
python
with BuildPart() as box:
Box(60, 40, 30)
# Remove top face to shell into an open container
shell(box.faces().sort_by(Axis.Z)[-1:], thickness=-2)python
with BuildPart() as box:
Box(60, 40, 30)
# 移除顶面,将实体抽壳为开放式容器
shell(box.faces().sort_by(Axis.Z)[-1:], thickness=-2)Troubleshooting
故障排除
| Problem | Fix |
|---|---|
| Run with |
| Viewer shows no models | Check that |
| Change port in |
| STEP export fails silently | Ensure the part solid is valid — check for |
| Python 3.12+ OCP errors | Pin to Python 3.11 as required by |
| Fillet fails on sharp geometry | Reduce fillet radius or apply after all cuts |
| 问题 | 解决方法 |
|---|---|
| 使用 |
| 查看器未显示任何模型 | 检查 |
| 修改 |
| STEP导出无提示失败 | 确保零件实体有效 — 导出前检查 |
| Python 3.12+版本出现OCP错误 | 按照 |
| 圆角操作在尖锐几何上失败 | 减小圆角半径,或在所有切割操作完成后再应用圆角 |
Validate a Part Before Export
导出前验证零件有效性
python
from build123d import *
with BuildPart() as my_part:
Box(50, 50, 20)python
from build123d import *
with BuildPart() as my_part:
Box(50, 50, 20)Check validity
检查有效性
assert my_part.part.is_valid, "Part geometry is invalid — check for bad operations"
export_step(my_part.part, "models/my_part/my_part.step")
print(f"Exported: volume={my_part.part.volume:.2f} mm³")
---assert my_part.part.is_valid, "零件几何无效 — 检查操作是否有误"
export_step(my_part.part, "models/my_part/my_part.step")
print(f"已导出:体积={my_part.part.volume:.2f} mm³")
---Skills Reference
技能参考
| Skill | Docs | Standalone Repo |
|---|---|---|
| CAD (STEP/STL/DXF/GLB) | | earthtojake/cad-skill |
| URDF (robots) | | earthtojake/urdf-skill |
| 技能 | 文档 | 独立仓库 |
|---|---|---|
| CAD(STEP/STL/DXF/GLB) | | earthtojake/cad-skill |
| URDF(机器人) | | earthtojake/urdf-skill |
Key Dependencies
核心依赖
| Package | Purpose |
|---|---|
| Pythonic 3D CAD modelling API |
| Geometry kernel (STEP, Boolean ops) |
| Underlying geometry utilities |
| Viewer frontend |
| In-browser geometry rendering |
| 包 | 用途 |
|---|---|
| 类Python风格的3D CAD建模API |
| 几何内核(支持STEP、布尔运算) |
| 底层几何工具库 |
| 查看器前端框架 |
| 浏览器内几何渲染 |