gda
SkillWeb & browsingGodot automation for AI agents to build and verify projects through a CLI, Agent Skill, or MCP server, with structured results, headless operations, and live runtime control.
Use gda in Claude, ChatGPT or Ahel Desktop
Free. Sign in, add gda and connect your AI. About a minute.
Also: Claude Code · Cursor · Codex
Then ask your AI: use the gda skill
Details
Instructions available. Your AI can read the instructions. Execution depends on the setup they require.
Account requirements not reviewed. Check the skill instructions before use; ahel provides instructions and does not run this skill.
No other account needed.
Add ahel to your AI once: Claude, ChatGPT, Cursor, Claude Code or Codex. Then ask it to use this.
What this skill tells your AI
The instructions your AI receives, as published by aigengame/godot-agent in src/gda/skill/SKILL.md and read by ahel’s review.
gda is an agent-facing CLI for Godot. Use headless operations to create and
inspect scenes, nodes, scripts, resources, shaders, themes, and project settings;
validate or run scripts and scenes; and export artifacts. Use live operations to
inspect a running game, inject input, capture the viewport, and read diagnostics
or performance data. Headless operations support Godot 4.4+ on all platforms.
Live operations use gda-daemon with Godot 4.6+ on macOS or Linux.
Configure and discover
- Set
GDA_GODOTto the Godot executable, or pass--godot PATHafter the command. If a command reportsbinary_not_found, find the Godot executable or ask the user for its path, then use it as above. - Pass
--project DIR, setGDA_PROJECT, or run inside the project directory. The project must containproject.godot. Use an explicit project when a script or asset depends onres://or project autoloads. - Keep the same engine and project for the related calls of one workflow.
- Use
gda --version --jsonto identify the installed CLI and its source in a long session. Usegda info --jsonto check the Godot engine. - Use
gda --helpfor command groups,gda <group> --helpfor a group's commands, andgda <group> <command> --helpfor usage. Usegda <group> <command> --schemafor that command's arguments, JSON result, and errors.gda schemadescribes the full installed surface. Consult these sources for exact options and fields instead of assuming this skill is a command catalog.
Pass --json on operations, for example
gda scene validate res://main.tscn --project game --json. Read the one JSON
object on stdout; engine output goes to stderr. On failure, branch on the
structured error.code and inspect any evidence; do not parse
error.message. An exit code of zero does not always mean the requested check
passed:
| Operation | Check in the successful result |
|---|---|
scene validate, script validate | valid; false is not a pass. |
scene preflight | status and started; static validation does not boot the target scene. |
script run, export smoke | Child exit_status and diagnostics; use --strict when non-zero status or a recognized shutdown leak must fail the command. |
game set | verified; false means the observed read-back differs. Follow up with game get or a domain-specific observation when the side effect matters. |
For precision-sensitive values, inspect the result or read-back. Godot can
change a decimal value while parsing it; gda refuses values that the parser
would destroy. Consult the relevant command schema for accepted value forms
and limits.
Headless workflow
With no project yet, run gda project create DIR --name NAME --json first.
DIR must be a new directory in an existing parent, or an empty directory;
dot-prefixed entries such as .git do not count. The new project.godot sets
only the name, so set the main scene and other settings with project set.
Then use DIR as the project.
Run gda project scan --json on a fresh checkout or a project the editor
never opened, and after you add, rename or delete a class_name script: the
engine finds a project class_name only through the index a scan writes, and
gda does not check whether that index is current.
- Create or edit a scene with
scene,node,script, andresourcecommands. Usescript attachto bind a script to a node; genericnode set --property scriptis refused. Create assets used bypreload("res://...")before you attach the script. Supply ares://Resource path when assigning a Resource-typed property. - Run
scene validateandscript validatefor the changed files. Check theirvalidverdicts.scene validatechecks dependencies and scripts, but does not prove that the target scene starts. - Run
scene preflightto boot the target scene for a bounded interval. Check its startup verdict and diagnostics. Usescript runfor a project test script; inspect the child status even whengdasucceeds. - Use
export listto select a preset. Optionally inspect it withexport get, then runexport run. If needed, useexport smokeon the built artifact. A smoke run proves only what that bounded process observed; it does not prove that the game completed its intended task.
When scene create uses a Control-derived root from --root-type, it writes
zero anchors and zero offsets. A root with no intrinsic minimum size renders as
a zero-size rect; a root with an intrinsic minimum size renders at that minimum
instead, not at viewport size. Set anchor_right and anchor_bottom to 1
with node set, then confirm the layout with game rect in an Engine session.
For a Control inside a Container, change minimum size, size flags, or
the container layout instead of offsets. A root from --inherits keeps the
base's anchors and offsets.
For a variant of a base scene, use scene create PATH --inherits BASE, not
node add --instance: the new scene's root is the base's root. In the variant,
override inherited nodes with node set and add its own nodes; edit or remove
inherited nodes in the base. scene get and node list show the variant's
composed tree and mark inherited nodes with inherited_from; an inherited
instance whose scene is missing carries no mark.
export run checks the export templates itself before it exports, and
refuses with export_templates_missing when they are not available.
--mode pack needs no templates. export get is optional inspection. Give
it the same engine, project, preset, and data root (--user-data-root) as
export run:
templates_installed: falsemeans that thetemplates_versiondirectory is missing undertemplates_root. Then a non-nulltemplates_root_hostmeans that the host has these templates but the data root hides them; a null value means that they are not installed.templates_installed: truemeans only that the version directory exists. It does not prove that the preset's platform can export.
To recover, put matching templates, including the files for the preset's
platform, under templates_root. With a data root, you can instead select
another data root, or run without one where the environment permits.
Template readiness does not prove that an export succeeds or that the
Export artifact runs.
Data root in restricted environments
A headless run sends the engine log to a private temporary file. Godot can still write to its data directory during engine initialization, including for a validation. If that directory is not writable, select a writable data root. The global option comes before the command group:
gda --user-data-root /writable/gda-data scene validate res://main.tscn --project game --json
The data root moves the engine data directory (user:// and the export
templates) and the engine log. The editor configuration and cache locations
depend on the platform and can stay in place; on Linux they do not move.
Judge the impact from the operation verdict and the engine diagnostics. A
directory warning does not by itself make a successful operation invalid.
script run reports engine_data_path and log_file; inspect them before
you treat a failed user:// save as a game defect.
- Use one data root for the engine-launching headless operations of one restricted workflow.
- Use a separate data root for each invocation that runs at the same time. Each launch truncates the one engine log under a data root.
- Do not set the data root (
GDA_USER_DATA_ROOT) for unrelated commands. - Do not give
export smokea data root unless it refuses withuser_data_unwritable. Without one, each smoke run creates a private data root, so nouser://state carries from one smoke run to the next. --user-data-rootdoes not reconfigure an Engine session that the daemon manages.- A successful validation under a data root does not prove that the export templates are available there.
Advanced Godot usages
Scene inheritance. One base scene holds the tree and its scripts. A
variant made with scene create PATH --inherits BASE keeps that tree and
stores only what it changes: overrides on the base's nodes, and nodes of its
own. Keep the logic in the base and specialize the visuals and values in each
variant. The commands and the rules are in the variant paragraph above.
Resource-based components. A class_name script that extends Resource
holds a behavior's data and logic, decoupled from the scene tree: the behavior
lives in a file that any node can hold and call, not in a node at a path, so
the agent defines and tunes it without a scene edit, and swaps it without
changing the node tree. project scan registers the class, resource create
writes the .tres, and node set --value res://….tres links it to a node
export typed with that class.
A shared component is the default: the .tres stays linked in every scene
file, and an edit of the .tres reaches all of them. For a per-instance
copy, choose one of two options:
- Local to scene (
resource set --property resource_local_to_scene --value true): the engine gives each scene instance its own copy when it instantiates the scene, before any_ready; the nodes of one instance share that copy, and a nested resource that is local to scene is copied too. On that copyget_local_scene()returns the scene root and the engine calls_setup_local_to_scene; aduplicate()copy gets neither. The risk: when the node that holds the component is one an inherited scene takes from its base, or the root of an instanced child, a re-save of that scene by any gda write or by the editor stores the copy in its file as an embeddedsub_resource. The link to the.tresis lost in that file, a later edit of the.tresdoes not reach it, and nothing reports it. duplicate()in the owner's script, for example in_ready: the.tresstays linked in every scene file, and the script makes the copy at runtime. The script then owns what the engine owned: a child's_readyruns before its parent's and sees the shared.tres; two nodes of one instance that duplicate separately do not share. On Godot 4.5+,duplicate(true)copies an embedded sub-resource but keeps a nested.tresshared, andduplicate_deep(Resource.DEEP_DUPLICATE_ALL)copies the nested.trestoo.
Rule of thumb: use duplicate() for a component on a node that the re-save
above can reach, and local to scene for a resource the engine must set up
per scene. The copy semantics above are the engine's, not a gda guarantee.
Live workflow
A live run needs a main scene. Set application/run/main_scene or pass a
valid --scene res://... to daemon start. An explicit res:// scene
also bypasses an unresolved uid:// main scene.
- Start the daemon with
gda daemon start --project game --json. This can install the gda harness and updateproject.godot; inspect the change. The Engine session starts when a live operation needs it. - Run
gda daemon wait-ready --project game --jsonbefore read-only diagnostics. Inspectclean_startandstartup_diagnostics. A serving session can still have a scene script that failed to compile. A nullclean_startmeans the startup log was unavailable, not that it was clean. - Discover runtime node paths with a bounded
game tree --max-depth Norgame findquery. Narrow with--root; a truncated result or a bounded empty search does not prove absence. Then usegame get,game rect, or other live commands on the exact path. - Use
inputfor interaction,diag errorsandlogger tailfor diagnostics, andperffor measurements. Start the daemon with--windowedif you needscreen capture; a rendered capture requires an available desktop session. - Stop with
gda daemon stop. This stops the daemon and its Engine session, but the gda harness stays installed. To remove the gda harness installation, rungda daemon uninstallafterdaemon stop. A disposable project copy is an optional way to keep the harness out of the source project. You do not need to uninstall beforegda export run: it removes the harness for the export and restores the project's prior harness state. Other export routes do not remove it.
For a windowed launch, live_windowed_unavailable means skip rendered
checks in this environment. live_windowed_permission_denied means retry
outside the restriction before deciding whether the host can render.
After updating gda, stop and start the daemon before using live commands.
Repeating daemon start updates the installed harness but does not reload
the code in the running game.
A live_timeout discards the Engine session. The next live operation starts
a new game, so do not assume that earlier runtime changes still exist.
Input has two injection routes, reported as injection_route. The default
input action uses action_state to change the polled action state; it
does not send an event to _input, _unhandled_input, or _gui_input.
A key or mouse command uses viewport_event to send an event through the
viewport. Use input action --as-event only when an event handler must
receive that action rather than the mapped key:
| Injection | Input.is_action_pressed | _input / _unhandled_input | _gui_input |
|---|---|---|---|
input action | yes | no | no |
input action --as-event | no | yes | yes (focused Control) |
input key of the mapped key | no | yes | yes (focused Control) |
The table describes eligible delivery under normal propagation and
consumption rules, not proof that a handler ran. For UI activation, use
input mouse-click or input tap to send a complete press/release
gesture. A default BaseButton activates on the release; action_mode or
subclasses such as MenuButton/OptionButton can activate on press.
To verify an interaction:
- Find out whether the game polls input state or handles input events. Select the route from the table.
- Find the runtime target with a bounded
game treeorgame findquery. - Inject the matching input.
- Read the expected game state, for example with
game get. This read is the proof. An injected gesture alone does not prove that the intended handler or gameplay action ran.
game rect reports coordinates relative to the Control's canvas. A
transformed CanvasLayer or an active Camera2D can make them differ from
click coordinates. Do not take click coordinates from the pixels of a
viewport capture.
script run runs your script as written. It does not add coordinate
conversion, gesture completion, or event timing to the script's own
push_input() calls. Your tests must establish those details and the
actual UI layout. Input that a script sends is separate from input that
gda injects with input commands into an Engine session. See Godot's
InputEvent guide.
A screen capture is evidence only when it shows the intended state:
- Use the
--await-*predicate to capture when the relevant state holds. The predicate must represent the visible state. Text kept on a hiddenLabelis not sufficient. - Use
--await-eventsto trigger a short-lived state and capture it in one operation. - Use
--settle-frameswhen the game draws the state later. A settle moves the capture later than the predicate's first match. The earlier state can be gone by then. - Inspect the image. When timing matters, also inspect the returned frame counters and predicate evidence.
- Do not assume that one settle count works for every state. Process frames are not a fixed wall-clock duration.
If the game needs structured records in logger tail, resolve the harness
by node path and check that the daemon launched the session. Do not refer to
the GdaHarness global in game code: a project or export without the harness
cannot parse that name.
var harness := get_node_or_null("/root/GdaHarness")
if harness != null and harness.is_daemon_launched():
harness.gda_log("info", "player spawned", {"hp": 100})
else:
print("player spawned")
Signals
- GitHub stars
- 43
- Forks
- 9
- Last commit
- Oct 2026
Advanced
- Item type
- skill
- Key
skill-aigengame- Source
- github.com/aigengame/godot-agent
github.com/aigengame/godot-agent
More in Web & browsing
Skill · browser-use
More in Web & browsingwebapp-testing
Skill · anthropics
More in Web & browsingplaywright-cli
Skill · microsoft
More in Web & browsingbenchmark
Skill · affaan-m
More in Web & browsingopen-source
Skill · browser-use
More in Web & browsingdeploy-to-vercel
Skill · vercel-labs
More in Web & browsing