Install the packaged add-on
- Open the latest release
Download the Godot ZIP from the release assets and extract it.
- Copy addons/gua
Expected layouttext your-game/ ├─ project.godot └─ addons/ └─ gua/ ├─ gua.gdextension ├─ gua_auto_adapter.gd ├─ plugin.cfg └─ bin/What each file does
Code Meaning project.godotThe main Godot project configuration. addons/gua/gua.gdextensionTells Godot how to load the native Gua extension. addons/gua/gua_auto_adapter.gdCollects Controls and routes external actions back into Godot. addons/gua/plugin.cfgDeclares the add-on and its editor entry point. addons/gua/bin/Contains the platform-specific native libraries loaded by the extension. - Open the project in Godot
Check the Godot output to confirm that the GDExtension loaded successfully.
Attach it from GDScript
- Preload the adapter explicitly
Explicit preload avoids depending on
class_nameregistration order.main.gdgdscript extends Control const GuaAutoAdapterScript := preload( "res://addons/gua/gua_auto_adapter.gd" ) var ui := GuaAutoAdapterScript.new() func _ready() -> void: ui.attach(self) ui.update("title") ui.start_inspector_bridge(8765) func _process(_delta: float) -> void: ui.update("title")Read main.gd from top to bottom
Code Meaning extends ControlMakes this script a root UI Control and a valid value for attach(self). preload("res://addons/gua/gua_auto_adapter.gd")Loads the adapter script explicitly before the scene starts. var ui := GuaAutoAdapterScript.new()Creates one adapter instance for collection and action dispatch. func _ready() -> void:Runs once after this Control and its children enter the scene tree. ui.attach(self)Sets this Control as the root; Controls below it become the collection scope. ui.update("title")Publishes the current Controls under the logical screen name title. ui.start_inspector_bridge(8765)Starts the WebSocket bridge used by Inspector, MCP, and external tests. func _process(_delta: float) -> void:Runs every rendered frame; the underscore marks the unused elapsed-time argument. ui.update("title")Re-collects state and dispatches queued external actions every frame. - Pin IDs only where stability matters
The default ID comes from the NodePath. Use metadata when an ID must survive scene-tree refactoring.
Stable and sensitive fieldsgdscript name_input.set_meta("gua_id", "login-user") password_input.set_meta("gua_id", "login-password") password_input.set_meta("gua_sensitive", true)What the metadata means
Code Meaning name_input.set_meta("gua_id", "login-user")Pins a test-facing ID that survives NodePath refactoring. password_input.set_meta("gua_id", "login-password")Pins a stable ID for the password field. password_input.set_meta("gua_sensitive", true)Prevents plaintext from entering the semantic tree, retained history, or diagnostics. Mask rendered screenshots separately.
Publish a World Object Tree
For a door, enemy, objective, or other non-UI object, add its Node2D or Node3D to the gua_world_object group and attach semantic metadata. The adapter collects position and state on each ui.update(), so game code does not call the native registration API directly.
@onready var reactor_door: Node2D = $World/ReactorDoor
var reactor_door_locked := true
func expose_reactor_door() -> void:
reactor_door.add_to_group(&"gua_world_object")
reactor_door.set_meta(&"gua_world_id", "reactor-door")
reactor_door.set_meta(&"gua_world_kind", "door")
reactor_door.set_meta(&"gua_world_label", "Reactor door")
reactor_door.set_meta(&"gua_world_visible_to_player", true)
reactor_door.set_meta(&"gua_world_tags", ["reactor", "mission-critical"])
update_reactor_door_state()
func update_reactor_door_state() -> void:
reactor_door.set_meta(&"gua_world_state", {
"locked": reactor_door_locked,
"power": "online"
})Call expose_reactor_door() once from _ready(), then call update_reactor_door_state() whenever the door changes. gua_world_id is required and unique within the frame. Position comes from global_position, and the nearest published ancestor becomes the parent. Keep state flat and limited to strings, finite numbers, booleans, or null. See World Object Tree for the conceptual model and query tools.
Export to Web
The same released add-on supports Godot Web Debug and Release exports. In the Web export preset, enable Extension Support and use the single-threaded variant. Godot reads gua.gdextension and selects the matching web.wasm32.single.debug or web.wasm32.single.release WASM automatically.
Commonly observed Controls
LineEdit, TextEdit, CheckBox, OptionButton, and ItemList
Focus, selection, value, scrolling, ranges, visibility, and enabled state