Documentation · v0.16.x

AgenticCAD documentation

Everything the app does, how it stores it, and how to drive it by chat, by hand, or from the agent's tools. For a guided walk-through, start with the tutorials.

Overview

AgenticCAD is a desktop CAD app with a Claude agent built in. You describe the part you want, the agent models it, and you watch it appear in a 3D viewer. From there you steer it however is quickest: keep talking, point at faces and bodies in the viewer, tweak dimensions in a parameters panel, or use a Fusion-style ribbon to press, pull, hole, fillet and sketch by hand.

Every design is exact solid geometry, so what you export is production-ready: STEP for other CAD tools and suppliers, STL at the resolution you choose for 3D printing, shop drawings with hole tables, and, if you have OrcaSlicer installed, a sliced print preview with time and filament estimates. An experimental CAM mode generates GRBL toolpaths for small mills and routers.

You need a Mac or Windows PC, the app (or the source), and a Claude sign-in: either Claude Code logged into your Anthropic account or an API key. Nothing else is required; the slicer is optional and only used if it is already on your machine.

One design and one agent conversation open at a time, on your own machine. For how the pieces fit together, see Architecture.

Desktop app

The desktop app is the same program in a native window with Python bundled. Two things to know:

Your data lives in the OS user-data folder: ~/Library/Application Support/AgenticCAD on macOS, %LOCALAPPDATA%\AgenticCAD\AgenticCAD on Windows (designs, library, machines, tools, history, exports, settings). Set AGENTICCAD_WORKSPACE to move it. The app picks a free localhost port; the UI is the same page you would see from a source install, so everything else in these docs applies. Intel Macs and Linux: run from source below.

Install from source

Requirements: Python 3.12, a Claude Code login (the Agent SDK's bundled binary uses it) or an ANTHROPIC_API_KEY, and a modern browser.

# unzip the release (or git clone https://github.com/agenticcad/agenticcad.git), then inside the folder:
python3 -m venv .venv && .venv/bin/pip install -r requirements.txt
.venv/bin/python server.py            # http://127.0.0.1:8765
VariableEffect
PORTListen port (default 8765).
ANTHROPIC_API_KEYUse an API key instead of the Claude Code login.
AGENTICCAD_MODELModel id override (the Settings dialog is the usual way).
AGENTICCAD_WORKSPACEWorkspace directory (default ./workspace).
AGENTICCAD_NO_AGENT=1Run the server without a Claude session (used by the tests).

The workspace

The AgenticCAD workspace in a real session
A real session: the viewer with File and Settings, the ribbon (Create, Modify, Inspect, Output), the Browser and Parameters cards, the ViewCube and a 3D-printing preview; the side panel (Chat, Code, CAM, Library) shows the agent's tool calls.

Design as script

A design is one build123d script that assigns result. The kernel executes it in a namespace that also provides import_step, from_library and the thread helpers.

# Mounting plate with a bossed bore
plate_l, plate_w, plate_t = 60, 40, 8
boss_d, boss_h, bore_d = 20, 15, 8
with BuildPart() as plate:
    Box(plate_l, plate_w, plate_t)
    with Locations((0, 0, plate_t / 2)):
        Cylinder(boss_d / 2, boss_h, align=(Align.CENTER, Align.CENTER, Align.MIN))
    Hole(bore_d / 2)                 # note: Hole takes a radius
result = {"Plate": plate.part}

Chat and selection

Click a face, an edge or a body in the viewer (or a row in the Browser) and it becomes a chip on the composer. ⇧-click for several. The sent message keeps its chips and the server expands them into a [Selected geometry] block: face id, body, analytic type, centre, normal, size, radius and the clicked point. Because face ids are renumbered on every rebuild, the agent is told to reference faces by geometry (faces().sort_by_distance((x, y, z))[0]) and to re-inspect after building. Hover a chip later to see a marker where that face was; click it to reselect the matching face by type and centre.

Selected faces stay lit (dimmer orange) while the agent works, until the next rebuild or click. Sketches are selectable as chips too.

Reference images

Attach photos, napkin sketches or old drawings with 📎, by dragging onto the composer or viewer, or by pasting. Images are downscaled in the browser (≤1600 px JPEG), sent inline so the agent sees them directly, kept as thumbnails in the bubble and saved to workspace/images/. Dimensions you type override what it estimates from the picture.

Bodies and the Browser

Ribbon tools

The ribbon at the top of the viewer gives you Fusion-style manual modelling without an agent turn. A tool opens a command dialog under the ViewCube that walks you through it: step indicator, a live prompt (“Click a face…”), chips for what you picked (× to drop), fields with units (↑↓ ±1, ⇧ ±10, ⌥ ±0.1), ↵ OK, ⌫ removes the last pick, Esc cancels.

ToolKeyPicksWritten to the script
Box / Cylinder / SphereB C Oa face (or the grid)a new body placed with its base on the face along its normal
SketchKa planar face, or none for a base planea sketch block (see Sketches)
Press/PullQa planar face; drag the handle or typebody + extrude(face_at(pt), amount, dir), or - to cut
HoleHa point on a facehole(body, d, at, depth|through) with counterbore/countersink, or tap(body, "M4", …)
Fillet / ChamferF Xedges, or a face for all its edgesbody.fillet(r, [...]) / body.chamfer(l, None, [...])
ShellLfaces to openoffset(body, amount=-t, openings=[...])
MoveVa bodyPos(...) * Rot(...) * (body)
MeasureIvertices, edges, facesnothing; see Measure

Face references use the point you clicked (faces().sort_by_distance((x, y, z))[0]), never face centres, so they survive most later edits. Every operation is undoable and the agent is notified.

Sketches

Select a planar face (or none for XY/XZ/YZ plus an offset) and press K. The camera squares up to the plane; draw rectangles, circles, polygons and slots by clicking (grid snap; ⌥ for free placement), toggle Subtract, edit numbers in the item list, then Finish. The sketch is stored in the script as a block:

# sketch:sketch1 {"plane": {...}, "items": [...]}
with BuildSketch(Plane(origin=(0, 0, 4), x_dir=(1, 0, 0), z_dir=(0, 0, 1))) as _sketch1:
    with Locations((-18, 0)):
        Rectangle(14, 20)
    with Locations((-18, 0)):
        Circle(3, mode=Mode.SUBTRACT)
sketch1 = _sketch1.sketch
# /sketch:sketch1

So sketch1 is a normal build123d Sketch that you or the agent can extrude, cut with (part - extrude(sketch1, amount=-h)) or revolve. The JSON header lets the editor reopen it (Browser ▸ Sketches ▸ double-click). Sketches render as cyan outlines. The agent edits sketches only through its sketch tool, in the same item format, so anything it draws stays editable by you.

Units

Everything is stored in millimetres, but you work in whichever unit you like. Settings ▸ Units is automatic by default: a US timezone means inches, anywhere else millimetres; or force mm or in. That choice sets how the viewer stats, measurements, parameters and shop drawings read, and how the agent interprets a number you give without a unit. In scripts inch (= 25.4), IN, ft, thou and mm are pre-imported, so plate_l = 2.5 * inch can sit next to plate_t = 6; the Parameters card shows each one in its own unit and writes edits back the same way. make_drawings(units="in") dimensions one sheet differently from the default.

Threads

threads.py carries ISO metric tables (pitch, tap drill, clearance fine/medium/coarse, hex and socket head sizes, nuts, washers) and helpers available in every script:

Inch threads too. Unified sizes work everywhere a size is accepted: 1/4-20, #10-32, 3/8-16 (a bare 3/8 means the coarse series). thread("1/4-20") gives major, pitch, tpi, tap drill and ASME close/normal/loose clearance holes in mm; tap, bolt, nut and washer use ASME B18 hardware tables, and drawings call out 1/4-20 UNC THRU alongside M4×0.7.

HelperWhat it does
iso("M4"), tap_drill, clearance_diatable lookups
tap(part, "M4", at=(x, y, z), depth=6 | through=True, real=False, axis=(0, 0, -1))cuts the tap-drill hole from the surface point along the axis and registers the thread; real=True models the helix via bd_warehouse
hole(part, d, at, depth | through, counterbore=(D, h), countersink=D)plain hole with optional counterbore or 90° countersink
tapped_hole(size, depth, at)a cosmetic cutter you subtract yourself
bolt(size, length, head="hex"|"socket"|"none"), nut, washerfasteners as bodies

Registered threads appear in the model summary and in shop drawings as callouts such as M4×0.7 ↧6 or M4×0.7 THRU instead of Ø3.3.

Gears

Scripts can call spur_gear(module, teeth, thickness, bore=0, pressure_angle=20, hub_d=0, hub_h=0, keyway=(w, depth)) for a true involute spur gear (Z up, tooth 0 on +X), involute_gear_profile(module, teeth) for the closed 2D outline, and gear_dims(...) / gear_centre_distance(module, za, zb) to lay out a train. Meshing gears share module and pressure angle; rotate one by half a tooth pitch so the teeth interleave. Ask for it in plain words: “a 20-tooth module 2 gear, 10 thick, 8 mm bore, with a 20 mm hub”.

For complex assemblies the agent builds one body at a time, checking each build before adding the next, so a slip in one part does not cost the whole attempt.

Parameters

Every top-level name = number in the script is a field in the Parameters card under the Browser (↑↓ ±1, ⇧ ±10, ⌥ ±0.1). Changing one rewrites that literal and rebuilds. Library parts saved as designs keep their parameters, so from_library("bracket", width=30) works. Agent tools: get_parameters, set_parameters. API: GET/POST /api/params.

Measure

Press I (or Measure on the ribbon); a measure panel appears over the viewer. The cursor snaps vertex > edge > face point with a live readout: line length, arc radius and sweep, circle Ø. Two picks give the distance with the closest points drawn and labelled, Δxyz, and the angle (line–line, line–plane, plane–plane) with parallel and perpendicular flags; two circles give centre spacing; two planes give the gap. Click bodies in the Browser for volume, mass and centre of mass (material names or g/cm³), two bodies for clearance or interference volume. ⌫ or right-click removes the last pick, Esc clears. Agent tools: measure (faces, edges, points, bodies), mass_properties.

Shop drawings

Ribbon ▸ Drawings (D) or File ▸ Shop drawings…, with the material and sheet size from ⚙ Settings ▸ Shop drawings: third-angle front, top and right views plus an isometric, with hidden lines (OCCT HLR projection), overall dimensions, hole callouts (n× Ø, THRU or depth, thread labels), lettered holes with a coordinate table, and a title block with size, mass, scale and date. One SVG per body plus an assembly sheet, and a DXF of the view geometry, written to workspace/drawings/. Agent tool: make_drawings.

Generated drawing
A generated sheet.

Part library

Parts live in workspace/library/<part>/ as either a parametric script (a whole design saved with its parameters) or an exact STEP body, with description, tags and a thumbnail.

STEP import and export

File ▸ Import STEP… (or drop a .step on the viewer) adds it as a new body (import_step("file.step") is added to the script, the file is copied to workspace/imports/), as a new design, or straight into the library. Export: File ▸ Export STEP (exact, bodies stay separate solids) and Export STL (dialog: resolution and all-or-one body). Agent: export_model(name, formats, tolerance, angular_tolerance, body). API: /api/export/{step|stl}.

3D printing

If OrcaSlicer (or Bambu Studio) is installed on your computer, the ribbon gains a Slice button (P), ⚙ Settings gains a 3D printing section and the agent gains the slice_for_printing tool. AgenticCAD does not bundle a slicer; without one none of these exist.

This is a hand-off, not a slicer UI: for per-object settings, modifiers, paint-on supports or multi-plate layouts, open the exported 3MF in the slicer.

Fidelity

CAM overview experimental

Experimental. The CAM toolpaths are geometrically correct and machine-checked, but not optimised: paths are long and conservative with many retracts, there is no stock simulation or collision checking, and nothing here has been cut on a real machine by anyone but the author. Inspect every program before running it. The modelling, export and drawing features are the stable part of AgenticCAD today.

CAM is a second script per design, cam.py (saved as <name>.cam.py), written against cam_kernel.py and built with the build_cam tool or the Code tab. It must assign program. The namespace provides model, part, bodies, tools and machines.

part = bodies["Plate"]
stock = Stock.from_model(part, margin=3, top=1.0)
setup = Setup(machines["Generic 3018"], stock, origin="stock-top-left")
t6 = apply_feeds(tools[1], "aluminium", setup.machine)
program = Program(setup, name="plate")
program.add(face(setup, t6, z_top=stock.top, z_bottom=19))
program.add(adaptive(setup, t6, stock_minus(setup, part, 0.0, expand=6), z_top=19, z_bottom=4, stepover=0.15))
program.add(drill(setup, tools[5], [h for h in holes(part) if h.diameter < 6], peck="auto"))
program.add(contour(setup, t6, section(part, 0.0), z_top=4, z_bottom=-4.5, tabs=4))

Geometry comes from the exact B-rep: section(part, z), silhouette(part), stock_minus(setup, part, z, expand), holes(part) (vertical round holes from concave cylindrical faces, with through detection), face_polygon(model.get_face(id)) for a clicked face, plus circle and rect. The CAM tab shows the setup, the operations with colour and visibility toggles, warnings, the machine and tool libraries, a feeds and speeds calculator and the G-code preview. Toolpaths, stock and the WCS origin are drawn in the viewer (rapids red), with a simulation slider and tool marker.

Machines and tools

workspace/machines/*.json: travel, max feeds per axis, rapid, spindle range, safe and clearance Z, tool-change policy (pause, none, split), arcs on/off and arc tolerance, start and end G-code. workspace/tools.json: flat, ball, V-bit and drill tools with diameter, flutes, flute length, feed, plunge, rpm, stepdown, stepover. Defaults: a Generic 3018 and a Shapeoko-class router, tools T1–T7. Edit them in the CAM tab or ask the agent (save_machine, save_tool). feeds(tool, material, machine) and apply_feeds(...) compute feeds for 13 materials with spindle and feed clamping and radial chip thinning; the CAM tab has a calculator with “Apply to tool”.

Operations

OpPurposeNotable parameters
facesurface the stock top down to a level with zigzag passesregion, stepover, angle
contourprofile around polygons, outside / inside / ondepth passes, tabs, tab_height, climb, lead (tangential quarter arcs), stock_to_leave
pocketconcentric clearing with islandsrest_from (previous tool, 2.5D rest)
adaptiveconstant-engagement HSM roughingstepover (fraction of Ø), helix_diameter, rest_from, chip_thinning
drilldrill at Hole objects or pointspeck (depth or "auto"), retract
parallel3dheightmap raster finishing, ball or flatregion, stepover, rest_from (3D tip-map difference)
rest_regionmaterial a previous tool could not reachmorphological opening by the tool radius

All operations work in model coordinates; the post translates to the WCS origin you chose: stock-top-left, stock-top-center, stock-bottom-left, stock-bottom-center, model-origin, or an (x, y, z).

Adaptive clearing

The adaptive op is constant-engagement by construction. It keeps a polygon of the region cleared so far; each pass is the boundary of that region offset inward by (radius − stepover), intersected with the cut region, so the tool's leading arc never exceeds the target engagement angle in open material. It starts with a helix entry, morphs spirals outward, links passes with short retracts, and slows the feed where geometry forces a higher engagement (concave corners, which the summary and G-code warn about). A fine-grid sweep audit in the test suite measures the leading-half contact angle along every pass. Rest machining removes what a larger previous tool could not reach.

Post and G-code

Program.gcode() writes the GRBL dialect: header comments (machine, stock, origin, time, warnings), G21 G90 G94 G17, G54, M3 S, G0/G1 with F on change, G2/G3 arcs fitted to circular runs (chord-sagitta checked, ≤180° per arc, collinear moves merged), M6/M0 tool-change pauses, M30. Checks: machine travel, spindle range, feeds clamped, cutting below the stock bottom, multiple tools with tool_change: none. Download from the CAM tab or /api/gcode; the agent's export_gcode writes to workspace/exports/ and reports line, move, arc and tool-change counts. Not yet: 4-axis, canned drilling cycles (GRBL has none), thread milling.

Settings and MCP

The Settings button next to the File menu (or File ▸ Settings…): Claude model (default Claude Opus 5.5; any model id, or the Claude Code default), effort (low … max), max steps per turn, thinking summaries, web tools, extra standing instructions, and MCP servers (stdio, http or sse configs as JSON with enable toggles and live connection status from the session). Saved to workspace/settings.json; “Save & restart agent” starts a fresh session with the new options and tells the agent its earlier history is gone. API: GET/POST /api/settings, GET /api/agent/status, POST /api/agent/restart. Settings also holds the Shop drawings defaults (material, sheet) and, when a slicer is installed, the 3D printing defaults (printer, quality, filament, layer height, infill, walls, supports, brim) used by the ribbon buttons and by the agent.

Agent tools reference

The agent runs in a Claude Agent SDK session with an in-process MCP server named cad. It has no shell; everything it knows about the model comes back from these tools.

ToolPurpose
build_model(code)replace the script, rebuild, return the summary (bodies, bbox, volume, sketches, threads) or the traceback
edit_model(edits?, append?)change the existing script in place: exact-text replacements plus code appended before result, then rebuild; a failed build leaves the previous design untouched
inspect_model(kind?, near?, body?, limit?)faces with id, type, area, centre, normal, size, radius
screenshot(view, highlight_faces?, show_edges?)the browser renders a view and returns it as an image
export_model(name?, formats?, tolerance?, body?)STEP / STL into workspace/exports/
get_code(), save_design(name?)read the script; save the design (only when asked)
get_parameters(), set_parameters({...})read and rewrite top-level numeric parameters
measure(...), mass_properties(...)distances, angles, hole spacing; volume, mass, centre of mass, clearance
make_drawings(material?)shop drawings (SVG + DXF)
library(action, ...)list, search, get, insert, save_design, save_body, delete
sketch(action, ...)list, get, set, delete sketch blocks in the editor's item format
slicer_info(machine?, search?), slice_for_printing(machine?, process?, filament?, body?, layer_height?, ...)only when a slicer is installed: printers and compatible profiles; slice for 3D printing and show the layers in the viewer
cam_context()machines, tools, model facts, holes, current program
build_cam(code), get_cam_code()build the CAM program from a script; read it
export_gcode(name?)write the .nc file and report counts
feeds_speeds(tool, material, ...)the feeds calculator
save_machine(...), save_tool(...)edit the CAM libraries
Tool results are size-capped (screenshots are JPEG) because the SDK drops results over 1 MB. If you add a tool, return the numbers the agent needs rather than raw data.

Keyboard shortcuts

KeysAction
left-dragorbit the view
right-drag, or ⌘/Ctrl/⇧ + left-dragpan (move the view sideways); trackpads: hold the modifier and drag
wheel / two-finger scroll, middle-dragzoom
ViewCube face, edge or corner · ⌂snap to that view · home / fit
B C O KBox, Cylinder, Sphere, Sketch
Q H F X L VPress/Pull, Hole, Fillet, Chamfer, Shell, Move
IMeasure
D PShop drawings, Slice for 3D printing (with the options in Settings)
↵ / Esc / ⌫OK / cancel / drop last pick in a command dialog
↑↓, ⇧, ⌥nudge a numeric field by 1, 10, 0.1
⇧-clickadd to the selection
⌘Bhide / show the side panel
⌘↩run the script in the Code tab
⏎ / ⇧⏎send / newline in chat

Architecture

A local server runs the kernel and the agent; the browser (or the desktop window) is the UI. There is no cloud component other than Claude itself, and the slicer is whatever you already have installed.

Your browser / desktop window 3D viewerthree.js · face, edge and body picking Ribbon and sketch editorpress/pull, holes, fillets, sketches Chatdescribe, point, attach photos Code, Design, CAM, Libraryscript, parameters, measure, drawings WebSocket · HTTP localhost only Local server server.py · FastAPI agent.pyClaude Agent SDK session · the agent's CAD tools (MCP) cad_kernel.pyruns the script · build123d on the exact OCCT B-rep · STEP, STL cam_kernel.py2.5D / 3D toolpaths · GRBL post (experimental) slicer.pyhands an STL to your slicer · reads the G-code back as layers drawing · threads · libraryshop drawings · ISO threads · part library Claude via Claude Code sign-in or API key workspace/designs · library · machines · tools · history · exports · slicing OrcaSliceroptional · your own install

The design itself is one Python script written against build123d. The agent edits it through its tools; chat, the ribbon, the parameters panel and the sketch editor all edit the same file, so every route stays reproducible. One server process holds one design and one agent session.

Files and API

PathContents
workspace/designs/*.py, *.cam.pydesigns and their CAM scripts; state.json remembers the open one
workspace/history/every successful build (Undo)
workspace/library/<part>/library parts (script or STEP, metadata, thumbnail)
workspace/machines/*.json, workspace/tools.jsonCAM libraries
workspace/exports/, drawings/, imports/, images/, screenshots/outputs and inputs
workspace/settings.jsonagent settings and MCP servers

HTTP endpoints: /api/designs, /api/design/{save,open,new,import,download}, /api/export/{fmt}, /api/import/step, /api/params, /api/measure, /api/drawings, /api/library/*, /api/sketches, /api/cam/{library,machine,tool}, /api/gcode, /api/gcode/preview, /api/settings, /api/agent/{status,restart}, /api/version. The WebSocket carries chat, builds, undo, quality, screenshots, and the manual operations (op, rename_body, set_sketch, add_primitive, transform_body, …).

Versioning

version.py holds the version (badge in the header, click for the changelog) and CHANGELOG.md follows Keep a Changelog. Pre-1.0: minor bump for features, patch bump for fixes; a release is a bump plus a git tag. /api/version serves both.

Tests and evals

.venv/bin/python -m pytest -q            # unit / API tests, seconds, no Claude calls
.venv/bin/python evals/run.py            # agent evals: real agent, headless, graded; ~$5 per run
.venv/bin/python evals/run.py --filter cam --model claude-sonnet-5 --repeat 3

Known gaps and roadmap

Roadmap, roughly in order: projects and sessions; CAM stock simulation and collision checks; assembly positioning and a standard-parts library; sketch upgrades; drag handles everywhere; a WebSerial G-code sender; drawing and import upgrades; deployment (Docker, auth, multi-user); other posts and 3D-printing exports. Issues and contributions: github.com/agenticcad/agenticcad.

Licence

AgenticCAD is free for non-commercial use under the PolyForm Noncommercial License 1.0.0: personal projects, research, education, hobby making, charities, schools and public institutions. Commercial use (in a business, in products or services, or as part of paid work) needs a commercial licence: A$99 per user per year, one licence per person who uses it. Buy online for the number of users you need; the Stripe receipt showing users and period is your licence record, with nothing to enter in the software. Volume or site licences: agenticcad@prodevelop.com.au.