# Clean Rhino

> One-shot "clean up the whole Rhino file" pipeline — runs the dedup + geometry-cleanup sibling skills, then purges unused block definitions / empty groups / empty layers, then assigns a white matte plaster material (named after the layer) to every layer that has no material. Non-destructive diagnose first at every stage, confirms scope, then applies. Trigger when the user wants to clean / tidy / purge / finalize the entire Rhino document (not just the current selection), assign missing materials, or prep a file for hand-off. Fire on Korean or English requests, e.g. "라이노 정리", "파일 전체 정리", "clean rhino", "clean up the whole file", "퍼지", "purge", "안 쓰는 레이어/블록 정리", "재질 없는 레이어 흰색으로", "assign white plaster to layers without material". For selection-only curve work use the sibling skills `clean-similar-curves` / `clean-geometry` directly.

- Skill: `hongikarchi/clean-rhino` (Agent Skill, multi-file: 3 files)
- Install (CLI): `npx skillmds@latest add hongikarchi/clean-rhino`
- Raw SKILL.md: https://api.skillmd.com/api/skills/hongikarchi/clean-rhino/raw
- Safety review: pending
- Works with: Claude Code, Claude.ai, OpenAI Codex
- Category: DevOps & Infra
- Author: hongikarchi (https://skillmd.com/u/hongikarchi)
- Updated: 2026-09-22
- Page: https://skillmd.com/skills/hongikarchi/clean-rhino

---


# clean-rhino

Whole-document cleanup orchestrator (task 3). Chains the two validated **selection** skills over
the whole model, then does document-level housekeeping (purge + material). Two new scripts live
next to this file: `cleanrhino_purge.py` and `cleanrhino_material.py` — both **non-destructive by
default** (report), destructive only when you set `APPLY=True`.

## Stages
1. **clean-similar** — remove duplicates/overlaps. Curves: `clean-similar-curves`. Non-curves
   (polysurface/brep/mesh/block): `clean-similar-objects` diagnose (report-only v1).
2. **clean-geometry** — CAD-clean curves: `clean-geometry`. Polysurfaces: `clean-geometry-solids`
   diagnose (open-vs-closed + extrusion, report-only v1).
3. **purge** — unused block definitions, empty groups, empty layers (`cleanrhino_purge.py`) +
   `_-Purge` for linetypes/hatch/dimstyles/materials.
4. **material** — white matte PBR "plaster" named after the layer, onto every material-less layer
   (`cleanrhino_material.py`).

## Procedure (do in order)

0. **Model safety — ask first.** clean-rhino is irreversible (purge can't be undone, dedup deletes,
   material writes). Use AskUserQuestion: **work on a SaveAs copy** (recommended — `-SaveAs` a new
   `.3dm` via `run_command`, then operate there) **vs the current doc** (must `SaveSmall` first).
1. **Select everything** to feed the selection skills the whole model: `run_command("_SelAll")`
   (or select by the layers/objects the user means). The sibling skills act on the current selection.
2. **clean-similar.** Glob + run `clean-similar-curves` (its `dedup_dryrun.py` → confirm →
   `dedup_delete.py`, per that skill's own procedure). Then, if present, Glob + run
   `**/clean-similar-objects/simobj_diagnose.py` and report non-curve duplicates (v1 = report only;
   no deletes without explicit per-item confirmation).
3. **clean-geometry.** Run `clean-geometry` (its diagnose → set SHORT_LEN → confirm → apply order,
   per that skill). Then, if present, run `**/clean-geometry-solids/cleangeosol_diagnose.py` and
   report open/burst polysurfaces + extrusion candidates (v1 = report only).
4. **purge.**
   ```python
   exec(open(r"<ABS>\cleanrhino_purge.py").read())                    # dry-run: counts
   ```
   Report counts, confirm, then:
   ```python
   PURGE_APPLY=True; exec(open(r"<ABS>\cleanrhino_purge.py").read())  # purge
   ```
   Then the remaining categories via command (verify tokens against the live echo first):
   `run_command("_-Purge")` toggling BlockDefinitions/DimStyles/Groups/HatchPatterns/Layers/
   Linetypes/Materials. **Purging all 7 is broader than the spec's layer/block/group — mention it
   and let the user opt out of the extra categories.**
5. **material.** Do this AFTER purge (so unused materials are gone and empty layers won't get one):
   ```python
   exec(open(r"<ABS>\cleanrhino_material.py").read())                  # dry-run: material-less layers
   MAT_APPLY=True; exec(open(r"<ABS>\cleanrhino_material.py").read())  # assign white plaster
   ```
6. **Report** per stage (deduped / cleaned / purged / materials assigned). Offer to save. Offer to
   update the `rhino-clean-geometry-method` / `rhino-curve-dedup-method` memories if anything new
   was learned.

## Why this order
- **selection skills before document housekeeping** — dedup/clean can empty layers and orphan
  block defs, which purge then sweeps.
- **purge before material** — purge clears empty layers (so material-assign only touches real,
  surviving layers) and removes unused materials before new ones are added. Do not reorder.

## Gotchas (baked in — do not "fix" out)
- **Both new scripts are dry-run unless `APPLY=True`.** Always run the dry-run, report, confirm, then
  APPLY. Same diagnose→confirm→apply discipline as the sibling skills.
- **`InstanceDefinitions.Purge(i)` self-checks** — it only deletes a block def that is truly unused
  (returns False otherwise), so it is safe to loop over all indices.
- **Layer delete order** — `cleanrhino_purge.py` deletes deepest-nested empty layers first so a
  parent isn't blocked by a child that was just emptied.
- **Material naming** — the material is named after the layer's short `Name`. White plaster =
  PBR BaseColor white / Metallic 0 / Roughness 1; legacy white-diffuse fallback if PBR is
  unavailable. PBR BaseColor is what maps cleanly to D5 albedo downstream.
- **`_-Purge` is not undoable** and neither are table deletes — SaveSmall or work on a copy (step 0).
- **`run_command` command tokens vary by build/locale** — prefer `_English` tokens and confirm the
  `_-Purge` option echo before committing a macro string.

## Not yet implemented / pending
- **Non-curve stages (2/3 of step 2–3) are report-only** and depend on the sibling skills
  `clean-similar-objects` / `clean-geometry-solids` (build separately). If they're absent, note it
  and continue with the curve + purge + material stages.
- **LIVE VERIFICATION PENDING.** `cleanrhino_purge.py` / `cleanrhino_material.py` are written from
  the RhinoCommon API but were authored while the Rhino MCP server was offline. Before trusting them,
  run the in-doc synthetic test (a material-less layer, an unused block def, an empty group) and
  assert the counts + that each material-less layer receives a white-plaster material named after it.

## Reference
Built 2026-07-01 (task 3 of the 6-task cleanup/export suite). Orchestrates `clean-similar-curves`
+ `clean-geometry` (validated) and the report-only non-curve siblings, plus purge + material.
See the plan and memories `rhino-clean-geometry-method` / `rhino-curve-dedup-method`.

