fabricating-assets is a skill from the Summer skill library: a guide your AI agent reads when the task matches, so it builds the good version on the first try. Fabricate meshes with a Blender script (summer_fabricate_3d): exact-size kits, VFX meshes, post-processing.
When your agent uses it
- Writing a Blender Python (bpy) script for summer_fabricate_3d and deciding whether fabrication, generation, or the free library is the right route for an asset
- A parametric hard-surface set with exact dimensions, booleans, bevels, and shared materials that must stay consistent across many pieces
- VFX meshes — shatter fragments, curve sweeps, trails, LOD chains — or decimating, UV-unwrapping, and baking a generated model before it goes into the scene
- A fabrication failed (blender_not_found, script_error, export_empty, import_failed, busy, timeout) and the result needs to be read correctly
Install
summer setup installs every skill for your agent. To add only this one:
claude-code for your agent, such as codex or cursor. See Skills for every option.
The skill
Overview
summer_fabricate_3d runs a Blender Python (bpy) script you write in the user’s own installed Blender, headless and supervised by the engine, validates the .glb the script’s objects were exported to, moves it under res://, waits for the import, and (optionally) instantiates it into the open scene with target_size normalization. One call: script → glb → import → scene.
It exists for a narrow slice of assets: the mesh-processing mid-tier that the engine does not have (exact booleans, bevels, UV unwrap, decimate, remesh, curve sweeps, fracture) and that generation and libraries serve badly. Everywhere else it is the wrong tool — route first.
Three facts shape every use:
- It is optional and detect-never-bundle. Summer does not ship, download, or install Blender. If the machine has none, the result is a structured
blender_not_foundwith the fix, and the decision to install belongs to the user. - It is blind until import. There is no viewport while the script runs. Perception comes back only through the result (
objects,dimensions,warnings,skipped) and then through the normal scene loop (summer_snapshot_diff+summer_screenshot). - One fabrication at a time per editor. A second call while one is in flight fails with
busy. Wait for the result; never fire in parallel.
Route first — fabricate, generate, or import?
Fabricate wins in exactly three rows. If the request is not one of them, stop here and use
asset-strategy to pick the specialist skill.
Prerequisite — the user’s Blender
The engine looks for Blender 4.2 LTS or newer in this order:blender_pathpassed in the call (only when the user named a path — never guess one);- the
SUMMER_BLENDER_BINenvironment variable of the editor process; - Editor Settings → FileSystem → Import → Blender → Blender Path (
filesystem/import/blender/blender_path, the same setting.blendimport uses); PATH, the platform’s well-known install locations, and~/.summer/tools/blender-<version>/.
failure_reason: blender_not_found with tried (every path checked) and a prescriptive error. Relay it as a one-line decision: “Fabrication needs Blender (4.2 LTS or newer) on this machine. Install it from the official Blender download page, or point SUMMER_BLENDER_BIN at an existing executable and restart the editor. Or I can generate the asset or import one from the free library instead.” Then do what the user chooses. Do not install software on their behalf, and do not retry the call hoping the answer changes.
The blender_version in every successful result is a fact, not a suggestion: bpy APIs change across majors, and models skew toward older bpy from training data. When a script_error names a missing attribute or operator, check it against the version that actually ran.
The script contract
source is plain bpy code. It runs in a factory-startup Blender (no user add-ons, no preferences, online access off) with an empty scene — no default cube, light, or camera — and these names already bound: bpy, bmesh, mathutils, math, Vector, Matrix, Euler.
The script must create mesh objects and leave them linked in the scene. Nothing else. The engine’s bootstrap then collects, audits, exports, and validates:
- Do not export, do not save, do not quit.
bpy.ops.export_scene.gltf,bpy.ops.wm.save_mainfile,bpy.ops.wm.quit_blenderin your script break the contract and the run. - What exports:
MESH,CURVE,SURFACE,META,FONTobjects become meshes;EMPTYandARMATUREkeep hierarchy and skins; cameras, lights, probes and speakers are dropped. - Hidden means helper. An object hidden in the viewport or disabled for render is treated as a boolean cutter or guide: it is not exported and is listed in
skipped. Use this deliberately for cutters; checkskippedwhen a piece is missing. - Modifiers are applied at export (
export_apply), including Geometry Nodes — the scene stays non-destructive, so do notmodifier_applyby hand unless you need the result for a later step (a boolean whose output feeds a second boolean, for instance). Consequence: shape keys are dropped when modifiers exist; awarningsays so. - Only a Principled BSDF surface survives glTF. Any other shader (Emission-only, Diffuse, custom node group) exports grey or black — a
warningnames the material. Build materials as Principled BSDF with constant values or Image Texture inputs. - Procedural Base Color is baked for you (Cycles, 2K cap, capped material count; meshes without UVs get a Smart UV Project first) and reported in
baked. Procedural Metallic / Roughness / Normal / Emission / Alpha are NOT baked — set constants, or bake them to an Image Texture in your script; thewarningslist tells you which channel was left procedural. - Axis and units: model in Blender’s native Z-up, in metres; the export converts to the engine’s +Y-up (
dimensionsin the result is already +Y-up). A 2 m wall segment isdimensions.y ≈ 2. - Naming: object names become node names in the imported scene. Name every object and material (
obj.name = "Wall_2m_A"). Thenameargument names the.glb(res://assets/fabricated/<name>.glbunlessout_pathsays otherwise) and the instantiated node; it is sanitized to[A-Za-z0-9_-]. - Determinism: seed anything random (
random.seed(7), noise textures with fixed seeds). A re-run must produce the same mesh so the loop below converges. - No network. Blender’s online access is off; scripts that fetch anything fail. Reference images and existing models come from the project on disk (below).
Minimal template
name: "wall_2m_door", import_to_scene: {parent: "./Kit"}, no target_size (the piece is already modelled at 2 × 0.2 × 3 m — a kit that snaps must keep its authored dimensions).
The loop
summer_get_project_context— confirm the engine is up and which project is bound; readprojectPathif the script needs a file from the project.summer_world_snapshot— the BEFORE baseline; keepsnapshot_id.summer_fabricate_3d—source,name,import_to_scene: {parent, position?}, andtarget_sizeonly when the asset is not dimension-authored (a hero prop whose size you are normalizing, not a kit piece). Defaultmax_seconds120 covers boot + script + bake + export for ordinary pieces; raise it (up to 600) for exact booleans on dense meshes or several bakes.- Read the result before looking at anything else.
okandran;objects[](each withvertices,faces,triangles,materials,modifiers) against what you meant to build;dimensionsin +Y-up metres against the spec;skippedfor pieces that vanished because they were hidden;warningsfor grey-material and unbaked-channel problems;bakedfor what the bootstrap did to your materials;outputfor your ownprint()s. A non-zeroexit_codeafter a validated export is a warning, not a failure — the artifact is what was verified. summer_snapshot_diff from_id:<the id>— the structural receipt: exactly one new subtree underparentnamed<name>, nothing else changed.summer_screenshot— look at it.target:"scene" framing:"camera"when materials or lighting matter; a preset framing for silhouette and scale checks.- Iterate on the script and re-run with the same
name— the.glbis overwritten in place (overwrote_existing: true), and the previously instantiated node is still in the scene: remove it withsummer_remove_nodebefore re-importing to scene, or import withoutimport_to_sceneand let the existing instance pick up the new file. summer_save_sceneonce the piece is right. Instantiation is one undo action in the open scene, not a save — an unsaved instance is lost when the editor closes.
verifying-scenes.
Post-processing a generated model
Generation delivers dense triangulated geometry with poor UVs. Fabrication is the fix:PROJECT_DIR (a string literal built from summer_get_project_context → projectPath); scripts have no res://. Write the result to a new out_path (res://assets/generated/goblin_statue_lod1.glb) so the original stays for comparison, and compare objects[].triangles before and after in the result.
Shatter fragments without add-ons
Factory startup disables add-ons, so cell-fracture operators are not available. Cut withbmesh.ops.bisect_plane in a loop over random planes, bmesh.ops.split_edges / separate by loose parts, and name each fragment Shard_00, Shard_01, … — the imported scene then carries one MeshInstance3D per shard, ready for a RigidBody3D wrap in a summer_run_script pass.
Failure taxonomy — read failure_reason, then act
Every failure leaves the project untouched except
import_failed / instantiate_failed, which are honest about the .glb they did write. A no_rewind_point: true on any result means no SummerGit checkpoint exists for the run — say so before doing more destructive work.
Licensing and attribution
- Blender is the user’s. Summer runs the executable they installed as a separate process and talks to it only through arguments, files, and the exit code. Nothing in Summer links against Blender or imports bpy; the small export bootstrap the engine writes to a scratch directory is a separately licensed GPL file precisely because it does. Do not move project logic into bpy scripts expecting it to stay proprietary.
- Output is unencumbered. Meshes made with Blender belong to the user; the
.glbin their project carries no Blender licence obligation. - Scripts you write here are created on the user’s machine and never distributed by Summer. If you adapt a bpy snippet from elsewhere, respect its licence — prefer your own code or CC0 sources, and record the origin in
.summer/memory/decisions/when it matters for the project. - Trademark. “Blender” is a trademark of the Blender Foundation. Refer to it factually as the dependency (“requires Blender”); never describe the feature as powered by, built on, or branded with Blender, and never use its logo. Summer’s name for this capability is mesh fabrication.
- Imported library assets keep their own licences (
assets.searchresults carrylicense); fabrication does not change that.
Red Flags — STOP
Related skills:
asset-strategy— the route decision for every “I need a [thing]”.environment-kit,prop-model,character-model— the generation and library specialists fabrication defers to.scene-scripting— in-scene geometry, placement loops, and wrapping fabricated pieces in bodies and collisions.verifying-scenesandverification-before-completion— the evidence discipline after import.
From a shell
No Summer MCP tools in this session? Run each one as a command; whensummer --version is missing or below 4.0, use npx -y summer-engine@latest in place of summer. Fields are flags in kebab-case (--scene-path res://main.tscn) or one --input '<json>', and summer ops describe <op> prints the exact input. The summer-cli skill has the rest.
Related skills
asset-strategy: Route any ‘I need a [thing]’ asset request to the right skill: 2D, 3D, audio, video, VFX or animation.environment-kit: Generate a modular environment kit: walls, floor tiles, pillars, doors, arches in one visual style.prop-model: Generate one static 3D prop (sword, barrel, chest, lantern, statue): one object, no rig, a MeshInstance3D.character-model: Generate a rigged humanoid (player, NPC, enemy, boss) from a T-pose reference, previewed before rigging.scene-scripting: Build scenes, levels, HUDs and wiring with one editor GDScript (summer_run_script) instead of call chains.verifying-scenes: Prove scene work landed: snapshot, diff, screenshots, runtime reads, 3D audits, shot sheets and zooms.verification-before-completion: Run verification and read its output before claiming work done, fixed or passing: evidence first.
Source:
library/skills/fabricating-assets/SKILL.md, rendered from summer-engine@4.3.0 on npm.
