Skip to content
Game dev

Phaser 4 guard for Phaser 3 pipelines, FX and masks

Stop agents writing setPipeline, preFX, postFX, BitmapMask and setTintFill into Phaser 4 games, and catch the Math.TAU change that compiles but breaks rotations.

Verified install Not agent-tested v1.0.0 MIT updated phasertypescript
Equips
  • 2 2 Rules
  • 1 1 Skills
  • – 0 MCP

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.

This 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.

What's in it

  • 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

You'll need

  • Tools: node, python3
Level 1 · automated

Verification

Verified install

Checked at commit cc18d7e · 9 passed, 0 failed, 1 not applicable

CheckResultWhat we found
Listinglisting.yaml matches the schema and declares every file in the folder. Pass
Schema valid; 8 files declared, none missing or extra
  • tested.status: untested (agent tests are separate from Level 1)
Files parseJSON parses; SKILL.md and .mdc front matter is valid YAML with the fields each agent needs; code fences are closed. Pass All 8 files parse; front matter valid
AdaptersCLAUDE.md imports @AGENTS.md, GEMINI.md imports @./AGENTS.md, and both match the generator. Pass
CLAUDE.md and GEMINI.md import AGENTS.md and are up to date
  • CLAUDE.md: matches the generator
  • GEMINI.md: matches the generator
Install pathsEvery file lands where each agent documents it, with no collisions, and the laid-out project is re-discovered correctly. Pass
Correct paths for all 6 agents; layouts re-discovered
  • 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/
MCP configmcp.json is structurally valid, converts to each agent's format, declares no literal secrets, and referenced packages exist on npm/PyPI. Not applicable No MCP servers in this loadout
Safety scanThe intake scanner finds no credentials, risky shell, hidden Unicode, instructions hidden in HTML comments or after long blank padding, or prompt-injection and covert wording (such as telling the agent to keep something from you), and the listing's network flag is honest. Pass
Clean: no credentials, risky shell, hidden text or covert instructions
  • Scanner intake-precheck/2: verdict clean; network yes (listing says yes)
ReferencesLinks and file paths between the loadout's files resolve, including for each agent's installed layout. Pass 3 references between files resolve for every agent
Size limitsFile count and sizes are within the submission limits; SKILL.md bodies stay under 500 lines. Pass
8 files, 16.8 KB total; largest skills/phaser-4-guard/scripts/phaser4_guard.py 7.1 KB
  • Limits: 30 files, 32 KB per file, 128 KB total, 500 lines per skill or rule
LicenceA recognised SPDX licence, with the licence text available. Pass MIT, by SetupBay; text in the repository LICENSE
Starter buildA minimal fixture project with the loadout applied installs and builds or type-checks, and the loadout's own code examples compile. Pass
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
  • 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

What this means: a script checked the files themselves: they parse, they install where each agent looks, any MCP config is sound, the safety scan is clean, references between files resolve, and, where a free and repeatable fixture exists, a small starter project builds with the loadout applied. No AI agent was run. Per-agent results from agent runs are separate and stay untested until an agent actually runs.

Install

Choose your agent. Run the commands from your project root, or download a zip already laid out in the right folders.

Claude Code reads CLAUDE.md (imports AGENTS.md with @AGENTS.md) and skills from .claude/skills/.

Download zip
curl -fsSL --create-dirs -o AGENTS.md https://setupbay.com/raw/phaser-4-api-guard/1.0.0/AGENTS.md
curl -fsSL --create-dirs -o CLAUDE.md https://setupbay.com/raw/phaser-4-api-guard/1.0.0/CLAUDE.md
curl -fsSL --create-dirs -o .claude/skills/phaser-4-guard/SKILL.md https://setupbay.com/raw/phaser-4-api-guard/1.0.0/skills/phaser-4-guard/SKILL.md
curl -fsSL --create-dirs -o .claude/skills/phaser-4-guard/scripts/phaser4_guard.py https://setupbay.com/raw/phaser-4-api-guard/1.0.0/skills/phaser-4-guard/scripts/phaser4_guard.py
curl -fsSL --create-dirs -o .claude/skills/phaser-4-guard/references/v3-to-v4.md https://setupbay.com/raw/phaser-4-api-guard/1.0.0/skills/phaser-4-guard/references/v3-to-v4.md
curl -fsSL --create-dirs -o .claude/skills/phaser-4-guard/references/phaser3-sample.ts.txt https://setupbay.com/raw/phaser-4-api-guard/1.0.0/skills/phaser-4-guard/references/phaser3-sample.ts.txt
FileGoes to
AGENTS.mdAGENTS.md
CLAUDE.mdCLAUDE.md
skills/phaser-4-guard/SKILL.md.claude/skills/phaser-4-guard/SKILL.md
skills/phaser-4-guard/scripts/phaser4_guard.py.claude/skills/phaser-4-guard/scripts/phaser4_guard.py
skills/phaser-4-guard/references/v3-to-v4.md.claude/skills/phaser-4-guard/references/v3-to-v4.md
skills/phaser-4-guard/references/phaser3-sample.ts.txt.claude/skills/phaser-4-guard/references/phaser3-sample.ts.txt

Already have an AGENTS.md or CLAUDE.md? The commands above overwrite it — download the file instead and merge the sections you want. Which file wins when several are present: what Claude Code reads.

Or as a Claude Code plugin

Adds the skill to Claude Code for all your projects, without copying files. Plugins can't carry project rules, so add AGENTS.md and CLAUDE.md with the commands above. About the plugin marketplace.

/plugin marketplace add https://setupbay.com/marketplace.json
/plugin install phaser-4-api-guard@setupbay

Files

Rules AGENTS.md Version check, Phaser 4 rules and the done checklist. 34 lines
Download Raw
# AGENTS.md: Phaser 4 game (Phaser 3 API guard)

This game runs **Phaser 4** (`phaser` 4.2.x), with TypeScript. `npm i phaser` has installed Phaser 4 since
April 2026, and 3.90.0 was the last Phaser 3 release. Nearly every Phaser tutorial and answer you learnt from is
Phaser 3, and Phaser 4 replaced the renderer: pipelines, preFX/postFX and BitmapMask are gone.

## Check the version first
- Read `package.json`. If `phaser` is `3.x`, this file doesn't apply: write Phaser 3 code and don't use any
  Phaser 4 API. If it's `4.x`, follow the rules below. If you're not sure, stop and ask.
- Phaser 4 ships its own agent skills in the package: `node_modules/phaser/skills/`. Read
  `node_modules/phaser/skills/v3-to-v4-migration/SKILL.md` before porting Phaser 3 code, and the topic skill
  (for example `filters-and-postfx`, `render-textures`) before using an API you're unsure of.
- The types are the truth: `node_modules/phaser/types/phaser.d.ts`. If `tsc` says a property doesn't exist, it's
  gone. Don't cast to `any` to get round it.

## Rules
- Write Phaser 4 code only. The `phaser-4-guard` skill has the table. The common ones are:
  - `setPipeline('Light2D')` → `setLighting(true)` (and `this.lights.enable()`)
  - `preFX` / `postFX` → `obj.enableFilters()`, then `obj.filters.internal` / `obj.filters.external`, or `camera.filters`
  - `BitmapMask` → `obj.filters.internal.addMask(maskObject)`
  - `setTintFill(c)` → `setTint(c).setTintMode(Phaser.TintModes.FILL)`
  - `Geom.Point` → `Phaser.Math.Vector2`. `Structs.Set` / `Map` → native `Set` / `Map`
  - `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.
  - `colorMatrix.sepia()` → `colorMatrix.colorMatrix.sepia()`
- `RenderTexture` / `DynamicTexture` drawing is buffered: call `.render()` after `draw()`, `stamp()` and so on.
- `roundPixels` now defaults to `false`. For pixel art set `pixelArt: true` or choose a `vertexRoundMode`.
- Don't make raw WebGL calls. Use an `Extern` game object if you need to.
- Don't upgrade or downgrade Phaser without asking.

## Before you say "done"
1. Run the `phaser-4-guard` scanner on `src` and `package.json`. It must report `0 error(s)`. Any warning you leave needs a reason.
2. Run `npx tsc --noEmit`. It must pass, with no new `any` or `@ts-ignore` around Phaser calls.
3. If you changed rendering, filters or lighting, run the game and look at it.
Adapter CLAUDE.md Imports AGENTS.md for Claude Code. 11 lines
Download Raw
# CLAUDE.md

@AGENTS.md

## Claude Code notes

- Skills from this loadout live in `.claude/skills/`: `phaser-4-guard`. Use them when their description matches the task.
- Follow AGENTS.md above; where this file and AGENTS.md disagree, AGENTS.md wins.

<!-- From SetupBay "Phaser 4 guard for Phaser 3 pipelines, FX and masks" v1.0.0 — https://setupbay.com/loadouts/phaser-4-api-guard/ -->
Adapter GEMINI.md Imports AGENTS.md for Gemini CLI. 11 lines
Download Raw
# GEMINI.md

@./AGENTS.md

## Gemini CLI notes

- Skills from this loadout live in `.agents/skills/`: `phaser-4-guard`. Use them when their description matches the task.
- Follow AGENTS.md above; where this file and AGENTS.md disagree, AGENTS.md wins.

<!-- From SetupBay "Phaser 4 guard for Phaser 3 pipelines, FX and masks" v1.0.0 — https://setupbay.com/loadouts/phaser-4-api-guard/ -->
Cursor rule .cursor/rules/phaser-4-only.mdc Never/always table for game source and package.json. 24 lines
Download Raw
---
description: Phaser 4 only; never Phaser 3 pipelines, FX or masks
globs: "src/**/*.ts,src/**/*.js,package.json"
alwaysApply: false
---

This game uses Phaser 4 (check `package.json`; if it says 3.x, ignore this rule and stay on Phaser 3).

| Never (Phaser 3) | Always (Phaser 4) |
|---|---|
| `sprite.setPipeline("Light2D")` | `sprite.setLighting(true)` and `this.lights.enable()` |
| `sprite.preFX.addGlow()`, `postFX` | `sprite.enableFilters()` then `sprite.filters.internal.addGlow()` |
| `new Display.Masks.BitmapMask(...)`, `setMask` | `sprite.filters.internal.addMask(maskObject)` |
| `setTintFill(0xff0000)` | `setTint(0xff0000).setTintMode(Phaser.TintModes.FILL)` |
| `new Geom.Point(x, y)` | `new Phaser.Math.Vector2(x, y)` |
| `Math.PI2`; `Math.TAU` meaning a quarter turn | `Math.TAU` (= PI * 2); `Math.PI_OVER_2` |
| `new Structs.Set()` / `Structs.Map` | native `Set` / `Map` |
| `cm.sepia()` | `cm.colorMatrix.sepia()` |
| `rt.draw(obj)` and nothing else | `rt.draw(obj).render()` |
| `this.add.mesh()`, `textures.generate()` | removed; ask |

- Official guide: `node_modules/phaser/skills/v3-to-v4-migration/SKILL.md`.
- After editing, run the `phaser-4-guard` skill's scanner and `npx tsc --noEmit`.
Skill skills/phaser-4-guard/SKILL.md Scan for Phaser 3 APIs and silent changes, then type-check against Phaser 4's types. 43 lines
Download Raw
---
name: phaser-4-guard
description: 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.
---

# Phaser 4 guard

`npm i phaser` gives you Phaser 4, but most Phaser examples online are Phaser 3. Phaser 4 replaced the renderer,
so the commonest Phaser 3 calls (`setPipeline`, `preFX`, `postFX`, `BitmapMask`) no longer exist. Some changes don't
fail at all: `Math.TAU` changed value, and RenderTexture drawing does nothing until `render()`.

## 1. Confirm the version
- `node -p "require('phaser/package.json').version"` should print `4.x`. If it's `3.x`, stop: this skill is for Phaser 4.

## 2. Scan
```bash
python3 .agents/skills/phaser-4-guard/scripts/phaser4_guard.py src package.json
```
(Use the path the skill was installed to: `.claude/skills/...` for Claude Code, `.agents/skills/...` for the others.)

- Each `error` line is a Phaser 3 API that Phaser 4 removed. Fix it with the replacement on the line, or look it up
  in `references/v3-to-v4.md`.
- Each `warn` line is a change that compiles but may behave differently: `Math.TAU`, a texture `draw()` that may need
  `.render()`, `roundPixels`, `GeometryMask` (Canvas only), Grid `outline*` names, raw WebGL. Check each one. When it's
  right, add `// guard: ok <reason>` to the line.

## 3. Type-check against Phaser 4
```bash
npx tsc --noEmit
```
- Phaser 4's types are generated from its source, so `Property 'postFX' does not exist` means the API is gone, not
  that the types are wrong. Never cast to `any` or add `@ts-ignore` to keep a Phaser 3 call.
- For JavaScript projects, add `// @ts-check` to the file or `"checkJs": true` to get the same errors.

## 4. Read the official guide when porting
Phaser ships agent skills in the package. For anything not in the table, read
`node_modules/phaser/skills/v3-to-v4-migration/SKILL.md`, then the topic skill such as
`node_modules/phaser/skills/filters-and-postfx/SKILL.md`.

## 5. Report
Say which Phaser 3 calls you replaced, which warnings you kept and why, and that the scanner and `tsc` were clean.
If you changed rendering, filters or lighting, say whether you ran the game and looked at it.
Skill file skills/phaser-4-guard/scripts/phaser4_guard.py Read-only scanner for removed Phaser 3 APIs and Phaser 4 behaviour changes. 152 lines
Download Raw
#!/usr/bin/env python3
"""Find Phaser 3 APIs that Phaser 4 removed or changed, in a Phaser 4 game's .ts/.js files.

Usage: python3 phaser4_guard.py [PATH ...]        (default: the current folder)
       python3 phaser4_guard.py --list            (print every rule)

A "guard: ok" comment on a line silences its warnings (never its errors).
Prints one line per finding:  path:line: level [rule] what is wrong -> what to use
Exit 0 when nothing at "error" level is found, 1 when something is, 2 on bad usage.
Standard library only. Read-only: it never edits a file and makes no network calls.
"""
import fnmatch
import os
import re
import sys

# (rule id, level, regex, message, file patterns). Patterns run against each line with comments removed.
RULES = [
    ('set-pipeline', 'error', '\\.setPipeline\\(|\\.setPostPipeline\\(|\\.resetPipeline\\(|pipelines\\.(add|get)\\(',
     'pipelines were removed in Phaser 4 -> render nodes (RenderConfig#renderNodes); for lights use setLighting(true)', []),
    ('prefx-postfx', 'error', '\\.(preFX|postFX)\\b',
     'preFX/postFX were replaced by filters -> obj.filters.internal / obj.filters.external (enable with obj.enableFilters())', []),
    ('bitmap-mask', 'error', '\\bBitmapMask\\b|\\.createBitmapMask\\(',
     'BitmapMask was removed -> obj.filters.internal.addMask(maskObject)', []),
    ('geometry-mask-webgl', 'warn', '\\bcreateGeometryMask\\(|\\bGeometryMask\\b',
     'GeometryMask only works in the Canvas renderer in Phaser 4 -> the Mask filter for WebGL', []),
    ('set-tint-fill', 'error', '\\.setTintFill\\(|\\.tintFill\\b',
     'setTintFill()/tintFill were removed -> setTint(c).setTintMode(Phaser.TintModes.FILL)', []),
    ('geom-point', 'error', '\\bGeom\\.Point\\b',
     'Geom.Point was removed -> Phaser.Math.Vector2', []),
    ('math-pi2', 'error', '\\bMath\\.PI2\\b',
     'Phaser.Math.PI2 was removed -> Phaser.Math.TAU (now PI * 2)', []),
    ('struct-set-map', 'error', '\\bStructs\\.(Set|Map)\\b',
     'Phaser.Structs.Set/Map were removed -> native Set / Map', []),
    ('mesh-plane', 'error', '\\.add\\.(mesh|plane)\\(|\\bGameObjects\\.(Mesh|Plane)\\b',
     'Mesh and Plane were removed in Phaser 4', []),
    ('textures-generate', 'error', '\\btextures\\.generate\\(|\\bCreate\\.GenerateTexture\\b',
     'TextureManager.generate / Create.GenerateTexture were removed -> draw to a Graphics and generateTexture(), or load an image', []),
    ('bloom-shine-fx', 'error', '\\.add(Bloom|Shine|Circle|Gradient)\\(',
     'the Bloom/Shine/Circle/Gradient FX were removed -> Phaser.Actions.AddEffectBloom/AddEffectShine/AddMaskShape, or the Gradient game object', []),
    ('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)\\(',
     'ColorMatrix methods moved onto .colorMatrix -> filter.colorMatrix.sepia()', []),
    ('spine-bundled', 'error', 'SpinePlugin|phaser/plugins/spine',
     'the bundled Spine plugins are no longer updated -> the official Spine plugin from Esoteric Software', []),
    ('camera3d', 'error', 'Camera3D|Layer3D|phaser-ie9',
     'Camera3D/Layer3D plugins and phaser-ie9 were removed', []),
    ('math-tau', 'warn', '\\bMath\\.TAU\\b',
     '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', []),
    ('render-texture-draw', 'warn', '\\b(rt|dt|\\w*Texture|\\w*RT)\\.(draw|drawFrame|stamp|erase|fill|repeat)\\(',
     'DynamicTexture/RenderTexture commands are buffered in Phaser 4 -> call .render() after drawing (mark the line guard: ok once it does)', []),
    ('round-pixels', 'warn', '\\broundPixels\\b',
     'roundPixels now defaults to false and only applies to unscaled, axis-aligned objects -> see GameObject#vertexRoundMode', []),
    ('grid-outline', 'warn', '\\b(outlineFillColor|outlineFillAlpha|setOutlineStyle)\\b',
     'Grid shape outline* properties were renamed to stroke* in Phaser 4', []),
    ('raw-gl', 'warn', '\\b(renderer\\.gl|getContext\\(\\s*[\\"\']webgl)',
     "direct WebGL calls desync Phaser 4's WebGL state -> use an Extern game object", []),
    ('phaser3-pin', 'error', '[\\"\']phaser[\\"\']\\s*:\\s*[\\"\'][~^]?3\\.',
     'package.json pins Phaser 3 -> phaser 4.x', ['package.json']),
]
FILES = ['*.ts', '*.tsx', '*.js', '*.mjs', '*.jsx', 'package.json']
COMMENT = '//'
SKIP_DIRS = {".git", ".venv", "venv", "node_modules", "__pycache__", ".agents", ".claude", ".cursor", "dist", "build", "target", ".godot"}
COMPILED = [(rid, lvl, re.compile(rx), msg, globs) for rid, lvl, rx, msg, globs in RULES]


def strip_comment(line):
    """Drop a trailing comment, leaving string literals alone."""
    q = None
    i = 0
    while i < len(line):
        c = line[i]
        if q:
            if c == "\\":
                i += 2
                continue
            if c == q:
                q = None
        elif c in "\"'`":
            q = c
        elif line.startswith(COMMENT, i):
            return line[:i]
        i += 1
    return line


def wanted(name):
    return any(fnmatch.fnmatch(name, g) for g in FILES)


def walk(paths):
    for p in paths:
        if os.path.isfile(p):
            yield p
            continue
        for root, dirs, files in os.walk(p):
            dirs[:] = sorted(d for d in dirs if d not in SKIP_DIRS)
            for f in sorted(files):
                if wanted(f):
                    yield os.path.join(root, f)


def scan(path):
    out = []
    name = os.path.basename(path)
    try:
        with open(path, encoding="utf-8", errors="replace") as fh:
            lines = fh.read().splitlines()
    except OSError as e:
        return [(path, 0, "error", "unreadable", str(e))]
    for n, raw in enumerate(lines, 1):
        code = strip_comment(raw)
        if not code.strip():
            continue
        accepted = "guard: ok" in raw  # a person accepted the warnings on this line
        for rid, lvl, rx, msg, globs in COMPILED:
            if accepted and lvl == "warn":
                continue
            if globs and not any(fnmatch.fnmatch(name, g) for g in globs):
                continue
            if rx.search(code):
                out.append((path, n, lvl, rid, msg))
    return out


def main(argv):
    if "--list" in argv:
        for rid, lvl, _, msg, globs in RULES:
            print(f"{lvl:5} [{rid}] {msg}" + (f"  (only {', '.join(globs)})" if globs else ""))
        return 0
    if any(a.startswith("-") for a in argv):
        print(__doc__)
        return 2
    paths = argv or ["."]
    for p in paths:
        if not os.path.exists(p):
            print(f"no such path: {p}", file=sys.stderr)
            return 2
    files = list(walk(paths))
    findings = []
    for f in files:
        findings.extend(scan(f))
    for path, n, lvl, rid, msg in findings:
        print(f"{os.path.relpath(path)}:{n}: {lvl} [{rid}] {msg}")
    errors = sum(1 for x in findings if x[2] == "error")
    warns = sum(1 for x in findings if x[2] == "warn")
    print(f"phaser4_guard: {len(files)} file(s), {errors} error(s), {warns} warning(s)")
    return 1 if errors else 0


if __name__ == "__main__":
    sys.exit(main(sys.argv[1:]))
Skill file skills/phaser-4-guard/references/v3-to-v4.md Phaser 3 to Phaser 4 table for the calls agents get wrong. 29 lines
Download Raw
# Phaser 3 to Phaser 4, the calls agents get wrong

From the official migration guide shipped in `phaser` 4.2.1 (`node_modules/phaser/changelog/v4/4.0/MIGRATION-GUIDE.md`,
also 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.

| Phaser 3 | Phaser 4 |
|---|---|
| `sprite.setPipeline("Light2D")` | `sprite.setLighting(true)`; `this.lights.enable()` |
| custom `WebGLPipeline` / `PostFXPipeline` | a render node registered with `RenderConfig#renderNodes` |
| `sprite.preFX.addGlow()` / `sprite.postFX.addBlur()` | `sprite.enableFilters()`; `sprite.filters.internal.addGlow()` / `sprite.filters.external.addBlur()` |
| `camera.postFX.addColorMatrix()` | `camera.filters.external.addColorMatrix()` |
| `cm.sepia()` | `cm.colorMatrix.sepia()` |
| `postFX.addBloom()` / `addShine()` / `addCircle()` | `Phaser.Actions.AddEffectBloom(obj)` / `AddEffectShine(obj)` / `AddMaskShape(obj)` |
| `addGradient()` FX | the `Gradient` game object |
| `new Display.Masks.BitmapMask(scene, obj)` + `setMask` | `sprite.filters.internal.addMask(obj)` |
| `GeometryMask` in WebGL | the `Mask` filter (GeometryMask is Canvas only) |
| `sprite.setTintFill(c)`, `tintFill` | `sprite.setTint(c).setTintMode(Phaser.TintModes.FILL)` |
| `new Geom.Point(x, y)` | `new Phaser.Math.Vector2(x, y)` |
| `Point.GetMagnitude(p)` | `v.length()` |
| `Phaser.Math.PI2` | `Phaser.Math.TAU` |
| `Phaser.Math.TAU` (was PI / 2) | `Phaser.Math.PI_OVER_2` (TAU is now PI * 2) |
| `Phaser.Structs.Set` / `Map` | native `Set` / `Map` |
| `rt.draw(obj)` drawing at once | `rt.draw(obj).render()` (commands are buffered) |
| `this.add.mesh()`, `this.add.plane()` | removed |
| `this.textures.generate(key, { data })` | draw to a `Graphics` and call `generateTexture(key, w, h)` |
| bundled `SpinePlugin` | the official Spine plugin from Esoteric Software |
| `roundPixels` true by default | false by default; `pixelArt: true` or `GameObject#vertexRoundMode` |
| Grid `outlineFillColor`, `setOutlineStyle` | the `stroke*` equivalents |
Skill file skills/phaser-4-guard/references/phaser3-sample.ts.txt A Phaser 3.90 scene for checking the guard. 26 lines
Download Raw
// A Phaser 3.90 scene, used to check the guard. Phaser 4 removed or changed every marked call.
import Phaser from "phaser";

export class GameScene extends Phaser.Scene {
  create() {
    const hero = this.add.sprite(100, 100, "hero");
    hero.setTintFill(0xff0000);
    hero.setPipeline("Light2D");
    hero.preFX?.addGlow(0xffffff);
    const glow = hero.postFX.addBloom();
    const mask = new Phaser.Display.Masks.BitmapMask(this, this.add.image(0, 0, "mask"));
    hero.setMask(mask);
    const p = new Phaser.Geom.Point(1, 2);
    const quarter = Phaser.Math.TAU;
    const full = Phaser.Math.PI2;
    const seen = new Phaser.Structs.Set<string>();
    const rt = this.add.renderTexture(0, 0, 64, 64);
    rt.draw(hero);
    const mesh = this.add.mesh(0, 0, "hero");
    const cm = this.cameras.main.postFX.addColorMatrix();
    cm.sepia();
    this.textures.generate("dot", { data: ["1"] });
    console.log(p, quarter, full, seen, glow, mesh);
  }
}

All files: source zip · Licence MIT · By SetupBay · First listed

Installing and checks

How do I install Phaser 4 guard for Phaser 3 pipelines, FX and masks in Claude Code?

From your project root, put AGENTS.md, CLAUDE.md, skills/phaser-4-guard/SKILL.md at .claude/skills/phaser-4-guard/SKILL.md, skills/phaser-4-guard/scripts/phaser4_guard.py at .claude/skills/phaser-4-guard/scripts/phaser4_guard.py, skills/phaser-4-guard/references/v3-to-v4.md at .claude/skills/phaser-4-guard/references/v3-to-v4.md, skills/phaser-4-guard/references/phaser3-sample.ts.txt at .claude/skills/phaser-4-guard/references/phaser3-sample.ts.txt. The "Claude Code" tab on this page has the curl commands, or download https://setupbay.com/download/phaser-4-api-guard/claude-code.zip, which is already laid out. Do not overwrite an existing AGENTS.md or CLAUDE.md; merge it.

How do I install Phaser 4 guard for Phaser 3 pipelines, FX and masks in Codex CLI?

From your project root, put AGENTS.md, skills/phaser-4-guard/SKILL.md at .agents/skills/phaser-4-guard/SKILL.md, skills/phaser-4-guard/scripts/phaser4_guard.py at .agents/skills/phaser-4-guard/scripts/phaser4_guard.py, skills/phaser-4-guard/references/v3-to-v4.md at .agents/skills/phaser-4-guard/references/v3-to-v4.md, skills/phaser-4-guard/references/phaser3-sample.ts.txt at .agents/skills/phaser-4-guard/references/phaser3-sample.ts.txt. The "Codex CLI" tab on this page has the curl commands, or download https://setupbay.com/download/phaser-4-api-guard/codex.zip, which is already laid out. Do not overwrite an existing AGENTS.md or CLAUDE.md; merge it.

How do I install Phaser 4 guard for Phaser 3 pipelines, FX and masks in Cursor?

From your project root, put AGENTS.md, .cursor/rules/phaser-4-only.mdc, skills/phaser-4-guard/SKILL.md at .agents/skills/phaser-4-guard/SKILL.md, skills/phaser-4-guard/scripts/phaser4_guard.py at .agents/skills/phaser-4-guard/scripts/phaser4_guard.py, skills/phaser-4-guard/references/v3-to-v4.md at .agents/skills/phaser-4-guard/references/v3-to-v4.md, skills/phaser-4-guard/references/phaser3-sample.ts.txt at .agents/skills/phaser-4-guard/references/phaser3-sample.ts.txt. The "Cursor" tab on this page has the curl commands, or download https://setupbay.com/download/phaser-4-api-guard/cursor.zip, which is already laid out. Do not overwrite an existing AGENTS.md or CLAUDE.md; merge it.

How do I install Phaser 4 guard for Phaser 3 pipelines, FX and masks in Gemini CLI?

From your project root, put AGENTS.md, GEMINI.md, skills/phaser-4-guard/SKILL.md at .agents/skills/phaser-4-guard/SKILL.md, skills/phaser-4-guard/scripts/phaser4_guard.py at .agents/skills/phaser-4-guard/scripts/phaser4_guard.py, skills/phaser-4-guard/references/v3-to-v4.md at .agents/skills/phaser-4-guard/references/v3-to-v4.md, skills/phaser-4-guard/references/phaser3-sample.ts.txt at .agents/skills/phaser-4-guard/references/phaser3-sample.ts.txt. The "Gemini CLI" tab on this page has the curl commands, or download https://setupbay.com/download/phaser-4-api-guard/gemini-cli.zip, which is already laid out. Do not overwrite an existing AGENTS.md or CLAUDE.md; merge it.

How do I install Phaser 4 guard for Phaser 3 pipelines, FX and masks in Antigravity CLI?

From your project root, put AGENTS.md, skills/phaser-4-guard/SKILL.md at .agents/skills/phaser-4-guard/SKILL.md, skills/phaser-4-guard/scripts/phaser4_guard.py at .agents/skills/phaser-4-guard/scripts/phaser4_guard.py, skills/phaser-4-guard/references/v3-to-v4.md at .agents/skills/phaser-4-guard/references/v3-to-v4.md, skills/phaser-4-guard/references/phaser3-sample.ts.txt at .agents/skills/phaser-4-guard/references/phaser3-sample.ts.txt. The "Antigravity CLI" tab on this page has the curl commands, or download https://setupbay.com/download/phaser-4-api-guard/antigravity-cli.zip, which is already laid out. Do not overwrite an existing AGENTS.md or CLAUDE.md; merge it.

How do I install Phaser 4 guard for Phaser 3 pipelines, FX and masks in GitHub Copilot?

From your project root, put AGENTS.md, skills/phaser-4-guard/SKILL.md at .agents/skills/phaser-4-guard/SKILL.md, skills/phaser-4-guard/scripts/phaser4_guard.py at .agents/skills/phaser-4-guard/scripts/phaser4_guard.py, skills/phaser-4-guard/references/v3-to-v4.md at .agents/skills/phaser-4-guard/references/v3-to-v4.md, skills/phaser-4-guard/references/phaser3-sample.ts.txt at .agents/skills/phaser-4-guard/references/phaser3-sample.ts.txt. The "GitHub Copilot" tab on this page has the curl commands, or download https://setupbay.com/download/phaser-4-api-guard/copilot.zip, which is already laid out. Do not overwrite an existing AGENTS.md or CLAUDE.md; merge it.

What has been checked in Phaser 4 guard for Phaser 3 pipelines, FX and masks?

It passed the Level 1 automated install checks on 2026-10-29: the files parse, install to each agent's documented paths, and pass the safety scan. No AI agent has run it yet, so no agent pass or fail is claimed.

More for Claude Code, Codex, Cursor, Gemini CLI, Antigravity CLI and GitHub Copilot.