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
- Parametric first — every dimension is a named variable at the top of the file.
- Verify before trusting — a script that printed
[OK]is NOT proof of success. Always check geometry validity and solid count before declaring done. - Avoid OCC fragility — prefer simple primitives + boolean operations over
fragile chained features. See
references/occ_pitfalls.md. - One part, one file — each part is its own
.pyproducing 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-cadtoolkit 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:
- 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.
- Write the part file following the structure in
references/part_file_structure.md. - Run it and read the full terminal output, not just the last line.
- Verify geometry validity, solid count, volume, and bounding box (see below).
- 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:
| File | When to read |
|---|---|
references/occ_pitfalls.md | Before any shell, fillet, countersink, or loft. This is the most important reference. |
references/diagnosis.md | When a part fails verification — the symptom→diagnosis→fix decision tree, and how to auto-repair. |
references/part_file_structure.md | When writing a new part file from scratch. |
references/verification.md | When a STEP won't open, or geometry looks wrong. |
references/solidworks_checks.md | When validating a part inside SolidWorks. |
references/environment.md | When cadquery or OCP import fails, or on first setup. |
Scripts
| Script | Purpose |
|---|---|
scripts/diagnose.py | The 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.py | Project-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.py | Lightweight 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
cskHoleon 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_volumeby running the build and pastingVolume()'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, labelledregression_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.
レビュー
まだレビューはありません。使ってみた感想をお寄せください。