{"id":51314215,"url":"https://github.com/aigengame/godot-agent","last_synced_at":"2026-07-01T06:02:07.344Z","repository":{"id":363366799,"uuid":"1262808460","full_name":"aigengame/godot-agent","owner":"aigengame","description":"Godot AI agent CLI, Skill, and MCP server with structured JSON/schema output — headless scene/script/export automation plus live runtime control.","archived":false,"fork":false,"pushed_at":"2026-06-30T08:54:20.000Z","size":3455,"stargazers_count":23,"open_issues_count":18,"forks_count":5,"subscribers_count":0,"default_branch":"main","last_synced_at":"2026-06-30T09:25:22.372Z","etag":null,"topics":["agent-skill","agent-tools","ai-agent","automation","cli","coding-agent","game-development","gamedev","godot","godot-ai","godot-engine","godot-mcp","headless","llm","mcp","model-context-protocol","skill","structured-output"],"latest_commit_sha":null,"homepage":"","language":"Python","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/aigengame.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":"AGENTS.md","dco":null,"cla":null}},"created_at":"2026-06-08T10:43:05.000Z","updated_at":"2026-06-30T08:54:23.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/aigengame/godot-agent","commit_stats":null,"previous_names":["aigengame/godot-agent"],"tags_count":48,"template":false,"template_full_name":null,"purl":"pkg:github/aigengame/godot-agent","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/aigengame%2Fgodot-agent","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/aigengame%2Fgodot-agent/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/aigengame%2Fgodot-agent/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/aigengame%2Fgodot-agent/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/aigengame","download_url":"https://codeload.github.com/aigengame/godot-agent/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/aigengame%2Fgodot-agent/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":34994877,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-05-26T15:22:16.424Z","status":"online","status_checked_at":"2026-07-01T02:00:05.325Z","response_time":130,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["agent-skill","agent-tools","ai-agent","automation","cli","coding-agent","game-development","gamedev","godot","godot-ai","godot-engine","godot-mcp","headless","llm","mcp","model-context-protocol","skill","structured-output"],"created_at":"2026-07-01T06:01:39.142Z","updated_at":"2026-07-01T06:02:07.336Z","avatar_url":"https://github.com/aigengame.png","language":"Python","funding_links":[],"categories":[],"sub_categories":[],"readme":"# godot-agent (`gda`): Godot AI Agent CLI, Skill, and MCP Server\n\n![godot-agent title image](https://raw.githubusercontent.com/aigengame/godot-agent/main/assets/godot-agent-title.png)\n\n**Read this in:** [简体中文](docs/README.zh-CN.md) · [Español](docs/README.es.md) · [日本語](docs/README.ja.md)\n\n\u003e **`gda` gives your AI coding agent — or your shell scripts and CI — structured, machine-readable\n\u003e control of the [Godot Engine](https://godotengine.org).** Create scenes, edit nodes \u0026 scripts,\n\u003e and export builds headlessly, then drive a *running* game live: runtime tree, input,\n\u003e screenshots, performance — one command surface, three ways in.\n\n[![pre-1.0](https://img.shields.io/badge/status-pre--1.0-orange)](https://pypi.org/project/gda/)\n[![CI](https://github.com/aigengame/godot-agent/actions/workflows/ci.yml/badge.svg?branch=main\u0026event=push)](https://github.com/aigengame/godot-agent/actions/workflows/ci.yml?query=branch%3Amain+event%3Apush)\n[![Python](https://img.shields.io/badge/python-3.13%2B-blue)](https://www.python.org/)\n[![Godot](https://img.shields.io/badge/godot-4.4%2B%20(live%204.6%2B)-478CBF)](https://godotengine.org)\n[![Platform](https://img.shields.io/badge/platform-macOS%20%C2%B7%20Linux%20%C2%B7%20Windows-lightgrey)](#how-it-works)\n[![MCP](https://img.shields.io/badge/MCP-server-000)](https://modelcontextprotocol.io)\n[![License](https://img.shields.io/badge/license-MIT-green)](LICENSE)\n\nAI agents are great at writing GDScript and terrible at *seeing what happened*. `gda`\ncloses that loop: your agent issues one operation and gets back a single clean JSON\nresult it can act on — never engine logs it has to scrape. It runs in **two modes**:\n\n- **Headless** — one-shot and stateless, zero setup. No editor plugin, no daemon,\n  nothing to install in your project. Create and edit scenes, nodes, scripts, resources,\n  shaders and themes; analyze the project; export builds.\n- **Live** — drive a *running* game through a background daemon for everything only a\n  live engine can do: read the runtime scene tree, get/set runtime properties, simulate\n  input, capture screenshots, and sample performance.\n\n\u003e `gda` is **pre-1.0**: every command works end-to-end today, but the CLI surface may\n\u003e still change before 1.0.\n\n---\n\n## Contents\n\n- [Why `gda`?](#why-gda)\n- [Capabilities at a glance](#capabilities-at-a-glance)\n- [Installation](#installation)\n- [Quick start](#quick-start)\n- [Choose your integration](#choose-your-integration)\n- [How it works](#how-it-works)\n- [Command reference](#command-reference)\n- [Configuration](#configuration)\n- [Contributing](#contributing)\n- [License](#license)\n\n---\n\n## Why `gda`?\n\n- **🤖 Structured output, built for agents.** Every command emits **exactly one** JSON\n  object on stdout (`--json`); engine banners, warnings and `print()` go to stderr. Your\n  agent parses one result, not a wall of logs.\n- **📐 Typed \u0026 self-describing.** Every command's input and output are typed models that\n  also back a machine-readable `--schema` (a JSON-Schema contract), so an agent can\n  discover and validate the whole surface programmatically instead of guessing.\n- **🔀 CLI, Skill, and MCP — your agent's choice.** Drive Godot from a terminal or CI with the\n  raw `gda` CLI, hand your agent a bundled **Skill** (`gda skill`) that teaches it how and when\n  to use the CLI, or expose the same operations as **MCP** tools (`gda-mcp`, generated from the\n  CLI's own schemas). One command surface, three ways in — pick whatever your agent supports.\n- **🧩 Godot-native commands.** Grouped by Godot object (`gda scene create`,\n  `gda node add`, `gda game set`) with a tiny, consistent verb vocabulary — zero learning\n  curve if you already know Godot.\n- **⚡ Headless by default, live when you need it.** Headless operations need no daemon\n  and no editor — just a Godot binary. Live operations add real-time control of a running\n  game over a Unix-domain-socket daemon, addressed by the same CLI grammar.\n- **🛡️ Fails loudly, never silently.** A missing or hung engine is bounded by a timeout\n  and mapped to a **stable non-zero exit code** plus a structured `{\"error\": {…}}`\n  envelope — so a shell or agent can branch on the failure category without parsing prose.\n\n---\n\n## Capabilities at a glance\n\n| What you need | Reach for |\n| --- | --- |\n| Build project files from an agent or script | `scene` / `node` / `script` / `resource` / `shader` / `theme` — create \u0026 edit headlessly |\n| Parse results instead of scraping engine logs | `--json` (one clean object) and `--schema` (a JSON-Schema contract) |\n| Hand an agent Godot tools | the bundled **Skill** (`gda skill`) or the **`gda-mcp`** server |\n| Automate CI, exports, and project analysis | headless commands — no editor, no plugin, just a Godot binary |\n| Debug a *running* game's runtime behavior | `gda daemon start`, then `game` / `diag` / `logger` / `perf` / `input` / `screen` |\n\n---\n\n## Installation\n\n**Requirements:** Python 3.13+, and a [Godot](https://godotengine.org) binary — 4.4+ for\nheadless commands, 4.6+ on macOS/Linux for live (daemon) commands.\n\nInstall the CLI from PyPI onto your `PATH`:\n\n```bash\nuv tool install gda      # or: pipx install gda\ngda --help\n```\n\n\u003cdetails\u003e\n\u003csummary\u003eOther ways to install (pip, from source)\u003c/summary\u003e\n\nInto an existing environment:\n\n```bash\npip install gda\n```\n\nFrom source (for development or unreleased changes):\n\n```bash\ngit clone https://github.com/aigengame/godot-agent.git\ncd godot-agent\nuv sync                  # create the environment + install dependencies\nuv run gda --help\n```\n\u003c/details\u003e\n\n---\n\n## Quick start\n\n**Point `gda` at your Godot binary**, then ask the engine its version — no project needed:\n\n```bash\nexport GDA_GODOT=\"/path/to/Godot\"   # or pass --godot to any command\ngda info --json\n# {\"major\":4,\"minor\":6,\"patch\":3,\"status\":\"stable\",\"string\":\"4.6.3-stable (official)\",…}\n```\n\nstdout is always clean JSON you can pipe; all engine and script diagnostics go to stderr:\n\n```bash\ngda info --json | jq .major   # → 4\n```\n\n**Build a scene headlessly.** Point `gda` at a Godot project (a directory with `project.godot`)\nonce; relative paths then resolve *inside* it, and nodes are addressed by their path relative to\nthe scene root:\n\n```bash\nexport GDA_PROJECT=\"/path/to/your/godot-project\"   # or pass --project to any command\ngda scene create scenes/main.tscn --root-type Node2D --json\ngda node add  scenes/main.tscn --type Sprite2D --name Hero --json\ngda node set  scenes/main.tscn --node Hero --property position --value 10,20 --json\ngda scene get scenes/main.tscn --json\n# {\"path\":\"scenes/main.tscn\",\"root\":{\"name\":\"main\",\"type\":\"Node2D\",\"children\":[{\"name\":\"Hero\",…}]}}\n```\n\n\u003e No project? `gda` still runs **projectless** on plain filesystem paths (relative to your current\n\u003e directory) — only `res://` resolution needs a project. See [Configuration](#configuration).\n\n**Drive a *running* game live.** Live ops run the project's **main scene**, so point it at the\none you just built via Godot's `application/run/main_scene` project setting (the editor's\n*Application → Run → Main Scene*), then start the daemon (macOS/Linux, Godot 4.6+):\n\n```bash\ngda project set application/run/main_scene --value res://scenes/main.tscn --json  # a Godot project setting key\ngda daemon start             # start the daemon for $GDA_PROJECT (installs the in-game harness)\ngda game tree --json         # the runtime scene tree, after _ready\ngda perf monitors --json     # live engine counters: fps, memory, node count\ngda daemon stop\n```\n\n(`gda screen capture` works live too, but needs a windowed session — start the daemon\nwith `gda daemon start --windowed`.)\n\n---\n\n## Choose your integration\n\n`gda` exposes the **same command surface** three ways — pick whichever your agent (or you) supports:\n\n| Entry point | Best for | How |\n| --- | --- | --- |\n| **CLI** (`gda`) | humans, shell scripts, CI, and agents that can run commands | `gda \u003cgroup\u003e \u003ccommand\u003e --json` |\n| **Skill** (`gda skill`) | coding agents that support Agent Skills and prefer a token-light CLI workflow | print/install `SKILL.md` (below) |\n| **MCP** (`gda-mcp`) | agents that call tools over the Model Context Protocol | run the stdio server (below) |\n\n### Use it as a Skill\n\n`gda` ships an agent **Skill** — a `SKILL.md` that teaches an AI agent *how and when* to drive\nGodot from the CLI. It's the lightest way in (no server to register), bundled in the package and\nversion-locked to your install. Print it, or install it into your agent's skills directory:\n\n```bash\ngda skill                                              # print SKILL.md (redirect it anywhere)\ngda skill --install --provider claude --scope user     # resolve a known agent's skills dir\ngda skill --install --dir ~/.claude/skills/gda         # …or give the directory yourself\n```\n\n`--install --provider \u003cclaude|codex\u003e --scope \u003cproject|user\u003e` resolves a known agent's skills\ndirectory (`--scope` defaults to `user`); `--dir` is the neutral fallback for any other agent —\nthere's no built-in default. The [skill recipes](docs/gda-skill.md) list each agent's directory\n(Claude Code's `~/.claude/skills/`, Codex's `~/.agents/skills/`, …). Or fetch the same file straight\nfrom the repo, if you'd rather not go through `gda skill` — you still install `gda`, since the Skill\ndrives it:\n\n```bash\ncurl --create-dirs -o ~/.claude/skills/gda/SKILL.md \\\n  https://raw.githubusercontent.com/aigengame/godot-agent/main/src/gda/skill/SKILL.md\n```\n\n### Use it as an MCP server\n\n`gda` ships a stdio [MCP](https://modelcontextprotocol.io) server behind a `[mcp]` extra,\nso any MCP agent (Claude Code, Codex, Cursor, …) can drive Godot. Try it with no install:\n\n```bash\nuvx --from \"gda[mcp]\" gda-mcp\n```\n\nThe server resolves two pieces of context — which Godot **project** to drive and which Godot\n**binary** to run (MCP can't pass per-call flags):\n\n- **Project** — set `GDA_PROJECT` when your client can't advertise workspace **roots**; otherwise\n  `gda-mcp` auto-detects the project from the roots the client sends (the folder you have open). A\n  *set-but-invalid* `GDA_PROJECT` is a reported error, not a silent fallback. See\n  [Configuration](#configuration) for the full CLI-vs-MCP resolution order.\n- **Engine** — set `GDA_GODOT` to your Godot binary, e.g. `\"GDA_GODOT\": \"/path/to/Godot\"`.\n\n\n#### Register with Coding Agents\n\n\u003cdetails\u003e\n\u003csummary\u003eClaude Code\u003c/summary\u003e\n\nProject scope, `.mcp.json` at the repo root (auto-detects the project via `roots`):\n\n```json\n{\n  \"mcpServers\": {\n    \"gda-mcp\": {\n      \"command\": \"uvx\",\n      \"args\": [\"--from\", \"gda[mcp]\", \"gda-mcp\"]\n    }\n  }\n}\n```\n\nUser scope (every project) — the CLI, which writes `~/.claude.json`:\n\n```bash\nclaude mcp add --scope user gda-mcp -- uvx --from \"gda[mcp]\" gda-mcp\n```\n\n\u003c/details\u003e\n\n\u003cdetails\u003e\n\u003csummary\u003eCodex\u003c/summary\u003e\n\nProject scope, `.codex/config.toml` at the repo root (the project must be trusted):\n\n```toml\n[mcp_servers.gda-mcp]\ncommand = \"uvx\"\nargs = [\"--from\", \"gda[mcp]\", \"gda-mcp\"]\n\n[mcp_servers.gda-mcp.env]\nGDA_PROJECT = \"/absolute/path/to/your/godot/project\"\n```\n\nUser scope (available everywhere, but pinned to one project) — the same table in\n`~/.codex/config.toml`, or add it with the CLI. Codex has no workspace variable, so\n`GDA_PROJECT` is an absolute path; use project scope if you work across several projects:\n\n```bash\ncodex mcp add gda-mcp --env GDA_PROJECT=/absolute/path/to/your/godot/project -- \\\n  uvx --from \"gda[mcp]\" gda-mcp\n```\n\n\u003c/details\u003e\n\n\u003cdetails\u003e\n\u003csummary\u003eCursor\u003c/summary\u003e\n\nProject scope, `.cursor/mcp.json` at the repo root (`${workspaceFolder}`\ntracks the open project):\n\n```json\n{\n  \"mcpServers\": {\n    \"gda-mcp\": {\n      \"type\": \"stdio\",\n      \"command\": \"/path/to/uvx\",\n      \"args\": [\"--from\", \"gda[mcp]\", \"gda-mcp\"],\n      \"env\": {\n        \"GDA_PROJECT\": \"${workspaceFolder}\"\n      }\n    }\n  }\n}\n```\n\nUser scope (available everywhere, but pinned to one project) — the same config in\n`~/.cursor/mcp.json` with `GDA_PROJECT` set to an absolute path (`${workspaceFolder}` only\nworks in project scope; use project scope for several projects). Cursor has no `mcp add`\ncommand — register via the JSON above or the Settings → MCP UI.\n\n\u003e Cursor is GUI-launched with a minimal `PATH`, so a bare `uvx` may not resolve — hence the\n\u003e absolute `command` above; fill it with the output of `which uvx`. Full recipes — PATH\n\u003e injection, Claude Desktop, user vs project scope, per-agent project pinning — are in the\n\u003e [registration recipes](docs/gda-mcp-registration.md).\n\u003c/details\u003e\n\n---\n\n## How it works\n\n`gda` is three components serving operations in two modes:\n\n| Component        | Role                                                                  |\n| ---------------- | --------------------------------------------------------------------- |\n| **`gda`**        | The agent-facing CLI — exposes Godot with structured `--json` output. |\n| **`gda-mcp`**    | An MCP server exposing the same operations as tools, from `--schema`. |\n| **`gda-daemon`** | A per-project process supervising a running game for live operations. |\n\n- **Headless operations** run one-shot — no daemon, nothing to install (create a scene, edit\n  a script, export, analyze).\n- **Live operations** require a running game — `gda-daemon` launches it, injects an inert\n  in-game harness, and brokers requests over a Unix domain socket (runtime tree, input,\n  screenshots, performance, diagnostics).\n\nThe in-game harness `gda-daemon` injects is **dev-only**: `gda export run` strips it from the\nartifact entirely, and built any other way (editor GUI, raw `godot --export`) it still\nself-disables in the exported game — so a shipped game never *runs* anything daemon-related\n(and via `gda export run`, doesn't even carry it).\n\n**Platform \u0026 version support:**\n\n| Mode | Godot | Platforms |\n| ---- | ----- | --------- |\n| **Headless** | 4.4+ | macOS · Linux · Windows¹ |\n| **Live** (via `gda-daemon`) | 4.6+ | macOS · Linux² |\n\n¹ Headless is cross-platform by design (one-shot processes, no platform-specific\n  dependency) — Windows keeps the full headless surface, though CI does not exercise it yet.\n² Live operations use Unix domain sockets, so Windows is not supported yet.\n\n---\n\n## Command reference\n\n`gda` commands are **grouped by Godot domain object** and use a small, consistent verb\nvocabulary, so the same verb means the same thing in every group:\n\n| Verb                | Meaning                                                           |\n| ------------------- | ----------------------------------------------------------------- |\n| `create` / `delete` | Make / remove a **standalone** entity (scene, script, resource).  |\n| `add` / `remove`    | Add / remove a **sub-entity** within a container (node → scene).  |\n| `get` / `list`      | Read one entity / enumerate many.                                 |\n| `set`               | Mutate a property.                                                |\n| domain verbs        | `play`, `run`, `export`, `import`, … kept with their natural meaning. |\n\nEvery command supports `--json` and `--schema` — except `gda schema` itself, which emits\nthe aggregate manifest as JSON directly. Commands that read or mutate a `res://` path\nresolve a [project context](#configuration). Run `gda \u003cgroup\u003e \u003ccommand\u003e --help` for full\nflags — `gda --help` is the authoritative list of what is installed.\n\n**New here?** A good first path: `gda info` → `gda scene create` → `gda node add` →\n`gda script validate` → `gda export run`; then go live with `gda daemon start` → `gda game tree`.\n\n**Meta** — about `gda` / the engine itself\n\n| Command | What it does |\n| ------- | ------------ |\n| `gda info`   | Report the Godot engine version info. |\n| `gda schema` | Emit the whole command surface as one machine-readable JSON manifest. |\n| `gda skill`  | Emit or install the bundled Agent Skill (`SKILL.md`) that teaches an agent how to drive `gda`. |\n\n### Headless commands — Godot 4.4+, all platforms\n\n**`scene`** — scene files (`.tscn`)\n\n| Command | What it does |\n| ------- | ------------ |\n| `scene create` | Create a new `.tscn` with the given root node type. |\n| `scene get` | Read a scene and report its structured node tree. |\n| `scene list` | Enumerate the `.tscn` scenes in the resolved project. |\n| `scene get-exports` | List the `@export` properties a scene's nodes' scripts declare. |\n| `scene delete` | Delete a scene file and report what was removed. |\n\n**`node`** — nodes within a scene file\n\n| Command | What it does |\n| ------- | ------------ |\n| `node add` | Add a node under a parent (built-in type or `class_name` script). |\n| `node get` | Read a node's properties (by node path) as typed JSON. |\n| `node list` | List a scene's node tree with each node's path relative to the root. |\n| `node set` | Set a node property, coercing the value to its declared Godot type. |\n| `node remove` | Remove a node (and its subtree) by node path. |\n| `node duplicate` | Duplicate a node (and its subtree) under its parent. |\n| `node move` | Reparent a node (and its subtree) under a new parent. |\n| `node connect-signal` | Wire a source node's signal to a target node's method. |\n| `node disconnect-signal` | Unwire an existing signal→method connection. |\n\n**`script`** — GDScript files (`.gd`)\n\n| Command | What it does |\n| ------- | ------------ |\n| `script create` | Create a new `.gd` script from a template or verbatim `--content`. |\n| `script get` | Read a script's source plus its `class_name` / `extends` metadata. |\n| `script list` | Enumerate the `.gd` scripts in the resolved project. |\n| `script set` | Edit a script via search-replace, line-range, or full overwrite. |\n| `script delete` | Delete a script file and report what was removed. |\n| `script attach` | Attach a `.gd` script to a node (by node path) in a scene. |\n| `script validate` | Syntax/compile-check a `.gd` script. |\n\n**`project`** — the project as a whole (settings, autoloads, static analysis)\n\n| Command | What it does |\n| ------- | ------------ |\n| `project info` | Report project metadata (name, main scene, viewport, engine version). |\n| `project get` | Read a single project setting by section/key as typed JSON. |\n| `project list` | List the project's settings keys (customized by default; `--all` adds engine defaults, `--section` filters by prefix). |\n| `project set` | Set a project setting, coercing the value to its declared type. |\n| `project add-autoload` | Register an autoload singleton (name → script/scene). |\n| `project remove-autoload` | Unregister an autoload singleton by name. |\n| `project find-references` | Find every project file that references a given resource. |\n| `project dependencies` | Map each scene/resource to the resources it depends on. |\n| `project find-unused-resources` | Find resource files that nothing references. |\n| `project statistics` | Report the project's file/line counts, autoloads, and more. |\n\n**`resource`** — resource files (`.tres`)\n\n| Command | What it does |\n| ------- | ------------ |\n| `resource create` | Create a new `.tres` resource of the given type. |\n| `resource get` | Read a `.tres` resource's properties as typed JSON. |\n| `resource set` | Set a `.tres` property, coercing the value to its declared type. |\n| `resource delete` | Delete a `.tres` resource file and report what was removed. |\n| `resource uid` | Resolve a resource UID ↔ its `res://` path in both directions. |\n\n**`export`** — export presets and artifacts\n\n| Command | What it does |\n| ------- | ------------ |\n| `export list` | Enumerate the project's export presets (name, platform, …). |\n| `export get` | Report one preset's details plus export-template install status. |\n| `export run` | Export a named preset (`release` / `debug` / `pack`) to a destination. |\n\n**`shader`** — shader files (`.gdshader`)\n\n| Command | What it does |\n| ------- | ------------ |\n| `shader create` | Create a new `.gdshader` from a template or verbatim `--content`. |\n| `shader get` | Read a shader's source plus its `shader_type`. |\n| `shader set` | Edit a `.gdshader` via search-replace, line-range, or full overwrite. |\n\n**`theme`** — theme resources (`.tres`)\n\n| Command | What it does |\n| ------- | ------------ |\n| `theme create` | Create a new, loadable `.tres` Theme resource (no-clobber). |\n\n### Live commands — via `gda-daemon`; Godot 4.6+, macOS/Linux\n\n**`daemon`** — the live runtime lifecycle\n\n| Command | What it does |\n| ------- | ------------ |\n| `daemon start` | Start the per-project daemon and install the in-game harness; the engine session launches on the first live op (`--windowed` for `screen` capture). |\n| `daemon stop` | Stop the project's daemon and any running engine session. |\n| `daemon status` | Report the daemon's state (running, windowed mode, session). |\n| `daemon uninstall` | Remove the in-game `gda` harness (autoload entry + files) from the project — an explicit dev-tooling teardown; `gda export run` already strips it from exported artifacts automatically. |\n\n**`game`** — the running game's runtime scene graph\n\n| Command | What it does |\n| ------- | ------------ |\n| `game tree` | Read the running game's runtime scene tree (after `_ready`). |\n| `game get` | Read a runtime node's live properties by node path. |\n| `game set` | Set a runtime node property on the running game. |\n\n**`diag`** — runtime diagnostics\n\n| Command | What it does |\n| ------- | ------------ |\n| `diag errors` | Tail the running game's runtime errors (categorized). |\n\n**`logger`** — structured runtime log\n\n| Command | What it does |\n| ------- | ------------ |\n| `logger tail` | Tail the running game's whole runtime log as structured records (`--level`, `--limit`, `--raw`). |\n\n**`perf`** — performance monitoring\n\n| Command | What it does |\n| ------- | ------------ |\n| `perf monitors` | Snapshot the engine's performance counters (fps, memory, nodes, …). |\n| `perf monitor` | Sample a node property or signal over a frame window (timeline). |\n\n**`input`** — input simulation\n\n| Command | What it does |\n| ------- | ------------ |\n| `input key` | Inject a key event (with modifiers). |\n| `input mouse-click` | Inject a mouse click at `(x, y)`. |\n| `input mouse-move` | Inject mouse motion to `(x, y)`. |\n| `input action` | Press/release a mapped input action. |\n| `input sequence` | Inject a multi-frame event timeline. |\n\n**`screen`** — viewport capture\n\n| Command | What it does |\n| ------- | ------------ |\n| `screen capture` | Capture one viewport frame to a PNG. |\n| `screen frames` | Capture an N-frame PNG sequence. |\n\n### Global flags\n\n| Flag       | Description                                                          |\n| ---------- | ------------------------------------------------------------------- |\n| `--json`    | Emit the result as a single JSON object on stdout. Without it, commands print a concise human-readable rendering. |\n| `--schema`  | Emit the command's input/output JSON Schema contract (no Godot spawned). |\n| `--godot`   | Path to the Godot binary (overrides `$GDA_GODOT` and the default). |\n| `--project` | Godot project directory for `res://` resolution (overrides `$GDA_PROJECT`; defaults to the current directory if it is a project). Domain commands only. Resolving a project runs that project's code — see [Project code execution](#configuration). |\n| `--help`    | Show usage for `gda` or any command.                                |\n\n---\n\n## Configuration\n\n`gda` finds the Godot binary from the **`--godot \u003cpath\u003e`** flag, otherwise the\n**`GDA_GODOT`** environment variable — set one of these so `gda` can locate your engine.\n\nDomain commands resolve a **Godot project** (so `res://` paths and a scene's inter-resource\nreferences resolve deterministically) in this order:\n\n1. The **`--project \u003cdir\u003e`** flag.\n2. The **`GDA_PROJECT`** environment variable.\n3. The **current directory**, when it is a Godot project (contains `project.godot`).\n\nA named directory must be a project, or `gda` reports it as an error. When none resolves,\n`gda` runs **projectless** — only filesystem paths (absolute or cwd-relative) resolve, not\n`res://`. The **MCP server** has no flags, so it resolves a project a little differently:\n\n| Context | Project resolution order |\n| --- | --- |\n| **CLI** | `--project` → `GDA_PROJECT` (both strict — invalid is reported) → cwd if it holds `project.godot`, else projectless |\n| **MCP** (`gda-mcp`) | `GDA_PROJECT` (strict — set-but-invalid is reported, not skipped) → a *valid* client workspace `root` → a *valid* server cwd, else projectless |\n\n\u003cdetails\u003e\n\u003csummary\u003eProject code execution — what runs when you point at a project\u003c/summary\u003e\n\nResolving a project so `res://` paths work runs Godot against that project, and Godot runs\nsome of the project's own code as part of that. Concretely:\n\n- **Autoloads run on every `--project` operation.** When a project is resolved, the engine\n  constructs the project's autoload singletons at startup — before the command's own work\n  runs — so their `_init` (and `_ready`) execute on **every** operation, including read-only\n  ones like `scene get` and `node list`. Without a resolved project, no autoloads are\n  registered, so they do not run.\n- **Commands that instantiate a scene execute that scene's attached scripts' constructors.**\n  A command that needs a live node tree — every mutating command (`node add`, `node set`,\n  `node remove`, …), and `node get` (which reports runtime property defaults the stored data\n  does not carry) — loads and instantiates the scene, which constructs each node and runs the\n  `_init` of any script attached to a node in it. Commands that only read the stored scene\n  data (`scene get`, `scene list`, `node list`) walk it without instantiating, so they do not\n  run those scripts.\n\n`gda` treats the target project as trusted, so this is by design — see\n[ADR-0009](docs/adr/0009-trust-boundary-trusted-project.md) for the trust model.\n\u003c/details\u003e\n\n---\n\n\u003cdetails\u003e\n\u003csummary\u003e\u003cstrong\u003eUnder the hood\u003c/strong\u003e — the structured-output contract \u0026 exit codes\u003c/summary\u003e\n\nHeadless Godot interleaves its banner, warnings, and `print()` output into stdout. `gda`\nsolves this with a sentinel contract\n([ADR-0002](docs/adr/0002-headless-structured-output-contract.md)):\n\n- The GDScript payload emits **exactly one** result, wrapped in unique sentinels on stdout:\n\n  ```\n  \u003c\u003c\u003cGDA:RESULT\u003e\u003e\u003e{ …json… }\u003c\u003c\u003cGDA:END\u003e\u003e\u003e\n  ```\n\n- It routes **all** of its own diagnostics to stderr; stdout carries nothing but the contract.\n- `gda` extracts and parses only the bytes between the sentinels, ignoring the surrounding\n  engine noise, and surfaces stderr for inspection.\n\nThis is what makes `gda`'s output safe to consume programmatically, and it generalizes to\nthe per-message protocol the daemon uses for live operations.\n\n**Exit codes (the CLI ABI).** A failed `gda` run exits with a small, stable code so a shell\nor agent can branch on the failure **category without parsing the JSON error**:\n\n| Exit code | Category      | When                                                                  |\n| --------- | ------------- | --------------------------------------------------------------------- |\n| `0`       | —             | Success.                                                              |\n| `127`     | `environment` | The Godot binary could not be launched (shell convention: not found). |\n| `124`     | `environment` | Godot launched but did not return before the runner timeout (shell convention: timed out). |\n| `3`       | `version`     | The detected Godot version is below the supported minimum.            |\n| `4`       | `operation`   | The engine ran but the operation failed — a registered operation error, an engine crash, or an unstructured non-zero exit. |\n| `5`       | `parse`       | The process claimed success but violated the structured-output contract. |\n| `6`       | `live`        | A live operation failed — e.g. no running daemon/session, or a live timeout. |\n\nThese values are the public ABI; their authoritative source is\n[`src/gda/exit_codes.py`](src/gda/exit_codes.py). The `{\"error\": {category, code, …}}`\nenvelope carries a **finer `code`** within each category (e.g. `path_not_found`,\n`already_exists`, `node_not_found` all sit under `operation` / exit `4`). The full\nregistry lives in\n[ADR-0002's `GdaError.code` table](docs/adr/0002-headless-structured-output-contract.md#gdaerrorcode-registry).\n\u003c/details\u003e\n\n\u003cdetails\u003e\n\u003csummary\u003e\u003cstrong\u003eDevelopment\u003c/strong\u003e\u003c/summary\u003e\n\n```bash\nuv sync                       # set up the environment\n\nuv run pytest                 # run the full suite (includes e2e tests against a real Godot)\nuv run pytest -m \"not e2e\"    # unit tests only (no Godot binary required)\nuv run pytest -m e2e          # only the end-to-end tests (needs Godot 4.4+ on this machine)\n\nuv run ruff check .           # lint\nuv run ruff format .          # auto-format (append --check to verify without writing)\nuv run pyright                # type-check (src/ + tests/, basic mode)\n```\n\nThe `e2e` tier runs by default with `uv run pytest`, and **fails loudly** — naming the\nresolved path and how to fix it — if no Godot binary is found there, rather than skipping.\nDeselect the whole tier with `-m \"not e2e\"` (CI's per-PR job uses exactly this).\n\nLinting and formatting are enforced by [ruff](https://docs.astral.sh/ruff/) — one tool in\nplace of flake8 + black + isort, configured under `[tool.ruff]` in `pyproject.toml` and\npinned via `uv.lock` so local and CI agree. CI's `lint` job runs `ruff check .` and\n`ruff format --check .` on every PR; run `uv run ruff format .` before committing to stay\ngreen.\n\nTypes are checked by [pyright](https://microsoft.github.io/pyright/) in `basic` mode, covering\n`src/` and `tests/` and configured under `[tool.pyright]` in `pyproject.toml` (also pinned via\n`uv.lock`). CI's `type-check` job runs `uv run --frozen pyright` on every PR.\n\n```\nsrc/gda/\n  cli.py            # CLI entrypoint (Typer): all command groups, --json / --schema\n  surface.py        # walks the live Typer tree → the `gda schema` manifest\n  headless.py       # the per-command descriptor (one HeadlessCommand per command)\n  binary.py         # Godot binary resolution (flag \u003e $GDA_GODOT \u003e default)\n  runner.py         # the one-shot headless spawn seam (Protocol + subprocess impl)\n  live_runner.py    # the live-operation client that talks to gda-daemon\n  models.py         # typed I/O models (Pydantic) backing --json and --schema\n  errors.py / error_codes.py / exit_codes.py   # failure classification + the CLI ABI\n  render.py         # human-readable (non-JSON) rendering\n  ops/operations.gd # the headless GDScript payload, dispatched by operation name\n  daemon/           # gda-daemon: server, session supervision, IPC protocol, discovery\n  harness/          # the inert in-game `gda` autoload injected into a live session\n  mcp/              # gda-mcp: the schema → MCP-tool server\ntests/              # unit + e2e tests against a real engine (shared fixtures in conftest.py)\ndocs/adr/           # architecture decision records\nCONTEXT.md          # the project's shared domain language\n```\n\n`gda` has two external boundaries, each behind a seam fast tests inject through: spawning a\none-shot headless process (`runner.py`) and talking to a running game via the daemon\n(`live_runner.py`). The e2e suite drives a real engine across both.\n\u003c/details\u003e\n\n---\n\n## Contributing\n\nContributions are welcome. Read [`CONTEXT.md`](CONTEXT.md) to align with the project's\nshared language, and review the relevant [ADRs](docs/adr/) for the area you're touching.\nIssues and PRDs live as [GitHub issues](https://github.com/aigengame/godot-agent/issues).\nCommits follow the [Conventional Commits](https://www.conventionalcommits.org/) specification.\nPython code is linted and formatted with [ruff](https://docs.astral.sh/ruff/) and type-checked\nwith [pyright](https://microsoft.github.io/pyright/), both enforced in CI — run\n`uv run ruff format .` and `uv run pyright` before committing (see **Development** above).\n\n\u003e **Working with an AI coding agent?** This project is built to be agent-navigable —\n\u003e [`AGENTS.md`](AGENTS.md) is the entry point for coding agents, wiring in the project's\n\u003e rules, domain docs, and skills.\n\n## License\n\nReleased under the [MIT License](LICENSE). Copyright (c) 2026 aigengame.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Faigengame%2Fgodot-agent","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Faigengame%2Fgodot-agent","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Faigengame%2Fgodot-agent/lists"}