blender-scripting
SKILL.md
Blender Scripting
Overview
Automate Blender tasks using Python and the bpy API. Run scripts headlessly from the terminal to manipulate scenes, batch process files, import/export models, and build 3D pipelines without opening the GUI.
Instructions
1. Run a Blender script from the terminal
# Run a script in background mode (no GUI)
blender --background --python script.py
# Run with a specific .blend file
blender myfile.blend --background --python script.py
# Pass custom arguments (use -- to separate Blender args from script args)
blender --background --python script.py -- --output /tmp/result.png --scale 2.0
Parse custom arguments in the script:
import sys
argv = sys.argv
# Everything after "--" is a custom argument
if "--" in argv:
custom_args = argv[argv.index("--") + 1:]
else:
custom_args = []
2. Understand the bpy module structure
import bpy
# bpy.data — all data in the file (meshes, materials, objects, scenes)
bpy.data.objects["Cube"]
bpy.data.meshes["Cube"]
bpy.data.materials["Material"]
# bpy.context — current state (active object, selected objects, scene)
bpy.context.active_object
bpy.context.selected_objects
bpy.context.scene
# bpy.ops — operators (actions like add, delete, transform)
bpy.ops.mesh.primitive_cube_add(size=2, location=(0, 0, 0))
bpy.ops.object.delete()
3. Scene setup and cleanup
import bpy
def clear_scene():
"""Remove all objects from the scene."""
bpy.ops.object.select_all(action='SELECT')
bpy.ops.object.delete(use_global=False)
# Also clear orphan data
for block in bpy.data.meshes:
if block.users == 0:
bpy.data.meshes.remove(block)
for block in bpy.data.materials:
if block.users == 0:
bpy.data.materials.remove(block)
def setup_scene():
"""Set up a clean scene with basic settings."""
clear_scene()
scene = bpy.context.scene
scene.unit_settings.system = 'METRIC'
scene.unit_settings.scale_length = 1.0
4. Create and transform objects
import bpy
from mathutils import Vector, Euler
import math
# Add primitives
bpy.ops.mesh.primitive_cube_add(size=2, location=(0, 0, 0))
cube = bpy.context.active_object
cube.name = "MyCube"
# Transform
cube.location = (3, 0, 1)
cube.rotation_euler = (0, 0, math.radians(45))
cube.scale = (1, 2, 0.5)
# Duplicate
bpy.ops.object.duplicate(linked=False)
duplicate = bpy.context.active_object
duplicate.location.x += 5
# Parent objects
child = bpy.data.objects["ChildObj"]
parent = bpy.data.objects["ParentObj"]
child.parent = parent
5. Import and export 3D files
import bpy
# Import
bpy.ops.wm.obj_import(filepath="/path/to/model.obj")
bpy.ops.import_scene.fbx(filepath="/path/to/model.fbx")
bpy.ops.import_scene.gltf(filepath="/path/to/model.glb")
bpy.ops.wm.stl_import(filepath="/path/to/model.stl")
# Export
bpy.ops.wm.obj_export(filepath="/path/to/output.obj")
bpy.ops.export_scene.fbx(filepath="/path/to/output.fbx", use_selection=True)
bpy.ops.export_scene.gltf(filepath="/path/to/output.glb", export_format='GLB')
bpy.ops.wm.stl_export(filepath="/path/to/output.stl")
6. Batch process .blend files
import bpy
import glob
import os
blend_files = glob.glob("/path/to/projects/*.blend")
for filepath in blend_files:
bpy.ops.wm.open_mainfile(filepath=filepath)
# Do work on each file
for obj in bpy.data.objects:
if obj.type == 'MESH':
print(f" Mesh: {obj.name}, verts: {len(obj.data.vertices)}")
# Save modified file
output = filepath.replace(".blend", "_processed.blend")
bpy.ops.wm.save_as_mainfile(filepath=output)
print(f"Saved: {output}")
7. Work with custom properties
import bpy
obj = bpy.context.active_object
# Set custom properties
obj["my_property"] = 42
obj["tags"] = "hero,main"
# Read custom properties
value = obj.get("my_property", 0)
# Iterate all custom properties
for key, value in obj.items():
if key not in {"_RNA_UI"}:
print(f"{key}: {value}")
Examples
Example 1: Export all objects as separate OBJ files
User request: "Export every mesh object in my .blend file as a separate OBJ"
import bpy
import os
output_dir = "/tmp/exports"
os.makedirs(output_dir, exist_ok=True)
bpy.ops.object.select_all(action='DESELECT')
for obj in bpy.data.objects:
if obj.type == 'MESH':
bpy.ops.object.select_all(action='DESELECT')
obj.select_set(True)
bpy.context.view_layer.objects.active = obj
filepath = os.path.join(output_dir, f"{obj.name}.obj")
bpy.ops.wm.obj_export(filepath=filepath, export_selected_objects=True)
print(f"Exported: {filepath}")
Run: blender scene.blend --background --python export_all.py
Example 2: Batch rename objects by type
User request: "Rename all mesh objects to mesh_001, mesh_002, etc. and all lights to light_001, etc."
import bpy
counters = {}
for obj in sorted(bpy.data.objects, key=lambda o: o.name):
prefix = obj.type.lower()
counters[prefix] = counters.get(prefix, 0) + 1
obj.name = f"{prefix}_{counters[prefix]:03d}"
print(f"Renamed to: {obj.name}")
bpy.ops.wm.save_mainfile()
Example 3: Scene statistics report
User request: "Give me a summary of what's in this .blend file"
import bpy
print("=== Scene Report ===")
print(f"Objects: {len(bpy.data.objects)}")
print(f"Meshes: {len(bpy.data.meshes)}")
print(f"Materials: {len(bpy.data.materials)}")
print(f"Textures: {len(bpy.data.images)}")
print(f"Scenes: {len(bpy.data.scenes)}")
print(f"Collections: {len(bpy.data.collections)}")
total_verts = sum(len(m.vertices) for m in bpy.data.meshes)
total_faces = sum(len(m.polygons) for m in bpy.data.meshes)
print(f"Total vertices: {total_verts:,}")
print(f"Total faces: {total_faces:,}")
for obj in bpy.data.objects:
info = f" {obj.name} ({obj.type})"
if obj.type == 'MESH':
info += f" — {len(obj.data.vertices)} verts"
print(info)
Guidelines
- Always use
--backgroundwhen running scripts from the terminal to avoid opening the GUI. - Start scripts with
clear_scene()if building a scene from scratch to avoid leftover default objects. - Use
bpy.datafor direct data access (fast, reliable). Usebpy.opsfor complex operations that mirror user actions (operators require correct context). - When using operators, ensure the correct object is active and selected:
bpy.context.view_layer.objects.active = objandobj.select_set(True). - For batch processing, always save to a new file (not overwrite originals) unless the user explicitly requests in-place modification.
- Import/export operator names vary between Blender versions. The ones listed here work for Blender 3.6+. For older versions, check
dir(bpy.ops.import_scene). - Use
mathutilsfor vector math, quaternions, and matrix operations — it's bundled with Blender's Python. - To debug, use
print()statements — output goes to the terminal when running with--background.
Weekly Installs
1
Repository
terminalskills/skillsGitHub Stars
15
First Seen
7 days ago
Security Audits
Installed on
amp1
cline1
opencode1
cursor1
kimi-cli1
codex1