agentleFS
saitotakeuchisaitotakeuchi/MichelangeloCC/.claude/skills/3d-modeling/SKILL.md

3d-modeling

Skill4 starsChanged 10 months agoMITView on GitHub

Generate 3D printable models using MichelangeloCC. Creates STL files from natural language descriptions through build123d CAD operations. Use this skill when the user wants to create 3D models, generate STL files, or design objects for 3D printing.

3 other projects use a version of this.

Adopted by

Most recently taken up by

  • Other versions3 projects use a version of this.

    Word for word · 0

    None found.

    Edited · 0

    None found.

    Wrote their own version · 3

    1. jasonkneen/tiny-world-builder★ 1.6ksame name
    2. codeonym-org/codeonym-arch-design★ 0same name
    3. codeonym-oss/design-skills★ 0same name

    How matches are found. Word for word: the exact same text. Edited: shares passages with this file (“99% same” means 99% of its five-word phrases also appear here; 10% or more counts). Their own version: similar meaning, or, weakest, the same name. We can’t tell which project had it first. Projects are counted among the 200 most-starred candidates, and mentions are links to the repository we found, up to 50 per site, so both counts are a floor.

  • In this repositoryOne other file it gives its agents.

The file

Show its rules and text

We split this skill into the rules it gives an agent

38 rules. 0 are common, 22 are distinctive, and 16 are very specific to this project.

  • 0

    Common

    Most of the 3 edited versions we read keep these.

  • 22

    Distinctive

    This author's own choices. Worth a look.

  • 16

    Very specific

    Tied to their project's names, files or tools. Probably skip.

  • Common
  • Distinctive
  • Very specific
  1. Distinctive:

    When the user asks you to create a 3D model:

    line 12
  2. Distinctive:

    Design: - Create model using build123d operations

    line 15
  3. Very specific:

    Save: - Write the Python script to a .py file

    line 16
  4. Very specific:

    Preview: - Run mcc preview model <script.py> to visualize

    line 17
  5. Very specific:

    Validate: - Run mcc validate mesh <script.py> to check printability

    line 18
  6. Very specific:

    Export: - Run mcc export stl <script.py> -o <output.stl> when ready

    line 19
  7. Very specific:

    When running in an interactive session started with mcc session, you have a streamlined workflow:

    line 23
  8. Distinctive:

    Verify: - Check for Python errors before proceeding (see below)

    line 41
  9. Very specific:

    Export: when satisfied: mcc export stl model.py -o output/model.stl --quality high

    line 43
  10. Very specific:

    After saving model.py, you MUST check for errors:

    line 49
  11. Distinctive:

    If the command shows any errors (NameError, SyntaxError, TypeError, etc.):

    line 56
  12. Distinctive:

    Only then: ask the user for feedback

    line 60
  13. Distinctive:

    Keep parameters at the top of the file for easy adjustment

    line 72
  14. Very specific:

    Use the existing model.py structure - don't create new files unless necessary

    line 73
  15. Distinctive:

    Check the browser preview after each change before asking for feedback

    line 74
  16. Very specific:

    When finished, always export to output/ folder with high quality

    line 75
  17. Distinctive:

    Always create Python scripts following this pattern:

    line 91
  18. Distinctive:

    Default to 3mm minimum wall thickness for strength

    line 297
  19. Distinctive:

    Add 0.2mm tolerance for mating/sliding parts (holes, slots)

    line 298
  20. Distinctive:

    Add 0.1mm tolerance for press-fit parts

    line 299
  21. Distinctive:

    Use fillets (2-3mm) on stress concentration areas

    line 300
  22. Distinctive:

    Consider print orientation: overhangs should be < 45 degrees

    line 301
  23. Distinctive:

    Add draft angles (1-2 degrees) for parts that need to release from molds

    line 302
  24. Very specific:

    Use loft() and sweep() for smooth organic forms

    line 305
  25. Very specific:

    Use splines (Spline()) for natural curves

    line 306
  26. Very specific:

    Consider using make_hull() for organic boundaries

    line 307
  27. Very specific:

    Use shell() to create hollow parts

    line 311
  28. Distinctive:

    Add screw bosses (cylinders with holes) for assembly

    line 313
  29. Distinctive:

    Add ventilation slots if needed for electronics

    line 315
  30. Distinctive:

    If the preview shows "Error loading model", check the terminal for the actual Python error.

    line 392
  31. Very specific:

    Check for non-manifold geometry (run mcc validate mesh --verbose)

    line 459
  32. Distinctive:

    Verify boolean operations completed (no floating geometry)

    line 460
  33. Very specific:

    Use mcc repair auto for automatic fixes

    line 461
  34. Distinctive:

    Run validation frequently to catch floating parts early:

    line 543
  35. Very specific:

    Look for the DISCONNECTED_PARTS error message.

    line 549
  36. Distinctive:

    Check your boolean operations (+, -, &)

    line 550
  37. Distinctive:

    Verify parts overlap where they should connect

    line 551
  38. Distinctive:

    Make sure all components are combined into the final model

    line 552

“Common” is measured: kept by at least 6 in 10 of the 3 edited versions of this file we could read. “Very specific” is our guess from the words: it names a file, a command, a setting or the project itself.

Keep what fits and drop the rest. Your version, ready for your agents.
Files
SKILL.md

3D Model Generation with MichelangeloCC

You are an expert 3D modeler using the MichelangeloCC library built on build123d. Generate precise, printable 3D models from user descriptions.

Core Workflow

When the user asks you to create a 3D model:

  1. Understand - Clarify dimensions, tolerances, and intended use if not specified
  2. Design - Create model using build123d operations
  3. Save - Write the Python script to a .py file
  4. Preview - Run mcc preview model <script.py> to visualize
  5. Validate - Run mcc validate mesh <script.py> to check printability
  6. Export - Run mcc export stl <script.py> -o <output.stl> when ready

Interactive Session Mode

When running in an interactive session started with mcc session, you have a streamlined workflow:

Session Context

  • Working directory: The session folder (e.g., session_20260110_143052/)
  • Model file: model.py - This is the main file to edit
  • Preview: Browser is already open at http://localhost:8080 showing live preview
  • Output folder: output/ - Place exported STL files here
  • tmux session: Running inside tmux (detach with Ctrl+B, D, reattach with tmux attach)

How It Works

The browser shows a live 3D preview of model.py. When you edit and save model.py, the viewer automatically reloads and displays the updated model. This enables rapid iteration without manual refresh.

The file watcher detects all types of file changes including atomic writes (temp file + rename), so preview updates work reliably regardless of how the file is saved.

Session Workflow

  1. Read the current model.py to understand the starting template
  2. Modify model.py based on the user's request
  3. Wait - The browser automatically shows the updated model
  4. Verify - Check for Python errors before proceeding (see below)
  5. Ask the user for feedback and iterate
  6. Export when satisfied: mcc export stl model.py -o output/model.stl --quality high

CRITICAL: Verify Model Before Review

NEVER ask the user to review a model without first verifying it loads correctly.

After saving model.py, you MUST check for errors:

# Run this after every save to check for Python errors
python model.py

If the command shows any errors (NameError, SyntaxError, TypeError, etc.):

  1. Read the error message - it tells you exactly what's wrong
  2. Fix the issue in model.py
  3. Run python model.py again to verify the fix
  4. Only then ask the user for feedback

Common errors to watch for:

  • NameError: name 'Scale' is not defined → Use scale() function instead
  • SyntaxError → Check for missing colons, parentheses, quotes
  • TypeError → Check function arguments match expected types
  • AttributeError → Check method/property names are correct

The browser showing "Error loading model" means Python failed. Always check terminal output.

Best Practices in Session Mode

  • Make small, incremental changes - easier to debug if something goes wrong
  • Keep parameters at the top of the file for easy adjustment
  • Use the existing model.py structure - don't create new files unless necessary
  • Check the browser preview after each change before asking for feedback
  • When finished, always export to output/ folder with high quality

Session Commands

# Export final model (run from session folder)
mcc export stl model.py -o output/model.stl --quality high

# Validate before export
mcc validate mesh model.py --verbose

# Get model info
mcc info model.py

Model Script Structure

Always create Python scripts following this pattern:

"""
Model: [Name]
Description: [Brief description]
Author: Claude Code
Units: mm (millimeters)
"""

from build123d import *
from michelangelocc import MichelangeloModel, ModelMetadata

# === Parameters ===
# Define all dimensions as variables at the top for easy modification
length = 50.0  # mm
width = 30.0   # mm
height = 10.0  # mm

# === Model Construction ===
# Use build123d algebra mode (preferred for most operations)
part = Box(length, width, height)
part -= Cylinder(5, height)  # Subtract a hole

# For complex operations, use builder mode:
# with BuildPart() as builder:
#     Box(length, width, height)
#     with Locations((0, 0, height)):
#         Cylinder(5, 10, mode=Mode.SUBTRACT)
# part = builder.part

# === Export ===
model = MichelangeloModel(
    part=part,
    metadata=ModelMetadata(
        name="model_name",
        description="Description of the model",
        units="mm"
    )
)

Build123d Quick Reference

Primitive Shapes

Box(length, width, height)           # Rectangular prism
Cylinder(radius, height)             # Cylinder
Sphere(radius)                       # Sphere
Cone(bottom_radius, top_radius, height)  # Cone or truncated cone
Torus(major_radius, minor_radius)    # Donut shape

Boolean Operations (Algebra Mode)

part1 + part2      # Union (combine shapes)
part1 - part2      # Subtraction (cut)
part1 & part2      # Intersection

Positioning and Rotation

Pos(x, y, z) * shape       # Translate
Rot(x, y, z) * shape       # Rotate (degrees around each axis)
Pos(10, 0, 0) * Rot(0, 0, 45) * Box(5, 5, 5)  # Combined

Scaling (Non-Uniform)

# Use the scale() FUNCTION - NOT a Scale() class with * operator
scaled = scale(Sphere(10), by=(1, 0.5, 0.5))  # Scale Y and Z to 50%

# Uniform scaling
scaled = scale(Box(10, 10, 10), by=2)  # Double size in all directions

# In BuildPart mode:
with BuildPart() as bp:
    Sphere(10)
    scale(by=(1.5, 1, 0.8))  # Scale current part in place
part = bp.part

# Combined with positioning:
part = Pos(0, 0, 5) * scale(Sphere(10), by=(1, 0.5, 0.5))

Mirroring

# Use the mirror() FUNCTION - NOT a Mirror() class
mirrored = mirror(Box(10, 10, 10), about=Plane.XZ)  # Mirror about XZ plane

# In BuildPart mode (adds mirrored copy):
with BuildPart() as bp:
    Box(10, 10, 10)
    mirror(about=Plane.YZ)  # Creates symmetric part
part = bp.part

Edge Operations

fillet(part.edges(), radius)         # Round all edges
fillet(part.edges().filter_by(Axis.Z), radius)  # Round vertical edges only
chamfer(part.edges(), distance)      # Bevel edges

2D to 3D Operations

# Extrude a 2D shape
with BuildPart() as p:
    with BuildSketch():
        Rectangle(width, height)
        Circle(radius)  # Adds to sketch
    extrude(amount=depth)

# Revolve around axis
with BuildPart() as p:
    with BuildSketch(Plane.XZ):
        with BuildLine():
            Polyline([(0, 0), (10, 0), (10, 20), (0, 20)])
    revolve(axis=Axis.Z, revolution_arc=360)

# Loft between profiles
loft([profile1, profile2, profile3])

# Sweep along path
sweep(section=circle_profile, path=spline_path)

Sketching (2D Shapes)

with BuildSketch() as s:
    Rectangle(width, height)
    Circle(radius)
    RegularPolygon(radius, n_sides)
    Text("Label", font_size=10)

Selection and Filtering

part.edges()                         # All edges
part.faces()                         # All faces
part.vertices()                      # All vertices

# Filter by axis
part.edges().filter_by(Axis.Z)       # Edges parallel to Z
part.faces().filter_by(Axis.Z)       # Faces perpendicular to Z

# Sort and select
part.edges().sort_by(Axis.Z)[-1]     # Topmost edge
part.faces().sort_by(Axis.Z)[0]      # Bottom face

# Filter by position
part.edges().filter_by(lambda e: e.center().Z > 5)

Common Patterns

Hole Pattern (Grid)

for i in range(rows):
    for j in range(cols):
        part -= Pos(i * spacing, j * spacing, 0) * Cylinder(hole_r, height)

Hole Pattern (Circular)

import math
for i in range(num_holes):
    angle = i * (360 / num_holes)
    x = radius * math.cos(math.radians(angle))
    y = radius * math.sin(math.radians(angle))
    part -= Pos(x, y, 0) * Cylinder(hole_r, height)

Shell (Hollow Part)

# Open top face
top_face = part.faces().sort_by(Axis.Z)[-1]
part = shell(part, amount=-wall_thickness, openings=[top_face])

Fillet Specific Edges

# Fillet only top edges
top_edges = part.edges().filter_by(lambda e: e.center().Z > height/2)
part = fillet(top_edges, radius)

Counterbore Hole

# Through hole
part -= Cylinder(hole_diameter/2, height)
# Counterbore
part -= Pos(0, 0, height - counterbore_depth) * Cylinder(counterbore_diameter/2, counterbore_depth)

Text Embossing/Engraving

with BuildSketch(part.faces().sort_by(Axis.Z)[-1]):
    Text("LABEL", font_size=8)
extrude(amount=0.5)   # Emboss (raised)
extrude(amount=-0.5)  # Engrave (recessed)

Design Guidelines

For Mechanical Parts

  • Default to 3mm minimum wall thickness for strength
  • Add 0.2mm tolerance for mating/sliding parts (holes, slots)
  • Add 0.1mm tolerance for press-fit parts
  • Use fillets (2-3mm) on stress concentration areas
  • Consider print orientation: overhangs should be < 45 degrees
  • Add draft angles (1-2 degrees) for parts that need to release from molds

For Organic/Artistic Shapes

  • Use loft() and sweep() for smooth organic forms
  • Use splines (Spline()) for natural curves
  • Consider using make_hull() for organic boundaries
  • Higher polygon count is acceptable for artistic pieces

For Enclosures/Cases

  • Use shell() to create hollow parts
  • Standard wall thickness: 2-3mm
  • Add screw bosses (cylinders with holes) for assembly
  • Include snap-fit features with 0.3mm interference
  • Add ventilation slots if needed for electronics

Units and Tolerances

  • Always use millimeters (mm) as the base unit
  • Typical 3D printer accuracy: 0.1-0.2mm
  • Minimum feature size: 0.4mm (nozzle dependent)
  • Layer height typical: 0.1-0.3mm

CLI Commands Reference

# Create new project from template
mcc new my_project --template mechanical

# Preview in browser (with hot-reload)
mcc preview model ./model.py

# Validate for 3D printing
mcc validate mesh ./model.py --verbose

# Export to STL
mcc export stl ./model.py -o ./model.stl --quality high

# Get model info
mcc info ./model.py

# Preview existing STL
mcc preview stl ./model.stl

# Repair broken mesh
mcc repair auto ./broken.stl -o ./fixed.stl

Quality Settings for Export

QualityToleranceUse Case
draft0.1mmQuick preview, large models
standard0.01mmMost 3D printing
high0.001mmFine detail, small parts
ultra0.0001mmMaximum precision

Common Mistakes to Avoid

Invalid Transformation Operators

CRITICAL: These transformation classes DO NOT exist as * operators:

# WRONG - These will cause "Error loading model"
Scale(1, 0.5, 0.5) * Sphere(10)    # NameError: Scale not defined
Mirror() * Box(10, 10, 10)          # NameError: Mirror not defined
Transform(...) * shape              # Not available

ONLY these work with the * operator:

Pos(x, y, z) * shape       # Translation - VALID
Rot(x, y, z) * shape       # Rotation - VALID
Pos() * Rot() * shape      # Combined - VALID

For scaling and mirroring, use FUNCTIONS:

scale(shape, by=(x, y, z))         # Correct way to scale
mirror(shape, about=Plane.XZ)      # Correct way to mirror

Testing Incrementally

Build models step by step to catch errors early:

  1. Create basic shape → save → check preview works
  2. Add one transformation → save → verify no errors
  3. Add boolean operations → save → check geometry
  4. Add details → save → validate before export

If the preview shows "Error loading model", check the terminal for the actual Python error.

Reference Working Examples

ALWAYS reference these examples when creating similar models. All examples are tested and working - copy patterns from them.

Location: .claude/skills/3d-modeling/examples/

Mechanical Parts

ExampleKey PatternsUse When
gear.pyParametric design, involute curves, derived dimensions, conditional featuresGears, parametric mechanical parts
bracket.pyEdge filtering, hole patterns, fillets, try/except for complex opsMounting brackets, structural parts
enclosure.pyShell/offset for hollow parts, mating tolerances, snap-fit lidBoxes, cases, enclosures

Household Items

ExampleKey PatternsUse When
hook.pyCurved profiles, countersunk holes, load-bearing jointsHooks, hangers, wall mounts
phone_stand.pyAngled surfaces (Rot), cable routing holes, stability designStands, holders, angled parts
vase.pyLoft between profiles, easing functions, organic curvesVases, organic shapes, smooth forms

Functional Prints

ExampleKey PatternsUse When
keychain.pyText embossing, thin features, ring holes, RectangleRoundedKeychains, tags, labels, thin parts

Quick Pattern Reference

Shell/Hollow a part:

# From enclosure.py - use offset() with openings
top_face = part.faces().sort_by(Axis.Z)[-1]
offset(amount=-wall_thickness, openings=[top_face])

Angled geometry:

# From phone_stand.py - use Rot() for angles
angled_part = Rot(angle, 0, 0) * part

Text embossing:

# From keychain.py - use Text in BuildSketch
with BuildSketch(top_face):
    Text("LABEL", font_size=8)
extrude(amount=1.0)  # Positive = emboss, negative = engrave

Countersunk holes:

# From hook.py - two-step: through hole + countersink
Cylinder(hole_diameter/2, thickness)  # Through hole
Pos(0, 0, 0) * Cylinder(countersink_diameter/2, countersink_depth)  # Countersink

Mating parts tolerance:

# From enclosure.py - subtract clearance from mating dimension
clearance = 0.3  # mm - for easy fit
inner_size = outer_size - 2 * wall - 2 * clearance

Error Handling

If validation fails:

  1. Check for non-manifold geometry (run mcc validate mesh --verbose)
  2. Verify boolean operations completed (no floating geometry)
  3. Use mcc repair auto for automatic fixes
  4. For severe issues, use mcc repair auto --aggressive

Common issues:

  • NOT_WATERTIGHT: Mesh has holes - check boolean operations
  • DEGENERATE_FACES: Zero-area triangles - simplify geometry
  • SELF_INTERSECTION: Overlapping faces - check boolean order
  • DISCONNECTED_PARTS: Floating geometry - see section below

Avoiding Floating Parts

Floating or disconnected parts are a common issue that makes models unprintable. The validator will report DISCONNECTED_PARTS if your model has separate geometry that isn't connected.

Common Causes

  1. Boolean operations that don't intersect
    # WRONG - cylinder is outside the box, creates floating geometry
    box = Box(20, 20, 20)
    hole = Pos(50, 0, 0) * Cylinder(5, 20)  # Too far away!
    result = box - hole  # Subtraction has no effect, but may create artifacts
  2. Components with gaps
    # WRONG - parts don't touch, will be disconnected
    base = Box(50, 50, 10)
    top = Pos(0, 0, 15) * Box(30, 30, 10)  # Gap of 5mm!
    result = base + top  # Creates two separate parts
  3. Multiple shapes without union
    # WRONG - shapes are created but not combined
    part1 = Box(20, 20, 10)
    part2 = Pos(0, 0, 10) * Cylinder(10, 15)
    # Missing: result = part1 + part2
    model = MichelangeloModel(part=part1, ...)  # Only uses part1!

Best Practices

  1. Always union multi-part objects
    # RIGHT - explicit union creates single connected solid
    base = Box(50, 50, 10)
    pillar = Pos(0, 0, 10) * Cylinder(10, 30)
    result = base + pillar  # Union creates one connected part
  2. Ensure parts overlap for unions
    # RIGHT - parts overlap slightly to ensure solid connection
    base = Box(50, 50, 10)
    top = Pos(0, 0, 9) * Box(30, 30, 10)  # Overlaps by 1mm
    result = base + top  # Creates single watertight solid
  3. Position holes within solid bounds
    # RIGHT - hole is inside the box
    box = Box(50, 50, 20)
    # Hole at center, ensure it goes through
    hole = Cylinder(5, 20)  # Same height as box
    result = box - hole  # Clean subtraction
  4. Verify dimensions before boolean ops
    # Calculate positions based on part dimensions
    base_height = 10
    pillar_height = 30
    pillar_radius = 8
    
    base = Box(50, 50, base_height)
    # Position pillar to start at top of base (with 1mm overlap)
    pillar = Pos(0, 0, base_height - 1) * Cylinder(pillar_radius, pillar_height)
    result = base + pillar

Validation During Development

Run validation frequently to catch floating parts early:

mcc validate mesh model.py --verbose

Look for the DISCONNECTED_PARTS error message. If it appears:

  1. Check your boolean operations (+, -, &)
  2. Verify parts overlap where they should connect
  3. Make sure all components are combined into the final model

The preview viewer will also show a warning banner if disconnected parts are detected.

Example: Complete Workflow

# 1. User asks for a gear
# 2. Generate the model script (gear.py)
# 3. Preview it
mcc preview model ./gear.py

# 4. Validate
mcc validate mesh ./gear.py --verbose

# 5. If issues, repair
mcc repair auto ./gear.py -o ./gear_fixed.py

# 6. Export final STL
mcc export stl ./gear.py -o ./gear.stl --quality high

# Model is ready for slicing and printing!

Download now (ZIP)

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
What did you use it for? e.g. Reviewing pull requests in a Rails app

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.