Cited in 3DCodeBench: Benchmarking Agentic Procedural 3D Modeling Via Code (Google DeepMind, USC, 2026), §1.
Quickstart
/plugin marketplace add elithril/blender-kiln
/plugin install blender-kiln@blender-kiln
/kiln setup
/kiln A hanging iron lantern for a medieval inn, stylized, for the web
/kiln setup detects Blender, the MCP server and the optional tools, and says what
is missing. Blender 4.4+ with a Blender MCP running — see Requirements.
Give it a photo and it rebuilds the object: /kiln Rebuild the lamp in ./lamp.png as a game asset.
How it works, from a photo
- Read the photo before modeling. An inventory of every part and how it meets the next, from enlarged crops; the real size, the camera's height and angle — asked, or stated as assumptions. Given a 3D mesh generated from the same photo, its proportions are measured instead (TRELLIS.2, locally) — never shipped.
- Texture from scans, not noise. A Poly Haven CC0 texture set of the material family, chosen by eye against the photo, tinted to its palette, worn by the form.
- Measure against the photo.
plugin/tools/fidelity_check.pyrenders the model at the photo's camera under a studio light and lists the gaps — silhouette per height band, materials, metal that cannot exist. - Look at every joint. Each end of a long part that touches another is rendered alone: a part that joins another enters it.
- Ship, and measure the file that ships. Optimized (Draco, WebP), validated, re-measured
as a GLB — what the user gets, not the
.blend.
Measured, not claimed
A quality bench runs the skill headless, each session in a sandbox, and measures every GLB it ships after re-importing it. Photo references are Poly Haven previews, so the real 3D asset exists: each rebuild is scored against it from five sides — an asset the session never sees. Blender 5.2.2, Opus 5.5, one run each:
Shape score: silhouette overlap with the real asset from front, back, sides and top, 1 = identical;
openwork views left out for the chair. The text briefs were measured on the skill mid-way through
2.0 (2b313d2), the photo rebuilds on the final one. Size is assumed when a brief gives none —
the chair came out at an ordinary chair's height, 29 % short.
Close, not identical, on purpose. kiln stops at a few dollars per object. img2threejs, which rebuilds an image as Three.js code through eight vision-reviewed passes, keeps finer surface detail: on the same lantern its likeness was comparable — 0.866 against kiln's 0.861 — at about three times the cost, estimated on a run stopped after three of its eight passes. Several of its techniques were measured and adopted in kiln: traced wires, layered texture fields, a frosted-glass recipe (benchmarks § 4).
What did not improve is published too: the benchmarks — fifteen
versions of one lantern, what each fix broke, how the bench was kept honest — and every
number, render and GLB under 1 MB on the bench-results branch — kept
out of main so that installing the plugin does not download them.
What it does
Kiln is a Claude Code skill that turns you into a 3D asset production studio. By default Claude models in Blender by script (via MCP) — no AI model, nothing to install; optional AI generation (TRELLIS.2 first, FLUX.1-schnell concept art) and marketplace search (PolyHaven, Sketchfab) fit into a single coherent pipeline.
[1] CONFIG → [2] BRIEF → [3] SOURCE → [4] IMPORT → [5] CLEANUP → [5b] TEXTURING → [6] OPTIMIZE → [7] EXPORT
Pipeline phases
Key features
- Rebuild from a photo, measured: an inventory from enlarged crops, the size and camera settled first, the silhouette and materials measured against the photo, every joint rendered and looked at, the last measure on the shipped GLB (how)
- Textures from CC0 scans: Poly Haven texture sets chosen against the photo, tinted to its palette, worn by the form, baked to UVs — procedural only when no scan fits
- A 3D template when one exists: proportions read off a mesh generated from the same photo (TRELLIS.2, run locally) with
plugin/tools/template_profile.py— measured, never shipped - Both Blender MCP servers: ahujasid's
mcp-for-blenderand the Blender Foundation's official Lab MCP, the one behind Claude's Blender connector - Multi-method creation: scripted modeling (Blender Python, the default), geometry nodes, marketplace sourcing, or optional AI generation (TRELLIS.2 / TRELLIS / TripoSR Spaces, MIT; Hunyuan3D on request only)
- Local AI generation, never required: TRELLIS.2 on Apple Silicon (measured) or Hunyuan3D-2 Mini, for offline work
- Environment auto-detection:
/kiln setupscans your system and guides installation - Reference images: provide an image per asset (path, URL, or drag-and-drop) — guides all creation methods (AI input, scripted proportions, texture assignment), enriches the brief, and enables post-export visual comparison
- Concept art input: text prompt (FLUX.1-schnell HF Space, free), image path, image URL, or nano-banana (optional)
- Smart recommendations: auto-suggests the best creation method based on asset type and style
- Material audit: detects procedural nodes that will be lost on GLTF export, proposes bake workflow
- Optimized by default:
_final.glbships with Draco geometry and WebP textures, re-measured after compression; the uncompressed_original.glbis kept - Post-export validation: 8-point checklist (Babylon.js sandbox, Three.js console, material spot-check)
- Character support: T-pose enforcement, an animation-ready skeleton (joints at the bends, checked on a bent pose), bone validation, Blender 5.x bone collections
- Animation, routed by subject (see above): scripted idle/walk cycles for quadrupeds, UniMate text-to-motion for bipeds and winged creatures — pinned version, weekly drift check, seamless loops — and keyed articulated props
- Multi-asset sessions: cross-asset coherence (scale, materials, poly budget)
- Batch mode: wizard collects scene/theme/palette/reference images upfront, generates a YAML manifest, runner executes autonomously — ideal for overnight production or large asset sets
- Full logging: every asset produces a production log with copy-paste prompts
Running over Blender MCP
The skill drives a live Blender through the Blender MCP
addon. Below is SM_Barrel built, cleaned and exported inside a running Blender
session — object named to convention, sitting on Z=0, ready to export:
The MCP pass and the headless scripted pass agree to the byte — 111.9 kB GLB
either way, same 2,202 triangles, same three materials.
Check the integrations before you search
All four integrations ship off, as shown here. That matters more than it looks: while an integration is off, the addon does not register its commands at all, so a search does not come back "disabled" — it comes back
Unknown command type: search_polyhaven_assets
which reads like a version mismatch and sends you hunting for the wrong problem.
get_polyhaven_status, get_sketchfab_status, get_hunyuan3d_status and
get_hyper3d_status are registered unconditionally and return the fix step by
step — including the Sketchfab API key, which nothing else surfaces. Iron rule
23 requires checking them first. Tick the boxes in the BlenderMCP panel of the
3D Viewport sidebar (press N if hidden), then reconnect.
Gallery
Fifteen props across three themes, modelled from scratch by script, cleaned, audited, rendered and exported — all headless, on one laptop, with no cloud service and no paid API.
What this gallery is, and is not. These assets were produced by the scripts in
examples/gallery/, written to the skill's rules — see Which rules the scripts obey for the audit.They were not produced by running the skill. The skill drives Blender over MCP and its core loop is interactive:
get_scene_info()before each phase (rule 1),get_viewport_screenshot()after each modification (rule 2), and a prompt before anything destructive (rule 6). None of that is exercised here — this isblender --background --python, the scripted-modeling path only. Treat the gallery as reference output and a conventions check, not as end-to-end validation of the skill.
The measured optimization sizes, the rule-by-rule audit of the gallery scripts and how to reproduce them are in docs/gallery.md.
Animate
Phase 5d picks the route from the subject, because no single method held up across
all of them (references/animation.md has every
measurement):
UniMate was measured unusable for quadruped walking — on a cat, a Shiba, a horse
and the model author's own robot dog, with the solver ruled out — so a quadruped never
goes to it: unimate.py recognises the posture and points at quadruped.py.
What this showcase is, and is not. Each UniMate tile is the sample, out of 4, that
motion_loop.pykept for looping best, then approved by a reviewer — samples vary, and some prompts tried (wave, dance, run) were left out. UniMate's checkpoints are CC BY-NC 4.0: non-commercial use only. The scripted tiles are deterministic. As with the gallery, these come from scripts (examples/animation/showcase.sh, assets and credits alongside), not from an interactive session of the skill.
Commands
Requirements
Required
-
Blender 4.4 or newer, with the Blender MCP addon running (port 9876). Install the addon with
uvx blender-mcp install-addon.4.4 is a hard floor, not a preference. Layered actions arrived in 4.4, and the animation code here reaches F-curves through
action.layers[].strips[].channelbag(); on 4.0–4.3 that path does not exist. Everything in this repository is measured on 5.0 locally and 5.2 LTS in CI — 4.4 to 4.5 satisfy the API but are untested, so treat them as unverified rather than supported.
AI generation — optional, and honest about its limits
Most assets never need it: scripted modeling, geometry nodes and marketplaces cover props, and the bench ships all of its non-AI briefs without any generation service. When a brief does need AI generation, the user picks it, nothing needs installing, and kiln proposes the paths in this order (Space stages read on 2026-10-09; texture state from 2026-09-29):
- The free cloud path is one or two generations a day. Hugging Face's ZeroGPU
quota is 2 minutes without an account, 3.5 with a free one; a generation asks
60–120 s.
gradio_clientuses your saved Hugging Face token silently — kiln says whose account pays before the first call, and never touches the token. - Hunyuan3D's licence does not apply in the EU, the UK or South Korea (its
LICENSE, line 3), so kiln never proposes it first, and asks before any Hunyuan3D call. - Concept art comes from the FLUX.1-schnell Space (Apache-2.0, 5.6 s an image). Pollinations, the former default, now answers HTTP 402 after one image.
Optional
- nano-banana MCP — alternative concept art generation via Gemini (requires API key with billing)
- gltf-transform —
npm install -g @gltf-transform/cli— texture compression, Draco, and the Khronos validator every export runs. Strongly recommended - gltfpack —
npm install -g gltfpack(mesh simplification, LOD generation) - Sketchfab API token — free account, for marketplace downloads
Reality Converter / usdzconvert— not needed: Blender exports USDZ natively
Installation
As a Claude Code plugin (recommended)
/plugin marketplace add elithril/blender-kiln
/plugin install blender-kiln@blender-kiln
Then run /kiln setup to detect your environment and install what's missing.
As a standalone skill
git clone https://github.com/elithril/blender-kiln.git ~/.claude/skills/blender-kiln
Restart Claude Code, then run /kiln setup. The skill itself lives in plugin/; the
repository root links SKILL.md, references and tools to it, so a clone works as a
skill directory as it is. On Windows, enable symlinks in git (core.symlinks) or install
as a plugin.
Layout
A plugin install ships only plugin/ — about 0.7 MB:
plugin/
├── .claude-plugin/plugin.json
├── SKILL.md
├── LICENSE
├── tools/ # fidelity_check, template_profile, quadruped, motion_loop, bind_rigid_parts, unimate (+ patch), checks
└── references/
├── ai-generation.md
├── animation.md
├── batch-mode.md
├── setup-install.md
├── characters.md
├── cli-tools.md
├── export-targets.md
├── naming-conventions.md
├── sourcing-strategy.md
├── texturing-strategy.md
├── reference-fidelity.md
├── topology-rules.md
├── uv-materials.md
└── validation-checklist.md
Skill structure
Total: ~4,800 lines of production-tested 3D pipeline knowledge.
Continuous checks
plugin/tools/verify_docs.py runs on every push (.github/workflows/verify.yml) and
checks that this documentation is still true — text only, no Blender, a few
seconds:
- iron rules form one unbroken 1..N sequence across
plugin/SKILL.mdandbatch-mode.md - every cited
rule Nexists and means what the citation claims - the rule count above matches reality, and every line count in the structure table is within 15% of the file it describes
- every referenced file exists, and none point outside the plugin directory
- every README image resolves
- no bare
pip install(it fails on any PEP 668 Python) - the plugin manifest is valid and its
sourceis a real directory - documented commands use the invocable
/kiln <sub>form
plugin/tools/test_verify_docs.py seeds each of those regressions and asserts the
checker catches it — 24/24 (20 seeded regressions, 4 that must stay silent). Every case is a mistake that was actually made
here, including two renumberings that left a reference pointing at the wrong rule.
plugin/tools/verify_blender.py (.github/workflows/blender.yml, weekly and on demand)
re-checks what needed Blender to establish — the documented bpy API still exists,
the Principled sockets the docs name are real, Rigify's deform-bone counts still
match the tiers PHASE 5c routes on, geometry nodes still need the modifier applied
before export, USDZ still exports natively into a conforming archive, and rule 10's weld —
the code in validation-checklist.md, run as written — still keeps a faceted mesh's shading
and closes the tear a split-edge mesh opens at its first pose; on synthetic rigs built in the check,
the quadruped walk stays bent and in step, a bone-parented part follows its bone once folded,
and a clip cut mid-swing loops back to its exact period. It also fails on any
Blender DeprecationWarning reached by the docs or the gallery — its first run
surfaced Material.use_nodes, slated for removal in 6.0. Each check guards a
shipped bug; this notices when a Blender release makes one wrong again.
plugin/tools/unimate.py drift (.github/workflows/unimate-drift.yml, weekly) clones
UniMate's upstream HEAD and checks kiln's patch still applies to it — the text-to-motion
model of phase 5d is a research project that changed its pipeline, checkpoints and licence
within days of kiln first measuring it.
plugin/tools/test_fidelity_check.py runs in the same workflow and seeds what the review tool
claims to measure — a model against its own render (IoU 0.998), the same model 20 % wider
(measured +20.3 %), an unloaded texture (refused), a .blend (warned), the triangle range
(kept under twice its top, a reduction proposed past it), dark metal (reported; the same
colour as non-metal, silent), metal in hard scattered islands (reported; one soft region,
silent), metal painted mostly as non-metal (reported), grain measured but never listed as a gap,
joint close-ups (a rod resting on a sphere rendered; sunk or free,
not), and --view and --azimuth on a 2 x 1 x 1 box — 27/27. Its first run caught the tool framing views by
height only: anything wider than tall was clipped, a box measured 1:1 instead of 2:1.
plugin/tools/test_template_profile.py reads a seeded turned part back through
template_profile.py — radii, a free rod, a rod pressed against the body — 4/4.
Iron rules
The skill enforces 31 rules (26 core + 5 batch-specific). Key ones, by their real
number — the full text is in plugin/SKILL.md and plugin/references/batch-mode.md:
- Rule 1 — always
get_scene_info()before each phase - Rule 2 — always
get_viewport_screenshot()at the end of every phase that changed geometry or materials, two angles after texturing - Rule 4 — never hard-cap poly count: alert if out of range, never block
- Rule 5 — never spend money: a free service that answers HTTP 402 has stopped being free, so switch source; never remove a watermark
- Rule 6 — never silently destroy: decimate, simplify, delete are always proposed
- Rule 7 — always keep the
.blendfile - Rule 18 — never
export_apply=Truefor glTF: modifiers balloon file size - Rule 19 — always run the material export audit before a glTF export
- Rule 20 — never
gltf-transform optimize: use individual steps - Rule 22 — frame the viewport before screenshotting it, or the shot shows an apparently empty scene
- Rule 23 — always check integration status before searching a marketplace: a
disabled integration answers
Unknown command type, not "disabled" - Rule 25 — rename every import to the naming convention, whatever its source
- Rule 26 — never pick a rig without measuring vertices ÷ deform bones: a Rigify human needs ~3,200 vertices to be worth it
- Rule 30 — between batch assets, clear the scene by removing datablocks, never
with
read_homefile()
Output
Two storage modes, configurable at pipeline start:
Compact (default) — minimal footprint, .blend is the recovery point:
generated-assets/
└── wooden-chair/
├── wooden-chair_original.glb
├── wooden-chair_final.glb
├── wooden-chair.blend
└── wooden-chair_log.md
Full — all intermediate files for debug/comparison:
generated-assets/
└── wooden-chair/
├── wooden-chair_original.glb
├── wooden-chair_clean.glb
├── wooden-chair_textured.glb
├── wooden-chair_optimized.glb
├── wooden-chair_final.glb
├── wooden-chair.blend
└── wooden-chair_log.md
Batch mode — assets grouped under a batch folder with manifest and report:
generated-assets/
└── batch-corporate-office-2026-04-02/
├── batch-manifest.yaml
├── batch-report.md
├── desk/
├── chair/
└── keyboard/
At the end of a multi-asset session, Kiln proposes a cleanup of intermediate files with per-asset size breakdown.
Contributing
Fixes are welcome — see CONTRIBUTING.md. One rule shapes it: claims must be measured, not reasoned. Fifteen bugs in this repository's own documentation were found by running it, and none of them were visible in the text.
License
MIT © Nicolas Dolphens