.claude/skills/ts-blender-scripting/SKILL.md
Write and run Blender Python scripts for 3D automation. Use when the user wants to automate Blender tasks, run headless scripts, manipulate scenes, batch process .blend files, import/export 3D models, manage objects, or script Blender from the command line using the bpy API.
npx skillsauth add eliferjunior/Claude blender-scriptingInstall this skill globally with one command. Works with Claude Code, Cursor, and Windsurf.
3 of 9 scanners reported clean
Some scanners were skipped, did not run, or reported a non-clean status. Review each row below.
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.
# 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 = []
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()
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
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
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")
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}")
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}")
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
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()
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)
--background when running scripts from the terminal to avoid opening the GUI.clear_scene() if building a scene from scratch to avoid leftover default objects.bpy.data for direct data access (fast, reliable). Use bpy.ops for complex operations that mirror user actions (operators require correct context).bpy.context.view_layer.objects.active = obj and obj.select_set(True).dir(bpy.ops.import_scene).mathutils for vector math, quaternions, and matrix operations — it's bundled with Blender's Python.print() statements — output goes to the terminal when running with --background.development
Expert guidance for Fireworks AI, the platform for running open-source LLMs (Llama, Mixtral, Qwen, etc.) with enterprise-grade speed and reliability. Helps developers integrate Fireworks' inference API, fine-tune models, and deploy custom model endpoints with function calling and structured output support.
development
Convert any website into clean, structured data with Firecrawl — API-first web scraping service. Use when someone asks to "turn a website into markdown", "scrape website for LLM", "Firecrawl", "extract website content as clean text", "crawl and convert to structured data", or "scrape website for RAG". Covers single-page scraping, full-site crawling, structured extraction, and LLM-ready output.
tools
Expert guidance for Firebase, Google's platform for building and scaling web and mobile applications. Helps developers set up authentication, Firestore/Realtime Database, Cloud Functions, hosting, storage, and analytics using Firebase's SDK and CLI.
development
When the user needs to build file upload functionality for a web application. Use when the user mentions "file upload," "image upload," "upload endpoint," "multipart upload," "presigned URL," "S3 upload," "file validation," "upload to cloud storage," or "accept user files." Handles upload endpoints, file validation (type, size, magic bytes), cloud storage integration, and upload status tracking. For image/video processing after upload, see media-transcoder.