Open source · MIT · runs on your machine

Describe a part.
Get a program that prints it.

An LLM writes the OpenSCAD; OpenSCAD's Manifold backend renders it in milliseconds, colours and all. The program is the document — its parameters become sliders, its modules become cards, and every edit, by the model or by you, is a version you can go back to.

One turn, end to end: the agent writes the program, the sliders are the program's own parameters, the explode slider pulls the assembly apart, and the part comes out of the other end as a 3MF a slicer can print.

One prompt. One pass. A real part.

A parametric electronics enclosure for a 65 × 40 mm PCB: box and snap-on lid in two colours, four M2.5 standoffs, a USB-C cutout on one wall, ventilation slots on the lid, wall thickness, corner radius, PCB size and standoff height as parameters. Show it as an assembly.

That is the whole input. The agent is told to write the entire program in one call — named dimensions, a comment on each, a range where a slider makes sense, a module per component — so a part is one model round trip plus a render measured in milliseconds.

  • 2 bodies — box and lid, each its own closed solid
  • 26 parameters — every one of them a slider
  • 2 colours — two filaments, not two paint jobs
  • 1 turn — 21.3 cm³, built by Gemini 3.8 Flash
The enclosure pulled apart by the explode slider: an orange lid with ventilation slots floating above a grey box with four internal standoffs and a USB-C cutout.
The same part, pulled apart by the explode slider. Dragging it is a view, not an edit.

What you get

Not a chat window with a mesh in it. A CAD document that happens to be written by a model.

Parametric, not decorative

Every literal assignment in the program becomes a control — a slider from its // [min:step:max] comment, a toggle, a colour picker, a choice. Move one and the part re-renders, one history version per parameter.

Colour is volume

OpenSCAD exports 3MF, the one format it writes colours in. Two colours means two closed solids with a printable clearance between them, so a slicer opens the file as a multi-material part — not a painted surface.

Assemblies come apart

An object made of pieces is built as one body per piece with an explode parameter. The server works out each piece's take-apart direction; the browser moves the vertices. The program and the export are untouched.

Point at what is wrong

Click faces to select, click edges to measure a length, a diameter, an angle or a gap, or paint over the area that is wrong. Each becomes exact text in the next prompt, so “this” is never ambiguous.

The model sees what you see

After every render, four views — isometric, top, front and a section cut on the plane you are looking at — go in front of the model before its next step. A boss on the wrong side is caught inside the turn.

Every render is a version

History with a revert button on each entry, Ctrl+Z outside a text box, and “revert this turn” to put the document back to before the model's first edit. Hand edits splice into the model's own text, comments and layout intact.

How a part gets built

The agent has three tools: write_code replaces the program and renders it, edit_code changes one exact snippet, read_code shows it. Every render answers with numbers, not vibes:

118 lines · 56.9 cm³ · 55 × 70 × 86.6 mm · 254 tris
2 bodies · 15.0 cm³ + 7.0 cm³ · 2 colours
watertight · overhang 13% · thinnest wall 1.6 mm

The body count is what answers “did the handle actually join the mug”: pieces that merely touch come back as two bodies, and the report says so. Compiler errors and warnings come back with line numbers, and a program that fails to render is kept for the model to fix while the last good mesh stays on screen.

Read the long version →

The program panel: parameter groups for assembly, PCB dimensions, standoffs and enclosure dimensions, each parameter a labelled slider with a number field.
The program panel reads the file the way the OpenSCAD Customizer does, and goes a little further.

Bring your own model

VibeSCAD calls no model of its own. It calls yours.

An API key is enough

Put ANTHROPIC_API_KEY, OPENAI_API_KEY, GOOGLE_GENERATIVE_AI_API_KEY or OPENROUTER_API_KEY in .env and that provider shows up in the header's model picker with its catalogue. The choice is remembered per document and lives in the URL.

Or no key at all

With no key set, the app talks to a local OpenAI-compatible server at 127.0.0.1:8080/v1 — llama.cpp, Ollama, LM Studio, vLLM — using whatever model it serves. Local servers, overrides and trimmed lists go in a vibescad.json shaped like an opencode.json provider block.

Or drive it from the agent you already use

The document is also an MCP server, so a coding agent outside the app — Claude Code, Codex, Google's Antigravity CLI, anything that speaks MCP — can do the modelling while VibeSCAD renders, checks and shows the part. On this path VibeSCAD makes no model call at all: the client's model does the thinking, on the client's bill.

The tools are the built-in agent's own — write_code, edit_code, read_code, render_views, export_model, set_param, history and revert — over stdio or HTTP.

{
  "mcpServers": {
    "vibescad": {
      "command": "pnpm",
      "args": ["mcp"],
      "cwd": "/path/to/vibescad"
    }
  }
}

Does it actually work?

pnpm bench builds 26 parts — brackets, vessels, gears, assemblies, two-colour parts — three attempts each, and scores every render against what the prompt asked for: body count, bounding box, volume and hollowness, wall thickness, colours, a manifold surface, and how many renders it took. All runs below are from 2026-09-14, same prompts, same rubric.

ModelDriven byPassedMean scoreRenders / parts / part
gpt-6-astrabuilt-in agent72 / 7899%1.135
gpt-6-astra, max effortCodex CLI over MCP30 / 30 ¹100%1.2106
Gemini 3.8 Flash, highbuilt-in agent68 / 7898%1.979

¹ every prompt once, four of them twice; the full 78 is pending.

The two models fail differently. Gemini misses thin curved walls — a vase asked for 3 mm comes out 1.1. Astra occasionally leaves a non-manifold surface. Both are beaten by a 2 mm cable clip. Astra is also cheaper: about 20k tokens a part against 108k, writing plain OpenSCAD half as long.

Run it on a model that isn't here, and post the row →

What it is not

No STEP

OpenSCAD builds meshes, not B-rep solids, so there is no STEP for it to write. Open the 3MF in FreeCAD and convert if you need one; the result is a faceted solid, not a parametric one.

No fillets on anything

BOSL2 rounds the shapes it builds and the edges you name — not the edges of a finished boolean result. Ask for a round the library cannot express and you will get a chamfer-shaped argument instead.

No login yet

A shared instance is gated by one token with per-caller ceilings, which means one trusted user. A real login and a document directory per user are not there.

Run it

Linux x86_64, including WSL, with Node 22+ and pnpm. OpenSCAD and the BOSL2 and MCAD libraries are fetched for you, into the checkout, without root.

git clone https://github.com/Anerco/vibescad
cd vibescad && pnpm install
pnpm setup:openscad
echo 'ANTHROPIC_API_KEY=sk-ant-…' > .env
pnpm dev                       # http://localhost:3000

On macOS, arm64 or Windows outside WSL, install a current OpenSCAD yourself and point OPENSCAD_BIN at it — the nightly matters, since distribution packages predate the Manifold backend and cannot export colours. There is a Docker image too.