{
  "id": "phaser-4-api-guard",
  "type": "loadout",
  "title": "Phaser 4 guard for Phaser 3 pipelines, FX and masks",
  "summary": "Stop agents writing setPipeline, preFX, postFX, BitmapMask and setTintFill into Phaser 4 games, and catch the Math.TAU change that compiles but breaks rotations.",
  "description": "npm i phaser has installed Phaser 4 since April 2026, but nearly every Phaser example an agent learnt from is Phaser 3. Phaser 4 replaced the WebGL renderer, so the commonest Phaser 3 calls are gone: pipelines (setPipeline('Light2D')), preFX and postFX, BitmapMask, setTintFill, Geom.Point and Structs.Set. Other changes compile and still break the game: Math.TAU is now PI * 2 rather than PI / 2, RenderTexture drawing waits for render(), and roundPixels is off by default.\n\nThis loadout pairs a short Cursor rule and AGENTS.md (check the version, then a never/always table) with a skill that checks the work. A standard-library Python scanner reports removed Phaser 3 APIs as errors and the silent changes as warnings, then tsc checks the code against Phaser 4's own types. It also points the agent at the migration skills Phaser now ships inside the npm package. The verifier runs it on a Phaser 4 scene and a Phaser 3.90 sample with the pinned phaser 4.2.1 and TypeScript 7.0.2.\n",
  "highlights": [
    "Checks package.json first, and stays on Phaser 3 if the game is still 3.x",
    "Scanner flags pipelines, preFX/postFX, BitmapMask and setTintFill as errors",
    "Warns on Math.TAU, now PI * 2, and RenderTexture draws without render()",
    "tsc against Phaser 4.2.1's types rejects every removed call in the sample",
    "Points agents at the migration skills shipped in node_modules/phaser/skills"
  ],
  "version": "1.0.0",
  "license": "MIT",
  "author": {
    "name": "SetupBay",
    "url": "https://setupbay.com"
  },
  "credits": [
    {
      "title": "Phaser v3 to v4 migration guide",
      "url": "https://cdn.jsdelivr.net/npm/phaser@4.2.1/changelog/v4/4.0/MIGRATION-GUIDE.md"
    },
    {
      "title": "Phaser's v3-to-v4-migration agent skill",
      "url": "https://github.com/phaserjs/phaser/tree/master/skills/v3-to-v4-migration"
    },
    {
      "title": "phaser 4.2.1 on npm",
      "url": "https://www.npmjs.com/package/phaser/v/4.2.1"
    },
    {
      "title": "@shipthejam: npm i phaser now installs Phaser 4, so pin the version and tell the agent",
      "url": "https://x.com/shipthejam/status/2112434664006951184"
    },
    {
      "title": "@phaser_: building a Phaser 4 game with Codex",
      "url": "https://x.com/phaser_/status/2111917873304121443"
    }
  ],
  "categories": [
    "gamedev"
  ],
  "stacks": [
    "phaser",
    "typescript"
  ],
  "files": [
    {
      "path": "AGENTS.md",
      "role": "instructions",
      "description": "Version check, Phaser 4 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/phaser-4-api-guard/1.0.0/AGENTS.md",
      "raw_latest_url": "https://setupbay.com/raw/phaser-4-api-guard/latest/AGENTS.md",
      "bytes": 2450,
      "lang": "markdown",
      "content": "# AGENTS.md: Phaser 4 game (Phaser 3 API guard)\n\nThis game runs **Phaser 4** (`phaser` 4.2.x), with TypeScript. `npm i phaser` has installed Phaser 4 since\nApril 2026, and 3.90.0 was the last Phaser 3 release. Nearly every Phaser tutorial and answer you learnt from is\nPhaser 3, and Phaser 4 replaced the renderer: pipelines, preFX/postFX and BitmapMask are gone.\n\n## Check the version first\n- Read `package.json`. If `phaser` is `3.x`, this file doesn't apply: write Phaser 3 code and don't use any\n  Phaser 4 API. If it's `4.x`, follow the rules below. If you're not sure, stop and ask.\n- Phaser 4 ships its own agent skills in the package: `node_modules/phaser/skills/`. Read\n  `node_modules/phaser/skills/v3-to-v4-migration/SKILL.md` before porting Phaser 3 code, and the topic skill\n  (for example `filters-and-postfx`, `render-textures`) before using an API you're unsure of.\n- The types are the truth: `node_modules/phaser/types/phaser.d.ts`. If `tsc` says a property doesn't exist, it's\n  gone. Don't cast to `any` to get round it.\n\n## Rules\n- Write Phaser 4 code only. The `phaser-4-guard` skill has the table. The common ones are:\n  - `setPipeline('Light2D')` → `setLighting(true)` (and `this.lights.enable()`)\n  - `preFX` / `postFX` → `obj.enableFilters()`, then `obj.filters.internal` / `obj.filters.external`, or `camera.filters`\n  - `BitmapMask` → `obj.filters.internal.addMask(maskObject)`\n  - `setTintFill(c)` → `setTint(c).setTintMode(Phaser.TintModes.FILL)`\n  - `Geom.Point` → `Phaser.Math.Vector2`. `Structs.Set` / `Map` → native `Set` / `Map`\n  - `Math.PI2` → `Math.TAU`. **`Math.TAU` is now `PI * 2`**; in Phaser 3 it was `PI / 2`. Use `Math.PI_OVER_2` for a quarter turn.\n  - `colorMatrix.sepia()` → `colorMatrix.colorMatrix.sepia()`\n- `RenderTexture` / `DynamicTexture` drawing is buffered: call `.render()` after `draw()`, `stamp()` and so on.\n- `roundPixels` now defaults to `false`. For pixel art set `pixelArt: true` or choose a `vertexRoundMode`.\n- Don't make raw WebGL calls. Use an `Extern` game object if you need to.\n- Don't upgrade or downgrade Phaser without asking.\n\n## Before you say \"done\"\n1. Run the `phaser-4-guard` scanner on `src` and `package.json`. It must report `0 error(s)`. Any warning you leave needs a reason.\n2. Run `npx tsc --noEmit`. It must pass, with no new `any` or `@ts-ignore` around Phaser calls.\n3. If you changed rendering, filters or lighting, run the game and look at it.\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/phaser-4-api-guard/1.0.0/CLAUDE.md",
      "raw_latest_url": "https://setupbay.com/raw/phaser-4-api-guard/latest/CLAUDE.md",
      "bytes": 390,
      "lang": "markdown",
      "content": "# CLAUDE.md\n\n@AGENTS.md\n\n## Claude Code notes\n\n- Skills from this loadout live in `.claude/skills/`: `phaser-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 \"Phaser 4 guard for Phaser 3 pipelines, FX and masks\" v1.0.0 — https://setupbay.com/loadouts/phaser-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/phaser-4-api-guard/1.0.0/GEMINI.md",
      "raw_latest_url": "https://setupbay.com/raw/phaser-4-api-guard/latest/GEMINI.md",
      "bytes": 391,
      "lang": "markdown",
      "content": "# GEMINI.md\n\n@./AGENTS.md\n\n## Gemini CLI notes\n\n- Skills from this loadout live in `.agents/skills/`: `phaser-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 \"Phaser 4 guard for Phaser 3 pipelines, FX and masks\" v1.0.0 — https://setupbay.com/loadouts/phaser-4-api-guard/ -->\n"
    },
    {
      "path": ".cursor/rules/phaser-4-only.mdc",
      "role": "rules",
      "description": "Never/always table for game source and package.json.",
      "skill": null,
      "agent": null,
      "install_to": {
        "claude-code": null,
        "codex": null,
        "cursor": ".cursor/rules/phaser-4-only.mdc",
        "gemini-cli": null,
        "antigravity-cli": null,
        "copilot": null
      },
      "raw_url": "https://setupbay.com/raw/phaser-4-api-guard/1.0.0/.cursor/rules/phaser-4-only.mdc",
      "raw_latest_url": "https://setupbay.com/raw/phaser-4-api-guard/latest/.cursor/rules/phaser-4-only.mdc",
      "bytes": 1219,
      "lang": "markdown",
      "content": "---\ndescription: Phaser 4 only; never Phaser 3 pipelines, FX or masks\nglobs: \"src/**/*.ts,src/**/*.js,package.json\"\nalwaysApply: false\n---\n\nThis game uses Phaser 4 (check `package.json`; if it says 3.x, ignore this rule and stay on Phaser 3).\n\n| Never (Phaser 3) | Always (Phaser 4) |\n|---|---|\n| `sprite.setPipeline(\"Light2D\")` | `sprite.setLighting(true)` and `this.lights.enable()` |\n| `sprite.preFX.addGlow()`, `postFX` | `sprite.enableFilters()` then `sprite.filters.internal.addGlow()` |\n| `new Display.Masks.BitmapMask(...)`, `setMask` | `sprite.filters.internal.addMask(maskObject)` |\n| `setTintFill(0xff0000)` | `setTint(0xff0000).setTintMode(Phaser.TintModes.FILL)` |\n| `new Geom.Point(x, y)` | `new Phaser.Math.Vector2(x, y)` |\n| `Math.PI2`; `Math.TAU` meaning a quarter turn | `Math.TAU` (= PI * 2); `Math.PI_OVER_2` |\n| `new Structs.Set()` / `Structs.Map` | native `Set` / `Map` |\n| `cm.sepia()` | `cm.colorMatrix.sepia()` |\n| `rt.draw(obj)` and nothing else | `rt.draw(obj).render()` |\n| `this.add.mesh()`, `textures.generate()` | removed; ask |\n\n- Official guide: `node_modules/phaser/skills/v3-to-v4-migration/SKILL.md`.\n- After editing, run the `phaser-4-guard` skill's scanner and `npx tsc --noEmit`.\n"
    },
    {
      "path": "skills/phaser-4-guard/SKILL.md",
      "role": "skill",
      "description": "Scan for Phaser 3 APIs and silent changes, then type-check against Phaser 4's types.",
      "skill": "phaser-4-guard",
      "agent": null,
      "install_to": {
        "claude-code": ".claude/skills/phaser-4-guard/SKILL.md",
        "codex": ".agents/skills/phaser-4-guard/SKILL.md",
        "cursor": ".agents/skills/phaser-4-guard/SKILL.md",
        "gemini-cli": ".agents/skills/phaser-4-guard/SKILL.md",
        "antigravity-cli": ".agents/skills/phaser-4-guard/SKILL.md",
        "copilot": ".agents/skills/phaser-4-guard/SKILL.md"
      },
      "raw_url": "https://setupbay.com/raw/phaser-4-api-guard/1.0.0/skills/phaser-4-guard/SKILL.md",
      "raw_latest_url": "https://setupbay.com/raw/phaser-4-api-guard/latest/skills/phaser-4-guard/SKILL.md",
      "bytes": 2418,
      "lang": "markdown",
      "content": "---\nname: phaser-4-guard\ndescription: Check a Phaser 4 game for Phaser 3 APIs (pipelines, preFX/postFX, BitmapMask, setTintFill, Geom.Point, Math.PI2) and silent changes such as Math.TAU and buffered RenderTexture drawing, then type-check against Phaser 4's own types. Use after writing or editing Phaser scenes, when tsc says a Phaser property doesn't exist, or when porting a Phaser 3 tutorial.\n---\n\n# Phaser 4 guard\n\n`npm i phaser` gives you Phaser 4, but most Phaser examples online are Phaser 3. Phaser 4 replaced the renderer,\nso the commonest Phaser 3 calls (`setPipeline`, `preFX`, `postFX`, `BitmapMask`) no longer exist. Some changes don't\nfail at all: `Math.TAU` changed value, and RenderTexture drawing does nothing until `render()`.\n\n## 1. Confirm the version\n- `node -p \"require('phaser/package.json').version\"` should print `4.x`. If it's `3.x`, stop: this skill is for Phaser 4.\n\n## 2. Scan\n```bash\npython3 .agents/skills/phaser-4-guard/scripts/phaser4_guard.py src package.json\n```\n(Use the path the skill was installed to: `.claude/skills/...` for Claude Code, `.agents/skills/...` for the others.)\n\n- Each `error` line is a Phaser 3 API that Phaser 4 removed. Fix it with the replacement on the line, or look it up\n  in `references/v3-to-v4.md`.\n- Each `warn` line is a change that compiles but may behave differently: `Math.TAU`, a texture `draw()` that may need\n  `.render()`, `roundPixels`, `GeometryMask` (Canvas only), Grid `outline*` names, raw WebGL. Check each one. When it's\n  right, add `// guard: ok <reason>` to the line.\n\n## 3. Type-check against Phaser 4\n```bash\nnpx tsc --noEmit\n```\n- Phaser 4's types are generated from its source, so `Property 'postFX' does not exist` means the API is gone, not\n  that the types are wrong. Never cast to `any` or add `@ts-ignore` to keep a Phaser 3 call.\n- For JavaScript projects, add `// @ts-check` to the file or `\"checkJs\": true` to get the same errors.\n\n## 4. Read the official guide when porting\nPhaser ships agent skills in the package. For anything not in the table, read\n`node_modules/phaser/skills/v3-to-v4-migration/SKILL.md`, then the topic skill such as\n`node_modules/phaser/skills/filters-and-postfx/SKILL.md`.\n\n## 5. Report\nSay which Phaser 3 calls you replaced, which warnings you kept and why, and that the scanner and `tsc` were clean.\nIf you changed rendering, filters or lighting, say whether you ran the game and looked at it.\n"
    },
    {
      "path": "skills/phaser-4-guard/scripts/phaser4_guard.py",
      "role": "reference",
      "description": "Read-only scanner for removed Phaser 3 APIs and Phaser 4 behaviour changes.",
      "skill": "phaser-4-guard",
      "agent": null,
      "install_to": {
        "claude-code": ".claude/skills/phaser-4-guard/scripts/phaser4_guard.py",
        "codex": ".agents/skills/phaser-4-guard/scripts/phaser4_guard.py",
        "cursor": ".agents/skills/phaser-4-guard/scripts/phaser4_guard.py",
        "gemini-cli": ".agents/skills/phaser-4-guard/scripts/phaser4_guard.py",
        "antigravity-cli": ".agents/skills/phaser-4-guard/scripts/phaser4_guard.py",
        "copilot": ".agents/skills/phaser-4-guard/scripts/phaser4_guard.py"
      },
      "raw_url": "https://setupbay.com/raw/phaser-4-api-guard/1.0.0/skills/phaser-4-guard/scripts/phaser4_guard.py",
      "raw_latest_url": "https://setupbay.com/raw/phaser-4-api-guard/latest/skills/phaser-4-guard/scripts/phaser4_guard.py",
      "bytes": 7295,
      "lang": "markdown",
      "content": "#!/usr/bin/env python3\n\"\"\"Find Phaser 3 APIs that Phaser 4 removed or changed, in a Phaser 4 game's .ts/.js files.\n\nUsage: python3 phaser4_guard.py [PATH ...]        (default: the current folder)\n       python3 phaser4_guard.py --list            (print every rule)\n\nA \"guard: ok\" comment on a line silences its warnings (never its errors).\nPrints one line per finding:  path:line: level [rule] what is wrong -> what to use\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 and makes no network calls.\n\"\"\"\nimport fnmatch\nimport os\nimport re\nimport sys\n\n# (rule id, level, regex, message, file patterns). Patterns run against each line with comments removed.\nRULES = [\n    ('set-pipeline', 'error', '\\\\.setPipeline\\\\(|\\\\.setPostPipeline\\\\(|\\\\.resetPipeline\\\\(|pipelines\\\\.(add|get)\\\\(',\n     'pipelines were removed in Phaser 4 -> render nodes (RenderConfig#renderNodes); for lights use setLighting(true)', []),\n    ('prefx-postfx', 'error', '\\\\.(preFX|postFX)\\\\b',\n     'preFX/postFX were replaced by filters -> obj.filters.internal / obj.filters.external (enable with obj.enableFilters())', []),\n    ('bitmap-mask', 'error', '\\\\bBitmapMask\\\\b|\\\\.createBitmapMask\\\\(',\n     'BitmapMask was removed -> obj.filters.internal.addMask(maskObject)', []),\n    ('geometry-mask-webgl', 'warn', '\\\\bcreateGeometryMask\\\\(|\\\\bGeometryMask\\\\b',\n     'GeometryMask only works in the Canvas renderer in Phaser 4 -> the Mask filter for WebGL', []),\n    ('set-tint-fill', 'error', '\\\\.setTintFill\\\\(|\\\\.tintFill\\\\b',\n     'setTintFill()/tintFill were removed -> setTint(c).setTintMode(Phaser.TintModes.FILL)', []),\n    ('geom-point', 'error', '\\\\bGeom\\\\.Point\\\\b',\n     'Geom.Point was removed -> Phaser.Math.Vector2', []),\n    ('math-pi2', 'error', '\\\\bMath\\\\.PI2\\\\b',\n     'Phaser.Math.PI2 was removed -> Phaser.Math.TAU (now PI * 2)', []),\n    ('struct-set-map', 'error', '\\\\bStructs\\\\.(Set|Map)\\\\b',\n     'Phaser.Structs.Set/Map were removed -> native Set / Map', []),\n    ('mesh-plane', 'error', '\\\\.add\\\\.(mesh|plane)\\\\(|\\\\bGameObjects\\\\.(Mesh|Plane)\\\\b',\n     'Mesh and Plane were removed in Phaser 4', []),\n    ('textures-generate', 'error', '\\\\btextures\\\\.generate\\\\(|\\\\bCreate\\\\.GenerateTexture\\\\b',\n     'TextureManager.generate / Create.GenerateTexture were removed -> draw to a Graphics and generateTexture(), or load an image', []),\n    ('bloom-shine-fx', 'error', '\\\\.add(Bloom|Shine|Circle|Gradient)\\\\(',\n     'the Bloom/Shine/Circle/Gradient FX were removed -> Phaser.Actions.AddEffectBloom/AddEffectShine/AddMaskShape, or the Gradient game object', []),\n    ('color-matrix-direct', 'error', '(?<![.\\\\w])(cm|colorMatrix|matrixFX|cmFX|grade|fx)\\\\.(sepia|grayscale|blackWhite|brown|vintagePinhole|kodachrome|technicolor|polaroid|shiftToBGR|desaturate|saturate|hue|brightness|contrast|night|lsd|negative)\\\\(',\n     'ColorMatrix methods moved onto .colorMatrix -> filter.colorMatrix.sepia()', []),\n    ('spine-bundled', 'error', 'SpinePlugin|phaser/plugins/spine',\n     'the bundled Spine plugins are no longer updated -> the official Spine plugin from Esoteric Software', []),\n    ('camera3d', 'error', 'Camera3D|Layer3D|phaser-ie9',\n     'Camera3D/Layer3D plugins and phaser-ie9 were removed', []),\n    ('math-tau', 'warn', '\\\\bMath\\\\.TAU\\\\b',\n     'Phaser.Math.TAU is now PI * 2 (in Phaser 3 it was PI / 2) -> check intent; use Math.PI_OVER_2 for a quarter turn', []),\n    ('render-texture-draw', 'warn', '\\\\b(rt|dt|\\\\w*Texture|\\\\w*RT)\\\\.(draw|drawFrame|stamp|erase|fill|repeat)\\\\(',\n     'DynamicTexture/RenderTexture commands are buffered in Phaser 4 -> call .render() after drawing (mark the line guard: ok once it does)', []),\n    ('round-pixels', 'warn', '\\\\broundPixels\\\\b',\n     'roundPixels now defaults to false and only applies to unscaled, axis-aligned objects -> see GameObject#vertexRoundMode', []),\n    ('grid-outline', 'warn', '\\\\b(outlineFillColor|outlineFillAlpha|setOutlineStyle)\\\\b',\n     'Grid shape outline* properties were renamed to stroke* in Phaser 4', []),\n    ('raw-gl', 'warn', '\\\\b(renderer\\\\.gl|getContext\\\\(\\\\s*[\\\\\"\\']webgl)',\n     \"direct WebGL calls desync Phaser 4's WebGL state -> use an Extern game object\", []),\n    ('phaser3-pin', 'error', '[\\\\\"\\']phaser[\\\\\"\\']\\\\s*:\\\\s*[\\\\\"\\'][~^]?3\\\\.',\n     'package.json pins Phaser 3 -> phaser 4.x', ['package.json']),\n]\nFILES = ['*.ts', '*.tsx', '*.js', '*.mjs', '*.jsx', 'package.json']\nCOMMENT = '//'\nSKIP_DIRS = {\".git\", \".venv\", \"venv\", \"node_modules\", \"__pycache__\", \".agents\", \".claude\", \".cursor\", \"dist\", \"build\", \"target\", \".godot\"}\nCOMPILED = [(rid, lvl, re.compile(rx), msg, globs) for rid, lvl, rx, msg, globs in RULES]\n\n\ndef strip_comment(line):\n    \"\"\"Drop a trailing comment, leaving string literals alone.\"\"\"\n    q = None\n    i = 0\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        elif c in \"\\\"'`\":\n            q = c\n        elif line.startswith(COMMENT, i):\n            return line[:i]\n        i += 1\n    return line\n\n\ndef wanted(name):\n    return any(fnmatch.fnmatch(name, g) for g in FILES)\n\n\ndef walk(paths):\n    for p in paths:\n        if os.path.isfile(p):\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 wanted(f):\n                    yield os.path.join(root, f)\n\n\ndef scan(path):\n    out = []\n    name = os.path.basename(path)\n    try:\n        with open(path, encoding=\"utf-8\", errors=\"replace\") as fh:\n            lines = fh.read().splitlines()\n    except OSError as e:\n        return [(path, 0, \"error\", \"unreadable\", str(e))]\n    for n, raw in enumerate(lines, 1):\n        code = strip_comment(raw)\n        if not code.strip():\n            continue\n        accepted = \"guard: ok\" in raw  # a person accepted the warnings on this line\n        for rid, lvl, rx, msg, globs in COMPILED:\n            if accepted and lvl == \"warn\":\n                continue\n            if globs and not any(fnmatch.fnmatch(name, g) for g in globs):\n                continue\n            if rx.search(code):\n                out.append((path, n, lvl, rid, msg))\n    return out\n\n\ndef main(argv):\n    if \"--list\" in argv:\n        for rid, lvl, _, msg, globs in RULES:\n            print(f\"{lvl:5} [{rid}] {msg}\" + (f\"  (only {', '.join(globs)})\" if globs else \"\"))\n        return 0\n    if any(a.startswith(\"-\") for a in argv):\n        print(__doc__)\n        return 2\n    paths = argv or [\".\"]\n    for p in paths:\n        if not os.path.exists(p):\n            print(f\"no such path: {p}\", file=sys.stderr)\n            return 2\n    files = list(walk(paths))\n    findings = []\n    for f in files:\n        findings.extend(scan(f))\n    for path, n, lvl, rid, msg in findings:\n        print(f\"{os.path.relpath(path)}:{n}: {lvl} [{rid}] {msg}\")\n    errors = sum(1 for x in findings if x[2] == \"error\")\n    warns = sum(1 for x in findings if x[2] == \"warn\")\n    print(f\"phaser4_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/phaser-4-guard/references/v3-to-v4.md",
      "role": "reference",
      "description": "Phaser 3 to Phaser 4 table for the calls agents get wrong.",
      "skill": "phaser-4-guard",
      "agent": null,
      "install_to": {
        "claude-code": ".claude/skills/phaser-4-guard/references/v3-to-v4.md",
        "codex": ".agents/skills/phaser-4-guard/references/v3-to-v4.md",
        "cursor": ".agents/skills/phaser-4-guard/references/v3-to-v4.md",
        "gemini-cli": ".agents/skills/phaser-4-guard/references/v3-to-v4.md",
        "antigravity-cli": ".agents/skills/phaser-4-guard/references/v3-to-v4.md",
        "copilot": ".agents/skills/phaser-4-guard/references/v3-to-v4.md"
      },
      "raw_url": "https://setupbay.com/raw/phaser-4-api-guard/1.0.0/skills/phaser-4-guard/references/v3-to-v4.md",
      "raw_latest_url": "https://setupbay.com/raw/phaser-4-api-guard/latest/skills/phaser-4-guard/references/v3-to-v4.md",
      "bytes": 2070,
      "lang": "markdown",
      "content": "# Phaser 3 to Phaser 4, the calls agents get wrong\n\nFrom the official migration guide shipped in `phaser` 4.2.1 (`node_modules/phaser/changelog/v4/4.0/MIGRATION-GUIDE.md`,\nalso in the package's v3-to-v4-migration skill). The replacements used in the verifier's Phaser 4 scene type-check against Phaser 4.2.1.\n\n| Phaser 3 | Phaser 4 |\n|---|---|\n| `sprite.setPipeline(\"Light2D\")` | `sprite.setLighting(true)`; `this.lights.enable()` |\n| custom `WebGLPipeline` / `PostFXPipeline` | a render node registered with `RenderConfig#renderNodes` |\n| `sprite.preFX.addGlow()` / `sprite.postFX.addBlur()` | `sprite.enableFilters()`; `sprite.filters.internal.addGlow()` / `sprite.filters.external.addBlur()` |\n| `camera.postFX.addColorMatrix()` | `camera.filters.external.addColorMatrix()` |\n| `cm.sepia()` | `cm.colorMatrix.sepia()` |\n| `postFX.addBloom()` / `addShine()` / `addCircle()` | `Phaser.Actions.AddEffectBloom(obj)` / `AddEffectShine(obj)` / `AddMaskShape(obj)` |\n| `addGradient()` FX | the `Gradient` game object |\n| `new Display.Masks.BitmapMask(scene, obj)` + `setMask` | `sprite.filters.internal.addMask(obj)` |\n| `GeometryMask` in WebGL | the `Mask` filter (GeometryMask is Canvas only) |\n| `sprite.setTintFill(c)`, `tintFill` | `sprite.setTint(c).setTintMode(Phaser.TintModes.FILL)` |\n| `new Geom.Point(x, y)` | `new Phaser.Math.Vector2(x, y)` |\n| `Point.GetMagnitude(p)` | `v.length()` |\n| `Phaser.Math.PI2` | `Phaser.Math.TAU` |\n| `Phaser.Math.TAU` (was PI / 2) | `Phaser.Math.PI_OVER_2` (TAU is now PI * 2) |\n| `Phaser.Structs.Set` / `Map` | native `Set` / `Map` |\n| `rt.draw(obj)` drawing at once | `rt.draw(obj).render()` (commands are buffered) |\n| `this.add.mesh()`, `this.add.plane()` | removed |\n| `this.textures.generate(key, { data })` | draw to a `Graphics` and call `generateTexture(key, w, h)` |\n| bundled `SpinePlugin` | the official Spine plugin from Esoteric Software |\n| `roundPixels` true by default | false by default; `pixelArt: true` or `GameObject#vertexRoundMode` |\n| Grid `outlineFillColor`, `setOutlineStyle` | the `stroke*` equivalents |\n"
    },
    {
      "path": "skills/phaser-4-guard/references/phaser3-sample.ts.txt",
      "role": "reference",
      "description": "A Phaser 3.90 scene for checking the guard.",
      "skill": "phaser-4-guard",
      "agent": null,
      "install_to": {
        "claude-code": ".claude/skills/phaser-4-guard/references/phaser3-sample.ts.txt",
        "codex": ".agents/skills/phaser-4-guard/references/phaser3-sample.ts.txt",
        "cursor": ".agents/skills/phaser-4-guard/references/phaser3-sample.ts.txt",
        "gemini-cli": ".agents/skills/phaser-4-guard/references/phaser3-sample.ts.txt",
        "antigravity-cli": ".agents/skills/phaser-4-guard/references/phaser3-sample.ts.txt",
        "copilot": ".agents/skills/phaser-4-guard/references/phaser3-sample.ts.txt"
      },
      "raw_url": "https://setupbay.com/raw/phaser-4-api-guard/1.0.0/skills/phaser-4-guard/references/phaser3-sample.ts.txt",
      "raw_latest_url": "https://setupbay.com/raw/phaser-4-api-guard/latest/skills/phaser-4-guard/references/phaser3-sample.ts.txt",
      "bytes": 960,
      "lang": "markdown",
      "content": "// A Phaser 3.90 scene, used to check the guard. Phaser 4 removed or changed every marked call.\nimport Phaser from \"phaser\";\n\nexport class GameScene extends Phaser.Scene {\n  create() {\n    const hero = this.add.sprite(100, 100, \"hero\");\n    hero.setTintFill(0xff0000);\n    hero.setPipeline(\"Light2D\");\n    hero.preFX?.addGlow(0xffffff);\n    const glow = hero.postFX.addBloom();\n    const mask = new Phaser.Display.Masks.BitmapMask(this, this.add.image(0, 0, \"mask\"));\n    hero.setMask(mask);\n    const p = new Phaser.Geom.Point(1, 2);\n    const quarter = Phaser.Math.TAU;\n    const full = Phaser.Math.PI2;\n    const seen = new Phaser.Structs.Set<string>();\n    const rt = this.add.renderTexture(0, 0, 64, 64);\n    rt.draw(hero);\n    const mesh = this.add.mesh(0, 0, \"hero\");\n    const cm = this.cameras.main.postFX.addColorMatrix();\n    cm.sepia();\n    this.textures.generate(\"dot\", { data: [\"1\"] });\n    console.log(p, quarter, full, seen, glow, mesh);\n  }\n}\n"
    }
  ],
  "requires": {
    "tools": [
      "node",
      "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": true,
    "scripts": [
      "phaser4_guard.py"
    ],
    "notes": "The scanner only reads source files and package.json and prints findings; it never edits files and makes no network calls. Installing the project's pinned packages with npm downloads them."
  },
  "featured": false,
  "deprecated": false,
  "last_checked": "2026-10-29",
  "published": "2026-10-29",
  "updated": "2026-10-29",
  "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/phaser-4-api-guard/",
  "api_url": "https://setupbay.com/api/loadouts/phaser-4-api-guard.json",
  "verification": {
    "level": "verified-install",
    "status": "verified",
    "label": "Verified install",
    "verified": true,
    "checked_at": "2026-10-29T12:58:17Z",
    "commit": "cc18d7ef3e9c98d99f00c17e2ef9a0565a3f9597",
    "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 yes (listing says yes)"
        ]
      },
      {
        "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, 16.8 KB total; largest skills/phaser-4-guard/scripts/phaser4_guard.py 7.1 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": "phaser4_guard.py passes a Phaser 4 scene and flags every Phaser 3 line in the skill's sample: 13 removed APIs as errors, and the changed Math.TAU and an unrendered RenderTexture draw as warnings. With the pinned phaser 4.2.1, tsc passes the Phaser 4 scene and rejects the sample's removed calls, and ",
        "details": [
          "Applied 12 loadout files at every agent's paths",
          "✓ scanner: the Phaser 4 scene and package.json are clean: bash -c python3 .agents/skills/phaser-4-guard/scripts/phaser4_guard.py src package.json; echo \"exit=$?\"",
          "✓ scanner: the Phaser 3 sample is flagged line by line: bash -c mkdir -p phaser3-sample && cp .claude/skills/phaser-4-guard/references/phaser3-sample.ts.txt phaser3-sample/GameScene.ts && python3 .claude/skills/phaser-4-guard/scripts/phaser4_guard.py phaser3-sample; echo \"exit=$?\"",
          "✓ install phaser 4.2.1 and typescript 7.0.2 (exact pins): npm ci --no-audit --no-fund",
          "✓ tsc passes the Phaser 4 scene: bash -c node_modules/.bin/tsc -p tsconfig.json; echo \"tsc=$?\"",
          "✓ tsc rejects the Phaser 3 sample's removed calls: bash -c node_modules/.bin/tsc -p tsconfig.sample.json; echo \"tsc=$?\"",
          "✓ the installed Phaser 4 package: TAU, roundPixels and its bundled skills: node probe.cjs",
          "Covers: The scanner's Phaser 3 rules (pipelines, preFX/postFX, BitmapMask, setTintFill, Geom.Point, Math.PI2, Structs, Mesh, textures.generate, ColorMatrix) against a real Phaser 3.90 scene, and a clean Phaser 4 scene",
          "Covers: Phaser 4.2.1's own types: every replacement in the rule and skill type-checks; the removed calls don't",
          "Covers: Silent changes: Math.TAU's new value and the roundPixels default, read from the installed package",
          "Covers: Not covered: rendering in a browser (the fixture doesn't open a WebGL context), so buffered RenderTexture drawing is checked by the scanner's warning only"
        ]
      }
    ]
  },
  "install": {
    "claude-code": {
      "files": [
        {
          "path": "AGENTS.md",
          "target": "AGENTS.md",
          "raw_url": "https://setupbay.com/raw/phaser-4-api-guard/1.0.0/AGENTS.md",
          "role": "instructions"
        },
        {
          "path": "CLAUDE.md",
          "target": "CLAUDE.md",
          "raw_url": "https://setupbay.com/raw/phaser-4-api-guard/1.0.0/CLAUDE.md",
          "role": "adapter"
        },
        {
          "path": "skills/phaser-4-guard/SKILL.md",
          "target": ".claude/skills/phaser-4-guard/SKILL.md",
          "raw_url": "https://setupbay.com/raw/phaser-4-api-guard/1.0.0/skills/phaser-4-guard/SKILL.md",
          "role": "skill"
        },
        {
          "path": "skills/phaser-4-guard/scripts/phaser4_guard.py",
          "target": ".claude/skills/phaser-4-guard/scripts/phaser4_guard.py",
          "raw_url": "https://setupbay.com/raw/phaser-4-api-guard/1.0.0/skills/phaser-4-guard/scripts/phaser4_guard.py",
          "role": "reference"
        },
        {
          "path": "skills/phaser-4-guard/references/v3-to-v4.md",
          "target": ".claude/skills/phaser-4-guard/references/v3-to-v4.md",
          "raw_url": "https://setupbay.com/raw/phaser-4-api-guard/1.0.0/skills/phaser-4-guard/references/v3-to-v4.md",
          "role": "reference"
        },
        {
          "path": "skills/phaser-4-guard/references/phaser3-sample.ts.txt",
          "target": ".claude/skills/phaser-4-guard/references/phaser3-sample.ts.txt",
          "raw_url": "https://setupbay.com/raw/phaser-4-api-guard/1.0.0/skills/phaser-4-guard/references/phaser3-sample.ts.txt",
          "role": "reference"
        }
      ],
      "manual_steps": [],
      "zip_url": "https://setupbay.com/download/phaser-4-api-guard/claude-code.zip"
    },
    "codex": {
      "files": [
        {
          "path": "AGENTS.md",
          "target": "AGENTS.md",
          "raw_url": "https://setupbay.com/raw/phaser-4-api-guard/1.0.0/AGENTS.md",
          "role": "instructions"
        },
        {
          "path": "skills/phaser-4-guard/SKILL.md",
          "target": ".agents/skills/phaser-4-guard/SKILL.md",
          "raw_url": "https://setupbay.com/raw/phaser-4-api-guard/1.0.0/skills/phaser-4-guard/SKILL.md",
          "role": "skill"
        },
        {
          "path": "skills/phaser-4-guard/scripts/phaser4_guard.py",
          "target": ".agents/skills/phaser-4-guard/scripts/phaser4_guard.py",
          "raw_url": "https://setupbay.com/raw/phaser-4-api-guard/1.0.0/skills/phaser-4-guard/scripts/phaser4_guard.py",
          "role": "reference"
        },
        {
          "path": "skills/phaser-4-guard/references/v3-to-v4.md",
          "target": ".agents/skills/phaser-4-guard/references/v3-to-v4.md",
          "raw_url": "https://setupbay.com/raw/phaser-4-api-guard/1.0.0/skills/phaser-4-guard/references/v3-to-v4.md",
          "role": "reference"
        },
        {
          "path": "skills/phaser-4-guard/references/phaser3-sample.ts.txt",
          "target": ".agents/skills/phaser-4-guard/references/phaser3-sample.ts.txt",
          "raw_url": "https://setupbay.com/raw/phaser-4-api-guard/1.0.0/skills/phaser-4-guard/references/phaser3-sample.ts.txt",
          "role": "reference"
        }
      ],
      "manual_steps": [],
      "zip_url": "https://setupbay.com/download/phaser-4-api-guard/codex.zip"
    },
    "cursor": {
      "files": [
        {
          "path": "AGENTS.md",
          "target": "AGENTS.md",
          "raw_url": "https://setupbay.com/raw/phaser-4-api-guard/1.0.0/AGENTS.md",
          "role": "instructions"
        },
        {
          "path": ".cursor/rules/phaser-4-only.mdc",
          "target": ".cursor/rules/phaser-4-only.mdc",
          "raw_url": "https://setupbay.com/raw/phaser-4-api-guard/1.0.0/.cursor/rules/phaser-4-only.mdc",
          "role": "rules"
        },
        {
          "path": "skills/phaser-4-guard/SKILL.md",
          "target": ".agents/skills/phaser-4-guard/SKILL.md",
          "raw_url": "https://setupbay.com/raw/phaser-4-api-guard/1.0.0/skills/phaser-4-guard/SKILL.md",
          "role": "skill"
        },
        {
          "path": "skills/phaser-4-guard/scripts/phaser4_guard.py",
          "target": ".agents/skills/phaser-4-guard/scripts/phaser4_guard.py",
          "raw_url": "https://setupbay.com/raw/phaser-4-api-guard/1.0.0/skills/phaser-4-guard/scripts/phaser4_guard.py",
          "role": "reference"
        },
        {
          "path": "skills/phaser-4-guard/references/v3-to-v4.md",
          "target": ".agents/skills/phaser-4-guard/references/v3-to-v4.md",
          "raw_url": "https://setupbay.com/raw/phaser-4-api-guard/1.0.0/skills/phaser-4-guard/references/v3-to-v4.md",
          "role": "reference"
        },
        {
          "path": "skills/phaser-4-guard/references/phaser3-sample.ts.txt",
          "target": ".agents/skills/phaser-4-guard/references/phaser3-sample.ts.txt",
          "raw_url": "https://setupbay.com/raw/phaser-4-api-guard/1.0.0/skills/phaser-4-guard/references/phaser3-sample.ts.txt",
          "role": "reference"
        }
      ],
      "manual_steps": [],
      "zip_url": "https://setupbay.com/download/phaser-4-api-guard/cursor.zip"
    },
    "gemini-cli": {
      "files": [
        {
          "path": "AGENTS.md",
          "target": "AGENTS.md",
          "raw_url": "https://setupbay.com/raw/phaser-4-api-guard/1.0.0/AGENTS.md",
          "role": "instructions"
        },
        {
          "path": "GEMINI.md",
          "target": "GEMINI.md",
          "raw_url": "https://setupbay.com/raw/phaser-4-api-guard/1.0.0/GEMINI.md",
          "role": "adapter"
        },
        {
          "path": "skills/phaser-4-guard/SKILL.md",
          "target": ".agents/skills/phaser-4-guard/SKILL.md",
          "raw_url": "https://setupbay.com/raw/phaser-4-api-guard/1.0.0/skills/phaser-4-guard/SKILL.md",
          "role": "skill"
        },
        {
          "path": "skills/phaser-4-guard/scripts/phaser4_guard.py",
          "target": ".agents/skills/phaser-4-guard/scripts/phaser4_guard.py",
          "raw_url": "https://setupbay.com/raw/phaser-4-api-guard/1.0.0/skills/phaser-4-guard/scripts/phaser4_guard.py",
          "role": "reference"
        },
        {
          "path": "skills/phaser-4-guard/references/v3-to-v4.md",
          "target": ".agents/skills/phaser-4-guard/references/v3-to-v4.md",
          "raw_url": "https://setupbay.com/raw/phaser-4-api-guard/1.0.0/skills/phaser-4-guard/references/v3-to-v4.md",
          "role": "reference"
        },
        {
          "path": "skills/phaser-4-guard/references/phaser3-sample.ts.txt",
          "target": ".agents/skills/phaser-4-guard/references/phaser3-sample.ts.txt",
          "raw_url": "https://setupbay.com/raw/phaser-4-api-guard/1.0.0/skills/phaser-4-guard/references/phaser3-sample.ts.txt",
          "role": "reference"
        }
      ],
      "manual_steps": [],
      "zip_url": "https://setupbay.com/download/phaser-4-api-guard/gemini-cli.zip"
    },
    "antigravity-cli": {
      "files": [
        {
          "path": "AGENTS.md",
          "target": "AGENTS.md",
          "raw_url": "https://setupbay.com/raw/phaser-4-api-guard/1.0.0/AGENTS.md",
          "role": "instructions"
        },
        {
          "path": "skills/phaser-4-guard/SKILL.md",
          "target": ".agents/skills/phaser-4-guard/SKILL.md",
          "raw_url": "https://setupbay.com/raw/phaser-4-api-guard/1.0.0/skills/phaser-4-guard/SKILL.md",
          "role": "skill"
        },
        {
          "path": "skills/phaser-4-guard/scripts/phaser4_guard.py",
          "target": ".agents/skills/phaser-4-guard/scripts/phaser4_guard.py",
          "raw_url": "https://setupbay.com/raw/phaser-4-api-guard/1.0.0/skills/phaser-4-guard/scripts/phaser4_guard.py",
          "role": "reference"
        },
        {
          "path": "skills/phaser-4-guard/references/v3-to-v4.md",
          "target": ".agents/skills/phaser-4-guard/references/v3-to-v4.md",
          "raw_url": "https://setupbay.com/raw/phaser-4-api-guard/1.0.0/skills/phaser-4-guard/references/v3-to-v4.md",
          "role": "reference"
        },
        {
          "path": "skills/phaser-4-guard/references/phaser3-sample.ts.txt",
          "target": ".agents/skills/phaser-4-guard/references/phaser3-sample.ts.txt",
          "raw_url": "https://setupbay.com/raw/phaser-4-api-guard/1.0.0/skills/phaser-4-guard/references/phaser3-sample.ts.txt",
          "role": "reference"
        }
      ],
      "manual_steps": [],
      "zip_url": "https://setupbay.com/download/phaser-4-api-guard/antigravity-cli.zip"
    },
    "copilot": {
      "files": [
        {
          "path": "AGENTS.md",
          "target": "AGENTS.md",
          "raw_url": "https://setupbay.com/raw/phaser-4-api-guard/1.0.0/AGENTS.md",
          "role": "instructions"
        },
        {
          "path": "skills/phaser-4-guard/SKILL.md",
          "target": ".agents/skills/phaser-4-guard/SKILL.md",
          "raw_url": "https://setupbay.com/raw/phaser-4-api-guard/1.0.0/skills/phaser-4-guard/SKILL.md",
          "role": "skill"
        },
        {
          "path": "skills/phaser-4-guard/scripts/phaser4_guard.py",
          "target": ".agents/skills/phaser-4-guard/scripts/phaser4_guard.py",
          "raw_url": "https://setupbay.com/raw/phaser-4-api-guard/1.0.0/skills/phaser-4-guard/scripts/phaser4_guard.py",
          "role": "reference"
        },
        {
          "path": "skills/phaser-4-guard/references/v3-to-v4.md",
          "target": ".agents/skills/phaser-4-guard/references/v3-to-v4.md",
          "raw_url": "https://setupbay.com/raw/phaser-4-api-guard/1.0.0/skills/phaser-4-guard/references/v3-to-v4.md",
          "role": "reference"
        },
        {
          "path": "skills/phaser-4-guard/references/phaser3-sample.ts.txt",
          "target": ".agents/skills/phaser-4-guard/references/phaser3-sample.ts.txt",
          "raw_url": "https://setupbay.com/raw/phaser-4-api-guard/1.0.0/skills/phaser-4-guard/references/phaser3-sample.ts.txt",
          "role": "reference"
        }
      ],
      "manual_steps": [],
      "zip_url": "https://setupbay.com/download/phaser-4-api-guard/copilot.zip"
    }
  },
  "source_zip_url": "https://setupbay.com/download/phaser-4-api-guard/source.zip",
  "claude_code_plugin": {
    "name": "phaser-4-api-guard",
    "marketplace_url": "https://setupbay.com/marketplace.json",
    "install": [
      "/plugin marketplace add https://setupbay.com/marketplace.json",
      "/plugin install phaser-4-api-guard@setupbay"
    ],
    "zip_url": "https://setupbay.com/plugins/phaser-4-api-guard.zip",
    "sha256": "b04c440ccd05a44361c35b10987ad73c0eeea0625d4bfb20d44086fbe6e74fa9",
    "carries": [
      "skills"
    ],
    "note": "Plugins do not carry project rules (AGENTS.md, CLAUDE.md); install those from install.claude-code."
  }
}