A code-first parametric CAD tool for the browser
ChiselCAD is a personal, opinionated fork of zalo's CascadeStudio. It runs the full OpenCascade (OCCT 8.0) kernel compiled to WebAssembly, with a Three.js viewport and a Monaco editor, and it is built around two main workflows:
- draw a sketch, pull it into a feature, tune numbers in code or via variables with realtime sliders.
- get an LLM to do everything like some sort of personal CAD wizard.
The main idea is GUI for creation, code for editing. Writing geometry from scratch in code is slow and clunky - way easier to click and draw out lines, shapes and constraints directly in the 3D view. But the moment a sketch is committed it becomes plain JavaScript in the editor — and from then on the code is the model. Changing a radius is right there, you don't have to go back into sketch editors and layers of menus; no open/edit/save modal loop, no property dialogs to hunt through, etc. If you want to go even faster, you can assign a value to a named variable and make a slider out of it.
There's also cool dynamic things you can do with this - notice in the example chisel model that when you use the slider to make the blade wider, the embossed number also changes to match. You can link things to other things however you'd like, it's all just code.
This took 30 seconds. I probably spent longer drawing my crummy sketch than it took to make it and get it into Bambu studio to print.
(This process was done with Fable in the browser chat window - given information was the example chisel code + the sketch photo. No additional MCPs or skills needed)
- In-viewport sketching — hit Sketch and pick your plane right in the 3D view: ghost quads for the three origin planes, or any flat face of the model (sketch-on-face). The camera flattens square-on into an orthographic view with a grid aligned to the picked plane. Draw with Line, Rect, Circle, Trim and Dimension tools; snapping keeps mouse-derived values on clean round numbers while anything you type is treated as exact and left untouched. Saving emits a tidy
new Sketch(...).LineTo(...).End(true).Face()block into the editor as a single undoable edit — face sketches bake their plane as{ origin, normal, xDir }literals, so the code stands alone. - Blender-style navigation — middle-mouse orbits, Shift+middle (or right-drag) pans, wheel zooms. Certain hotkeys like camera view controls being 1,3,5,7. Blender theme support if you want themes.
- A lightweight constraint solver — a small relaxation solver (sequential projection, no heavyweight algebraic engine) keeps a deliberately short list of relations satisfied: anchor, horizontal, vertical, parallel, perpendicular, equal, concentric, tangent, plus persistent dimensions. Endpoints that snap together are genuinely shared points, so corners stay closed through any edit. Drag a point or edge and everything constrained to it follows in real time. Over-constrain it and the offending relations simply tint red — no modal "mating error" dialogs.
- Feasibility feedback that floats — when a dimension or relation can't be satisfied, ChiselCAD finds the nearest legal value and floats a message up, e.g. "this line can't be longer than 28.28 here — held by anchors + dimensions." The rejected edit reverts cleanly instead of leaving red behind. Trying to avoid janky failure states and crazy things happening to you.
- A feature command bar — one click to Extrude / Revolve / Loft / Pipe the latest sketch, or to Fillet / Chamfer / Union / Cut / Intersect by clicking the bodies in the viewport. Each emits code with the key number (depth, angle, radius) pre-selected so you can immediately type over it. Picking a sketch face auto-wraps it in a plane-aware
Extrude, so "cut this sketch out of that solid" is two clicks. - Live evaluation — the model re-evaluates continuously as you type (debounced) and while you drag GUI sliders; evaluations serialize and coalesce so heavy models stay responsive.
- Bidirectional code ↔ 3D ↔ GUI linking — the cursor's line highlights its GUI control and glows the geometry that line produced; clicking a shape in the viewport selects the whole block of code that built it and jumps the cursor to its defining line.
- A Blender-style viewport popover — ground plane and grid toggles moved out of the control panel into a bottom-right ◐ popover that applies live and persists across sessions.
- Powerful standard library for primitives, booleans, sweeps, lofts, fillets, and more
- Sketch API with a plane parameter (
new Sketch([x,y], 'XZ')) for drawing in XY, XZ, or YZ - Selector API for querying edges and faces:
Edges(shape).parallel([0,0,1]).max([0,0,1]).indices() - Measurement functions:
Volume(),SurfaceArea(),CenterOfMass() - JavaScript and OpenSCAD editor modes with IntelliSense autocomplete (full TypeScript defs + JSDoc)
- Modeling history timeline to scrub through build steps in the 3D viewport
- Agent API (
window.CascadeAPI) for programmatic control via Playwright or developer tooling - Reusable CAD engine — the
cascade-corepackage embeds CAD modeling in any web app, no GUI required - Access to the full OpenCASCADE kernel via the
oc.namespace, with automatic caching of standard-library operations .STEP/.IGES/.STLimport and.STEP/.STL/.OBJexport- URL serialization of code and GUI state for easy sharing, plus Save/Load of full projects
- Integrated GUI system (sliders, checkboxes, buttons) via Tweakpane
chiselCAD.brennan.computer for the live web version
Or you can clone and run it locally:
npm install
npm run build
npx http-server ./packages/cascade-studio/dist -p 8080 -c-1
# Open http://localhost:8080Use -c-1 to disable caching, and a new port whenever you change JS, since browsers cache ES modules aggressively.
- Click ✎ Sketch
Sin the command bar and pick a plane. The view flattens and the sketch tools appear. - Draw with Line / Rect / Circle (keys
L/R/C). Endpoints snap to existing points, the origin, and the grid.Tto trim lines from other lines. - Switch to Select, then add relations from the Relations row or with the hotkeys —
Anchor,Horizontal,Vertical,Parallel, perpendicular (X),Equal, concentric (Q), tanGent. Drag points to see the solver hold everything together. - Use Dimension (
D) to pin a length or radius. Type a number for an exact value, or a word to create aletvariable the sketch drives. - Save
ENTER— the sketch is written into the editor as code. - Back in feature mode, click Extrude
E(or Revolve / Loft / Pipe -- still beta), to make bodies from sketches.
Then: Cut / Union / Intersect and click the bodies involved. (first: the body effected, second: the body effecting it)
Or fillet and chamfer edges by selecting them in the 3D view, and adjusting the values in the code.
// Primitives
Box(x, y, z, centered?)
Sphere(radius)
Cylinder(radius, height, centered?)
Cone(r1, r2, height)
Circle(radius, wire?) // wire=true for Loft/Pipe, false for Extrude
Polygon(points, wire?)
Text3D(text, size, height, font?)
// Sketch API — draw in any plane
let face = new Sketch([0, 0]) // default XY plane
.LineTo([20, 0]).Fillet(3)
.LineTo([20, 10]).Fillet(3)
.LineTo([0, 10])
.End(true).Face();
let profile = new Sketch([0, 0], "XZ") // XZ plane for Revolve profiles
.LineTo([15, 0]).LineTo([10, 8]).LineTo([0, 8])
.End(true).Face();
Revolve(profile, 360);
// Transforms — all return NEW shapes
Translate([x, y, z], shape)
Rotate([ax, ay, az], degrees, shape)
Scale(factor, shape)
Mirror([vx, vy, vz], shape)
// Booleans
Union(shapes)
Difference(mainBody, [tools])
Intersection(shapes)
// Operations
Extrude(face, [dx, dy, dz], keepFace?)
Revolve(shape, degrees, [ax, ay, az]?)
Loft([wires])
Pipe(shape, wirePath)
Offset(shape, distance)
FilletEdges(shape, radius, edgeIndices)
ChamferEdges(shape, distance, edgeIndices)
// Selectors
Edges(shape).ofType("Line"|"Circle").parallel([axis]).max([axis]).min([axis]).indices()
Faces(shape).ofType("Plane"|"Cylinder").max([axis]).indices()
// Measurement
Volume(shape)
SurfaceArea(shape)
CenterOfMass(shape)Switch to OpenSCAD via the dropdown in the bottom bar of the code editor; ChiselCAD transpiles it to the JavaScript standard library.
difference() {
cube([20, 20, 20], center=true);
sphere(r=12);
}ChiselCAD exposes window.CascadeAPI for programmatic control via Playwright or other browser automation.
// Navigate and wait for WASM to load
await page.goto('http://localhost:8080');
await page.waitForFunction(() => window.CascadeAPI?.isReady());
// Learn the API
const guide = await page.evaluate(() => CascadeAPI.getQuickStart());
// Run CAD code and check results
const result = await page.evaluate(code => CascadeAPI.runCode(code), `
let profile = new Sketch([0, 0], "XZ")
.LineTo([15, 0]).LineTo([10, 8]).LineTo([0, 8])
.End(true).Face();
Revolve(profile, 360);
`);
// result = { success: true, errors: [], logs: [...], historySteps: [...] }
// Set camera angle and take a screenshot
await page.evaluate(() => {
CascadeAPI.setCameraAngle(30, 20); // azimuth, elevation
CascadeAPI.saveScreenshot('model.png');
});npm run build
npx playwright test # 12 tests, ~25sThere is also primitive support for LLMs in the loop natively. In the top menu there's API access for either Anthropic or Openrouter (all API keys and data are local to your browser, Chisel has no central server or any user data of any kind) and then a chat interface in the bottom left bar. This is extremely beta, but I'd love to hear what did / didn't work for you, and eventually which models seem to be adequate. I've been using Fable so far but that's probably overkill.
You can also copy/paste into any LLM chat window, there's a prompt (quasi-skill) in that menu to get started with. Testing so far as been encouragingly successful.
ChiselCAD is a fork of CascadeStudio by Johnathon Selstad (@zalo) — all of the kernel, standard library, editor and engine groundwork is his, and remains under his MIT license
Built on:
- opencascade.js — CAD kernel (OCCT 8.0.0 RC4 via Embind)
- Three.js r170 — 3D rendering
- Monaco Editor — code editor with IntelliSense
- Dockview — panel layout system
- Tweakpane v4 — GUI controls
- opentype.js — font parsing for Text3D
- fflate — URL code compression
- potpack — texture atlas packing
- esbuild — bundler
- Playwright — testing
Dedication:
For Alex
ChiselCAD carries two sets of terms, both in the LICENSE file:
- Upstream CascadeStudio code — MIT License, © 2020 Johnathon Selstad. Unchanged and irrevocable.
- ChiselCAD — free and source-available for both commercial and non-commercial use (personal, hobbyist, business, educational, research), © 2026 Brennan Letkeman. The editor program itself may not be sold, repackaged or built into a commercial product / service without written permission.