Install any skill in seconds. Free to start, no credit card required.
Get Started Free →Writes OpenSCAD code and drives the `openscad` command-line compiler to produce STL/3MF/AMF/DXF/SVG/PNG outputs from parametric `.scad` models. This skill should be used when the user asks to design a 3D-printable part, generate a laser-cut 2D plate, render a preview image of a CAD model, export STL for 3D printing, batch-render parametric variants, or convert between mesh formats. Invoked via "/hardware:use-openscad".
.claude/skills/fradser-use-openscad/SKILL.md| Test case | Without → With | Effect | Δ tokens | Δ turns |
|---|---|---|---|---|
| case-12 | ✗→✓ | ▲ Improved | 85% | 0% |
| case-14 | ✗→✓ | ▲ Improved | 24% | 0% |
| case-16 | ✗→✓ | ▲ Improved | 39% | 0% |
| case-18 | ✗→✓ | ▲ Improved | 130% | 0% |
| case-04 | ✓→✓ | = Same ✓ | 104% | 0% |
Design parametric 3D and 2D parts in OpenSCAD and compile them to fabrication outputs with the openscad CLI. OpenSCAD is a functional code-based CAD language — modules and functions, CSG booleans, extrusion — ideal for an agent to write and iterate.
openscad_run --version first to confirm it works..scad model using references/language.md for syntax. Make dimensions -D variables when the user wants parametric control from the command line.references/cli.md. Use references/workflows.md for end-to-end recipes and references/design.md for printability rules.--render is NOT needed for them. --render only affects PNG image export (without it, PNG uses OpenCSG preview). A plain openscad -o out.stl model.scad produces a complete mesh. For STL, explicitly pass --export-format binstl (ASCII is the current default; binary is the planned future default). After export, scan stderr for manifold warnings — see below./Applications/OpenSCAD.app/Contents/MacOS/OpenSCAD. On Linux try openscad or openscad-nightly; on Windows invoke openscad.com (the wrapper, not openscad.exe). On remote servers, use the Docker image (see hardware/scripts/docker/openscad/). MUST confirm with openscad_run --version before building a pipeline.--hardwarnings makes the first warning fatal. Do NOT assume — for CI gating, run with --hardwarnings and treat any non-zero exit as failure. When unsure of a flag, run openscad --help and read the actual list.is_undef(x), not x == undef. -D var=val constants from the CLI override top-level program values.use libraries, do not include them. include <lib.scad> is literal copy-paste that runs top-level geometry and confuses error line numbers; use <lib.scad> suppresses top-level geometry and exposes only functions/modules. Use use for any library file.-D values need shell quoting. -D 'mode="parts"' (bash) — the inner quotes are part of the OpenSCAD expression. Numeric -D w=60 needs no quotes.2>&1 and grep for manifold, self-intersect, degenerate, warning — OpenSCAD prints mesh problems to stderr even when the exit code is zero. See references/workflows.md.| User wants | Flags | Reference | |---|---|---| | STL for 3D printing | --export-format binstl -o out.stl | references/cli.md | | 3MF / AMF | -o out.3mf | references/cli.md | | 2D DXF / SVG (laser cut) | -o out.dxf | references/cli.md | | Preview PNG | --preview --imgsize W,H --viewall --autocenter (--render for accurate non-preview) | references/cli.md | | Parametric variants | -D var=val (repeatable) | references/cli.md | | Batch render | shell loop over -D values | references/workflows.md | | Mesh conversion (STL→3MF) | import() in a re-export .scad | references/workflows.md | | Language syntax | modules, functions, CSG, extrusion | references/language.md | | Printability rules | walls, overhangs, clearance | references/design.md |
bash# Resolve the OpenSCAD binary — local binary or Docker container __openscad_resolve() { # 1. macOS .app bundle local mac="/Applications/OpenSCAD.app/Contents/MacOS/OpenSCAD" if [[ -x "$mac" ]]; then echo "local:$mac"; return; fi # 2. PATH if command -v openscad &>/dev/null; then echo "local:openscad"; return; fi if command -v openscad-nightly &>/dev/null; then echo "local:openscad-nightly"; return; fi # 3. Docker (image must exist locally) if command -v docker &>/dev/null; then local img="${OPENSCAD_DOCKER_IMAGE:-openscad-cli}" if docker image inspect "$img" &>/dev/null 2>&1; then echo "docker:$img" return fi fi echo "" } OPENSCAD_TARGET="$(__openscad_resolve)" if [[ -z "$OPENSCAD_TARGET" ]]; then echo "ERROR: OpenSCAD not found." >&2 echo " Install locally: brew install openscad (macOS) or apt install openscad (Linux)" >&2 echo " Build Docker: docker build -t openscad-cli '${CLAUDE_PLUGIN_ROOT:-.}/scripts/docker/openscad/'" >&2 exit 1 fi # Run wrapper — transparently handles local binary vs Docker openscad_run() { local mode="${OPENSCAD_TARGET%%:*}" # "local" or "docker" local target="${OPENSCAD_TARGET#*:}" # binary path or image name if [[ "$mode" = "docker" ]]; then docker run --rm -v "$PWD:/work" -w /work "$target" "$@" else "$target" "$@" fi } openscad_run --version
The openscad_run function wraps every invocation. Usage is identical to calling openscad directly:
bashopenscad_run --export-format binstl -o out.stl model.scad openscad_run -o preview.png --preview --imgsize=1280,960 model.scad
Docker image: Build with docker build -t openscad-cli hardware/scripts/docker/openscad/ from the repo root. Override the image name with OPENSCAD_DOCKER_IMAGE=my-registry/openscad:latest.
references/language.md — OpenSCAD syntax: modules/functions, variables and scope, control flow, CSG booleans, primitives, transforms, extrusion and projection, import/include/use.references/cli.md — full openscad CLI: output and format flags, -D variables, rendering modes, image/camera options, diagnostics, --enable features, headless notes.references/design.md — printability heuristics (min wall, overhangs, bridges, clearance, manifold) and 2D-for-laser rules.references/workflows.md — end-to-end recipes (parametric STL, 2D DXF, preview PNG, batch variants, mesh conversion, stderr validation).| Case | Status | Duration (ms) | Turns | Tokens | Tool calls | ||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| Without | With | Δ | Without | With | Δ | Without | With | Δ | Without | With | Δ | ||
case-01 | fail→fail | 39,133 | 19,986 | -49% | 1 | 1 | 0% | 8,259 | 2,462 | -70% | 0 | 0 | — |
case-02 | fail→fail | 18,375 | 15,838 | -14% | 1 | 1 | 0% | 3,605 | 2,660 | -26% | 0 | 0 | — |
case-03 | fail→fail | 18,029 | 8,811 | -51% | 1 | 1 | 0% | 2,901 | 2,487 | -14% | 0 | 0 | — |
case-04 | pass→pass | 8,404 | 13,891 | +65% | 1 | 1 | 0% | 1,553 | 3,162 | +104% | 0 | 0 | — |
case-05 | pass→pass | 4,421 | 3,114 | -30% | 1 | 1 | 0% | 720 | 2,341 | +225% | 0 | 0 | — |
case-06 | pass→pass | 11,776 | 8,845 | -25% | 1 | 1 | 0% | 2,122 | 3,380 | +59% | 0 | 0 | — |
case-07 | pass→pass | 11,314 | 9,543 | -16% | 1 | 1 | 0% | 1,960 | 3,335 | +70% | 0 | 0 | — |
case-08 | pass→pass | 12,550 | 5,279 | -58% | 1 | 1 | 0% | 2,067 | 2,767 | +34% | 0 | 0 | — |
case-09 | pass→pass | 3,744 | 2,517 | -33% | 1 | 1 | 0% | 586 | 2,239 | +282% | 0 | 0 | — |
case-10 | pass→pass | 14,800 | 14,336 | -3% | 1 | 1 | 0% | 2,854 | 4,290 | +50% | 0 | 0 | — |
case-11 | pass→pass | 7,402 | 6,175 | -17% | 1 | 1 | 0% | 1,226 | 2,899 | +136% | 0 | 0 | — |
case-12 | fail→pass | 10,718 | 9,400 | -12% | 1 | 1 | 0% | 1,851 | 3,417 | +85% | 0 | 0 | — |
case-13 | pass→pass | 10,616 | 5,997 | -44% | 1 | 1 | 0% | 1,754 | 2,881 | +64% | 0 | 0 | — |
case-14 | fail→pass | 12,801 | 4,496 | -65% | 1 | 1 | 0% | 2,113 | 2,611 | +24% | 0 | 0 | — |
case-15 | pass→pass | 7,218 | 6,846 | -5% | 1 | 1 | 0% | 1,255 | 3,165 | +152% | 0 | 0 | — |
case-16 | fail→pass | 13,064 | 6,259 | -52% | 1 | 1 | 0% | 2,116 | 2,931 | +39% | 0 | 0 | — |
case-17 | pass→pass | 18,845 | 7,977 | -58% | 1 | 1 | 0% | 3,150 | 2,943 | -7% | 0 | 0 | — |
case-18 | fail→pass | 7,021 | 2,830 | -60% | 1 | 1 | 0% | 959 | 2,204 | +130% | 0 | 0 | — |
case-19 | pass→pass | 9,519 | 11,180 | +17% | 1 | 1 | 0% | 1,432 | 3,898 | +172% | 0 | 0 | — |
case-20 | pass→pass | 5,591 | 10,347 | +85% | 1 | 1 | 0% | 1,108 | 3,677 | +232% | 0 | 0 | — |
case-21 | fail→fail | 7,577 | 7,360 | -3% | 1 | 1 | 0% | 1,402 | 3,251 | +132% | 0 | 0 | — |
case-22 | pass→pass | 14,214 | 9,864 | -31% | 1 | 1 | 0% | 2,627 | 3,579 | +36% | 0 | 0 | — |
DecimalAI ran this skill against gemini-3.6-flash twice over the same eval suite — once with the skill loaded and once without — and compared the two runs case by case. 22 cases were attempted, and 19 counted toward the lift figure. The other 3 produced results that are not comparable between the two arms, so they are excluded from the headline rather than averaged into it. The headline lift of +18 percentage points is the difference between those two pass rates over the 19 comparable cases. 1 case got worse with the skill loaded, and it is included in that figure.
Without the skill loaded, the model failed this case. With it loaded, the same prompt on the same model passed. This is one improved case from the latest verified run; every case, including any that regressed, is in the table above.
Other measured skills in the registry, with their headline benchmark lift.