Godot 4
Godot 4 CLAUDE.md
GDScript 2.0 rules that refuse Godot 3 APIs.
Verified on 2026-10-15 · zip downloads · version-pinned
Verified for
- Godot 4.7.2-stable (18 August 2026)
- GDScript 2.0
Last tested 2026-10-15
Run-tested (parse)
doc-verified; GDScript sample parsed by Godot 4.7.2 headless (--check-only), with a Godot 3 control script correctly rejected
The rules
Stops agents writing Godot 3 into a Godot 4 project: KinematicBody2D, yield, export var, and move_and_slide(velocity). Pinned to Godot 4.7.2 with an explicit rename table from the official upgrade guide.
Related fixes
Who it's for
People using Cursor, Claude Code, or Copilot on a Godot 4 game, especially anyone who has seen the agent emit Godot 3 code.
Loadout Pro Bundle
$1+ · pay what you want
What you get
- Phaser 4 (4.2.1)
- three.js (r186)
- FastAPI (0.143 / Pydantic 2.14)
Each pack ships as AGENTS.md, CLAUDE.md, Cursor .mdc, and Copilot instructions, with 12 months of free updates.
Get Pro on GumroadInstall
Copy one file, or download the zip for that tool. The zip already uses the path below.
Cursor
.cursor/rules/godot-4.mdc
- Download the Cursor zip, or copy the .mdc file from this page.
- Save it as .cursor/rules/godot-4.mdc.
- Commit it. Cursor reads project rules from that folder.
Claude Code
CLAUDE.md
- Download the Claude zip, or copy CLAUDE.md.
- Put CLAUDE.md in the project root.
- Claude Code reads it as project memory on the next session.
AGENTS.md
AGENTS.md
- Download the Agents zip, or copy AGENTS.md.
- Put AGENTS.md in the project root.
- Agents that read AGENTS.md, including Codex and Cursor, pick it up there.
GitHub Copilot
.github/copilot-instructions.md
- Download the Copilot zip, or copy the instructions file.
- Save it as .github/copilot-instructions.md.
- Copilot reads repository instructions from that path.
Questions
- What does the Godot 4 pack do?
- Stops agents writing Godot 3 into a Godot 4 project: KinematicBody2D, yield, export var, and move_and_slide(velocity). Pinned to Godot 4.7.2 with an explicit rename table from the official upgrade guide.
- Who is the Godot 4 pack for?
- People using Cursor, Claude Code, or Copilot on a Godot 4 game, especially anyone who has seen the agent emit Godot 3 code.
- Which versions does the Godot 4 pack pin?
- Godot: 4.7.2-stable (18 August 2026) GDScript: 2.0 Last tested 2026-10-15.
- How do I install the Godot 4 pack?
- Copy .cursor/rules/godot-4.mdc into the repo for Cursor, CLAUDE.md for Claude Code, AGENTS.md for other agents, and .github/copilot-instructions.md for GitHub Copilot. A format zip already uses that path. Then commit the files.
- When was the Godot 4 pack last tested, and how?
- Last tested 2026-10-15. doc-verified; GDScript sample parsed by Godot 4.7.2 headless (--check-only), with a Godot 3 control script correctly rejected.
Plain text
The same pack as markdown, plus each rules file on its own URL.
Files
.cursor/rules/godot-4.mdc
---
description: Godot 4.7 GDScript 2.0. CharacterBody, move_and_slide(), @export, and a Godot 3 ban list.
globs: "**/*.gd"
alwaysApply: false
---
# Godot 4.7 GDScript 2.0
Pinned to Godot 4.7.2 stable (18 August 2026), GDScript 2.0. Write only Godot 4 code. The list at the bottom is banned even if an old tutorial or an older model suggests it.
## Scenes and scripts
- Do not delete `.godot/`, `project.godot`, `.import`, or `.uid` files. Do not hand-edit `.import` files.
- Put gameplay code on the node that owns the behavior. Use `@onready` to cache child nodes. Do not call `get_node()` every frame.
- `@export` is for designer-facing values only. Give it a type and a default.
```gdscript
extends CharacterBody2D
@export var speed: float = 200.0
@onready var sprite: Sprite2D = $Sprite2D
func _physics_process(_delta: float) -> void:
var input := Input.get_vector("ui_left", "ui_right", "ui_up", "ui_down")
velocity = input * speed
move_and_slide()
```
## Movement
- Bodies are `CharacterBody2D` and `CharacterBody3D`. They own a `velocity` property (`Vector2` or `Vector3`).
- Set `velocity`, then call `move_and_slide()` with no arguments. Do not pass the velocity, an up vector, or a delta into `move_and_slide`.
- Do not multiply horizontal `velocity` by `delta`. `move_and_slide()` applies the timestep. Gravity is the exception: `velocity.y += gravity * delta` before the call.
- Read input with `Input.get_vector` or `Input.is_action_pressed` using actions from the Input Map. Do not hardcode key scancodes in gameplay code.
- Run movement in `_physics_process`, not `_process`.
## Signals and loading
- Connect with a Callable: `button.pressed.connect(_on_pressed)`. Disconnect with `disconnect`. Emit with `hit.emit(amount)`, not `emit_signal("hit", amount)`.
- Declare a signal as `signal hit(amount: int)`.
- Load a scene with `preload("res://player.tscn")` when the path is fixed, and instance it with `instantiate()`, not `instance()`.
- Change scene with `get_tree().change_scene_to_file("res://main.tscn")`.
- Read and write files with `FileAccess.open`. List directories with `DirAccess`. Both are static. There is no `File.new()`.
## Never write these (Godot 3, or removed)
| Do not write | Write instead |
| --- | --- |
| `KinematicBody2D`, `KinematicBody` | `CharacterBody2D`, `CharacterBody3D` |
| `yield(...)`, `yield(self, "completed")` | `await` |
| `export var`, `export(int)`, `onready var` | `@export var`, `@onready var` |
| `move_and_slide(velocity)` | set `velocity`, then `move_and_slide()` |
| `connect("pressed", self, "_on_pressed")` | `pressed.connect(_on_pressed)` |
| `emit_signal("hit", n)` | `hit.emit(n)` |
| `packed.instance()` | `packed.instantiate()` |
| `File.new()`, `Directory.new()` | `FileAccess`, `DirAccess` |
| `Spatial`, `SpatialMaterial` | `Node3D`, `StandardMaterial3D` |
| `rand_range(a, b)` | `randf_range(a, b)` |
| `PoolStringArray`, `PoolIntArray` | `PackedStringArray`, `PackedInt32Array` |
| `change_scene("res://x.tscn")` | `change_scene_to_file("res://x.tscn")` |
| `OS.get_window_size()`, `OS.window_fullscreen` | `DisplayServer` window methods |
If you are about to type any name in the left column, stop and use the right column.
## Typing and timing
- Use static types on variables, parameters, and return values (`var hp: int = 10`, `func hit(n: int) -> void`). Use `:=` only when the type is obvious from the right side.
- Wait for a timer with `await get_tree().create_timer(1.0).timeout`.
- Animate with `var tween := create_tween()`. Do not create a `Tween` node with `Tween.new()`.
- Mark editor scripts with `@tool` on the first line, and check `Engine.is_editor_hint()` inside them.
- Property accessors use the GDScript 2.0 `get:` / `set(value):` blocks, not `setget`.
## Done checklist
1. The Godot editor shows no parser errors on the edited scripts.
2. Nothing from the ban list appears in the diff.
3. You said whether the scene was actually run.
Changelog
Placeholder. This is the first published cut, last verified on 2026-10-15. Version notes will replace this block when the pack is revised.