Custom Nodes
Custom nodes allow you to extend RUNE Interface with your own functionality. You can create reusable nodes that perform specific tasks using Luau scripts. This guide explains how to create custom nodes using YAML definitions and Luau scripts.
Looking for native C/C++ plugins?
This page covers Luau-based custom nodes. For compiled plugins that register nodes via the C API, see Creating Native Plugins with the RUNE Plugin SDK.
Overview
A custom node consists of two files:
- YAML Definition File (
.yamlor.yml) - Defines the node's structure, inputs, outputs, and metadata - Luau Script File (
.luau) - Contains the execution logic that runs when the node executes
The YAML file tells RUNE Interface what the node looks like and how it connects to other nodes. The Luau script contains the actual code that runs when the node executes.
File Locations
Custom nodes can be placed in two locations:
Global Nodes
Place nodes in the global nodes directory to make them available to all flows:
flows/
nodes/
MyNode.yaml
lua/
MyNode.luau
Per-Flow Nodes
Place nodes in a flow-specific directory to make them available only to that flow:
flows/
my-flow/
nodes/
MyNode.yaml
lua/
MyNode.luau
Note: The script path in the YAML file is relative to the nodes/ directory. If your script is in nodes/lua/MyNode.luau, the YAML should reference it as lua/MyNode.luau.
YAML Definition File
The YAML file defines your node's structure. Here's the complete structure:
Required Fields
type(string): Unique identifier for your node type. Must be unique across all nodes.name(string): Display name shown in the node menu and on the canvas.category(string): Category for organizing nodes in the menu (e.g., "Output", "Flow Control", "Utilities").script(string): Path to the Luau script file, relative to thenodes/directory.
Optional Fields
inputs(array): Data input pins that accept values from other nodes.outputs(array): Data output pins that provide values to other nodes.executionInputs(array): Execution input pins that control flow execution.executionOutputs(array): Execution output pins that continue flow execution.color(array): RGB color values[R, G, B]for node visualization (0-255).
Input/Output Pin Structure
Each pin in the inputs, outputs, executionInputs, or executionOutputs arrays has:
name(string): Pin identifier (used in scripts and connections).type(string): Data type (e.g.,"string","number","boolean") or"execution"for execution pins.
Example YAML File
Here's the complete YAML file for the CustomLogger node:
type: CustomLogger
name: Custom Logger
category: Output
inputs:
- name: Message
type: string
- name: Level
type: string
executionInputs:
- name: In
type: execution
executionOutputs:
- name: Out
type: execution
script: lua/CustomLogger.luau
color: [255, 200, 100]
Luau Script File
The Luau script contains the execution logic for your node. When the node executes, RUNE Interface:
- Loads the script file
- Creates an
inputstable with all input values - Creates an empty
outputstable - Executes your script
- Reads values from the
outputstable
Accessing Inputs
All input pins are available in the inputs table by their pin name:
local message = inputs.Message or ""
local level = inputs.Level or "info"
Setting Outputs
Write output values to the outputs table:
outputs.Result = "some value"
outputs.Status = "success"
Full Luau API Access
Your script has access to the full Luau API, including:
- Session state functions (
session-state-get,session-state-set, etc.) - Logger functions (
logger-info,logger-warn,logger-error,logger-debug) - File operations (
flow-file-read,flow-file-write, etc.) - HTTP requests (
http-request) - And more...
See the Luau API documentation for complete details.
Example Luau Script
Here's the complete Luau script for the CustomLogger node:
-- CustomLogger node: Logs a message with a custom log level
-- Inputs: Message (string), Level (string: "info", "warn", "error", "debug")
-- This demonstrates how custom nodes can extend functionality
local message = inputs.Message or ""
local level = inputs.Level or "info"
-- In a real implementation, this would call the logging system
-- For now, this is a placeholder that shows the concept
print("[" .. string.upper(level) .. "] " .. message)
Complete Example: CustomLogger
Let's walk through the CustomLogger example to see how everything works together.
Step 1: Create the YAML Definition
Create flows/nodes/CustomLogger.yaml:
type: CustomLogger
name: Custom Logger
category: Output
inputs:
- name: Message
type: string
- name: Level
type: string
executionInputs:
- name: In
type: execution
executionOutputs:
- name: Out
type: execution
script: lua/CustomLogger.luau
color: [255, 200, 100]
Step 2: Create the Luau Script
Create flows/nodes/lua/CustomLogger.luau:
-- CustomLogger node: Logs a message with a custom log level
local message = inputs.Message or ""
local level = inputs.Level or "info"
print("[" .. string.upper(level) .. "] " .. message)
Step 3: Use the Node
- Restart RUNE Interface (or reload custom nodes)
- The "Custom Logger" node appears in the "Output" category
- Drag it onto your canvas
- Connect it to other nodes
- Set the
MessageandLevelinputs - When executed, it prints the formatted log message
Execution Flow
When a custom node executes:
- Input Collection: RUNE Interface collects values from connected nodes or node properties and populates the
inputstable - Script Execution: Your Luau script runs with access to the
inputstable - Output Extraction: Values written to the
outputstable are stored and made available to connected nodes - Execution Continuation: Execution continues through
executionOutputspins
Best Practices
Naming Conventions
- Type: Use PascalCase (e.g.,
CustomLogger,DataProcessor) - Name: Use clear, descriptive names (e.g., "Custom Logger", "Data Processor")
- Category: Use existing categories when possible, or create new ones for related nodes
- Pin Names: Use PascalCase for pin names (e.g.,
Message,Result,Status)
File Organization
- Keep related nodes together in the same category
- Use descriptive file names that match the node type
- Place scripts in the
lua/subdirectory for organization
Script Development
- Always provide default values for inputs:
local value = inputs.Value or "" - Validate input types and ranges when necessary
- Use the logger functions for debugging:
logger-info("Debug message") - Handle errors gracefully
Testing
- Create a simple test flow with your custom node
- Test with various input values
- Verify outputs are set correctly
- Check execution flow through execution pins
- Test edge cases (empty strings, null values, etc.)
Common Pitfalls
Script Path Issues
Problem: Script file not found
Solution: Ensure the script path in YAML is relative to the nodes/ directory. If your file is at flows/nodes/lua/MyNode.luau, use lua/MyNode.luau in the YAML.
Input/Output Mismatch
Problem: Inputs or outputs not working
Solution: Ensure pin names in the YAML match the names used in your Luau script. Pin names are case-sensitive.
Missing Default Values
Problem: Script errors when inputs are not connected
Solution: Always provide default values: local value = inputs.Value or ""
Execution Flow Issues
Problem: Node doesn't continue execution
Solution: Ensure you have executionOutputs defined in your YAML if the node should continue the flow.
Debugging Tips
-
Use Logger Functions: Add logging to see what's happening:
logger-info("Input Message: " .. tostring(inputs.Message)) -
Check Session State: Outputs are stored in session state with keys like
node_{id}_{pinName} -
Test Incrementally: Start with a simple script that just sets outputs, then add logic gradually
-
Verify File Locations: Ensure both YAML and Luau files are in the correct directories
-
Check Node Registry: Look at the application logs to see if your node was loaded successfully
Next Steps
- Explore the Luau API documentation to see what functions are available
- Review existing node documentation to understand node patterns
- Check out other custom node examples in your flows directory