Thanks for helping improve this repository. This document describes how to set up locally, extend skills, rules, snippets, and the template, and submit changes.
-
Fork the repository on GitHub.
-
Clone your fork:
git clone https://github.com/<your-username>/Blender-Developer-Tools.git cd Blender-Developer-Tools
-
Create a branch for your work:
git checkout -b your-feature-name
This repo is a content collection (skills, rules, snippets, and one template) for Blender Python development. There is no runtime, no MCP server, and no test runner; CI validates frontmatter, syntax, and aggregate counts.
skills/
<skill-name-kebab>/
SKILL.md
rules/
<rule-name>.mdc
snippets/
<snippet-name>.py
templates/
<template-name>/
blender_manifest.toml
__init__.py
README.md
showcase/
README.md
gallery.json
<piece-name>/
README.md
skills/- one directory per skill, each containingSKILL.mdwith YAML frontmatter (name,description,standards-version).rules/- Cursor-style rules as.mdcfiles with YAML frontmatter (description,alwaysApply,globs,standards-version).snippets/- small standalone.pyfiles (5 to 50 lines) demonstrating a single canonical pattern.templates/- copy-paste starting points; one directory per template.showcase/- budget-conformance props, sibling ofexamples/. Not API contracts. Conventions:showcase/README.md.
-
Add a kebab-case directory under
skills/, e.g.skills/procedural-materials/. -
Create
SKILL.mdwith YAML frontmatter:--- name: procedural-materials description: One-line description, under 200 chars. standards-version: <current meta-repo STANDARDS_VERSION> ---
-
Aim for 150 to 350 lines covering the canonical pattern, common AI mistakes, version-correctness notes, and one or two worked code examples. Cite Blender API doc URLs where relevant. Avoid encyclopedic API tours.
-
The skill
namein frontmatter must match the directory name exactly (CI enforces this).
-
Add a
.mdcfile underrules/, e.g.rules/avoid-python-loops-on-vertices.mdc. -
Start with YAML frontmatter:
--- description: One-line summary for humans and tooling. alwaysApply: true globs: - "**/*.py" standards-version: <current meta-repo STANDARDS_VERSION> ---
-
Write 30 to 80 lines: the anti-pattern, a code example showing it wrong, a code example showing it right, and a short "Why it matters" section.
- Add a
.pyfile undersnippets/, e.g.snippets/depsgraph-evaluated-mesh.py. - Keep it 5 to 50 lines, fully working code, with a header comment naming the snippet and citing the relevant Blender doc URL or research section.
- Snippets are validated for Python syntax in CI.
- Add a directory under
templates/, e.g.templates/headless-batch-script-template/. - Include all files needed for an immediate copy-paste starting point. For add-on templates, include
blender_manifest.toml,__init__.py, and a briefREADME.md.
Read showcase/README.md first. Showcase asserts
budget conformance, never an API contract.
- Add
showcase/<kebab-name>/with a script, a README that includes an exit-code table, and a falsifier that breaks one pipeline stage so a named budget fails. - List the directory in
.cursor-plugin/plugin.json"showcase"and add atests/smoke/catalog.jsonrow. The runner takes opaque script paths. - Add a
showcase/gallery.jsonpieces[]entry, render a still, and runpython scripts/build_gallery.py. Do not hand-editdocs/gallery/HTML. - Update the README showcase-piece count.
validate-countschecks it separately from the example total.
Content targets Blender 5.2 LTS as primary, Blender 5.1 as prior stable, and Blender 4.5 LTS as fallback. When the API differs, branch on bpy.app.version and document both paths. Example:
if bpy.app.version >= (5, 0, 0):
# 5.x path
...
else:
# 4.5 LTS path
...Default PR smoke is Blender 5.2 and 4.5 (.github/workflows/blender-smoke.yml).
5.1 is not in that matrix.
- Apply the
needs-5.1label when the change can diverge on 5.1 (bake, UV RNA, version-branched API). That starts a 5.1 smoke job. Auto-label will not apply this; it is opt-in. - Run any series on demand: Actions > Blender Smoke Test > Run workflow,
pick the branch and the
seriesinput. - Monday 07:00 UTC cron still runs 5.2, 5.1, and 4.5. Do not treat cron as PR evidence.
- There is deliberately no
pushtrigger onblender-smoke.yml. Squash-merging a green PR makesmainidentical to the content already smoke-tested, so a push job would re-prove the same tree at double the CI cost. Absence of post-merge smoke is not a coverage gap. pages.ymlis path-filtered. A workflow-or-docs-only merge does not deploy Pages. Observed on13ea521(ci:#137): Validate, drift-check, and Release ran; Pages did not. Intentional, not a failed job.
Three roles, not one global table. Do not copy a code from one script into
another and assume it means the same thing. 9 is a valid sequential-check
code; there is no rule against it.
Per-script exits (examples and headless templates). 0 success. 2
argument or usage error, matching argparse. 3 and above for that script's
own sequential check failures, in the order the checks run. These codes are
file-local and are not portable. no-mesh is 2 in
templates/headless-batch-script-template/ and 5 in
templates/ai-asset-pipeline-template/; both are correct. Copy a template's
own table from that template, not from this paragraph.
FATAL wrapper. sys.exit(1) on an uncaught exception in the __main__
guard. Uniform across the examples. 1 means crashed, never a named check.
Smoke protocol. Owned by tests/ and the runner, not by product check
tables. 0 pass, 1 fail (tests/smoke/run_example.py,
tests/check_import_export_rules.py), 77 skip (tests/smoke/canary_skip.py,
and the product scripts that self-skip: examples/gn-bundle-roundtrip/,
examples/exit-pre-sidecar/). A script under test prints SMOKE_SKIP: and
exits 77; the runner records SKIP and returns 0 so the YAML step stays green.
Version-gated falsifiers. A falsifier for a cross-version removal or
rename is version-gated by nature. It exits its documented code on versions
where the API changed and exits 0 on versions where the old API still works.
That is the correct witness: the naive script is still valid on the older
binaries. It differs from every other falsifier in the tree (for example
--same-axis), which is red on all three versions.
Do not "fix" these flags to fail unconditionally. The examples that behave this way:
examples/vse-linear-modifiers/(--assume-present)examples/gn-socket-rename/(--legacy-ids)examples/eval-mesh-datablock-name/(--assume-distinct-names)examples/mesh-automasking-settings/(--assume-brush-attrs)
Files that participate in ecosystem drift checking must carry a standards-version marker matching the current meta-repo STANDARDS_VERSION (which is decoupled from this repo's VERSION):
AGENTS.md,CLAUDE.md,ROADMAP.md: HTML comment first line, e.g.<!-- standards-version: <STANDARDS_VERSION> -->.skills/*/SKILL.md,rules/*.mdc: YAML frontmatter fieldstandards-version: <STANDARDS_VERSION>.
The drift-check workflow enforces these on every push and PR.
README.md declares aggregate counts (e.g. "16 skills, 9 rules, 3 templates, 27 snippets, 59 examples, and 1 showcase piece"). The validate-counts job in .github/workflows/validate.yml enforces these substrings against the filesystem on every push and PR. Showcase pieces are counted separately from examples. When you add or remove content, update the README counts in the same commit.
- Update docs if you change skill or rule lists, content counts, or versioning (
README.md,CLAUDE.md,ROADMAP.mdas appropriate). The release workflow rewritesCHANGELOG.md,CLAUDE.md**Version:**line, andROADMAP.md**Current:**line automatically when afeat:orfix:commit lands onmain, so only edit those files for content beyond the version markers. - Open a PR against
mainwith a clear title and summary of changes. - Use Conventional Commits for the PR title (and the squash-merge subject, which is what the release workflow scans). Prefixes:
feat:(minor bump),fix:(patch bump),feat!:/fix!:/BREAKING CHANGE(major bump),chore:/docs:/ci:/refactor:(no release — the workflow runs and exits without tagging). A mixed range still releases if any commit since the last tag is afeat:/fix:.[skip ci]remains an optional override and is no longer required to avoid a release for non-release commits. - Respond to review feedback; CI must pass before merge. Documentation-only and chore changes do not trigger a release.
This project uses CC-BY-NC-ND-4.0 as its outbound license, which forbids derivatives. Every pull request is a derivative. Contributions are accepted inbound under a broader grant via the Developer Certificate of Origin (DCO), which resolves the conflict so the project can accept and redistribute contributions.
By submitting a contribution to this repository, you certify that you have the right to do so under the Developer Certificate of Origin (DCO) 1.1, and you grant TMHSDigital a perpetual, worldwide, non-exclusive, royalty-free, irrevocable license to use, reproduce, prepare derivative works of, publicly display, publicly perform, sublicense, and distribute your contribution under the project's current license (CC-BY-NC-ND-4.0) or any successor license chosen by the project.
Every commit in a pull request must have a Signed-off-by: trailer matching the commit author:
Signed-off-by: Jane Developer <jane@example.com>
Signing is done at commit time:
git commit -s -m "feat: add new skill"The GitHub DCO App enforces this on every PR.
For the full inbound/outbound model and rationale, see standards/licensing.md in the Developer-Tools-Directory meta-repo.
This project follows the guidelines in CODE_OF_CONDUCT.md. By participating, you agree to uphold them.