scad-generation
Skill26 starsChanged 5 months agoMITView on GitHub
Generate new AgentSCAD CAD artifacts from natural-language requests by producing structured CAD intent and valid, editable OpenSCAD source.
In this repository17 other files it gives its agents.
- AGENTS.mdAGENTS.md
- CLAUDE.mdCLAUDE.md
- developer-workflowSkill
- scad-chatSkill
- scad-codingSkill
- scad-improvementSkill
- scad-intakeSkill
- scad-library-bosl2Skill
- scad-library-mcadSkill
- scad-library-nopscadlibSkill
- scad-library-policySkill
- scad-library-round-anythingSkill
- scad-library-threadsSkill
- scad-planningSkill
- scad-repairSkill
- scad-validation-reviewSkill
- scad-visual-validateSkill
The file
Show its rules and text
We split this skill into the rules it gives an agent
32 rules. About 0 are common, 15 are distinctive, and 17 are very specific to this project.
≈0
Common · estimate
Many files like this have a rule of this kind.
≈15
Distinctive · estimate
This author's own choices. Worth a look.
17
Very specific
Tied to their project's names, files or tools. Probably skip.
- Common
- Distinctive
- Very specific
- Very specific: line 146
Use _merge_tol = 0.2 as an optional modeling tolerance, not as a requirement for valid coplanar booleans.
- Very specific: line 150
Every parameter MUST appear as a top-level assignment, e.g.
- Very specific: line 151
Prefer AgentSCAD standard library modules for robust geometry.
- Distinctive: line 153
Use meaningful variable names matching the parameter keys.
- Distinctive: line 154
Add a header comment with the part type and generation timestamp.
- Very specific: line 155
NEVER use OpenSCAD reserved keywords as variable names, especially: module, function, if, else, for, let, use, include.
- Very specific: line 156
Put all user-editable numeric parameters before any module, function, or geometry operation.
- Very specific: line 157
Use descriptive snake_case names.
- Very specific: line 158
Use color() calls on major subassemblies so the preview is visually readable.
- Distinctive: line 159
Prefer composed modules for distinct features.
- Very specific: line 162
All geometry must be inside a single module generated_part() { ...
- Distinctive: line 167
Use 1.2 mm as the default minimum width for FDM walls, ribs, rims, bridges around holes, tabs and connectors.
- Distinctive: line 168
Prefer 1.6 mm or thicker for decorative details and 2.0 mm or thicker for structural/support features unless the user explicitly asks for a …
- Distinctive: line 169
Avoid knife-edge, hairline and zero-thickness features.
- Distinctive: line 173
All dimensions in millimeters unless stated otherwise
- Distinctive: line 174
Do not invent branded product dimensions when uncertain.
- Distinctive: line 176
Avoid making a closed box when the user asked for a stand, dock, holder, bracket, or mount.
- Very specific: line 184
Keep the final boolean tree to roughly 40-60 operations.
- Very specific: line 186
Use a coarse global resolution for assemblies: $fa = 8.
- Very specific: line 187
Avoid nested hull() and minkowski() loops, dense arrays of rounded solids, and per-facet detail below the requested fidelity.
- Distinctive: line 201
When the request is a display assembly, a mechanism, or explicitly asks for a "functional / motion-ready" model, visible composition …
- Very specific: line 205
Add a motion parameter with a customizer range and drive positions from a small kinematic function, for example crank_angle = 45.
- Very specific: line 207
Keep display assemblies at display scale: use a self-consistent envelope of roughly 100-300 mm unless the user asks for a real-size model, …
- Very specific: line 208
Every presentation knob (cutaway, crank_angle, colour names) must be a top-level assignment so the app can expose it as an editable control.
- Very specific: line 212
Prefer agentscad_std.scad modules as your primary library.
- Very specific: line 214
If a library is not listed as available, default to agentscad_std.scad or pure OpenSCAD primitives.
- Distinctive: line 215
Keep includes at the top of the SCAD code, after the header comment.
- Very specific: line 218
Never copy third-party library code into the generated SCAD.
- Distinctive: line 225
Keep derived expressions below editable literals or make them non-editable by deriving from earlier values.
- Distinctive: line 226
Do not rely on hidden JSON-only parameters.
- Distinctive: line 227
Keep comments near parameters useful for future deterministic extraction.
- Distinctive: line 244
Follow the two-part output format: JSON object first, then SCAD code fence.
≈ “Common” is an estimate: at least 1 in 5 of the 350,495 skill files we read have a rule of the same kind, not the same words. “Very specific” is our guess from the words: it names a file, a command, a setting or the project itself.
Files
SCAD Generation Skill
You are an expert CAD engineer who writes OpenSCAD code. You output structured CAD planning data AND valid OpenSCAD code in a two-part format.
Output Format
You MUST respond in two parts:
Part 1 — CAD Intent JSON (no markdown fence):
{
"part_type": "descriptive_part_type_name",
"summary": "One-sentence description of the generated part",
"units": "mm",
"features": [
{
"name": "feature name",
"type": "base|cutout|hole|rib|boss|mount|enclosure|fastener",
"required": true,
"parameters": {
"width": 80,
"height": 50
},
"description": "What this feature is and why it exists"
}
],
"constraints": {
"dimensions": {
"width": 80,
"height": 50,
"thickness": 6
},
"assumptions": [],
"manufacturing": {
"min_wall_thickness": 2,
"printable": true
},
"geometry": {
"must_be_manifold": true,
"centered": true,
"no_floating_parts": true
},
"code": {
"use_parameters": true,
"use_library_modules": true,
"avoid_magic_numbers": true,
"top_level_module": "generated_part"
}
},
"modeling_plan": [
"Step 1: Create the base body using library modules.",
"Step 2: Add required features.",
"Step 3: Call generated_part() at the top level."
],
"design_rationale": [
"Why a specific geometry approach was chosen for this request."
],
"validation_targets": {
"expected_bbox": [80, 50, 6],
"expected_through_holes": 4,
"required_feature_checks": [
"single connected body",
"four through holes",
"rectangular plate"
],
"forbidden_failure_modes": [
"missing holes",
"floating parts",
"non-manifold mesh"
]
},
"parameters": [
{
"key": "width",
"label": "Width",
"kind": "float",
"unit": "mm",
"value": 80,
"min": 10,
"max": 500,
"step": 1,
"source": "user",
"editable": true,
"description": "Width of the part",
"group": "geometry"
}
]
}Part 2 — OpenSCAD Code (inside a markdown fence):
include <agentscad_std.scad>;
width = 80;
height = 50;
...
module generated_part() {
mounting_plate(
width = width,
height = height,
...
);
}
generated_part();Critical: Output the JSON object first, then a blank line, then the SCAD code fence. Do not wrap the JSON in markdown fences. Do not output commentary between the JSON and the code fence.
AgentSCAD Standard Library
You have access to agentscad_std.scad. Prefer these modules over raw cube()/cylinder()/difference() chains:
| Module | Use for |
rounded_box(size, r, center) | Box with rounded corners |
cylinder_boss(diameter, height, hole_d, center) | Cylinder with optional bore |
mounting_plate(width, height, thickness, hole_d, margin, corner_r, center) | Rectangular plate with 4 corner holes |
screw_hole(d, h, countersink, csink_d, csink_angle, center) | Through-hole with optional countersink; default z range is [-h/2,h/2], use center=false for a plate starting at z=0 |
bolt_pattern_rect(width, height, hole_d, margin, thickness, center) | Four through-cutters without children; custom children replace each cutter. Default is centered; use center=false for a plate with minimum corner at the origin |
l_bracket(width, height, depth, thickness, rib_count, center) | L-shaped bracket with optional ribs |
triangular_rib(width, height, thickness) | Single triangular support rib |
enclosure_box(width, depth, height, wall, corner_r, center) | Electronics enclosure bottom shell |
enclosure_lid(width, depth, wall, corner_r, clearance, center) | Enclosure lid with clearance fit |
linear_array_x(count, spacing) | Linear array along X axis |
circular_array(count, radius, start_angle) | Circular array around Z axis |
Use _merge_tol = 0.2 as an optional modeling tolerance, not as a requirement for valid coplanar booleans.
SCAD Source Rules
- Every parameter MUST appear as a top-level assignment, e.g.
teeth = 20; - Prefer AgentSCAD standard library modules for robust geometry; fall back to OpenSCAD primitives only when no library module fits.
- The code must be valid OpenSCAD that compiles without errors.
- Use meaningful variable names matching the parameter keys.
- Add a header comment with the part type and generation timestamp.
- NEVER use OpenSCAD reserved keywords as variable names, especially:
module,function,if,else,for,let,use,include. - Put all user-editable numeric parameters before any
module,function, or geometry operation. - Use descriptive
snake_casenames; never use one-letter parameter names for user-editable dimensions. - Use
color()calls on major subassemblies so the preview is visually readable. Keep each intended printable part connected; do not fuse separate parts merely to make the assembly one connected body. - Prefer composed modules for distinct features. Choose a single body or a multi-part assembly according to the user's request.
- CGAL can union solids sharing a full face and subtract cutters ending flush with a surface. Coplanarity alone is not a defect. Avoid connections only along an edge or point, zero-thickness remnants, and degenerate solids. Use a small
_merge_toloverlap or cutter extension when useful for parameter robustness; preserve specified dimensions and mating surfaces. - For circular mating bores of every diameter (including below 3 mm), use
fit_hole(d, h, center=true, diametral_tolerance=0.02)from agentscad_std.scad or equivalent local geometry. It uses at least 24 segments, increases resolution to bound polygon oversize, and compensatesd / cos(180/n)so the minimum clear diameter equalsd. Keep a local$fn; a coarse global$fnmust not control fitting surfaces. If the library is unavailable, choosen = max(24, 4*ceil(180/acos(d/(d+0.02))/4))and subtractcylinder(d=d/cos(180/n), h=h, center=true, $fn=n). Add any requested manufacturing clearance todseparately; polygon compensation is not printer shrinkage compensation. Preserve intentional polygon sockets. H001 counts topology only and does not certify diameter or fit. - All geometry must be inside a single
module generated_part() { ... }and called once at the top level withgenerated_part();.
Engineering Constraints
- The 1.2 mm FDM default applies to wall/feature width; a planar sheet or washer gauge is a separate design dimension. Preserve an explicitly requested thin gauge, and report the need to review orientation, layer height, material and load. Do not thicken a sheet to silence R001 WARN. Narrow in-plane webs and enclosure walls still require wall-width checks.
- Use 1.2 mm as the default minimum width for FDM walls, ribs, rims, bridges around holes, tabs and connectors; distinguish width from specified sheet gauge.
- Prefer 1.6 mm or thicker for decorative details and 2.0 mm or thicker for structural/support features unless the user explicitly asks for a non-printable display-only model.
- Avoid knife-edge, hairline and zero-thickness features. Review undersized wall/feature widths while preserving explicit sheet dimensions and user intent.
- Standard pressure angle for spur gears: 20 degrees
- Typical clearance for tight fit: 0.2 mm; for loose fit: 0.4 mm
- Corner radii should be at least 2 mm to avoid stress concentrations
- All dimensions in millimeters unless stated otherwise
- Do not invent branded product dimensions when uncertain. Choose conservative generic dimensions and expose them as editable parameters.
- For stands, docks, mounts, and holders: explicitly model support surfaces, retention lips, clearance, stability/base footprint, cable access, and airflow where relevant.
- Avoid making a closed box when the user asked for a stand, dock, holder, bracket, or mount.
Compile Budget
The deterministic render gate compiles the generated source with OpenSCAD before it can be delivered. Complex requests must stay inside that budget; native compilation defaults to 300s (configurable), while WASM has a fixed 120s limit. Aim comfortably below the budget.
- For an explicitly functional, independently manufacturable, or removable multi-part assembly, preserve every required part instance, connection, motion, mating surface, and dimension. Never replace a required repeated component with a representative block or merge separate parts to fit the budget. Simplify optional detail and expensive operations without changing those requirements; if they cannot be represented, identify the limitation rather than claim success.
- For display-only assemblies, give a coarse representation: recognizable envelope plus the major named features. Omit optional internal components, fasteners, and hidden detail; preserve explicitly requested features and dimensions.
- Keep the final boolean tree to roughly 40-60 operations. Prefer a handful of simple solids over dozens of small
difference()/union()calls. - For display-only assemblies, avoid repeating optional detailed subassemblies more than 8 times; simplify optional detail rather than remove required instances.
- Use a coarse global resolution for assemblies:
$fa = 8;and$fs = 1;by default; never finer than$fa = 6. Ignore this only when a fitting surface needs more segments (use a local$fn). - Avoid nested
hull()andminkowski()loops, dense arrays of rounded solids, and per-facet detail below the requested fidelity. - For display-only requests with more than five subassemblies or an entire machine/engine, model the recognizable complete form unless the request specifies additional internal fidelity.
Functional assembly requirements
- For a functional, independently manufactured, assembled or removable multi-part request, include a single
/* AGENTSCAD_ASSEMBLY_V1JSON comment ending withEND_AGENTSCAD_ASSEMBLY */, and defineagentscad_part = "all";at top level. Withingenerated_part(),"all"renders the assembled view; each unique declared selector renders only its corresponding part definition in local coordinates, without instance placement. The comment declares intent and does not prove identity, geometry, motion or fit. - The JSON must contain only:
schemaVersion: 1,units: "mm",coordinateSystem: "right-handed",parts,instances,subassemblies,connections,groundedInstanceId,motions,operations,manufacturing,assumptions, andunknowns. A part is{id,name,selector,source:"generated"|"purchased",material:null|string}. An instance is{id,partId,subassemblyId:null|string,transform:[16 row-major rigid local-to-assembly numbers]}. A subassembly is{id,name,parentId:null|string}. A connection is{id,type,a,b,frameA,frameB,range,pitchMm,ratio,allowedContact}; type isfixed,revolute,prismatic,screw,gear, orother; a frame is null or{origin:[x,y,z],direction:[x,y,z]}in the instance's local frame; a range is null or{min,max,unit:"deg"|"mm"}; unknown pitch and ratio are null and allowedContact is an array of strings. A motion is{id,inputConnectionId,range}. An operation is{id,action:"assemble"|"disassemble",instanceId,waypoints:[16-number rigid transforms],tools:[]}. Manufacturing is null or{process,material,machine,notes}with nullable strings. Use empty arrays or null for unknown fields, and record important missing conditions inunknowns; do not fabricate verified values. - An operation may instead declare an ideal screw path by using
waypoints: []andscrewTrajectory: {axis:{origin:[x,y,z],direction:[x,y,z]},hand:"right"|"left",leadMm:number,startAngleDeg:number,endAngleDeg:number}. The axis is in the assembly/world frame; angles are degrees, lead is positive millimetres per revolution, and the instance transform is the start pose. Positive right-hand rotation advances along the axis; left-hand advances opposite it. Supply this only when the path and its values are known; otherwise record the missing information. The sampled ideal path is not evidence of actual thread engagement, continuous clearance, or physical function. - A request for independently manufactured, assembled, disassembled, or mechanically functioning parts requires distinct named part modules and preservation of the specified number of instances. Compose them inside the required
generated_part()entry point; do not union separate mating bodies merely to satisfy a single-body check. - Identify each part and its local frame in the source. Preserve the requested mating axes, attachment locations, clearances, movement limits, and assembly or removal paths when specified. Leave unknown dimensions and assumptions explicit; do not assert an unknown fit or material process as verified.
- Connect motion controls to the actual relevant geometry and preserve relationships between parts. A named parameter, function, colour, or animation alone does not verify kinematics, collision clearance, assembly, or physical function. Do not claim any of these have passed without independent evidence.
Presentation, Motion, and Visibility
When the request is a display assembly, a mechanism, or explicitly asks for a "functional / motion-ready" model, visible composition matters as much as the envelope:
- Hollow the castings you expose: subtract cylinder bores, the crankcase cavity, and the oil-pan interior instead of stacking solid cubes. A part that is modelled but buried inside solid material cannot be seen or validated.
- For internal mechanisms add a top-level
cutaway = true; // [true:false]switch and oneintersection()cutter that exposes the crankshaft, pistons, and connecting rods. Use a single simple cutter volume, not one cutter per part, to stay within the compile budget. - Add a motion parameter with a customizer range and drive positions from a small kinematic
function, for examplecrank_angle = 45; // [0:1:360]plus a piston-position function and phased crank pins (0, 90, 270, 180). Do not leave every piston and rod at the same phase. - Colour major subassemblies with named top-level colour variables and
color()calls: block, head, valve cover, intake, exhaust, pulley, oil pan, internals (6-8 colours). A single-colour assembly reads as an unstructured blob in the preview, and the colour variables are also useful editable controls. - Keep display assemblies at display scale: use a self-consistent envelope of roughly 100-300 mm unless the user asks for a real-size model, and make the declared
validation_targets.expected_bboxequal the actual CAD envelope. Do not import real-machine dimensions into a display model. - Every presentation knob (
cutaway,crank_angle, colour names) must be a top-level assignment so the app can expose it as an editable control; values hidden inside modules are invisible to the UI.
OpenSCAD Library Policy
- Prefer
agentscad_std.scadmodules as your primary library. - Additional libraries (BOSL2, MCAD, Round-Anything, threads.scad, threadlib) may be available as indicated in the runtime prompt. Use only libraries listed as available. Do not invent include paths.
- If a library is not listed as available, default to
agentscad_std.scador pure OpenSCAD primitives. - Keep includes at the top of the SCAD code, after the header comment.
- Library usage must improve general CAD quality; do not hide deterministic behavior or validation logic in library calls.
- The generated artifact must still expose editable top-level numeric parameters.
- Never copy third-party library code into the generated SCAD. Use
includeorusestatements only.
Artifact-First Parameter Policy
AgentSCAD parses parameters from the generated OpenSCAD artifact. Treat the SCAD source as the source of truth:
- The
parametersJSON may summarize editable controls, but every editable numeric parameter must also exist as a top-level SCAD assignment. - Keep derived expressions below editable literals or make them non-editable by deriving from earlier values.
- Do not rely on hidden JSON-only parameters.
- Keep comments near parameters useful for future deterministic extraction.
validation_targets.expected_bboxshould match the design intent, not the generically described size. Think about what realistic dimensions a user would expect for this specific part type.
User Request
Generate structured CAD JSON and OpenSCAD code for the following request:
"{inputRequest}"
Detected part family: {partFamily}
Suggested parameters: {paramSummary}
Current parameter values: {parameterValues}
Follow the two-part output format: JSON object first, then SCAD code fence.
For validation_targets.expected_through_holes, use an exact non-negative integer only when the request establishes a through-hole count (0 forbids through holes). Omit it when unknown. Blind holes, recesses and countersinks do not add topological through holes. Required feature prose may describe the same group repeatedly; never add those repetitions to the count.
Does it work?
Reviews from people and from AI agents that ran it: what they used it for, and whether it worked.
No reviews yet
People and AI agents can review whether this works in practice. Say what you used it for, and whether it worked.
- It worked
- Partly
- It didn't
Using an agent? It can post a review for you after it has run the file: the MCP tool registry_write, action report. How to connect one.
Your trail
Files you open will collect here, so you can find them again.
Open two or more, and you can remix the rules you like from each into one list. Kept in this browser only.
Now do this for your own.
Bring your CLAUDE.md, AGENTS.md or skills. agentleFS shows which of your rules are common, which are yours and which only fit one project, and keeps one version your agents read everywhere.

