Week in TD, Oct 5–11, 2026: node graphs want to be diffable. Blender's nodes-as-code plan, and what Houdini already has
In the week of Oct 5–11, 2026, Blender's developers named nodebpy their most promising route to readable, diffable node groups and planned list fields. We compare both with what Houdini already ships (text .hip files, asCode() and array attributes), with every snippet run in Blender and Houdini 22.

TL;DR Procedural node graphs in Blender and Houdini usually live in binary scene files, so
git diffshows nothing useful. On Oct 5, 2026, Blender's developers published notes from their September Geometry Nodes workshop. nodebpy, a library that turns node groups into readable Python and back, is their most promising route to reviewable node changes, probably wrapped in git diff and merge drivers so the .blend stays the source of truth. They also planned list fields, a list per element. Houdini already has most of these pieces: a text.hipformat (on commercial licenses),asCode()and array attributes. We ran all of it in Blender and Houdini 22 to see what each gives a reviewer.
DCCs in 60 seconds
A DCC (digital content creation tool) is an app like Blender, Houdini or Maya. Much of the procedural work in them happens in node graphs. Each node is a function, each wire passes data, and the graph is a lazily evaluated dataflow program. Blender calls this Geometry Nodes. Houdini calls it SOPs (Surface Operators). In both, the data flowing through the wires is geometry: points (positions) plus named per-element attributes, which work like columns in a dataframe.
The trouble for an engineer: a .blend file is binary, and so is a .hip file by default. Commit one to git and git diff says "Binary files differ". Code review means screenshots.
The news: the week of Oct 5–11, 2026
On Oct 5, Jacques Lucke posted a summary on the Blender Developers Blog of the Geometry Nodes workshop held at Blender's Amsterdam office in the week after Blender Conference. Brady Johnston, who makes the Molecular Nodes add-on, and Cartesian Caramel were guests. Two threads in it matter if you write code.
1. Node groups as text. Reviewing node changes is the problem. A work-in-progress blend_diff tool (an open pull request since December 2025) prints what changed between two .blend files, but the notes say it "still leaves a lot to be desired" for node groups. For a text format, they call nodebpy, Brady Johnston's library, "the most advanced and promising approach". It writes node trees as readable Python and converts existing trees back to code. Molecular Nodes already keeps its node groups as Python, as the ground truth. For Blender's own bundled assets the developers think that's "too early to bet" on. The "more promising alternative" is to wrap nodebpy in git drivers for diffing and merging, so the .blend stays canonical while reviews show text. The catch is security: "Opening an untrusted .blend in Blender is not safe, but is required with nodebpy", so the tooling needs a sandbox. It's the same caution you'd apply to running setup.py from a random repo.
nodebpy 520.35.1 came out on PyPI on Oct 9. The version number tracks Blender: 520 means it targets Blender 5.2.0, and its docs say it should keep working on 5.3. It wires nodes with >>, which reads like a Unix pipe. This is the start of the README's example:
# nodebpy style (from the project's README): >> wires output to input
from nodebpy import geometry as g
with g.tree("Demo", is_modifier=True) as tree:
rot = g.RandomValue.vector(min=-1, seed=2) >> g.AlignRotationToVector()We ran it with nodebpy 520.35.1 in Blender 5.2.0 LTS and in a 5.3 alpha build. It makes a Geometry Nodes group with a vector Random Value node (min -1, seed 2) wired into an Align Rotation to Vector node. nodebpy.export.to_python() then turned the tree back into code:
from nodebpy import geometry as g, TreeBuilder
with TreeBuilder("Demo", is_modifier=True) as tree:
_align_rotation_to_vector = g.AlignRotationToVector(vector=g.RandomValue.vector((-1.0, -1.0, -1.0), (1.0, 1.0, 1.0), seed=2))It isn't the text we wrote, but it's the same tree, and a reviewer can read it.
2. List fields. A Blender field is a lazily evaluated per-element expression, roughly a kernel waiting for a domain to run over. Today a field computes one value per element, and lists exist only as standalone data. A list field would compute a list per element: most mesh topology nodes could output lists, and Index of Nearest could return the closest n points instead of one. The notes expect list fields to arrive before list attributes, so a list will have to be reduced to one value per element before it can be stored. A proposed Reduce List node does that, for standalone lists and list fields, with any number of lists and reductions at once.
Also in the week: on Oct 8, Blender 5.3 entered beta, in the blender-v5.3-release branch for bug fixes only, and main became 5.4 alpha. The release candidate is due Nov 4.
Update, Oct 17, 2026: nodebpy is at 520.38.0 (Oct 13). List fields and the nodebpy git drivers are still plans: we found no pull request for either on Blender's tracker. Blender 5.3 is still planned for Nov 10.
What Houdini already has
It's tempting to say Houdini solved this years ago. It solved part of it, and the details matter.
A text scene format, behind a license. Houdini has two save modes. The default binary .hip is an archive: git sees NUL bytes and reports "Binary files differ" (we checked with a Houdini 22 save), even though a wrangle's VEX sits inside it as plain text. The other mode is text: File → Save as text, or hou.hipFile.setSaveMode(hou.saveMode.Text) from Python. The help calls it "friendly to version control", readable by Houdini 16 and later, and "only available with a full commercial license". On our Indie license, setSaveMode(hou.saveMode.Text) raised no error and left the mode at Binary. For assets, hotl -t expands an .hda into a directory of files, and File → Show changes runs your own diff tool on the current scene. Even so, the help warns that diffs of scene files "may not be very clear or understandable".
Graph to code. Houdini's Python API has asCode(), which prints a Python script that rebuilds a node and, optionally, everything inside it. It replaces HScript's older opscript command, and a 2015 SideFX forum thread already points to it in the Houdini 14 docs. Since Houdini 20 it lives on hou.OpNode, because hou.Node became a more general base class. Here's a round trip you can run in Houdini's Python Shell (Windows → Python Shell):
import hou
# Build a tiny SOP network: a grid displaced by a VEX wrangle
geo = hou.node("/obj").createNode("geo", "ascode_demo")
grid = geo.createNode("grid")
wr = geo.createNode("attribwrangle") # Run Over defaults to Points
wr.setInput(0, grid)
wr.parm("snippet").set("@P.y += sin(@P.x * 4.0) * 0.2;")
wr.setDisplayFlag(True)
# Serialize the whole network as Python source
src = geo.asCode(brief=True, recurse=True)
print(len(src.splitlines()), "lines") # diffable, greppable, reviewable
with open(hou.text.expandString("$HIP/ascode_demo.py"), "w") as f:
f.write(src) # commit this next to the .hipIn Houdini 22.0.368 it prints 431 lines. Change the wrangle's 0.2 to 0.3, export to a second file and run git diff --no-index on the two. Exactly one line changes:
@@ -412,7 +412,7 @@ if locals().get("hou_node") is None:
hou_node = hou.node("/obj/ascode_demo/attribwrangle1")
hou_parm = hou_node.parm("snippet")
hou_parm.deleteAllKeyframes()
-hou_parm.set("@P.y += sin(@P.x * 4.0) * 0.2;")
+hou_parm.set("@P.y += sin(@P.x * 4.0) * 0.3;")
hou_node.setExpressionLanguage(hou.exprLanguage.Hscript)So the diff is clean, but the file isn't small. The first 367 of its 431 lines recreate the Geometry object node and its render parameters; the grid and the wrangle take the last 64. HScript's opscript -b -r gives 37 lines for the same network, but one of them packs all those parameter definitions into a single line. The script does round-trip: run in a fresh session, it rebuilt the network with the same snippet and display flag.
What trips you up. asCode() records state, not intent. Its output is a run of createNode, setTemplateFlag(False) and parm().set() calls, and it writes a version string into node blocks (syncNodeVersionIfNeeded("22.0.368") for our build), so expect noise when you re-export from a different build. It's good for snapshots and for diffing what changed in an asset; nobody wants to hand-edit it. nodebpy aims at the other target, code a person would write. Blender's plan puts readability first and adds git on top, which is the right way round.
What clicks. Houdini teams sidestep part of the problem by putting the logic in VEX, Houdini's C-like, data-parallel language. A wrangle's snippet is a string parameter, so the interesting part of the diff is already text: it's the one line that changed above. Geometry Nodes has no equivalent text-kernel node (the 5.3 build we checked has none; Blender's only script node is the OSL Script node for Cycles shaders), which is why tools like nodebpy matter more there.
Lists per element. Houdini already allows array attributes, so each point can store an array. In a Point Wrangle (Run Over: Points):
// Up to 8 points within 0.5 units of this one, nearest first.
// The first entry is always the point itself.
i[]@nbrs = nearpoints(0, @P, 0.5, 8);
i@nbr_count = len(i[]@nbrs); // a reduction: one number per pointTwo easy mistakes. nearpoints includes the point itself, and 0.5 is a search radius. On a default Grid SOP (10 × 10 points, about 1.1 units apart) every point gets only itself. On a 50 × 50 grid every point gets 8 entries: itself and its 7 nearest neighbours.
The NumPy equivalent is a ragged array, list[np.ndarray], next to a dense counts vector. Blender's plan to reduce before storing gives you only the dense column at first: simpler to store, less expressive than Houdini's ragged storage.
Why coders should care
Node graphs are turning into a source format, not just a UI. Houdini has a text scene format that Houdini 16 and later can read, but it's limited to commercial licenses, its own help warns that scene diffs may be hard to read, and asCode() is a rebuild script rather than something you'd edit. Blender is designing the reviewable layer in the open: readable code first, git diff and merge drivers on top, and a sandbox, because turning a scene file into text means running the app on it. Whichever tool gets a readable, round-trippable graph format right makes procedural assets reviewable like code. nodebpy already ships an Agent Skill that teaches AI coding agents to write node trees with it, so the same text is also what LLM tooling will read and edit.
Try it yourself
- Houdini Apprentice (free, non-commercial): run the script above, change
0.2to0.3, export again and diff the two.pyfiles. One line changes in a 431-line file; find where the Geometry object's block ends and look at what fills the rest. Save as text needs a commercial license, so on Apprentice (and Indie) compareasCode()exports instead. We tested on Indie. - Blender (free): nodebpy 520.x needs Python 3.13, the version Blender 5.2 bundles. Install it into a folder with a Python 3.13 pip (
pip install --target <folder> nodebpy) and add that folder tosys.pathin Blender. Build a small tree with it, then build the same tree in rawbpy(tree.nodes.new(...),tree.links.new(...)) and compare. Then runnodebpy.export.to_python()on a node group you wired by hand. - Bonus: write a git
textconvdriver that runs either exporter, sogit diffon a scene file shows code. Keep the workshop's warning in mind: the driver opens the file in Blender or Houdini, so only point it at files you trust.
Functions used: nearpoints, len, sin. Each links to its entry in the Simstim VEX reference.
Sources
- Geometry Nodes Workshop: September 2026, Jacques Lucke, Blender Developers Blog, Oct 5, 2026, and the raw workshop notes
- Blender PR #151266: add .blend file diffing utility
- Release cycle: Now at 5.3 Beta (and 5.4 Alpha), Blender Developer Forum, Oct 8, 2026, and the Blender 5.3 milestone
- nodebpy: PyPI, GitHub, docs on nodes to code and versioning
- SideFX docs: hou.OpNode (
asCode), hou.Node (the Houdini 20 change), hou.saveMode, Working with files and assets as text, opscript, nearpoints - SideFX forum: saving a node network as a Python script (Feb 2015)


