Every render here is code that runs.
These aren't mockups. Each example runs headless on Blender 5.2 LTS and 4.5 LTS in the smoke workflow, asserts its own correctness, and exits non-zero if the API drifted. Each still was rendered by that same script.
Browse all 52 rendered examples and 72 showcase pieces in the gallery →
Open the gallery — code, README, and full-size renders →Budget-conformance props, not API contracts.
Showcase pieces compose shipped skills into a recognizable asset and assert declared budgets — triangle counts, materials, UVs, LODs, colliders, exports. They are not examples. A still that merely rendered is not an assertion.
Workflows the AI loads by name.
Each skill is the canonical pattern for one job — operators, panels, bmesh, geometry nodes, slotted actions — plus the mistakes AI assistants actually make there. Where 4.5 LTS and 5.x diverge, both code paths are shown.
When to use (4)
- Wants to start a new Blender add-on
- Mentions
bl_info,blender_manifest.toml, "extension", "register_classes_factory" - Is migrating an existing add-on from the legacy
bl_infoformat to the Extensions Platform - Is unsure which file layout or registration pattern to use for Blender 4.5+ or 5.x
When to use (4)
- Has a generated or scanned GLB/glTF/FBX that is not engine-ready
- Mentions unit scale, unapplied transforms, triangle budget, LOD, or a collision hull
- Wants a headless cleanup pass (import in, cleaned mesh out)
- Is about to run mesh operators on an import without checking scale
When to use (4)
- Wants a tangent-space normal map from a dense source onto a game-resolution mesh
- Mentions cage bake,
use_selected_to_active,cage_extrusion, orbpy.ops.object.bake - Has an LOD from
DECIMATE COLLAPSE(or a retopo) and needs the missing surface detail in a map - Is about to call bake from EEVEE, on GPU in CI, or with
bake_type=
When to use (5)
- Has an existing add-on with a
bl_info = {...}dictionary at the top of__init__.py - Wants to publish to extensions.blender.org or distribute as a
.zipfor the Extensions Platform - Asks "is bl_info dead?" or "do I have to migrate?"
- Sees a deprecation warning at install time about legacy add-ons
- Mentions
blender_manifest.toml, "Install legacy Add-on", or "the new extension system"
When to use (4)
- Wants to attach data to objects, scenes, or other Blender datablocks that survives save and load
- Mentions
bpy.props,PropertyGroup,PointerProperty, "custom properties" - Is unsure where to store add-on settings
- Sees a deprecation warning about property assignment
obj.data. Covers evaluated_get, to_mesh, to_mesh_clear, and the lifetime rules that prevent crashes and memory leaks. Targets Blender 5.2 LTS.
When to use (5)
- Is writing an exporter, measurement script, or inspection tool
- Reports that "modifiers are missing from my export" or "the vertex positions don't match what I see"
- Mentions
evaluated_depsgraph_get,evaluated_get,to_mesh,to_mesh_clear - Reads from
obj.data.verticesand gets unexpectedly raw geometry - Needs final positions after armature deformation, shape keys, modifiers, or geometry nodes
When to use (5)
- Wants property A to follow property B with some math (driver)
- Asks about
driver_add,FCurve.driver,driver.expression,driver_namespace - Wants to run code on file save, file load, frame change, depsgraph update, or process exit
- Mentions
bpy.app.handlers,save_pre,load_post,depsgraph_update_post,exit_pre - Has a driver expression that fails security checks because it tries to call a Python function
When to use (4)
- Needs a Unity, Godot, or Unreal export from Blender Python
- Mentions Y-up, Z-up, centimeter scale,
export_yup,axis_forward, oraxis_up - Is about to pass FBX axis kwargs to
bpy.ops.export_scene.gltf - Wants a headless preset the later
ai-asset-pipeline-templatecan call
When to use (4)
- Wants to build a Geometry Nodes tree from a script rather than the editor
- Mentions
GeometryNodeTree,node_groups.new,tree.interface,tree.links.new - Needs to apply a generated GN tree as a modifier on an object
- Asks about Bundles, Repeat Zones, or for-each Element zones from Python
When to use (4)
- Wants to render, export, or process .blend files from a CLI or CI pipeline
- Mentions
blender --background,--python, "headless", "batch render", "no UI" - Has an operator script that fails with
RuntimeError: Operator bpy.ops.X.Y.poll() failed, context is incorrect - Needs to pass arguments to a Blender Python script
When to use (5)
- Wants to create, modify, or read mesh geometry from Python
- Mentions
bmesh,mesh.vertices,foreach_set,from_pydata,evaluated_get - Has a script that's slow and uses
bpy.ops.mesh.*in a loop - Needs the mesh after modifiers (subdivision surface, mirror, geometry nodes) have been applied
- Asks why their bmesh script crashes on the second run
When to use (4)
- Wants to create a new
bpy.types.Operator - Mentions
bl_idname,bl_label,bl_options, "redo panel", "F6 panel", "operator props" - Needs an action triggered from a button, menu, keymap, or chat command
- Asks why their operator's properties don't show up in the redo panel
When to use (5)
- Wants to create or edit materials from Python rather than the shader editor
- Mentions
bpy.data.materials,node_tree,ShaderNodeBsdfPrincipled,inputs[...].default_value - Needs to generate many materials parametrically (asset libraries, batch import, color variations)
- Asks about EEVEE Next vs Cycles material differences
- Asks about "Layered Textures" or "the new shader system" (see version-correctness section)
When to use (4)
- Wants to create or edit animation from Python in Blender 5.x
- Mentions
Action,slot,channelbag,keyframe_insert,fcurves - Has older 4.x animation code (
action.fcurves.new(...)) that no longer works in 5.x - Asks how to insert keyframes programmatically and have them persist
When to use (4)
- Wants a sidebar tab in the 3D viewport, properties editor, or any other space
- Mentions
bpy.types.Panel,bl_space_type,bl_region_type, "N panel", "sidebar" - Needs to expose properties or operators in a custom UI
- Asks why a property is showing without a label or in the wrong column
When to use (5)
- Builds or inspects a VSE / sequencer timeline from a script
- Mentions
sequence_editor,strips,sequences,new_effect, COLOR strips, orStripTransform - Hits
AttributeError: 'SequenceEditor' object has no attribute 'sequences'on 5.x - Hits
TypeErroronnew_effectkwargs (frame_endvslength) - Renders a sequencer composite whose COLOR cells ignore
transform.scale_*after a resolution change
No skill matches that filter.
Anti-patterns, caught before they ship.
Guardrails that load whenever a matching file is open, for the failure modes that make Blender Python look right and run wrong: ops in loops, leaked bmesh, deprecated context dicts, per-vertex Python loops.
| Rule | Scope | Flags |
|---|---|---|
| always-free-bmesh | **/*.py | Flag bmesh.new() calls without a paired bm.free() in a try/finally block. BMesh allocates C-side memory that Python's garbage collector cannot reclaim; missing free() leaks and eventually crashes Blender. |
| no-unapplied-modifiers-on-export | **/*.py | Flag an export call on objects that still carry unapplied modifiers when the export arguments do not request evaluated geometry. The engine then receives the authored cage, not the modifier result. |
| prefer-data-over-ops-in-loops | **/*.py | Flag bpy.ops.* calls inside iteration over many objects, meshes, or frames. Each bpy.ops call triggers a full depsgraph evaluation and UI redraw; loops slow down by orders of magnitude. Use bpy.data.* and bmesh instead. |
| prefer-temp-override-over-context-copy | **/*.py | Flag uses of bpy.context.copy() to override context for an operator call. The copy-and-pass pattern was deprecated in Blender 4.x and the override semantics were removed in 5.x. Use bpy.context.temp_override(**overrides) as a context manager instead. |
| target-extensions-platform-format | **/__init__.py, **/blender_manifest.toml | Flag new Blender add-ons that ship only a legacy bl_info dict without a blender_manifest.toml. New add-ons must use the Extensions Platform format. bl_info may appear alongside as a fallback for backward compatibility, but the manifest is the source of truth. |
| type-annotate-props-and-defend-context | **/*.py | Flag two related anti-patterns. (1) bpy.props defined as class-level assignments instead of type annotations (deprecated since 2.8). (2) Code that touches bpy.context.active_object without guarding for None. |
| use-correct-axis-rna-per-exporter | **/*.py | Flag export_scene.gltf calls that pass FBX axis_forward or axis_up, and export_scene.fbx calls that pass glTF export_yup. The two exporters do not share axis RNA. |
| use-foreach-set-for-bulk-data | **/*.py | Flag Python loops that set vertex coordinates, normals, UVs, or other bulk per-element data one element at a time. For meshes of more than a few thousand elements, this is 100x to 1000x slower than mesh.vertices.foreach_set("co", flat_array), which writes through to C-level storage in one pass. |
| validate-imported-mesh-scale | **/*.py | Flag a glTF or FBX import followed by mesh operations with no transform_apply and no unit-scale check. Generated files often arrive with non-identity object scale or a non-meter scene scale; mesh edits then bake the wrong size. |
No rule matches that filter.
Canonical patterns, five to fifty lines.
Standalone, paste-ready answers to the questions that come up every session: the right way to create and delete objects, read bulk vertex data, bind properties, bridge the 4.x/5.x API boundary.
Plus 3 starter templates: ai-asset-pipeline-template, extension-addon-template, and headless-batch-script-template.
Clone it. Point your AI at it.
- Clone the repo:
git clone https://github.com/TMHSDigital/Blender-Developer-Tools - Cursor: copy
rules/into your project's.cursor/rules/— they auto-apply via scope globs; reference skills by name in chat - Claude Code: copy
skills/andrules/into your project workspace, or point Claude Code at the checkout - Grab
snippets/andtemplates/as starting points for add-ons and headless batch jobs