# Cadquery Render

> Render five preview images (isometric, rear isometric, top, right, front) of a CadQuery part or assembly using `cadquery.vis.show`. Use after every meaningful geometry change inside the `cadquery-assembly` workflow — after the high-level layout, after each part finishes its functional / detailing / DFM pass, after every interference fix — to visually confirm the geometry is correct before moving on.

- Skill: `leoai-org/cadquery-render` (Agent Skill)
- Install (CLI): `npx skillmds@latest add leoai-org/cadquery-render`
- Raw SKILL.md: https://api.skillmd.com/api/skills/leoai-org/cadquery-render/raw
- Safety review: pending
- Works with: Claude Code, Claude.ai, OpenAI Codex
- Category: Productivity
- Author: leoai-org (https://skillmd.com/u/leoai-org)
- Updated: 2026-09-22
- Page: https://skillmd.com/skills/leoai-org/cadquery-render

---


# CadQuery render — five-view preview

## Purpose

Visual **gate** after every geometry change. The orchestrator must **read the PNGs** (Read tool) and decide pass / iterate — never assume success from exit code alone.

## Renderer

Use `cadquery.vis.show` directly — it does its own tessellation, off-screen rendering, and PNG writing. No external snippets are needed.

```python
from cadquery.vis import show
show(result, interact=False, screenshot="preview_isometric.png", gradient=False)
```

## Python environment

Use the interpreter that has CadQuery installed with `cadquery.vis` available (VTK-backed):

```
PY=/Users/dimiasael/miniforge3/envs/dev_arm64_311/bin/python
```

If `cadquery.vis` import fails on the chosen interpreter, switch to the env above before re-running.

## Camera angles for the five views

`show()` applies `Roll → Elevation → Azimuth` after `ResetCamera()` (default camera: position +Z, looking at origin, viewup +Y — i.e. the top view). The five canonical views map to:

| View | roll | elevation | azimuth |
|------|-----:|----------:|--------:|
| `preview_isometric.png`      | -35  | -45   |   0 |
| `preview_isometric_rear.png` | -35  | -45   | 180 |
| `preview_top.png`            |   0  |   0   |   0 |
| `preview_front.png`          |   0  | -89.9 |   0 |
| `preview_right.png`          |   0  | -89.9 |  90 |

(Elevation is kept at -89.9 instead of -90 to avoid VTK's gimbal-lock guard. Front = camera at -Y; right = camera at +X; both with viewup +Z.)

## Standard render command

Run from the **project directory** that contains the target `.py` file (so PNGs land next to it):

```bash
cd <project_dir> && $PY -c "
import runpy
from cadquery.vis import show

ns = runpy.run_path('<target.py>')
result = ns['result']

views = [
    ('preview_isometric.png',      -35, -45.0,   0),
    ('preview_isometric_rear.png', -35, -45.0, 180),
    ('preview_top.png',              0,   0.0,   0),
    ('preview_front.png',            0, -89.9,   0),
    ('preview_right.png',            0, -89.9,  90),
]
for fname, roll, elev, az in views:
    show(result, interact=False, screenshot=fname,
         roll=roll, elevation=elev, azimuth=az, gradient=False)
"
```

### Expected outputs (next to target file's directory)

- `preview_isometric.png`
- `preview_isometric_rear.png`
- `preview_top.png`
- `preview_right.png`
- `preview_front.png`

Verify each file exists and size > 1 KB.

## Pre-render smoke test

Before rendering, confirm the script executes and produces `result`:

```bash
cd <project_dir> && $PY -c "import runpy; ns=runpy.run_path('<target.py>'); assert ns.get('result') is not None"
```

If this fails, fix the CadQuery script — rendering will not help.

## What to look for

| Symptom | Likely cause | Next skill |
|---------|--------------|------------|
| Part missing | Boolean tool had history; `result` inside branch | `cadquery-part` |
| Part at global origin in assembly view | `.translate()` on empty WP; wrong `loc=` | functional part / high-level |
| Sharp edges where fillets expected | Selector dropped fillet | `cadquery-part-detailing` |
| Overlapping solids | Clash | `cadquery-interference-check` |
| Appliance too short/tall vs spec | Envelope wrong in `common.py` | `cadquery-high-level-design` |
| Empty / white PNG | Exec failed or null shape | fix script |

## Assembly-specific checks

When rendering `assembly.py` or `high_level_assembly.py`:

- Count major envelopes in iso view vs decomposition table
- Compare overall bbox to `HOUSING_*` (or equivalent) in `common.py`:

```bash
python -c "
import runpy, cadquery as cq
ns = runpy.run_path('assembly.py')
# walk assembly for bbox ...
"
```

## Report format (to orchestrator)

```text
RENDER — <file>
Status: PASS | ITERATE
Findings: <1-3 bullets>
Next: <skill or file to edit>
```

## Hand-off

This skill **never edits geometry**. Orchestrator routes failures to the correct pass.

