What Happened
Scriptable . Write parametric 2D and 3D models export them to 3MF, STL, OBJ, PLY, OFF, AMF, or SCAD, or render them straight to a PNG.
LuaCAD embeds Lua 5.4 in a Rust engine that evaluates CSG operations directly (via Manifold) or generates OpenSCAD code for external rendering.
my_cube = cube { size = { 1, 2, 3 } } function my_sphere(radius) return sphere({ r = radius }):translate(5, 0, 0) end model = my_cube + my_sphere(2) render(model) Equivalent OpenSCAD: module my_cube() { cube(size=[1,2,3]); } module my_sphere(radius) { translate([5,0,0]) sphere(r = radius); } union() { my_cube(); my_sphere(2); } Getting Started cargo install luacad # CLI for running and converting LuaCAD scripts cargo install luacad-studio # GUI desktop 3D preview Or from source, which requires Rust:
://github.com/ad-si/LuaCAD.git cd LuaCAD make install Both crates vendor their C/C++ dependencies, so no system libraries installed — but a C++ compiler available . luacad builds Manifold and Clipper2; luacad-studio additionally builds OpenCSG, which needs OpenGL development headers (on Debian/Ubuntu: libgl1-mesa-dev, libx11-dev, libxcb1-dev, libxkbcommon-dev, libxrandr-dev, libwayland-dev).
Why It Matters
luacad convert model.lua output.3mf # Convert to 3MF luacad convert model.lua output.stl # Convert to STL luacad convert model.lua output.scad # Export as OpenSCAD luacad watch model.lua output.3mf # Rebuild on file changes luacad render model.lua preview.png # Render to a PNG image luacad info model.lua # Print triangle counts and bounding box luacad lint model.lua # Lint with selene (also takes directories) luacad run model.lua # Execute (side-effects only) convert format from the output extension; --format <fmt> overrides it, and --via-openscad hands the export to an installed OpenSCAD binary instead of building Manifold.
LuaCAD has full support for the Belfry OpenSCAD Library v2, reimplemented in LuaCAD itself, so it renders, previews and exports to a mesh without OpenSCAD or BOSL2 installed:
bosl.cuboid { {40, 40, 40}, rounding = 2 } bosl.regular_prism { 5, r = 10, h = 25 } bosl.spur_gear { circ_pitch = 5, teeth = 20, thickness = 5 } Exporting to .scad still writes the BOSL2 call itself, exported script that produced it.
text() outlines a system font into a sketch and text3d() extrudes , so text becomes real geometry rather than SCAD output:
What Comes Next
render(text("LuaCAD", { size = 12, halign = "center" }):linear_extrude(2)) import() format LuaCAD writes and returns a transform and combine like any primitive; return a 2D sketch instead, ready to extrude.
script returns becomes its own 3MF object, so slicers individually movable parts. :name(…) to control how they appear in the object list. The other formats cannot express separate objects, so they flatten everything into a single mesh.
Explore more: Software & AI Guide