Agent-friendly procedural map generation SDK built on Blender's Python API
Project description
blender-cli
Agent-friendly procedural map generation SDK built on Blender's Python API.
blender-cli provides a Python SDK and a CLI for building 3D scenes declaratively through a project.json file — procedural terrain, PBR materials, object placement with snap/raycast, GPU-instanced scatter, cameras, lights, and Bevy/Blenvy ECS component embedding — then exports to GLB.
Installation
Requires Python 3.13+ and uv.
# Install from source
uv pip install .
# Or run directly with uvx (no install needed)
uvx --from . blender-cli
# From a git repo
uvx --from git+https://github.com/julien-blanchon/blender_cli blender-cli
Quick start
CLI
# Create a project
blender-cli project new --name "Alpine" --profile hd1080p -o project.json
# Add materials
blender-cli material add --project project.json grass --pbr-folder ./textures/grass/ --tiling 4 4
# Build terrain
blender-cli terrain init --project project.json --width 512 --height 512 --seed 42
blender-cli terrain op --project project.json noise type=fbm amp=15 freq=0.008 octaves=6
blender-cli terrain op --project project.json smooth radius=3 iters=1
blender-cli terrain material --project project.json grass
# Place objects (snapped to terrain)
blender-cli project add-object --project project.json Wall \
--primitive box --primitive-params '{"size":[10,0.3,3]}' \
--at 50 50 0 --material rock --snap -Z --tags building
# Add camera and light
blender-cli project add-camera --project project.json Main --at 0 -50 30 --lens 35
blender-cli project add-light --project project.json Sun --type SUN --energy 5.0
# Export to GLB
blender-cli project export --project project.json --out scene.glb
# Render a preview
blender-cli render still --glb scene.glb --project project.json --preset iso --out preview.png
Python SDK
from blender_cli import ProjectFile
pf = ProjectFile.new("Alpine", profile="hd1080p")
# Materials
pf.add_material("grass", pbr_folder="./textures/grass/", tiling=[4, 4])
pf.add_material("rock", pbr_folder="./textures/rock/", tiling=[2, 2])
# Terrain
pf.set_terrain(512, 512, seed=42)
pf.terrain_op("noise", type="fbm", amp=12.0, freq=0.008, octaves=6)
pf.terrain_op("smooth", radius=3, iters=1)
pf.terrain_op("erode", type="hydraulic", iterations=40)
pf.set_terrain_material("grass")
# Anchors (named spatial references)
pf.add_anchor("village", [256, 256, 0], annotation="center")
# Objects (snapped to terrain at export)
pf.add_object("Cottage", asset_path="./assets/cottage.glb",
location=pf.anchor_pos("village"), tags=["building"], snap=True)
# Camera, light
pf.add_camera("Main", location=[0, -50, 30], look_at=[256, 256, 0], lens=35)
pf.add_light("Sun", "SUN", energy=5.0, rotation=[0.5, 0.0, 0.0])
# Export
pf.save("project.json")
pf.export_glb("scene.glb")
Architecture
project.json ──[export_glb]──► scene.glb
▲ │
│ │
└────────[import_glb]──────────┘
Everything goes through project.json as the single source of truth. Edit it via the Python SDK (ProjectFile) or the CLI (blender-cli), then export to GLB. You can also import an existing GLB back into a project file.
Features
Terrain
Procedural heightfield terrain built from a chain of operations:
| Operation | Effect |
|---|---|
flat |
Start flat at elevation z |
noise |
Add fbm/ridged noise |
smooth |
Gaussian blur |
terrace |
Plateau effect |
clamp |
Clamp height range |
stamp |
Local circular/ring edit |
erode |
Hydraulic/thermal erosion |
radial_falloff |
Island/crater falloff |
remap_curve |
Height remapping curve |
Materials
PBR texture folders (auto-detects diffuse, normal, roughness, AO, displacement) or flat colors with metallic/roughness control.
Objects & Primitives
Primitives: box, plane, cylinder, sphere, cone, torus. Also supports prefab GLB assets and empties.
Snap system — raycast objects onto geometry at export time:
| Axis | Use case | Policy | Effect |
|---|---|---|---|
-Z |
Floor/terrain | FIRST |
Sit on first surface hit |
+Z |
Ceiling mount | ORIENT |
Align to surface normal |
+X |
Wall mount | HIGHEST |
Highest hit Z |
Filter snapping with target_tags and exclude_tags.
Anchors
Named spatial reference points. Place objects, cameras, and lights relative to anchors instead of hardcoded coordinates:
pf.add_anchor("gate", [100, 100, 0])
pf.add_object("Tower", location=pf.anchor_pos("gate", [5, 0, 0]), snap=True)
Instances
GPU-instanced scatter groups for vegetation, rocks, and props with per-point rotation and scale.
Cameras
Static cameras or animated paths (orbit, dolly, flyover). Ghost cameras are excluded from GLB export and used only for debug renders.
Lights
SUN, POINT, SPOT, AREA light types. Ghost lights for debug previews.
Bevy / Blenvy Integration
Embed Bevy ECS components directly in the GLB. The SDK validates component names against a Bevy registry.json:
blender-cli blenvy set-registry --project project.json assets/registry.json
blender-cli blenvy add-component --project project.json Ground RigidBody Static
blender-cli blenvy validate --registry assets/registry.json --project project.json
Render & Debug
Render stills from named cameras or presets (top, iso). Supports:
- Tag-based show/hide (
--hide-tag ceilingfor dollhouse views) - Wireframe mode
- Highlight + ghost mode
- Decomposition render (flat colors per object/tag)
- Multi-pass (beauty, depth, normal)
Session
Undo/redo with named snapshots.
REPL
Interactive prompt for exploring scenes:
blender-cli repl --project project.json
Render profiles
| Profile | Engine | Resolution | Samples | Use case |
|---|---|---|---|---|
default |
EEVEE | 1920x1080 | 64 | General development |
preview |
EEVEE | 960x540 | 16 | Quick iteration |
hd1080p |
CYCLES | 1920x1080 | 128 | High quality |
4k |
CYCLES | 3840x2160 | 256 | Ultra quality |
product_render |
CYCLES | 2048x2048 | 512 | Transparent bg |
animation_preview |
EEVEE | 1280x720 | 16 | Animation testing |
CLI reference
blender-cli [--project FILE] [--json] COMMAND
| Command | Description |
|---|---|
project |
Create, info, export, import projects |
terrain |
Init, add ops, set mesh/material |
material |
Add/list PBR or flat-color materials |
anchor |
Add/list/remove spatial anchors |
object |
Add/remove/manage objects |
instance |
Add/list/remove GPU-instanced groups |
camera |
Add cameras and animated paths |
render |
Render stills, focus shots, decomposition |
world |
Set background color or HDRI |
blenvy |
Bevy component validation and embedding |
session |
Undo/redo/history |
select |
Query objects with DSL |
inspect |
Inspect GLB scene contents |
stats |
Scene statistics |
repl |
Interactive REPL |
align |
Image-to-3D alignment pipeline |
animation |
Keyframe animation |
modifier |
Geometry modifiers |
op |
Low-level Blender operations |
run |
Execute build scripts |
measure |
Measure distances and dimensions |
raycast |
Raycast queries |
candidates |
Placement candidate generation |
assets |
Asset management |
manifest |
Scene manifest operations |
Pass --json for machine-readable JSON output on all commands.
Development
# Install dev dependencies
uv sync --group dev
# Run tests
uv run pytest
# Type check
uv run pyright
License
MIT
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file blender_cli-0.1.1.tar.gz.
File metadata
- Download URL: blender_cli-0.1.1.tar.gz
- Upload date:
- Size: 201.4 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
17868708cfb2ab769e86282ceec6338fdac7aadd308287b6351017be6b8ff9f0
|
|
| MD5 |
6fda7e77d1478ddb397d203e53f4fbf9
|
|
| BLAKE2b-256 |
be2fa1e85698827b7f81c9059eefa2eba97a3e99ad1b4a2384f3e83dc176ed2f
|
Provenance
The following attestation bundles were made for blender_cli-0.1.1.tar.gz:
Publisher:
publish.yml on julien-blanchon/blender_cli
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
blender_cli-0.1.1.tar.gz -
Subject digest:
17868708cfb2ab769e86282ceec6338fdac7aadd308287b6351017be6b8ff9f0 - Sigstore transparency entry: 1149203384
- Sigstore integration time:
-
Permalink:
julien-blanchon/blender_cli@4e2f68d50c3841a3282197c8dbd81de96dba1801 -
Branch / Tag:
refs/tags/v0.1.1 - Owner: https://github.com/julien-blanchon
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@4e2f68d50c3841a3282197c8dbd81de96dba1801 -
Trigger Event:
release
-
Statement type:
File details
Details for the file blender_cli-0.1.1-py3-none-any.whl.
File metadata
- Download URL: blender_cli-0.1.1-py3-none-any.whl
- Upload date:
- Size: 250.1 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
2bf5a35d8023dc0d235b430b32692315c23f6329932a9c33db4a83cf7945d287
|
|
| MD5 |
0f9f093896b436d8d30a784c59cfcc66
|
|
| BLAKE2b-256 |
214d3c6844ac82758cd6e9e84bf05430b4fed7f3849c28b9754a587f269aeb80
|
Provenance
The following attestation bundles were made for blender_cli-0.1.1-py3-none-any.whl:
Publisher:
publish.yml on julien-blanchon/blender_cli
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
blender_cli-0.1.1-py3-none-any.whl -
Subject digest:
2bf5a35d8023dc0d235b430b32692315c23f6329932a9c33db4a83cf7945d287 - Sigstore transparency entry: 1149203652
- Sigstore integration time:
-
Permalink:
julien-blanchon/blender_cli@4e2f68d50c3841a3282197c8dbd81de96dba1801 -
Branch / Tag:
refs/tags/v0.1.1 - Owner: https://github.com/julien-blanchon
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@4e2f68d50c3841a3282197c8dbd81de96dba1801 -
Trigger Event:
release
-
Statement type: