本文へ移動
cccskills
無料GitHub で公開

cadquery-modeling

Create, edit, or debug parametric 3D CAD parts in CadQuery (Python) that export to STEP for SolidWorks. Use when the request involves CadQuery, .step/.stl export, or modelling a physical part — enclosure, bracket, PCB, motor mount, cam, gear. Also use when a STEP will not open in CAD, or geometry looks correct in STL but is invalid as a solid. Applies a verification discipline before export and documented OCC pitfalls.

インストール方法を見る

含まれるファイル(10)

  • SKILL.md14.0 KB
  • references/diagnosis.md7.5 KB
  • references/environment.md3.3 KB
  • references/occ_pitfalls.md13.7 KB
  • references/part_file_structure.md4.1 KB
  • references/solidworks_checks.md3.1 KB
  • references/verification.md4.1 KB
  • scripts/diagnose.py25.9 KB
  • scripts/preflight.py7.1 KB
  • scripts/verify_step.py3.0 KB

SKILL.md(原文)

インストールする前に、エージェントに与えられる指示の中身を確認できます。

CadQuery Modeling for Manufacturable CAD

This skill turns natural-language part requests into clean, verified, parametric CadQuery code whose STEP output reliably opens in SolidWorks. It encodes hard-won rules from real multi-part product design.

Core philosophy

  1. Parametric first — every dimension is a named variable at the top of the file.
  2. Verify before trusting — a script that printed [OK] is NOT proof of success. Always check geometry validity and solid count before declaring done.
  3. Avoid OCC fragility — prefer simple primitives + boolean operations over fragile chained features. See references/occ_pitfalls.md.
  4. One part, one file — each part is its own .py producing its own STEP/STL. Assemblies are done in SolidWorks, not baked into a single STEP.

Before creating anything: confirm where

Files land in whatever directory Claude Code was started in — that is the single thing that determines whether the user finds their STEP later. Before creating a project or the first part, state the absolute path you are about to write to, and stop to confirm if it looks wrong:

  • a cloud-synced path (OneDrive, Dropbox, iCloud — note that on Windows the Desktop and Documents folders usually ARE OneDrive)
  • Downloads, a home directory root, or a system folder
  • the claude-cad toolkit repo itself
  • a path containing spaces, parentheses, or non-ASCII characters

If any of those apply, say so and suggest a clean location such as C:\cad_project before writing files. Getting this wrong is silent: everything succeeds, and the user simply can't find the output.

The standard workflow

When the user asks for a part, follow this loop:

  1. Match the questions to how specified the request is. Never invent a critical dimension — ask instead. Default to millimeters.
    • Underspecified (e.g. "a bracket to hold a 60 mm pipe"): don't guess, and don't refuse. Ask one focused batch of questions covering only what you truly can't proceed without — typically overall size, thickness/wall, the coordinate system/orientation, and any dimension that must match another part or a real component. Keep it short; propose sensible defaults the user can accept ("I'll assume 4 mm thick unless you say otherwise").
    • Fully specified: don't interrogate. Build it, and list any assumption you had to make in the final report.
    • If the user asks you to write a spec first, produce it as text (coordinate system, overall dimensions, every feature with size + position, interfaces) and get approval before writing code.
  2. Write the part file following the structure in references/part_file_structure.md.
  3. Run it and read the full terminal output, not just the last line.
  4. Verify geometry validity, solid count, volume, and bounding box (see below).
  5. Report the verification numbers to the user and note any assumptions made.

Read references/occ_pitfalls.md before writing any code that uses shell, fillet after shell, countersinks, or lofts — the operations with a history of silent corruption. Each pitfall now carries a Verified behaviour block saying what the current kernel actually does; the one reliably reproduced silent failure is shelling a solid whose removed face was filleted (Pitfall 4b).

Project layout

Always use this structure so STEP files collect in one place for SolidWorks:

project/
├── parts/        # one .py per part
│   ├── housing.py
│   └── pcb.py
├── output/       # STEP + STL land here (git-ignored)
└── docs/
    └── assembly_guide.md

Resolve the output path relative to the script file, not the working directory. A bare "../output/..." breaks the moment the script is run from the project root instead of from parts/ — the export silently lands one folder too high. Always use this pattern:

from pathlib import Path
OUT = Path(__file__).resolve().parent.parent / "output"
OUT.mkdir(parents=True, exist_ok=True)

cq.exporters.export(part, str(OUT / "housing.step"))
cq.exporters.export(part, str(OUT / "housing.stl"))
print(f"[OK] exported to {OUT}")

This works whether the user runs py -3.11 parts/housing.py from the project root or py -3.11 housing.py from inside parts/. Printing the resolved path also makes it obvious where the files went.

Mandatory verification block

Every part file MUST verify before export — either with this inline block, or (preferred) with the check() helper from scripts/diagnose.py shown after it. One of the two is required; a bare [OK] print is never sufficient. STL is forgiving and hides geometry errors that survive into the STEP — and CAD import is no safety net either: SolidWorks has opened a provably invalid STEP without warning (references/occ_pitfalls.md, "Do not count on CAD import to reject bad geometry").

# ===== Verification (do not skip) =====
from OCP.BRepCheck import BRepCheck_Analyzer

solid = part.val()
shape = solid.wrapped

# 1. Geometry validity — catches silent OCC corruption
analyzer = BRepCheck_Analyzer(shape)
is_valid = analyzer.IsValid()
print(f"[verify] IsValid = {is_valid}")
if not is_valid:
    raise RuntimeError("Invalid geometry — part is unusable; CAD may still open it without warning.")

# 2. Single-body check — catches stray cut/union debris
n_solids = len(solid.Solids())
print(f"[verify] solid count = {n_solids}")
if n_solids != 1:
    raise RuntimeError(f"Expected 1 solid, found {n_solids}.")

# 3. Volume — ASSERT it against a range DERIVED FROM YOUR PARAMETERS, not the
#    built result. Validity and solid count both pass on a part whose hollow/cut
#    silently did nothing (bbox too); volume is the tell. Compute expected_lo/hi from
#    the dimensions above (e.g. solid block minus the intended cavity, +/-15%).
#    NEVER run the build first and paste Volume()'s output back here.
vol = solid.Volume()
print(f"[verify] volume   = {vol:.2f} mm^3")
assert expected_lo <= vol <= expected_hi, (
    f"Volume {vol:.1f} outside derived range — a hollow/cut may have done nothing.")
print(f"[verify] bbox     = {solid.BoundingBox()}")

# Signature — always end with this line. Its presence in the output is how the
# user can tell the skill's checks actually ran (vs a part written with none).
print("[verify] claude-cad — checks applied")

Prefer the diagnostic helper

The block above is the minimum. For real work, use scripts/diagnose.py, which does the same checks but also classifies what's wrong and safely auto-repairs the unambiguous cases (e.g. discarding tiny offcut debris from a multibody result):

Setup (once per project): copy scripts/diagnose.py from this skill into the project's parts/ folder, next to the part files. Python puts a script's own directory on the import path, so from diagnose import check then resolves when running py -3.11 parts/<name>.py. Without this copy the import fails with ModuleNotFoundError: No module named 'diagnose'. (project_init also keeps a canonical copy in claude-cad/ alongside preflight.py; the parts/ copy is the one imports resolve against — keep them in sync, and preflight.py warns if they drift.)

Prefer export_verified() — it runs the checks and raises before it writes, so a failing part is not written by this function. This is a rule you follow, not a mechanism that prevents export: cq.exporters.export is a plain function, so a script that skips this helper bypasses every check. Prefer it so the safe path is the easy one.

from pathlib import Path
from diagnose import export_verified        # diagnose.py must be in parts/

OUT = Path(__file__).resolve().parent.parent / "output"

# expect_volume is DERIVED from the parameters above — e.g. solid block minus the
# intended cavity, +/-15%. A range is the honest form; NEVER paste Volume()'s output.
export_verified(part, OUT, "bottom_housing",
    expect_volume=(28000, 38500),           # derived band (preferred over a scalar)
    expect_bbox=(94, 65, 27.2),             # from the stated dimensions
    inside=[(0, 0, 1)],                     # design intent: floor is solid here
    outside=[(47, -12, 10)],                # design intent: this port is void here
    regression_volume=32163.55,             # optional: labelled re-run baseline
)

This verifies, exports STEP + STL, and writes bottom_housing.verified.txt beside them — a durable record of what was checked, since terminal output vanishes when the window closes. Use the lower-level check() / assert_points() directly only for intermediate steps mid-build.

The independent checks are expect_bbox and the assert_points — lead with those. The bounding box is read straight off the stated dimensions, and the inside/outside points encode design intent (which wall a port is on) — they catch a feature that is missing, misplaced, or on the wrong face, which validity cannot see (they caught a microSD port cut into the wrong wall in the sbc-case example).

expect_volume is the weakest check — DERIVE it, don't measure it. Validity, solid-count, and bbox all PASS on a part whose .shell() silently did nothing (the outer box is unchanged), so among those numbers volume is the tell for that failure (references/occ_pitfalls.md, Pitfall 4b) — an interior spot-check catches it too. But volume only helps if it is computed from the parameters before building, as a range (a silent no-op reads several times too high; ±15% catches it). If you omit it, the report prints "VOLUME UNCHECKED" instead of a clean PASS. Keep the exact measured figure only as a separate, labelled regression_volume.

Use assert_points for anything with a position that matters — ports, holes, bosses, openings on specific walls. Geometry can be valid, single-bodied, and the right volume while a feature sits on the wrong face; no topological check sees that. Sample the middle of each opening (expect outside) and the wall beside it (expect inside).

When a part fails, don't guess — follow the symptom→diagnosis→fix decision tree in references/diagnosis.md. Auto-repair only touches safe, unambiguous cases; invalid topology is reported (not patched) so a real design error is never hidden.

Verification, in SolidWorks

After import, the user should confirm in SolidWorks:

  • Mass Properties — center of mass on expected symmetry axes (X/Y ≈ 0 for a symmetric part) is the fastest correctness check.
  • Principal moments of inertia — the relative sizes confirm which axis is long/short, catching swapped dimensions.
  • The part opens as a solid body, not a surface.

See references/solidworks_checks.md for the exact menu paths and what each number tells you.

Reference files

Load these as needed:

FileWhen to read
references/occ_pitfalls.mdBefore any shell, fillet, countersink, or loft. This is the most important reference.
references/diagnosis.mdWhen a part fails verification — the symptom→diagnosis→fix decision tree, and how to auto-repair.
references/part_file_structure.mdWhen writing a new part file from scratch.
references/verification.mdWhen a STEP won't open, or geometry looks wrong.
references/solidworks_checks.mdWhen validating a part inside SolidWorks.
references/environment.mdWhen cadquery or OCP import fails, or on first setup.

Scripts

ScriptPurpose
scripts/diagnose.pyThe intelligence layer. Diagnoses a part (classifies validity / multibody / degenerate issues) and safely auto-repairs what it can. Use from diagnose import check inside a build, or run it on a .step from the CLI.
scripts/preflight.pyProject-level: runs and verifies every parts/*.py, then writes a committable VERIFICATION.md summary at the project root. Copy it into the project's claude-cad/ folder and run py -3.11 claude-cad/preflight.py.
scripts/verify_step.pyLightweight standalone check of any STEP/STL: validity, solid count, volume, bbox.

Hard rules (never violate)

  • Never invent a critical/interface dimension. Ask instead.
  • Never declare success on [OK] alone — only after the verification block passes.
  • Never use cskHole on a shelled (thin-wall) face — build a cutter solid instead. (Portability rule: the historical failure does not reproduce on the current kernel — see Pitfall 1's Verified behaviour — but the cutter pattern is explicit, uniform across hole types, and version-proof, at zero cost.)
  • Never bake a multi-part assembly into a single STEP unless the user explicitly wants a static snapshot; do assemblies in SolidWorks.
  • Always default to millimeters and state the unit.
  • Always print the absolute output directory after exporting, so the user never has to guess where the file went.
  • Never treat IsValid + single-solid as sufficient. Always check volume against a range derived from the named parameters (solid block minus intended cavity, or bbox volume × a stated fill fraction) — it is the only check that catches a hollow or cut that silently did nothing.
  • Never derive expect_volume by running the build and pasting Volume()'s output back as the expectation — that checks the geometry against itself. Compute it from the dimensions, in a comment above it, as a range. Keep any measured figure only as a separate, labelled regression_volume.
  • For any feature whose position matters, verify it with point classification (assert_points), not just topology — this is the strongest intent check, not an afterthought.

レビュー

まだレビューはありません。使ってみた感想をお寄せください。

このスキルの問題を報告する