Files
step-parse/skill.src/SKILL.md
T
Jason Stedwell c1abe36822 phase 0
2026-06-17 16:03:26 -05:00

17 KiB
Raw Blame History

STEP File Processor Skill

Purpose

This skill enables Claude to work with STEP/STP CAD files used in manufacturing. It provides:

  • PNG thumbnail extraction at 6 camera angles
  • Parts manifest / BOM export to CSV with automatic Chinese→English translation
  • Optional English-labeled STEP copy (source file never modified)
  • Natural language geometric query interface (holes, faces, dimensions, quantities)

Designed for MPMedia's display enclosure and mounting kit product lines.


When to invoke this skill

Trigger on any of:

  • User provides a .step or .stp file path and asks to process, view, extract, or query it
  • User asks to "generate thumbnails" or "render views" of a STEP file
  • User asks to "extract BOM", "get parts list", or "show manifest" from a STEP file
  • User asks a geometric question about a STEP file: holes, faces, dimensions, quantities
  • User asks to "translate" a STEP file's part names
  • Claude Code context where a STEP file is present in the working directory

Read this entire SKILL.md before writing any code.


Library Stack

Primary: build123d

  • Modern OpenCASCADE Python wrapper; native Apple Silicon arm64 wheels
  • Clean, Pythonic API for STEP reading, assembly traversal, geometry queries
  • Offscreen PNG rendering via: build123d → export GLB/OBJ → trimesh → pyrender
  • Install: pip install build123d trimesh pyrender pillow numpy pandas anthropic
  • ARM64 OCP wheel required first — see INSTALL.md

Fallback: FreeCAD headless

  • Native macOS-arm64 build available via conda-forge (verified Nov 2024)
  • Used when build123d fails to load or render a specific file
  • Invoked via subprocess calling FreeCADCmd or by importing FreeCAD + Part
  • Never import FreeCADGui — headless only, GUI modules will crash
  • Install: conda install -c conda-forge freecad (arm64 native, no Rosetta)

Translation: Claude API (claude-sonnet-4-20250514)

  • Translates Chinese part names with manufacturing context awareness
  • e.g. 安装支架 → "Mounting Bracket" (not just "installation support")
  • Requires ANTHROPIC_API_KEY in environment

Supporting libraries (both tracks)

  • Pillow — PNG save/compose
  • numpy — geometry math
  • pandas — CSV/BOM output
  • trimesh + pyrender — GLB→PNG rendering fallback path

File Structure

step-processor/
  step_processor.py       ← CLI entry point + REPL
  modules/
    loader.py             ← STEP loading (build123d primary, FreeCAD fallback)
    bom.py                ← Assembly tree traversal + BOM extraction
    renderer.py           ← Offscreen PNG rendering (6 views)
    translator.py         ← Claude API translation layer
    rewriter.py           ← STEP label patcher (_EN copy only, never modifies source)
    query_engine.py       ← Geometric query handler (holes, faces, dimensions)
  INSTALL.md
  SKILL.md

Dual-Track Fallback Pattern

Every module must implement this pattern:

def load_step(filepath):
    try:
        return _load_via_build123d(filepath)
    except ImportError:
        logger.warning("build123d not available — falling back to FreeCAD")
        return _load_via_freecad(filepath)
    except Exception as e:
        logger.warning(f"build123d failed ({e}) — falling back to FreeCAD")
        return _load_via_freecad(filepath)

Always log fallbacks at WARNING level so the user knows which path ran.

FreeCAD fallback invocation pattern (subprocess, cleanest isolation):

import subprocess, json, tempfile

def _load_via_freecad(filepath):
    script = f"""
import FreeCAD, Part, json
shape = Part.read("{filepath}")
# extract data, write to temp JSON
"""
    result = subprocess.run(["FreeCADCmd", "--console", "-c", script], capture_output=True)
    # parse result...

Camera Views

Always produce these 6 views unless user specifies otherwise:

View Name Camera Direction File Suffix
Front +Y looking toward origin _front.png
Bottom -Z looking up _bottom.png
Left -X looking right _left.png
Right +X looking left _right.png
Iso Left +X+Y+Z (left-forward) _iso_left.png
Iso Right -X+Y+Z (right-forward) _iso_right.png

Default resolution: 1024×768. All PNGs saved to same folder as source STEP file.


Output Naming Convention

Given input: /path/to/EnclosureA.step

Output Path
Thumbnails (×6) /path/to/EnclosureA_front.png etc.
BOM CSV /path/to/EnclosureA_bom.csv
English STEP copy /path/to/EnclosureA_EN.step

Never overwrite or modify the source STEP file.

_EN.step is only created when Chinese labels are detected. If all labels are already ASCII/English, skip silently and note it in output.


BOM CSV Schema

part_number, part_name_original, part_name_english, quantity, level, parent,
bbox_x_mm, bbox_y_mm, bbox_z_mm, notes
  • level = assembly depth (0 = root, 1 = direct children, etc.)
  • parent = part_name_english of parent assembly
  • notes = translator flags (e.g. "machine-translated", "ambiguous term")
  • Bounding boxes in millimeters, 2 decimal places
  • If no translation needed, part_name_original == part_name_english

Translation Logic

bom.py extracts all part names
  → translator.py checks each name for CJK unicode range (\u4e00-\u9fff)
  → if any found: batch call Claude API with this system prompt:

    "You are a mechanical engineering translator specializing in Chinese
     manufacturing CAD files for display and enclosure products. Translate
     the following part names from Chinese to English. Preserve technical
     precision. Use standard hardware terminology. Output ONLY a JSON object
     mapping original → translated, nothing else.
     Example: {\"安装支架\": \"Mounting Bracket\", \"螺钉M4\": \"M4 Screw\"}"

  → inject translations into BOM CSV
  → if translation requested: produce _EN.step via rewriter.py

Flag uncertain translations in the notes column rather than silently guessing.


STEP Label Rewriting (_EN copy)

rewriter.py produces a translated copy — line-by-line, targeted replacement:

  1. Read source file line by line
  2. Identify lines containing PRODUCT(', PRODUCT_DEFINITION_CONTEXT( etc.
  3. Extract quoted name strings (first argument of PRODUCT entity)
  4. Replace CJK strings with translated equivalents from the translation map
  5. Write to {filename}_EN.step
  6. Validate: entity # count before == after. If mismatch → abort, warn, delete partial output

Do not use broad regex that could touch entity reference numbers (#123 etc.) Target only the quoted string arguments of known STEP entity types.


Geometric Query Engine

query_engine.py handles natural language queries about loaded geometry.

Supported Query Types

Query pattern What it extracts
"list all mounting holes" Cylindrical faces, axis ⊥ to primary face, dia < 15mm
"list all holes" All cylindrical through-features
"holes diameter [N]mm" Filter holes by diameter
"tapped holes" / "threaded" Cylinders with helical features (if present in model)
"face count" Total face count by type (planar, cylindrical, etc.)
"bounding box" Overall model extents in mm
"part [name] dimensions" Bounding box of a specific named part
"largest face" Largest planar face area in mm²
"wall thickness" Min distance between opposing parallel faces
"all parts" Full assembly listing with quantities

Query Invocation

CLI (single query, exit after):

python step_processor.py enclosure.step --query "list all mounting holes with diameter and depth"

REPL (interactive, geometry stays loaded in memory between queries):

python step_processor.py enclosure.step --repl
> list mounting holes
> bounding box
> how many M4 holes
> exit

Query Output Format

Always return a structured table:

MOUNTING HOLES — EnclosureA.step
─────────────────────────────────────────────────────────────
 #   Part Name          Diameter    Depth      Position (x,y,z)
─────────────────────────────────────────────────────────────
 1   Front Panel        4.20 mm     8.00 mm    (12.50, 0.00, 45.20)
 2   Front Panel        4.20 mm     8.00 mm    (87.50, 0.00, 45.20)
─────────────────────────────────────────────────────────────
Total: 8 holes across 3 parts

CLI Reference

python step_processor.py <file.step> [options]

Options:
  --thumbnails          Generate 6 PNG views (default: on)
  --no-thumbnails       Skip PNG generation
  --bom                 Export BOM CSV (default: on)
  --no-bom              Skip BOM export
  --translate           Auto-translate Chinese labels in BOM + produce _EN.step
  --no-translate        Skip translation even if Chinese labels detected
  --query "..."         Run a single geometric query and exit
  --repl                Enter interactive query REPL
  --resolution WxH      Thumbnail resolution (default: 1024x768)
  --views front,iso_left,iso_right  Comma-separated subset of views
  --verbose             Show library selection, fallback notices, timing

Default behavior (no flags): --thumbnails --bom plus auto-detect translation.


Error Handling

Condition Behavior
File not found Exit with clear message, no partial output
Neither library available Exit with INSTALL.md reference
build123d render fails Auto-fallback to FreeCAD path, log warning
Translation API unavailable Write BOM with original names only, note in output
STEP has no assembly structure Treat as single part, one-row BOM
Chinese detected, no translate flag Auto-translate by default (skip with --no-translate)
_EN.step entity count mismatch Abort rewrite, warn, delete partial file
FreeCAD headless GUI module import Catch ImportError, skip that module, continue

INSTALL.md Summary

build123d (primary — native arm64, no conda):

# 1. Install the arm64 OCP wheel from CadQuery GitHub releases:
#    https://github.com/CadQuery/OCP/releases — pick macosx_*_arm64.whl for your Python
pip install path/to/cadquery_ocp-*.whl

# 2. Install build123d and rendering stack
pip install build123d trimesh pyrender pillow numpy pandas anthropic

# 3. Set API key
export ANTHROPIC_API_KEY=sk-ant-...

FreeCAD (fallback — native arm64 via conda):

# Install Miniforge arm64 if not already present:
# https://github.com/conda-forge/miniforge/releases

conda install -c conda-forge freecad
# Verify headless works:
FreeCADCmd --version

No Rosetta. No x64 sub-environment. Both libraries run natively on Apple Silicon.


Notes for Claude

  • Default run = thumbnails + BOM + auto-translate if Chinese detected
  • When a user asks a geometry question, invoke query_engine — don't describe the STEP file from the BOM alone
  • Always confirm output file locations at end of run
  • If Chinese labels found, proactively note it and offer to show the translation map
  • In REPL mode, keep responses tight — it's a terminal session
  • When describing holes or geometry, lead with the table, not prose
  • If build123d fallback fires, tell the user which library ran

Sub-skill: External Dimensional Diagram

Purpose

Generates a standardized external dimensional diagram for installation planning, product reference, and non-CAD users. NOT a manufacturing drawing. Think: installation reference sheet with clean orthographic views + one ISO.

Terminology

Use: "external dimensional diagram" Never use: shop drawing, manufacturing drawing, fabrication drawing

Entry point

from modules.external_diagram import step_external_diagram

meta = step_external_diagram(
    path="enclosure.step",
    mode="enclosure_only",              # or enclosure_plus_mounting, mounting_only
    mapping_file="MR28UW_mapping.json", # optional
    datablock_file="MR28UW.md",         # optional, auto-detected if omitted
    options={
        "style": "line_drawing",        # or "rendered" — auto if omitted
        "pdf": True,                    # default False
        "mounting_variant": "Wall Mount", # for enclosure_plus_mounting mode
        "render_variants": True,        # generate diagram per mounting variant
    }
)

Modes

  • enclosure_only — enclosure body only (default when no mapping file)
  • enclosure_plus_mounting — enclosure + selected mounting subassembly
  • mounting_only — mounting geometry only

Styles

  • line_drawing — pure SVG wireframe (MR28 reference style). Auto-selected for simple enclosures.
  • rendered — rendered ISO views composited with dimensioned orthographic line views (MR16 reference style). Auto-selected for complex assemblies (>200 faces).

Layout auto-selection

  • single_sheet — default for most models
  • multi_page — auto-selected when any dimension > 1200mm or part count > 60

Outputs per run

File Always? Description
{stem}__external-diagram.svg Yes Source SVG, always retained
{stem}__external-diagram.png Yes PNG export via cairosvg
{stem}__external-diagram.pdf Optional (--pdf flag) PDF via cairosvg
{stem}__meta.json Yes Full metadata per schema
Individual view PNGs Rendered style only front, side, rear, iso
Variant diagrams If render_variants=True One set per mounting variant

Dimensions shown

Required: overall width, height, depth Auto-detected and shown when found:

  • Active area / screen aperture (with diagonal in mm and inches)
  • Mounting hole chain spacing (horizontal or vertical, auto-selected by readability)
  • VESA pattern if detected
  • Edge offsets to mounting geometry Units: metric primary (mm) with imperial in parentheses, smaller italic

Parts mapping file

JSON file per product model — classifies parts as enclosure/mounting/internal/fastener. Drives show/hide logic per mode. Supports mounting variants. Schema: schemas/parts_mapping_schema.json Example: schemas/parts_mapping_schema.jsonexamples array

Datablock / title block

Sourced from a .md file alongside the STEP file (auto-detected by matching stem name) or passed explicitly as datablock_file. Template: templates/datablock_template.md Edit the template to configure: model number, display name, revision, date, company, and any custom fields. Custom fields appear in the data block footer.

Metadata schema

Full JSON schema: schemas/external_diagram_schema.json Designed for AI consumption, Odoo product data integration, search indexing, and CoWork documentation workflows. All geometry in mm.

CLI

# Basic — enclosure only, auto style
python step_processor.py enclosure.step --diagram

# With options
python step_processor.py enclosure.step --diagram --diagram-mode enclosure_plus_mounting \
  --diagram-style line_drawing --diagram-pdf \
  --mapping mapping/MR28UW_mapping.json \
  --datablock MR28UW.md

# Render all mounting variants
python step_processor.py enclosure.step --diagram --diagram-mode enclosure_plus_mounting \
  --diagram-variants

Notes for Claude

  • When a user says "generate a diagram", "make a dimensional sheet", or "create reference drawing" → invoke this sub-skill
  • Always confirm mode with user if unclear (enclosure_only vs with mounting)
  • If no mapping file exists, default to enclosure_only and note it
  • If multiple mounting variants detected in assembly tree, offer to render each
  • The meta.json output is the primary artifact for downstream AI/workflow consumption
  • cairosvg is required for PNG/PDF export: pip install cairosvg
  • Weight/mass fields in meta.json are reserved for future Odoo product data integration