Language → CadQuery → STEP, driven by a Cursor agent with an interactive 3D studio.
Describe a product in plain English. AgentCAD writes parametric CadQuery, builds the solid, shows it in VTK, and lets you revise by chat — with parts, version history, drafting/refinement modes, and crash recovery.
| Area | What you get |
|---|---|
| Agent design | Cursor SDK writes generated/current_design.py (Grok / Claude / OpenAI / Composer) |
| Studio | Orbit/zoom 3D preview + Agent / Ask chat |
| Parts | Named parts — view, export, or edit one at a time |
| Reference import | Load STEP/STP, IGES, STL, OBJ, PLY as agent constraints (bbox, holes, topology) |
| Drafting vs refinement | Initial design is always reviewed; studio edits can skip review (draft) or keep reviewing (refine) |
| Version history | Snapshot each change; rollback design + chat (Ctrl+Z) |
| Self-repair | CadQuery errors fed back to the agent until build succeeds |
| Crash recovery | Context worksheet + new agent resume after API / context failures |
- Python 3.10+ (3.11–3.13 recommended)
- Linux / macOS / Windows with a working display (Tk + VTK)
- A Cursor API key for live designs
(optional: offline mock backend for UI demos)
git clone <your-repo-url> AgentCAD
cd AgentCAD
python -m venv .venv
source .venv/bin/activate # Windows: .venv\Scripts\activate
pip install -r requirements.txtConfigure environment:
cp .env.example .env
# Edit .env and set:
# CURSOR_API_KEY=cursor_...Or export for the session:
export CURSOR_API_KEY=cursor_...python start_design.py- Enter a design brief (e.g. “a wooden dining chair with a slight recline”).
- Wait while the agent generates CadQuery and builds the mesh.
- The Studio opens — orbit the model, revise in Agent, ask questions in Ask.
- Ctrl+S saves STEP + matching
.pyundermodels/.
Orbit the solid on the left. Named parts in the whole-design view use contrasting colors so contacting pieces are easy to tell apart. Revise in Agent, inspect dimensions in Ask, switch Drafting / Refinement, and roll back from History.
Renders from designs produced in this repo (parametric CadQuery → tessellated preview).
Regenerate these images with python docs/render_readme_images.py.
python start_design.py --fast # Cursor model fast mode
python start_design.py --no-fast # force fast off even if DESIGN_FAST=1
python start_design.py --model grok-4.6
python start_design.py --model claude
python start_design.py --model openai
python start_design.py --list-models
DESIGN_LLM=mock python start_design.py # offline demo, no API key- Drafting (default) — the initial design still runs the multi-round feature / physics review. After the studio opens, Agent revisions stop once the design compiles, renders, and passes collision / weld / assembly checks. Fast iteration.
- Refinement — after every studio build, check key features + physics; refine until pass or budget ends.
After every successful build with two or more named parts, compile-time feasibility runs:
- Collision — overlapping volume between named parts is a failure (face contact is OK)
- Weld contact — each
fixedjoint must be in contact. Unrelated parts, or parts that are not directly welded, may float - Assembly — closed loops must not thread each other (chain links), and a ring must not sit on a shaft / H-beam whose profile is larger than the hole at both ends. Open a gap in the ring, or keep one end smaller than the opening. A pin that can slide off one end is OK.
Any of these failures is treated like a compile error and the agent is asked to rebuild.
Designs should expose named parts via parts() (assembly in build()).
- View — isolate a part in the 3D preview. Whole design colors contacting parts differently.
- Export part STEP / Export all STEP — separate STEP files
- Export part STL — single-part triangle mesh
- ZIP all STLs — folder of part meshes + a
.zipundermodels/ - Export URDF — package folder with
*.urdf+ per-part STL meshes - Import reference — add STEP/STP, IGES, BREP, STL, OBJ, or PLY as agent context (ghost overlay)
Multi-part designs must define joints(): a tree of {type, parent, child} relations for the URDF. Use revolute / prismatic when that motion is part of the product function. Use fixed only for parts that are actually fastened. Unrelated parts are left unwelded (separate roots).
Load a reference before the first prompt (Load reference… on the start dialog) or later with Import reference in the studio.
Accepted formats: STEP/STP, IGES/IGS, BREP, STL, OBJ, ASCII PLY.
The agent does not only display the file. It:
- Copies it to
generated/references/<name>.<ext>(kept out of the Cursor agent via.cursorignore) - Extracts bbox, volume, solid count, face types, and cylinder radii (holes/shafts) when the file is B-rep
- Writes
generated/references/<name>.mdand injects those facts into generate / revise / Ask / review - Can use the exact shape in CadQuery via
import_reference("name")(injected at runtime)
The live design stays parametric CadQuery. The imported file is a constraint (mate, envelope, matching holes). A translucent overlay in the 3D view shows the reference next to the current design. The agent is told not to open the binary — only the measured facts and import_reference().
- Edit scope (Agent tab) — apply a revision to the whole design or one part
- Agent — language edits that rewrite CadQuery and rebuild
- Ask — read-only Q&A about dimensions / structure (source + measured facts; no RGB by default)
Every successful design (open + each Agent apply) is snapshotted under generated/versions/.
- Pick a version in History → Rollback
- Or Ctrl+Z for the previous version
Rollback restores CAD, features, and chat transcript, and clears the Cursor agent conversation.
| Shortcut | Action |
|---|---|
| Ctrl+Enter | Send Agent / Ask message |
| Ctrl+S | Save full assembly STEP + script |
| Ctrl+Z | Roll back to previous version |
Copy from .env.example. Common variables:
| Variable | Default | Meaning |
|---|---|---|
CURSOR_API_KEY |
— | Cursor Integrations API key |
DESIGN_MODEL |
grok-4.5 |
Cursor SDK model id or alias (grok-4.6, claude, openai, …). CLI --model overrides |
DESIGN_LLM |
auto |
auto | cursor | mock |
DESIGN_MODE |
draft |
draft (studio revisions skip review) | refine (review every build). Initial design always reviews. |
DESIGN_FAST |
off | 1 / true → model fast=true |
DESIGN_DEBUG_RETRIES |
5 |
Build → debug / collision-fix cycles |
DESIGN_COLLISION |
on | 0 / false to skip compile-time collision, weld-contact, and assembly checks |
DESIGN_REVIEW_ROUNDS |
3 |
Review → refine rounds (initial design, and every studio build in refine mode) |
DESIGN_AGENT_RECOVERIES |
3 |
Worksheet relaunches per failed send |
DESIGN_UI_SCALE |
auto | Override HiDPI UI scale (e.g. 2.0) |
--model / DESIGN_MODEL accept an alias or a raw Cursor SDK id. --model wins over the env var.
| Flag / alias | Resolves to |
|---|---|
grok-4.5 (default) |
grok-4.5 |
grok-4.6 |
grok-4.6 |
claude |
claude-sonnet-5 |
claude-opus |
claude-opus-5 |
openai |
gpt-5.4 |
composer |
composer-2.5 |
Run python start_design.py --list-models for the full alias list. Any other string is passed through as the Cursor model id.
AgentCAD/
├── start_design.py # Entry: prompt → agent → studio
├── requirements.txt
├── .env.example
├── cad_pipeline/
│ ├── agent.py # Cursor/mock agent, review, recovery
│ ├── runtime.py # Execute CadQuery, parts, STEP export
│ ├── joints.py # joints() parse / URDF tree validation
│ ├── urdf.py # URDF + mesh package export
│ ├── studio.py # Tk + VTK interactive UI
│ ├── versioning.py # Design / chat snapshots
│ ├── context_worksheet.py # Crash-recovery memory
│ └── ...
├── docs/images/ # README studio + design gallery
├── generated/ # Working design, renders, versions (gitignored)
└── models/ # Saved STEP + .py exports
Generated CadQuery is expected to look like:
def parts():
return {
"seat": ...,
"leg_fl": ...,
"backrest": ...,
}
def joints():
return [
{"type": "fixed", "parent": "seat", "child": "leg_fl"},
{"type": "fixed", "parent": "seat", "child": "backrest"},
# revolute / prismatic only when that motion is part of the product
]
def build():
solid = None
for p in parts().values():
solid = p if solid is None else solid.union(p)
return solid- Prefer Drafting while exploring form; switch to Refinement before locking a design.
- Use Edit scope for local changes (e.g. only
backrest) so other parts stay stable. - If the Cursor agent stalls or hits context limits, check
generated/context_worksheet.md— recovery relaunches from that file automatically. - On 4K/5K displays, set
DESIGN_UI_SCALE=2.0(or similar) if chrome feels too small/large.
Add your preferred license here.





