{
  "id": "godot-4-api-guard",
  "type": "loadout",
  "title": "Godot 4 guard against Godot 3 code",
  "summary": "Stop agents writing yield, export var, KinematicBody2D and other Godot 3 code into Godot 4 projects, with a scanner that finds every case and Godot's own check.",
  "description": "The most common complaint from people making games in Godot with coding agents is the same every week: ask for Godot 4 code and get Godot 3. yield(), export var, onready, setget, KinematicBody2D, move_and_slide(velocity) and connect(\"signal\", self, \"method\") all come from years of Godot 3 tutorials, and Godot 4 refuses to parse most of them. A rules file alone helps, but it is a request, not a check.\n\nThis loadout pairs a short Cursor rule and AGENTS.md (a never/always table) with a skill that checks the work. A standard-library Python scanner reports every Godot 3 keyword and renamed API in one pass, using the official upgrade guide and the engine's own 3-to-4 rename map. Godot's parser stops at the first error, so the scanner is what saves the extra runs. Then `godot --headless --check-only --script` confirms each changed script really loads in Godot 4. The verifier runs both against a Godot 4 project and a Godot 3 sample with the pinned Godot 4.7.2 binary.\n",
  "highlights": [
    "Never/always table for GDScript 2.0 in a .gd-scoped Cursor rule",
    "Scanner finds 30+ Godot 3 keywords and renamed APIs in one pass, read-only",
    "Godot's --check-only confirms each changed script parses in Godot 4",
    "CharacterBody2D traps: built-in velocity, move_and_slide() with no arguments",
    "Rename table built from the official upgrade guide and engine rename map"
  ],
  "version": "1.0.0",
  "license": "MIT",
  "author": {
    "name": "SetupBay",
    "url": "https://setupbay.com"
  },
  "credits": [
    {
      "title": "Godot docs: upgrading from Godot 3 to Godot 4",
      "url": "https://docs.godotengine.org/en/stable/tutorials/migrating/upgrading_to_godot_4.html"
    },
    {
      "title": "Godot engine source: renames_map_3_to_4.cpp (the upgrade tool's rename list)",
      "url": "https://github.com/godotengine/godot/blob/master/editor/project_upgrade/renames_map_3_to_4.cpp"
    },
    {
      "title": "Godot docs: command line tutorial (--headless, --check-only)",
      "url": "https://docs.godotengine.org/en/stable/tutorials/editor/command_line_tutorial.html"
    },
    {
      "title": "@shipthejam: let the agent run godot --headless --check-only on its own code",
      "url": "https://x.com/shipthejam/status/2112875220184789383"
    },
    {
      "title": "@VibeKitLab: a .gd-scoped Cursor rule to stop Godot 3 syntax",
      "url": "https://x.com/VibeKitLab/status/2111850753765904736"
    }
  ],
  "categories": [
    "gamedev"
  ],
  "stacks": [
    "godot",
    "gdscript",
    "python"
  ],
  "files": [
    {
      "path": "AGENTS.md",
      "role": "instructions",
      "description": "Godot 4 version facts, rules and the done checklist.",
      "skill": null,
      "agent": null,
      "install_to": {
        "claude-code": "AGENTS.md",
        "codex": "AGENTS.md",
        "cursor": "AGENTS.md",
        "gemini-cli": "AGENTS.md",
        "antigravity-cli": "AGENTS.md",
        "copilot": "AGENTS.md"
      },
      "raw_url": "https://setupbay.com/raw/godot-4-api-guard/1.0.0/AGENTS.md",
      "raw_latest_url": "https://setupbay.com/raw/godot-4-api-guard/latest/AGENTS.md",
      "bytes": 2045,
      "lang": "markdown",
      "content": "# AGENTS.md: Godot 4 project (Godot 3 guard)\n\nThis is a **Godot 4** project. Much of what you remember about Godot is Godot 3, and Godot 4 does not parse it.\nTreat every GDScript line you write as suspect until the guard and Godot have both checked it.\n\n## Version facts\n- Engine: Godot 4.x (see `project.godot`: `config_version=5`; the 4.x minor is in `config/features`).\n- GDScript 2.0: annotations (`@export`, `@onready`, `@tool`, `@rpc`), `await`, first-class signals and callables,\n  typed arrays (`Array[Node]`), property setters/getters inline.\n- If you are not sure an API exists in Godot 4, look it up in the class reference for this version\n  (https://docs.godotengine.org/en/stable/classes/) instead of guessing. Do not copy Godot 3 tutorials or answers.\n\n## Rules\n- Write Godot 4 only. The `godot-4-guard` skill has the full Godot 3 → 4 rename table; the common traps are:\n  `@export`/`@onready`/`@tool` (not keywords), `await` (not `yield`), `CharacterBody2D` (not `KinematicBody2D`),\n  `instantiate()`, `is_empty()`, `deg_to_rad`, `randf_range`, `snapped`, `change_scene_to_file`, `Time.get_ticks_msec()`.\n- Static types everywhere: `var speed: float = 200.0`, `func hit(amount: int) -> void:`.\n- `CharacterBody2D`/`3D` have a built-in `velocity`. Do not declare your own; call `move_and_slide()` with no arguments.\n- Signals: `signal died`, `died.emit()`, `button.pressed.connect(_on_pressed)`.\n- Never hand-edit `.tscn` or `.tres` files saved by Godot 3 (`format=2`), and never edit `.godot/`.\n- Never run the project upgrade tool or convert a Godot 3 project yourself. Ask the human, after a commit.\n\n## Before you say \"done\"\n1. Run the `godot-4-guard` scanner on the folders you touched; it must report `0 error(s)`.\n2. Run `godot --headless --path . --check-only --script res://<file>.gd` for every changed script; no `SCRIPT ERROR`.\n3. Run the project headless for a few seconds (`godot --headless --path . --quit-after 300`) and read the output.\n4. Tell the human what to try by hand (controls, feel) in one or two lines.\n"
    },
    {
      "path": "CLAUDE.md",
      "role": "adapter",
      "description": "Imports AGENTS.md for Claude Code.",
      "skill": null,
      "agent": "claude-code",
      "install_to": {
        "claude-code": "CLAUDE.md",
        "codex": null,
        "cursor": null,
        "gemini-cli": null,
        "antigravity-cli": null,
        "copilot": null
      },
      "raw_url": "https://setupbay.com/raw/godot-4-api-guard/1.0.0/CLAUDE.md",
      "raw_latest_url": "https://setupbay.com/raw/godot-4-api-guard/latest/CLAUDE.md",
      "bytes": 371,
      "lang": "markdown",
      "content": "# CLAUDE.md\n\n@AGENTS.md\n\n## Claude Code notes\n\n- Skills from this loadout live in `.claude/skills/`: `godot-4-guard`. Use them when their description matches the task.\n- Follow AGENTS.md above; where this file and AGENTS.md disagree, AGENTS.md wins.\n\n<!-- From SetupBay \"Godot 4 guard against Godot 3 code\" v1.0.0 — https://setupbay.com/loadouts/godot-4-api-guard/ -->\n"
    },
    {
      "path": "GEMINI.md",
      "role": "adapter",
      "description": "Imports AGENTS.md for Gemini CLI.",
      "skill": null,
      "agent": "gemini-cli",
      "install_to": {
        "claude-code": null,
        "codex": null,
        "cursor": null,
        "gemini-cli": "GEMINI.md",
        "antigravity-cli": null,
        "copilot": null
      },
      "raw_url": "https://setupbay.com/raw/godot-4-api-guard/1.0.0/GEMINI.md",
      "raw_latest_url": "https://setupbay.com/raw/godot-4-api-guard/latest/GEMINI.md",
      "bytes": 372,
      "lang": "markdown",
      "content": "# GEMINI.md\n\n@./AGENTS.md\n\n## Gemini CLI notes\n\n- Skills from this loadout live in `.agents/skills/`: `godot-4-guard`. Use them when their description matches the task.\n- Follow AGENTS.md above; where this file and AGENTS.md disagree, AGENTS.md wins.\n\n<!-- From SetupBay \"Godot 4 guard against Godot 3 code\" v1.0.0 — https://setupbay.com/loadouts/godot-4-api-guard/ -->\n"
    },
    {
      "path": ".cursor/rules/godot-4-only.mdc",
      "role": "rules",
      "description": "Never/always table for .gd files.",
      "skill": null,
      "agent": null,
      "install_to": {
        "claude-code": null,
        "codex": null,
        "cursor": ".cursor/rules/godot-4-only.mdc",
        "gemini-cli": null,
        "antigravity-cli": null,
        "copilot": null
      },
      "raw_url": "https://setupbay.com/raw/godot-4-api-guard/1.0.0/.cursor/rules/godot-4-only.mdc",
      "raw_latest_url": "https://setupbay.com/raw/godot-4-api-guard/latest/.cursor/rules/godot-4-only.mdc",
      "bytes": 1182,
      "lang": "markdown",
      "content": "---\ndescription: Godot 4 GDScript only; never Godot 3 syntax or APIs\nglobs: \"**/*.gd\"\nalwaysApply: false\n---\n\nThis project is Godot 4 (`config_version=5`). Never write Godot 3 GDScript.\n\n| Never (Godot 3) | Always (Godot 4) |\n|---|---|\n| `tool`, `export var`, `onready var` | `@tool`, `@export var`, `@onready var` |\n| `yield(timer, \"timeout\")` | `await get_tree().create_timer(t).timeout` |\n| `setget` | `var x: int: set = _set_x` |\n| `connect(\"sig\", self, \"_m\")` | `sig.connect(_m)` |\n| `KinematicBody2D`, `Spatial` | `CharacterBody2D`, `Node3D` |\n| `move_and_slide(velocity, Vector2.UP)` | set `velocity`, then `move_and_slide()` |\n| `.instance()`, `.empty()` | `.instantiate()`, `.is_empty()` |\n| `deg2rad`, `rand_range`, `stepify` | `deg_to_rad`, `randf_range`, `snapped` |\n| `change_scene(path)` | `change_scene_to_file(path)` |\n| `OS.get_ticks_msec()`, `File.new()` | `Time.get_ticks_msec()`, `FileAccess.open()` |\n| `Tween.new()` + `interpolate_property` | `create_tween().tween_property()` |\n\n- Type every variable, parameter and return value.\n- After editing a `.gd` file, run the `godot-4-guard` skill's scanner and `godot --headless --check-only --script res://<file>`.\n"
    },
    {
      "path": "skills/godot-4-guard/SKILL.md",
      "role": "skill",
      "description": "Scan for Godot 3 code, then let Godot check each script.",
      "skill": "godot-4-guard",
      "agent": null,
      "install_to": {
        "claude-code": ".claude/skills/godot-4-guard/SKILL.md",
        "codex": ".agents/skills/godot-4-guard/SKILL.md",
        "cursor": ".agents/skills/godot-4-guard/SKILL.md",
        "gemini-cli": ".agents/skills/godot-4-guard/SKILL.md",
        "antigravity-cli": ".agents/skills/godot-4-guard/SKILL.md",
        "copilot": ".agents/skills/godot-4-guard/SKILL.md"
      },
      "raw_url": "https://setupbay.com/raw/godot-4-api-guard/1.0.0/skills/godot-4-guard/SKILL.md",
      "raw_latest_url": "https://setupbay.com/raw/godot-4-api-guard/latest/skills/godot-4-guard/SKILL.md",
      "bytes": 3564,
      "lang": "markdown",
      "content": "---\nname: godot-4-guard\ndescription: Check GDScript for Godot 3 syntax and renamed APIs before saying a Godot 4 change is done. Use after writing or editing any .gd file, when Godot reports a parse error, or when porting Godot 3 code, tutorials or snippets into a Godot 4 project.\n---\n\n# Godot 4 guard\n\nModels trained on years of Godot 3 tutorials still write `yield`, `export var`, `onready`, `KinematicBody2D` and\n`move_and_slide(velocity)` into Godot 4 projects. Godot 4 refuses to parse most of it, but its parser stops at the\nfirst error, so fixing one line at a time wastes runs. This skill finds them all at once, then lets Godot itself confirm.\n\n## 1. Confirm the project is Godot 4\n- `project.godot` must contain `config_version=5`. If it says `config_version=4`, this is a Godot 3 project:\n  stop and tell the human. Porting a whole project is the editor's job (Project → Tools → Upgrade Project), after a commit.\n- `godot --version` should print `4.x`. If `godot` is not on the PATH, ask where the Godot 4 binary is.\n\n## 2. Scan for Godot 3 code\n```bash\npython3 .agents/skills/godot-4-guard/scripts/gd3_guard.py scenes autoload\n```\n(Use the path the skill was installed to: `.claude/skills/...` for Claude Code, `.agents/skills/...` for the others.\nWith no arguments it scans the whole project, skipping `.godot/`, `addons/` and agent folders.)\n\n- Every `error` line is Godot 3 code. Fix each one with the replacement the line gives. `references/rename-table.md`\n  has the full table with examples.\n- `warn` lines are style: `emit_signal(\"x\")` still works but `x.emit()` is the Godot 4 form; untyped functions\n  should get `-> void` or a return type; `TileMap` is deprecated since 4.3 in favour of `TileMapLayer`.\n- Run it again until it prints `0 error(s)`.\n\n## 3. Let Godot check every changed script\n```bash\ngodot --headless --path . --check-only --script res://scenes/player/player.gd\n```\n- Run it for each `.gd` file you changed. Any `SCRIPT ERROR` or `Parse Error` line means the script does not load,\n  whatever the exit code says.\n- If it complains about an unknown `class_name`, run `godot --headless --path . --import` once so the global class\n  cache exists, then check again.\n- `--check-only` does not load autoloads. A script that names one (`GameState.score = 10`) reports\n  `Identifier not found: GameState` even though the game runs. For those scripts, the headless run below is the check.\n- Then run the project briefly: `godot --headless --path . --quit-after 300` and read the output for errors.\n\n## 4. Fixes that need care\n- **`move_and_slide`**: `CharacterBody2D` already has `velocity` and `up_direction`. Delete any `var velocity`\n  you added (it now clashes with the built-in), set `velocity`, call `move_and_slide()` with no arguments.\n- **`yield` with a function state**: `await some_function()` waits for a coroutine; `await signal` waits for a signal.\n- **`setget`**: move the setter into the property (`var hp: int = 3: set = set_hp`). In Godot 4 the setter also\n  runs when the class assigns `hp` itself (Godot 3 skipped it without `self.`), so check code that relied on that.\n  Inside an inline `set(value):` block, `hp = value` stores the value directly without calling the setter again.\n- **Scenes (`.tscn`)**: never rewrite a Godot 3 scene by hand. Ask the human to open it in the Godot 4 editor.\n\n## 5. Report\nSay how many Godot 3 lines you replaced, which files, and that the guard and `--check-only` were clean. If something\ncould only be checked by playing (input feel, physics), say what the human should try.\n"
    },
    {
      "path": "skills/godot-4-guard/scripts/gd3_guard.py",
      "role": "reference",
      "description": "Read-only scanner for Godot 3 GDScript and APIs.",
      "skill": "godot-4-guard",
      "agent": null,
      "install_to": {
        "claude-code": ".claude/skills/godot-4-guard/scripts/gd3_guard.py",
        "codex": ".agents/skills/godot-4-guard/scripts/gd3_guard.py",
        "cursor": ".agents/skills/godot-4-guard/scripts/gd3_guard.py",
        "gemini-cli": ".agents/skills/godot-4-guard/scripts/gd3_guard.py",
        "antigravity-cli": ".agents/skills/godot-4-guard/scripts/gd3_guard.py",
        "copilot": ".agents/skills/godot-4-guard/scripts/gd3_guard.py"
      },
      "raw_url": "https://setupbay.com/raw/godot-4-api-guard/1.0.0/skills/godot-4-guard/scripts/gd3_guard.py",
      "raw_latest_url": "https://setupbay.com/raw/godot-4-api-guard/latest/skills/godot-4-guard/scripts/gd3_guard.py",
      "bytes": 7928,
      "lang": "markdown",
      "content": "#!/usr/bin/env python3\n\"\"\"Find Godot 3 GDScript and API names in a Godot 4 project.\n\nUsage: python3 gd3_guard.py [PATH ...]        (default: the current folder)\n       python3 gd3_guard.py --list            (print every rule)\n\nScans .gd files (skips .godot/ and addons/ unless named). Prints one line per finding:\n  path:line: [rule] what is wrong -> what Godot 4 uses\nExit 0 when nothing at \"error\" level is found, 1 when something is, 2 on bad usage.\nStandard library only. Read-only: it never edits a file.\n\"\"\"\nimport os\nimport re\nimport sys\n\n# (rule id, level, regex, message). Patterns are matched against code with comments and strings removed.\nRULES = [\n    (\"yield\", \"error\", r\"\\byield\\s*\\(\", \"yield() was removed -> await signal (await get_tree().create_timer(t).timeout)\"),\n    (\"onready-keyword\", \"error\", r\"^\\s*onready\\s+var\\b\", \"onready keyword -> @onready var\"),\n    (\"export-keyword\", \"error\", r\"^\\s*export\\b(\\s*\\(.*\\))?\\s+var\\b\", \"export keyword -> @export var (@export_range, @export_enum, ...)\"),\n    (\"tool-keyword\", \"error\", r\"^\\s*tool\\s*$\", \"tool keyword -> @tool annotation\"),\n    (\"setget\", \"error\", r\"\\bsetget\\b\", \"setget -> property syntax: var x: int: set = _set_x, get = _get_x\"),\n    (\"rpc-keywords\", \"error\", r\"^\\s*(remote|remotesync|master|mastersync|puppet|puppetsync)\\s+func\\b\", \"network keywords -> @rpc(\\\"any_peer\\\") / @rpc(\\\"authority\\\") annotations\"),\n    (\"connect-string-target\", \"error\", r\"\\.connect\\(\\s*\\\"[A-Za-z_]\\w*\\\"\\s*,\\s*[A-Za-z_]\\w*\\s*,\", \"connect(\\\"signal\\\", obj, \\\"method\\\") -> signal_name.connect(obj.method)\"),\n    (\"kinematic-body\", \"error\", r\"\\bKinematicBody(2D)?\\b\", \"KinematicBody / KinematicBody2D -> CharacterBody3D / CharacterBody2D\"),\n    (\"spatial\", \"error\", r\"\\b(Spatial|SpatialMaterial)\\b\", \"Spatial -> Node3D, SpatialMaterial -> StandardMaterial3D\"),\n    (\"move-and-slide-args\", \"error\", r\"\\bmove_and_slide\\(\\s*[^)\\s]\", \"move_and_slide(velocity, ...) -> set velocity (and up_direction), then move_and_slide()\"),\n    (\"instance\", \"error\", r\"\\.instance\\(\\s*\\)\", \"PackedScene.instance() -> instantiate()\"),\n    (\"array-empty\", \"error\", r\"\\.empty\\(\\s*\\)\", \".empty() -> .is_empty()\"),\n    (\"deg2rad\", \"error\", r\"\\b(deg2rad|rad2deg)\\s*\\(\", \"deg2rad / rad2deg -> deg_to_rad / rad_to_deg\"),\n    (\"rand-range\", \"error\", r\"\\brand_range\\s*\\(\", \"rand_range -> randf_range (floats) or randi_range (ints)\"),\n    (\"stepify\", \"error\", r\"\\bstepify\\s*\\(\", \"stepify -> snapped\"),\n    (\"str2var\", \"error\", r\"\\b(str2var|var2str|bytes2var|var2bytes)\\s*\\(\", \"str2var / var2str -> str_to_var / var_to_str\"),\n    (\"linear-interpolate\", \"error\", r\"\\.linear_interpolate\\s*\\(\", \"linear_interpolate -> lerp\"),\n    (\"pool-arrays\", \"error\", r\"\\bPool(Byte|Int|Real|String|Vector2|Vector3|Color)Array\\b\", \"PoolXArray -> PackedXArray (PoolRealArray -> PackedFloat32Array)\"),\n    (\"change-scene\", \"error\", r\"\\.change_scene\\s*\\(\", \"change_scene(path) -> change_scene_to_file(path)\"),\n    (\"change-scene-to\", \"error\", r\"\\.change_scene_to\\s*\\(\", \"change_scene_to(packed) -> change_scene_to_packed(packed)\"),\n    (\"os-ticks\", \"error\", r\"\\bOS\\.get_(ticks_msec|ticks_usec|unix_time|datetime)\\s*\\(\", \"OS time functions -> Time.get_ticks_msec(), Time.get_unix_time_from_system(), ...\"),\n    (\"mouse-button\", \"error\", r\"\\bBUTTON_(LEFT|RIGHT|MIDDLE|WHEEL_UP|WHEEL_DOWN)\\b\", \"BUTTON_LEFT -> MOUSE_BUTTON_LEFT\"),\n    (\"file-directory\", \"error\", r\"\\b(File|Directory)\\.new\\(\\s*\\)\", \"File.new() / Directory.new() -> FileAccess.open(...) / DirAccess.open(...)\"),\n    (\"funcref\", \"error\", r\"\\bfuncref\\s*\\(\", \"funcref(obj, \\\"m\\\") -> Callable(obj, \\\"m\\\") or obj.m\"),\n    (\"tween-node\", \"error\", r\"\\.interpolate_property\\s*\\(|\\bTween\\.new\\(\\s*\\)\", \"Tween node -> var t := create_tween(); t.tween_property(...)\"),\n    (\"editor-hint\", \"error\", r\"\\bEngine\\.editor_hint\\b\", \"Engine.editor_hint -> Engine.is_editor_hint()\"),\n    (\"rect-props\", \"error\", r\"\\brect_(position|size|min_size|rotation|scale|global_position|pivot_offset)\\b\", \"Control rect_* -> position, size, custom_minimum_size, rotation, scale, pivot_offset\"),\n    (\"raycast-cast-to\", \"error\", r\"\\bcast_to\\b\", \"RayCast cast_to -> target_position\"),\n    (\"renamed-nodes\", \"error\", r\"\\b(Position2D|Position3D|VisibilityNotifier2D|VisibilityNotifier|YSort|Navigation2D|Particles2D|Light2D\\.MODE_)\\b\", \"renamed or removed node -> Marker2D/3D, VisibleOnScreenNotifier2D/3D, y_sort_enabled, NavigationAgent2D, GPUParticles2D\"),\n    (\"set-input-handled\", \"error\", r\"get_tree\\(\\)\\.set_input_as_handled\\s*\\(\", \"get_tree().set_input_as_handled() -> get_viewport().set_input_as_handled()\"),\n    (\"os-window\", \"error\", r\"\\bOS\\.(window_size|window_fullscreen|set_window_title|window_position)\\b\", \"OS window API -> get_window().size / DisplayServer.window_set_mode(...)\"),\n    (\"emit-signal-string\", \"warn\", r\"\\bemit_signal\\(\\s*\\\"\", \"emit_signal(\\\"x\\\") still works, but Godot 4 style is x.emit(...)\"),\n    (\"tilemap-node\", \"warn\", r\"\\bextends\\s+TileMap\\b|:\\s*TileMap\\b\", \"TileMap is deprecated since Godot 4.3 -> one TileMapLayer node per layer\"),\n    (\"untyped-func\", \"warn\", r\"^\\s*func\\s+\\w+\\([^)]*\\)\\s*:\", \"function without a return type -> add -> void (or the type it returns)\"),\n]\nCOMPILED = [(rid, lvl, re.compile(rx), msg) for rid, lvl, rx, msg in RULES]\nSKIP_DIRS = {\".godot\", \".import\", \".git\", \".agents\", \".claude\", \".cursor\", \"addons\", \"build\", \"export\"}\n\n\ndef code_only(line):\n    \"\"\"Drop string contents and trailing comments, keeping quote marks so patterns can see a string was there.\"\"\"\n    out, i, q = [], 0, None\n    while i < len(line):\n        c = line[i]\n        if q:\n            if c == \"\\\\\":\n                i += 2\n                continue\n            if c == q:\n                q = None\n                out.append(c)\n            i += 1\n            continue\n        if c in \"\\\"'\":\n            q = c\n            out.append(c)\n        elif c == \"#\":\n            break\n        else:\n            out.append(c)\n        i += 1\n    return \"\".join(out)\n\n\ndef keep_strings_for(rule_id):\n    # A few rules need to see that the first argument is a string literal (not its contents).\n    return rule_id in (\"connect-string-target\", \"emit-signal-string\")\n\n\ndef scan_file(path):\n    found = []\n    with open(path, encoding=\"utf-8\", errors=\"replace\") as fh:\n        for n, raw in enumerate(fh, 1):\n            stripped = code_only(raw.rstrip(\"\\n\"))\n            if not stripped.strip():\n                continue\n            for rid, lvl, rx, msg in COMPILED:\n                # Strings are reduced to \"\" by code_only; patterns that need a quoted first arg match `\"\"`.\n                text = stripped\n                if keep_strings_for(rid):\n                    text = re.sub(r\"\\\"\\\"\", \"\\\"s\\\"\", stripped)\n                if rx.search(text):\n                    found.append((path, n, rid, lvl, msg))\n    return found\n\n\ndef iter_files(paths):\n    for p in paths:\n        if os.path.isfile(p):\n            if p.endswith(\".gd\"):\n                yield p\n            continue\n        for root, dirs, files in os.walk(p):\n            dirs[:] = sorted(d for d in dirs if d not in SKIP_DIRS)\n            for f in sorted(files):\n                if f.endswith(\".gd\"):\n                    yield os.path.join(root, f)\n\n\ndef main(argv):\n    if argv[:1] == [\"--list\"]:\n        for rid, lvl, _, msg in RULES:\n            print(f\"{lvl:5} {rid:22} {msg}\")\n        return 0\n    if any(a.startswith(\"-\") for a in argv):\n        print(__doc__.strip(), file=sys.stderr)\n        return 2\n    paths = argv or [\".\"]\n    files = list(iter_files(paths))\n    findings = [f for path in files for f in scan_file(path)]\n    for path, n, rid, lvl, msg in findings:\n        print(f\"{os.path.relpath(path)}:{n}: {lvl} [{rid}] {msg}\")\n    errors = sum(1 for f in findings if f[3] == \"error\")\n    warns = len(findings) - errors\n    print(f\"gd3-guard: {len(files)} file(s), {errors} error(s), {warns} warning(s)\")\n    return 1 if errors else 0\n\n\nif __name__ == \"__main__\":\n    sys.exit(main(sys.argv[1:]))\n"
    },
    {
      "path": "skills/godot-4-guard/references/rename-table.md",
      "role": "reference",
      "description": "Godot 3 to 4 table of syntax, nodes and methods.",
      "skill": "godot-4-guard",
      "agent": null,
      "install_to": {
        "claude-code": ".claude/skills/godot-4-guard/references/rename-table.md",
        "codex": ".agents/skills/godot-4-guard/references/rename-table.md",
        "cursor": ".agents/skills/godot-4-guard/references/rename-table.md",
        "gemini-cli": ".agents/skills/godot-4-guard/references/rename-table.md",
        "antigravity-cli": ".agents/skills/godot-4-guard/references/rename-table.md",
        "copilot": ".agents/skills/godot-4-guard/references/rename-table.md"
      },
      "raw_url": "https://setupbay.com/raw/godot-4-api-guard/1.0.0/skills/godot-4-guard/references/rename-table.md",
      "raw_latest_url": "https://setupbay.com/raw/godot-4-api-guard/latest/skills/godot-4-guard/references/rename-table.md",
      "bytes": 3756,
      "lang": "markdown",
      "content": "# Godot 3 → Godot 4: what agents get wrong most\n\nSources: the official \"Upgrading from Godot 3 to Godot 4\" guide and the engine's own rename map\n(`editor/project_upgrade/renames_map_3_to_4.cpp`). The guard script checks every row marked ✓.\n\n## GDScript syntax\n\n| Godot 3 | Godot 4 | ✓ |\n|---|---|---|\n| `tool` | `@tool` | ✓ |\n| `export var x = 1`, `export(int) var x` | `@export var x: int = 1`, `@export_range(0, 10) var x: int` | ✓ |\n| `onready var s = $Sprite` | `@onready var s: Sprite2D = $Sprite2D` | ✓ |\n| `yield(obj, \"signal\")` | `await obj.signal` | ✓ |\n| `yield(get_tree().create_timer(1), \"timeout\")` | `await get_tree().create_timer(1.0).timeout` | ✓ |\n| `var hp setget set_hp, get_hp` | `var hp: int: set = set_hp, get = get_hp` (or inline `set(value):`) | ✓ |\n| `connect(\"pressed\", self, \"_on_pressed\")` | `pressed.connect(_on_pressed)` | ✓ |\n| `emit_signal(\"died\")` | `died.emit()` (the old form still works; warning only) | ✓ |\n| `remote func`, `master func`, `puppet func` | `@rpc(\"any_peer\")`, `@rpc(\"authority\")` | ✓ |\n| `funcref(obj, \"m\")` | `Callable(obj, \"m\")` or `obj.m` | ✓ |\n\n## Nodes and classes\n\n| Godot 3 | Godot 4 | ✓ |\n|---|---|---|\n| `KinematicBody2D`, `KinematicBody` | `CharacterBody2D`, `CharacterBody3D` | ✓ |\n| `Spatial`, `SpatialMaterial` | `Node3D`, `StandardMaterial3D` | ✓ |\n| `Position2D` / `Position3D` | `Marker2D` / `Marker3D` | ✓ |\n| `VisibilityNotifier2D` | `VisibleOnScreenNotifier2D` | ✓ |\n| `YSort` | any `CanvasItem` with `y_sort_enabled = true` | ✓ |\n| `Navigation2D` | `NavigationAgent2D` + `NavigationRegion2D` | ✓ |\n| `Particles2D` | `GPUParticles2D` (or `CPUParticles2D`) | ✓ |\n| `Tween` node, `interpolate_property` | `create_tween().tween_property(node, \"position\", to, 0.3)` | ✓ |\n| `File.new()`, `Directory.new()` | `FileAccess.open(path, FileAccess.READ)`, `DirAccess.open(path)` | ✓ |\n| `PoolStringArray`, `PoolRealArray`, ... | `PackedStringArray`, `PackedFloat32Array`, ... | ✓ |\n| `TileMap` (4.0–4.2) | `TileMapLayer`, one node per layer (TileMap deprecated in 4.3) | warn |\n\n## Methods and properties\n\n| Godot 3 | Godot 4 | ✓ |\n|---|---|---|\n| `move_and_slide(velocity, Vector2.UP)` | set `velocity` (built in) and `up_direction`, then `move_and_slide()` | ✓ |\n| `scene.instance()` | `scene.instantiate()` | ✓ |\n| `array.empty()` | `array.is_empty()` | ✓ |\n| `deg2rad`, `rad2deg` | `deg_to_rad`, `rad_to_deg` | ✓ |\n| `rand_range(a, b)` | `randf_range(a, b)` / `randi_range(a, b)` | ✓ |\n| `stepify(x, s)` | `snapped(x, s)` | ✓ |\n| `str2var`, `var2str` | `str_to_var`, `var_to_str` | ✓ |\n| `a.linear_interpolate(b, t)` | `a.lerp(b, t)` | ✓ |\n| `get_tree().change_scene(path)` | `get_tree().change_scene_to_file(path)` | ✓ |\n| `change_scene_to(packed)` | `change_scene_to_packed(packed)` | ✓ |\n| `OS.get_ticks_msec()` | `Time.get_ticks_msec()` | ✓ |\n| `OS.window_size`, `OS.window_fullscreen` | `get_window().size`, `DisplayServer.window_set_mode(...)` | ✓ |\n| `BUTTON_LEFT` | `MOUSE_BUTTON_LEFT` | ✓ |\n| `Engine.editor_hint` | `Engine.is_editor_hint()` | ✓ |\n| `rect_position`, `rect_size`, `rect_min_size` | `position`, `size`, `custom_minimum_size` | ✓ |\n| `RayCast2D.cast_to` | `target_position` | ✓ |\n| `get_tree().set_input_as_handled()` | `get_viewport().set_input_as_handled()` | ✓ |\n\n## Things the guard can't see\n\n- Signal argument changes (for example `body_entered` handlers that expected extra binds): read the class reference.\n- `.tscn` files saved by Godot 3 (`format=2`). Never hand-convert scenes; open the project in the Godot 4 editor\n  and let it convert, after a commit.\n- Shader changes (`hint_color` → `source_color`, renamed built-ins). Check shaders against the shading reference.\n"
    },
    {
      "path": "skills/godot-4-guard/references/godot3-sample.gd.txt",
      "role": "reference",
      "description": "A Godot 3 player script for checking the guard.",
      "skill": "godot-4-guard",
      "agent": null,
      "install_to": {
        "claude-code": ".claude/skills/godot-4-guard/references/godot3-sample.gd.txt",
        "codex": ".agents/skills/godot-4-guard/references/godot3-sample.gd.txt",
        "cursor": ".agents/skills/godot-4-guard/references/godot3-sample.gd.txt",
        "gemini-cli": ".agents/skills/godot-4-guard/references/godot3-sample.gd.txt",
        "antigravity-cli": ".agents/skills/godot-4-guard/references/godot3-sample.gd.txt",
        "copilot": ".agents/skills/godot-4-guard/references/godot3-sample.gd.txt"
      },
      "raw_url": "https://setupbay.com/raw/godot-4-api-guard/1.0.0/skills/godot-4-guard/references/godot3-sample.gd.txt",
      "raw_latest_url": "https://setupbay.com/raw/godot-4-api-guard/latest/skills/godot-4-guard/references/godot3-sample.gd.txt",
      "bytes": 956,
      "lang": "markdown",
      "content": "# A Godot 3 player script, the kind agents still write into Godot 4 projects.\n# Kept as .txt so Godot never tries to load it. The guard's own check copies it to a .gd file.\ntool\nextends KinematicBody2D\n\nsignal died\n\nexport(float) var speed = 200.0\nexport var jump_force = 400.0\nonready var sprite = $Sprite\nvar hp = 3 setget set_hp\nvar motion = Vector2()\n\nfunc _ready():\n\t$HurtBox.connect(\"body_entered\", self, \"_on_hurt\")\n\tyield(get_tree().create_timer(0.5), \"timeout\")\n\nfunc _physics_process(delta):\n\tmotion.x = Input.get_action_strength(\"move_right\") - Input.get_action_strength(\"move_left\")\n\tmotion.x *= speed\n\tmotion.y += 980 * delta\n\tmotion = move_and_slide(motion, Vector2.UP)\n\nfunc set_hp(value):\n\thp = value\n\tif hp <= 0:\n\t\temit_signal(\"died\")\n\t\tget_tree().change_scene(\"res://scenes/ui/game_over.tscn\")\n\nfunc _on_hurt(body):\n\tvar puff = preload(\"res://scenes/fx/puff.tscn\").instance()\n\tpuff.rotation = deg2rad(rand_range(0, 360))\n\tadd_child(puff)\n"
    }
  ],
  "requires": {
    "tools": [
      "godot-4",
      "python3"
    ],
    "env": [],
    "mcp": []
  },
  "tested": {
    "status": "untested",
    "last_run": null,
    "fixture": null,
    "per_agent": {
      "claude-code": "untested",
      "codex": "untested",
      "cursor": "untested",
      "gemini-cli": "untested",
      "antigravity-cli": "untested",
      "copilot": "untested"
    }
  },
  "security": {
    "scanned": true,
    "scanner": "intake-precheck/2",
    "verdict": "clean",
    "network": false,
    "scripts": [
      "gd3_guard.py"
    ],
    "notes": "The scanner only reads .gd files and prints findings; it never edits files and makes no network calls."
  },
  "featured": false,
  "deprecated": false,
  "last_checked": "2026-10-24",
  "published": "2026-10-24",
  "updated": "2026-10-24",
  "compatibility": {
    "claude-code": "native",
    "codex": "native",
    "cursor": "native",
    "gemini-cli": "native",
    "antigravity-cli": "native",
    "copilot": "native"
  },
  "counts": {
    "rules": 2,
    "skills": 1,
    "mcp": 0
  },
  "url": "https://setupbay.com/loadouts/godot-4-api-guard/",
  "api_url": "https://setupbay.com/api/loadouts/godot-4-api-guard.json",
  "verification": {
    "level": "verified-install",
    "status": "verified",
    "label": "Verified install",
    "verified": true,
    "checked_at": "2026-10-24T10:30:13Z",
    "commit": "42646ff9a52315018c9b0947c291c7ad980e1dc7",
    "content_current": true,
    "agent_tests": "not-run",
    "counts": {
      "pass": 9,
      "fail": 0,
      "skip": 0,
      "not_applicable": 1
    },
    "meaning": "Level 1: automated checks on the files (parse, install paths, MCP config, safety scan, references, size, licence, starter build). No AI agent was run.",
    "checks": [
      {
        "id": "listing",
        "name": "Listing",
        "status": "pass",
        "summary": "Schema valid; 8 files declared, none missing or extra",
        "details": [
          "tested.status: untested (agent tests are separate from Level 1)"
        ]
      },
      {
        "id": "parse",
        "name": "Files parse",
        "status": "pass",
        "summary": "All 8 files parse; front matter valid",
        "details": []
      },
      {
        "id": "adapters",
        "name": "Adapters",
        "status": "pass",
        "summary": "CLAUDE.md and GEMINI.md import AGENTS.md and are up to date",
        "details": [
          "CLAUDE.md: matches the generator",
          "GEMINI.md: matches the generator"
        ]
      },
      {
        "id": "install-paths",
        "name": "Install paths",
        "status": "pass",
        "summary": "Correct paths for all 6 agents; layouts re-discovered",
        "details": [
          "Claude Code: 6 files, 1 skill in .claude/skills/",
          "Codex CLI: 5 files, 1 skill in .agents/skills/",
          "Cursor: 6 files, 1 skill in .agents/skills/, 1 rule",
          "Gemini CLI: 6 files, 1 skill in .agents/skills/",
          "Antigravity CLI: 5 files, 1 skill in .agents/skills/",
          "GitHub Copilot: 5 files, 1 skill in .agents/skills/"
        ]
      },
      {
        "id": "mcp",
        "name": "MCP config",
        "status": "n/a",
        "summary": "No MCP servers in this loadout",
        "details": []
      },
      {
        "id": "safety",
        "name": "Safety scan",
        "status": "pass",
        "summary": "Clean: no credentials, risky shell, hidden text or covert instructions",
        "details": [
          "Scanner intake-precheck/2: verdict clean; network no (listing says no)"
        ]
      },
      {
        "id": "references",
        "name": "References",
        "status": "pass",
        "summary": "3 references between files resolve for every agent",
        "details": []
      },
      {
        "id": "size",
        "name": "Size limits",
        "status": "pass",
        "summary": "8 files, 19.7 KB total; largest skills/godot-4-guard/scripts/gd3_guard.py 7.7 KB",
        "details": [
          "Limits: 30 files, 32 KB per file, 128 KB total, 500 lines per skill or rule"
        ]
      },
      {
        "id": "licence",
        "name": "Licence",
        "status": "pass",
        "summary": "MIT, by SetupBay; text in the repository LICENSE",
        "details": []
      },
      {
        "id": "starter-build",
        "name": "Starter build",
        "status": "pass",
        "summary": "The godot-4-guard scanner passes a Godot 4 project and flags every Godot 3 construct in the skill's sample; Godot 4.7.2 itself parses the project's scripts with --check-only (the autoload-using player through the headless run), rejects the Godot 3 sample, and runs the project headless with no script",
        "details": [
          "Applied 12 loadout files at every agent's paths",
          "godot 4.7.2-stable",
          "✓ scanner: Godot 4 project is clean: bash -c python3 .agents/skills/godot-4-guard/scripts/gd3_guard.py; echo \"exit=$?\"",
          "✓ scanner: Godot 3 sample is flagged line by line: bash -c mkdir -p /tmp/gd3-sample && cp .agents/skills/godot-4-guard/references/godot3-sample.gd.txt /tmp/gd3-sample/player3.gd && python3 .agents/skills/godot-4-guard/scripts/gd3_guard.py /tmp/gd3-sample; echo \"exit=$?\"",
          "✓ import project (headless): ${GODOT_BIN} --headless --import --path .",
          "✓ godot --check-only on scripts that use no autoload: bash -c for s in res://scenes/player/stats.gd res://autoload/game_state.gd; do \"$GODOT_BIN\" --headless --path . --check-only --script $s 2>&1 || echo \"FAILED $s\"; done; echo checked",
          "✓ godot --check-only rejects the Godot 3 sample: bash -c mkdir -p legacy && cp .agents/skills/godot-4-guard/references/godot3-sample.gd.txt legacy/player3.gd && \"$GODOT_BIN\" --headless --path . --check-only --script res://legacy/player3.gd 2>&1; echo \"exit=$?\"; rm -rf legacy",
          "✓ run headless (covers the player script, which uses the GameState autoload): ${GODOT_BIN} --headless --path . --quit-after 300",
          "Covers: The scanner's rules against real Godot 3 code: keywords (tool, export, onready, setget, yield), connect with string targets, KinematicBody2D, move_and_slide(velocity), renamed functions",
          "Covers: No false positives on a typed Godot 4 project with an inline setter, annotations, await and callables",
          "Covers: Godot's own --check-only as the second check: project scripts load, the Godot 3 sample does not",
          "Covers: --check-only does not load autoloads, so scripts that use one are checked by the headless run instead (the skill says so)",
          "Covers: Not covered: .tscn scenes saved by Godot 3 and shaders (the skill tells the agent to hand those to the editor)"
        ]
      }
    ]
  },
  "install": {
    "claude-code": {
      "files": [
        {
          "path": "AGENTS.md",
          "target": "AGENTS.md",
          "raw_url": "https://setupbay.com/raw/godot-4-api-guard/1.0.0/AGENTS.md",
          "role": "instructions"
        },
        {
          "path": "CLAUDE.md",
          "target": "CLAUDE.md",
          "raw_url": "https://setupbay.com/raw/godot-4-api-guard/1.0.0/CLAUDE.md",
          "role": "adapter"
        },
        {
          "path": "skills/godot-4-guard/SKILL.md",
          "target": ".claude/skills/godot-4-guard/SKILL.md",
          "raw_url": "https://setupbay.com/raw/godot-4-api-guard/1.0.0/skills/godot-4-guard/SKILL.md",
          "role": "skill"
        },
        {
          "path": "skills/godot-4-guard/scripts/gd3_guard.py",
          "target": ".claude/skills/godot-4-guard/scripts/gd3_guard.py",
          "raw_url": "https://setupbay.com/raw/godot-4-api-guard/1.0.0/skills/godot-4-guard/scripts/gd3_guard.py",
          "role": "reference"
        },
        {
          "path": "skills/godot-4-guard/references/rename-table.md",
          "target": ".claude/skills/godot-4-guard/references/rename-table.md",
          "raw_url": "https://setupbay.com/raw/godot-4-api-guard/1.0.0/skills/godot-4-guard/references/rename-table.md",
          "role": "reference"
        },
        {
          "path": "skills/godot-4-guard/references/godot3-sample.gd.txt",
          "target": ".claude/skills/godot-4-guard/references/godot3-sample.gd.txt",
          "raw_url": "https://setupbay.com/raw/godot-4-api-guard/1.0.0/skills/godot-4-guard/references/godot3-sample.gd.txt",
          "role": "reference"
        }
      ],
      "manual_steps": [],
      "zip_url": "https://setupbay.com/download/godot-4-api-guard/claude-code.zip"
    },
    "codex": {
      "files": [
        {
          "path": "AGENTS.md",
          "target": "AGENTS.md",
          "raw_url": "https://setupbay.com/raw/godot-4-api-guard/1.0.0/AGENTS.md",
          "role": "instructions"
        },
        {
          "path": "skills/godot-4-guard/SKILL.md",
          "target": ".agents/skills/godot-4-guard/SKILL.md",
          "raw_url": "https://setupbay.com/raw/godot-4-api-guard/1.0.0/skills/godot-4-guard/SKILL.md",
          "role": "skill"
        },
        {
          "path": "skills/godot-4-guard/scripts/gd3_guard.py",
          "target": ".agents/skills/godot-4-guard/scripts/gd3_guard.py",
          "raw_url": "https://setupbay.com/raw/godot-4-api-guard/1.0.0/skills/godot-4-guard/scripts/gd3_guard.py",
          "role": "reference"
        },
        {
          "path": "skills/godot-4-guard/references/rename-table.md",
          "target": ".agents/skills/godot-4-guard/references/rename-table.md",
          "raw_url": "https://setupbay.com/raw/godot-4-api-guard/1.0.0/skills/godot-4-guard/references/rename-table.md",
          "role": "reference"
        },
        {
          "path": "skills/godot-4-guard/references/godot3-sample.gd.txt",
          "target": ".agents/skills/godot-4-guard/references/godot3-sample.gd.txt",
          "raw_url": "https://setupbay.com/raw/godot-4-api-guard/1.0.0/skills/godot-4-guard/references/godot3-sample.gd.txt",
          "role": "reference"
        }
      ],
      "manual_steps": [],
      "zip_url": "https://setupbay.com/download/godot-4-api-guard/codex.zip"
    },
    "cursor": {
      "files": [
        {
          "path": "AGENTS.md",
          "target": "AGENTS.md",
          "raw_url": "https://setupbay.com/raw/godot-4-api-guard/1.0.0/AGENTS.md",
          "role": "instructions"
        },
        {
          "path": ".cursor/rules/godot-4-only.mdc",
          "target": ".cursor/rules/godot-4-only.mdc",
          "raw_url": "https://setupbay.com/raw/godot-4-api-guard/1.0.0/.cursor/rules/godot-4-only.mdc",
          "role": "rules"
        },
        {
          "path": "skills/godot-4-guard/SKILL.md",
          "target": ".agents/skills/godot-4-guard/SKILL.md",
          "raw_url": "https://setupbay.com/raw/godot-4-api-guard/1.0.0/skills/godot-4-guard/SKILL.md",
          "role": "skill"
        },
        {
          "path": "skills/godot-4-guard/scripts/gd3_guard.py",
          "target": ".agents/skills/godot-4-guard/scripts/gd3_guard.py",
          "raw_url": "https://setupbay.com/raw/godot-4-api-guard/1.0.0/skills/godot-4-guard/scripts/gd3_guard.py",
          "role": "reference"
        },
        {
          "path": "skills/godot-4-guard/references/rename-table.md",
          "target": ".agents/skills/godot-4-guard/references/rename-table.md",
          "raw_url": "https://setupbay.com/raw/godot-4-api-guard/1.0.0/skills/godot-4-guard/references/rename-table.md",
          "role": "reference"
        },
        {
          "path": "skills/godot-4-guard/references/godot3-sample.gd.txt",
          "target": ".agents/skills/godot-4-guard/references/godot3-sample.gd.txt",
          "raw_url": "https://setupbay.com/raw/godot-4-api-guard/1.0.0/skills/godot-4-guard/references/godot3-sample.gd.txt",
          "role": "reference"
        }
      ],
      "manual_steps": [],
      "zip_url": "https://setupbay.com/download/godot-4-api-guard/cursor.zip"
    },
    "gemini-cli": {
      "files": [
        {
          "path": "AGENTS.md",
          "target": "AGENTS.md",
          "raw_url": "https://setupbay.com/raw/godot-4-api-guard/1.0.0/AGENTS.md",
          "role": "instructions"
        },
        {
          "path": "GEMINI.md",
          "target": "GEMINI.md",
          "raw_url": "https://setupbay.com/raw/godot-4-api-guard/1.0.0/GEMINI.md",
          "role": "adapter"
        },
        {
          "path": "skills/godot-4-guard/SKILL.md",
          "target": ".agents/skills/godot-4-guard/SKILL.md",
          "raw_url": "https://setupbay.com/raw/godot-4-api-guard/1.0.0/skills/godot-4-guard/SKILL.md",
          "role": "skill"
        },
        {
          "path": "skills/godot-4-guard/scripts/gd3_guard.py",
          "target": ".agents/skills/godot-4-guard/scripts/gd3_guard.py",
          "raw_url": "https://setupbay.com/raw/godot-4-api-guard/1.0.0/skills/godot-4-guard/scripts/gd3_guard.py",
          "role": "reference"
        },
        {
          "path": "skills/godot-4-guard/references/rename-table.md",
          "target": ".agents/skills/godot-4-guard/references/rename-table.md",
          "raw_url": "https://setupbay.com/raw/godot-4-api-guard/1.0.0/skills/godot-4-guard/references/rename-table.md",
          "role": "reference"
        },
        {
          "path": "skills/godot-4-guard/references/godot3-sample.gd.txt",
          "target": ".agents/skills/godot-4-guard/references/godot3-sample.gd.txt",
          "raw_url": "https://setupbay.com/raw/godot-4-api-guard/1.0.0/skills/godot-4-guard/references/godot3-sample.gd.txt",
          "role": "reference"
        }
      ],
      "manual_steps": [],
      "zip_url": "https://setupbay.com/download/godot-4-api-guard/gemini-cli.zip"
    },
    "antigravity-cli": {
      "files": [
        {
          "path": "AGENTS.md",
          "target": "AGENTS.md",
          "raw_url": "https://setupbay.com/raw/godot-4-api-guard/1.0.0/AGENTS.md",
          "role": "instructions"
        },
        {
          "path": "skills/godot-4-guard/SKILL.md",
          "target": ".agents/skills/godot-4-guard/SKILL.md",
          "raw_url": "https://setupbay.com/raw/godot-4-api-guard/1.0.0/skills/godot-4-guard/SKILL.md",
          "role": "skill"
        },
        {
          "path": "skills/godot-4-guard/scripts/gd3_guard.py",
          "target": ".agents/skills/godot-4-guard/scripts/gd3_guard.py",
          "raw_url": "https://setupbay.com/raw/godot-4-api-guard/1.0.0/skills/godot-4-guard/scripts/gd3_guard.py",
          "role": "reference"
        },
        {
          "path": "skills/godot-4-guard/references/rename-table.md",
          "target": ".agents/skills/godot-4-guard/references/rename-table.md",
          "raw_url": "https://setupbay.com/raw/godot-4-api-guard/1.0.0/skills/godot-4-guard/references/rename-table.md",
          "role": "reference"
        },
        {
          "path": "skills/godot-4-guard/references/godot3-sample.gd.txt",
          "target": ".agents/skills/godot-4-guard/references/godot3-sample.gd.txt",
          "raw_url": "https://setupbay.com/raw/godot-4-api-guard/1.0.0/skills/godot-4-guard/references/godot3-sample.gd.txt",
          "role": "reference"
        }
      ],
      "manual_steps": [],
      "zip_url": "https://setupbay.com/download/godot-4-api-guard/antigravity-cli.zip"
    },
    "copilot": {
      "files": [
        {
          "path": "AGENTS.md",
          "target": "AGENTS.md",
          "raw_url": "https://setupbay.com/raw/godot-4-api-guard/1.0.0/AGENTS.md",
          "role": "instructions"
        },
        {
          "path": "skills/godot-4-guard/SKILL.md",
          "target": ".agents/skills/godot-4-guard/SKILL.md",
          "raw_url": "https://setupbay.com/raw/godot-4-api-guard/1.0.0/skills/godot-4-guard/SKILL.md",
          "role": "skill"
        },
        {
          "path": "skills/godot-4-guard/scripts/gd3_guard.py",
          "target": ".agents/skills/godot-4-guard/scripts/gd3_guard.py",
          "raw_url": "https://setupbay.com/raw/godot-4-api-guard/1.0.0/skills/godot-4-guard/scripts/gd3_guard.py",
          "role": "reference"
        },
        {
          "path": "skills/godot-4-guard/references/rename-table.md",
          "target": ".agents/skills/godot-4-guard/references/rename-table.md",
          "raw_url": "https://setupbay.com/raw/godot-4-api-guard/1.0.0/skills/godot-4-guard/references/rename-table.md",
          "role": "reference"
        },
        {
          "path": "skills/godot-4-guard/references/godot3-sample.gd.txt",
          "target": ".agents/skills/godot-4-guard/references/godot3-sample.gd.txt",
          "raw_url": "https://setupbay.com/raw/godot-4-api-guard/1.0.0/skills/godot-4-guard/references/godot3-sample.gd.txt",
          "role": "reference"
        }
      ],
      "manual_steps": [],
      "zip_url": "https://setupbay.com/download/godot-4-api-guard/copilot.zip"
    }
  },
  "source_zip_url": "https://setupbay.com/download/godot-4-api-guard/source.zip"
}