blender-tools/AGENTS.md

5.0 KiB

Contributor and Agent Guide

This repository contains Blender extensions and standalone asset-pipeline tools. For Blender work, start with the extension authoring guide, then use the API notes and the testing and release guide as needed.

Repository map

  • blender/<extension_id>/: one installable Blender extension per directory. Each extension root contains blender_manifest.toml and __init__.py.
  • blender/tests/: headless Blender smoke tests. These run inside Blender's bundled Python, not ordinary system Python.
  • blender/scripts/: focused helpers for the current extension.
  • tools/: standalone tools that do not need to run inside Blender.
  • dist/: generated extension ZIP packages. Do not hand-edit them.
  • build-all.sh: discover and package every manifest under blender/.
  • install-all.sh / install-all.bat: build, install, and enable every extension for the current Blender user.

Rules for Blender extensions

  1. Use the Blender Extensions format introduced in Blender 4.2. Do not add a legacy bl_info dictionary. Metadata belongs in blender_manifest.toml.
  2. Keep each extension self-contained. Use relative imports inside its package. Bundle third-party dependencies as wheels and list them in the manifest; never run pip from an enabled extension.
  3. Treat the installed extension directory as read-only. Persistent extension data belongs under bpy.utils.extension_path_user(__package__, ...).
  4. Declare files, network, clipboard, camera, or microphone permissions in the manifest whenever the extension uses them. Network code must also respect bpy.app.online_access.
  5. Register Blender classes in dependency order and unregister them in reverse. Delete properties added to bpy.types during unregister() and remove every handler, timer, menu callback, preview collection, and keymap item created by register().
  6. Operators must have a useful poll(), use their passed context, report actionable failures, and return {'FINISHED'} or {'CANCELLED'} correctly.
  7. Prefer Blender's data API over bpy.ops. When an operator is necessary, make its context, selection, active object, object mode, and render engine requirements explicit.
  8. Preserve user state. Snapshot and restore temporary selection, active object, mode, render settings, material assignments, and temporary data in finally. Do not rely on Undo to reverse file writes or external side effects.
  9. Never mutate shared mesh or material data merely to simplify processing. Copy it, operate on the copy, and clean it up unless a persistent result is an explicit feature.
  10. Avoid hard-coded repository namespaces such as bl_ext.user_default. An extension may be installed from another repository; use __package__ and relative imports.

Adding an extension

  1. Create blender/<extension_id>/blender_manifest.toml and __init__.py.
  2. Use a lowercase snake-case manifest id; keep operator IDs and registered class names uniquely prefixed.
  3. Set a truthful blender_version_min, semantic version, SPDX license, and only the permissions actually required.
  4. Add a deterministic smoke test under blender/tests/. It must create its own scene data, exercise the public operator or API, assert the result, and check that temporary data and global state are restored.
  5. Add the test to blender/scripts/test.sh or replace that helper with a test dispatcher when a second extension needs its own Blender process.
  6. Document the user workflow in README.md or a focused file under docs/.
  7. Run the completion checks below.

Required completion checks

For any changed Blender extension, run checks proportional to the change. The minimum for code changes is:

./blender/scripts/test.sh
blender --factory-startup --command extension validate blender/<extension_id>
./build-all.sh
blender --factory-startup --command extension validate dist/<id>-<version>.zip

For registration, packaging, dependency, or manifest changes, also test the built package in an isolated Blender user profile and confirm the enabled extension is loaded. See Testing and releasing.

Before declaring success:

  • Test both the successful path and at least one important validation/failure path.
  • Confirm the original scene state is preserved unless the feature documents a persistent change.
  • Confirm no temporary objects, meshes, materials, images, handlers, or files survive unexpectedly.
  • Rebuild the ZIP after the final source edit; a previously built package is not evidence for the current source.
  • Bump the manifest version for a user-visible release.

Standalone tools

Code under tools/ runs in ordinary Python. Keep its dependencies in tools/requirements.txt, provide a helpful error when a dependency is absent, and test with ./tools/test.sh. Standalone tools must not import bpy.