원클릭으로
bl-info-migration
Migrate a legacy bl_info-format add-on to the Extensions Platform. Three concrete steps, before-and-after diff, dual-format pattern for backward compatibility, and answers to "is bl_info still supported?" Targets Blender 5.1.
메뉴
Migrate a legacy bl_info-format add-on to the Extensions Platform. Three concrete steps, before-and-after diff, dual-format pattern for backward compatibility, and answers to "is bl_info still supported?" Targets Blender 5.1.
Scaffold a Blender add-on against the Extensions Platform format with blender_manifest.toml, modular file layout, and the register_classes_factory pattern. Targets Blender 5.1 with 4.5 LTS fallback.
Define and bind Blender custom properties via bpy.props using the type annotation form, with PropertyGroup for grouping, PointerProperty for binding, and the four storage location options for Scene/Object/WindowManager/AddonPreferences. Targets 5.1.
Read the actual evaluated geometry the user sees by going through the dependency graph rather than reading raw `obj.data`. Covers `evaluated_get`, `to_mesh`, `to_mesh_clear`, and the lifetime rules that prevent crashes and memory leaks. Targets Blender 5.1.
Drive properties from expressions or other properties via the Driver API, and react to scene events via the bpy.app.handlers callbacks. Covers driver_namespace for Python functions, the new exit_pre handler in 5.1, and the must-be-fast contract for any handler.
Programmatically construct Geometry Nodes trees in Blender 5.x via bpy.data.node_groups, interface socket creation, node instantiation by RNA name, link wiring, and applying as a NODES modifier. Includes Bundles for grouped sockets.
Run Blender headless via blender --background --python script.py for batch jobs. What changes without a UI, how to avoid UI-dependent operators, the temp_override pattern when ops must be used, and argparse after the -- separator.
| name | bl-info-migration |
| description | Migrate a legacy bl_info-format add-on to the Extensions Platform. Three concrete steps, before-and-after diff, dual-format pattern for backward compatibility, and answers to "is bl_info still supported?" Targets Blender 5.1. |
| standards-version | 1.9.4 |
Use this skill when the user:
bl_info = {...} dictionary at the top of __init__.py.zip for the Extensions Platformblender_manifest.toml, "Install legacy Add-on", or "the new extension system"Yes, with caveats.
bl_info is supported as a fallback for legacy add-ons. The Edit > Preferences > Add-ons panel still has "Install legacy Add-on" and recognizes bl_info dicts.blender_manifest.toml. bl_info is ignored.blender_manifest.toml and keep the bl_info dict. The platform reads the manifest; legacy installers read bl_info. Both code paths work without conditional logic.The Blender Foundation's stated direction is that the Extensions Platform is the future and bl_info-only add-ons will degrade in discoverability over time, but they are not announcing a removal date.
A migration from a bl_info-only add-on to the Extensions Platform takes three small mechanical changes.
blender_manifest.tomlCreate a new file blender_manifest.toml next to __init__.py. Translate the bl_info fields:
bl_info key | Manifest key | Notes |
|---|---|---|
"name" | name = "..." | Same string |
"version": (1, 2, 3) | version = "1.2.3" | Tuple becomes a string |
"blender": (4, 5, 0) | blender_version_min = "4.5.0" | Renamed; semantics same |
"author" | maintainer = "Author <email>" | Email recommended |
"description" | tagline = "..." | Renamed |
"category" | tags = ["..."] | Now a list of allowed tags |
"location", "warning" | (no equivalent) | Drop |
| (none) | id = "..." | New required field; reverse-DNS or short slug |
| (none) | schema_version = "1.0.0" | Required |
| (none) | type = "add-on" | Required |
| (none) | license = ["SPDX:..."] | Required SPDX expression |
Minimal manifest:
schema_version = "1.0.0"
id = "my_addon"
version = "1.2.3"
name = "My Addon"
tagline = "What it does in one sentence"
maintainer = "Author Name <author@example.com>"
type = "add-on"
blender_version_min = "4.5.0"
license = [
"SPDX:GPL-3.0-or-later",
]
tags = ["3D View", "Mesh"]
The full schema and allowed tag list live in the Blender extensions documentation.
bl_info (or keep both)If you only want to support 5.x and the Extensions Platform: delete the bl_info = {...} block from __init__.py.
If you want to keep working with the 4.x "Install legacy Add-on" path while also publishing to the platform: leave bl_info in place. This is the dual-format pattern. The two metadata sources do not need to agree perfectly; the platform reads only the manifest, the legacy installer reads only bl_info.
__package__Legacy add-ons commonly use absolute imports:
from my_addon import operators
from my_addon.ui import panels
These break under the Extensions Platform because the package name is no longer my_addon at runtime; it's a generated synthetic name like bl_ext.user_default.my_addon. Two fixes that work everywhere:
Relative imports:
from . import operators
from .ui import panels
__package__ lookup (when you need the full package name as a string):
import importlib
operators = importlib.import_module(f"{__package__}.operators")
Both forms are stable across the legacy and Extensions Platform load paths.
__init__.py)bl_info = {
"name": "Cube Tools",
"author": "Acme <acme@example.com>",
"version": (1, 0, 0),
"blender": (4, 5, 0),
"location": "View3D > Sidebar > Cube",
"description": "Quick cube operations",
"category": "Object",
}
import bpy
from cube_tools import operators
from cube_tools.ui import panels
def register():
operators.register()
panels.register()
def unregister():
panels.unregister()
operators.unregister()
blender_manifest.toml:
schema_version = "1.0.0"
id = "cube_tools"
version = "1.0.0"
name = "Cube Tools"
tagline = "Quick cube operations"
maintainer = "Acme <acme@example.com>"
type = "add-on"
blender_version_min = "4.5.0"
license = [
"SPDX:GPL-3.0-or-later",
]
tags = ["Object"]
__init__.py:
import bpy
from . import operators
from .ui import panels
def register():
operators.register()
panels.register()
def unregister():
panels.unregister()
operators.unregister()
The bl_info dict is gone; the imports are now relative; everything else is identical.
Same blender_manifest.toml as above, plus keeping a slimmed bl_info for 4.x legacy users:
bl_info = {
"name": "Cube Tools",
"author": "Acme",
"version": (1, 0, 0),
"blender": (4, 5, 0),
"category": "Object",
}
import bpy
from . import operators
from .ui import panels
Note: the imports are still relative. Relative imports work in both load paths; absolute imports only work in the legacy path.
Once the manifest exists, build the Extension .zip:
blender --command extension build --source-dir .\cube_tools --output-dir .\dist
This produces a .zip in dist\ that the user installs via Edit > Preferences > Add-ons > Install... or that you upload to extensions.blender.org.
id in the manifest. id is required and must be a stable slug; changing it later is a breaking change that disconnects users from updates.version in the manifest. bl_info uses tuples, the manifest uses a string. Dot-separated semver, e.g., "1.2.3".license. The platform rejects manifests without a license expression. ["SPDX:GPL-3.0-or-later"] matches typical Blender add-on practice; commercial add-ons use other SPDX strings.blender_manifest.toml, lowercase, in the package root.permissions defaults. The manifest has a permissions key for network, file IO, etc. Default to declaring nothing if you don't need elevated permissions; over-declaration triggers user warnings.| Topic | 4.5 LTS | 5.1 stable |
|---|---|---|
bl_info recognized | Yes (primary path) | Yes (legacy fallback only) |
blender_manifest.toml recognized | Yes (Extensions Platform was added in 4.2) | Yes |
| Synthetic package name | bl_ext.<repo>.<id> | Same |
extension build command | Available | Available |
| Schema version | 1.0.0 | 1.0.0 |
The Extensions Platform shipped in Blender 4.2. Migrations done now will work on 4.2+ and 5.x without further changes. Code targeting 4.0 or earlier still needs the bl_info-only path.
addon-scaffolding: scaffolding a new Extensions Platform add-on from scratch.target-extensions-platform-format: encodes the policy that new add-ons should be Extensions-first.extension-addon-template: a working starter to compare your migration against.blender_manifest.toml schema: https://developer.blender.org/docs/handbook/extensions/schema/