Developer Docs

Build Nodes. Ship Pipelines.

The complete API reference for extending Vibrante-Node. From custom BaseNode classes to the Houdini bridge, action-list pattern, and headless execution.

custom_node.py
python
1from src.nodes.base import BaseNode
2
3class My_Node(BaseNode):
4 name = "my_node"
5
6 def __init__(self):
7 super().__init__()
8 # [AUTO-GENERATED-PORTS-START]
9 self.add_input("file_path", "string", widget_type="text")
10 self.add_input("scale", "float", widget_type="float", default=1.0)
11 self.add_output("result", "any")
12 # [AUTO-GENERATED-PORTS-END]
13
14 async def execute(self, inputs):
15 path = inputs.get("file_path", "")
16 scale = inputs.get("scale", 1.0)
17 # your logic here — async-safe
18 return {"result": path, "exec_out": True}
19
20def register_node():
21 return My_Node
BaseNode

Custom Node

Every node inherits BaseNode. super().__init__() adds exec_in/exec_out automatically. Only add your custom ports in the AUTO block.

Key Rules

  • super().__init__() adds exec_in/exec_out — do NOT add them again
  • Only add custom ports inside the AUTO block
  • Always return {"exec_out": True} in execute()
  • register_node() must return the class, not an instance
Houdini Bridge

Full Bridge API Reference

All 18 methods available on the HouBridge singleton. Every call goes over TCP JSON-RPC to your live Houdini session.

Method
Returns
Description
bridge.ping()
{"status": "ok", "version": "..."}
Check connection to Houdini
bridge.create_node(parent, type, name)
{"path": "/obj/geo1", ...}
Create a Houdini node
bridge.delete_node(path)
{"deleted": "/obj/geo1"}
Delete a node by path
bridge.set_parm(node, parm, value)
{"set": True}
Set a single parameter
bridge.set_parms(node, parms_dict)
{"set": True, "count": N}
Set multiple parameters at once
bridge.get_parm(node, parm)
{"value": <current>}
Read a parameter value
bridge.connect_nodes(from, to, out=0, in=0)
{"connected": True}
Wire two nodes together
bridge.cook_node(path, force=False)
{"cooked": True}
Cook a node network
bridge.run_code(code)
{"result": <value>}
Execute Python code inside Houdini
bridge.node_info(path)
{"path", "type", "category", "children", ...}
Get detailed node info
bridge.children(path)
[{"name", "type", "path"}, ...]
List child nodes
bridge.node_exists(path)
{"exists": bool}
Check if a node path exists
bridge.set_display_flag(path, on=True)
{"set": True}
Set display flag on a SOP
bridge.save_hip(path="")
{"saved": "/path/to.hip"}
Save the Houdini scene
bridge.scene_info()
{"hip_file", "fps", "frame", "frame_range", ...}
Get scene metadata
bridge.set_expression(node, parm, expr, lang)
{"set": True}
Set HScript or Python expression
bridge.set_frame(frame)
{"frame": N}
Jump to a specific frame
bridge.layout_children(path)
{"done": True}
Auto-layout child nodes
Import: from src.utils.hou_bridge import get_bridge. Never import hou directly. Never call hou_bridge.get_hou() — that function does not exist.
Node Format

The .json Node Schema

Every node is defined by a single JSON file. Drop it in nodes/ — no plugin system, no registration, no restart required.

Port Types

stringtextText input widget
floatfloatNumeric float widget
intintNumeric integer widget
boolcheckboxCheckbox widget
listnullList/array data
anynullGeneric exec/data port

Exec Pins (white squares)

Set use_exec: true to add exec flow. Always include exec_in and exec_out in the JSON arrays. In Python, super().__init__() adds them automatically — do not add them manually.

Categories

HoudiniMayaBlenderPrismLogicMathStringFile I/OCustom

Common Mistakes to Avoid

hou.node("/obj").createNode(...)
bridge.create_node("/obj", ...)
result = bridge.create_node(...); result.path()
result = bridge.create_node(...); path = result["path"]
Adding exec_in/exec_out manually
super().__init__() adds them automatically
Adding ports twice (in AUTO block + below)
Add each port exactly once