Godot 4 GDScript Rules for Cursor: a Working .mdc Setup
In short: put rules in .cursor/rules/*.mdc (not .md). Make two or three short rules always-on (core, Godot 3→4 table, workflow). Scope the rest with globs: **/*.gd. Then make the agent run godot --headless --check-only after each edit.
1. The mistake that silently disables your rules
Cursor's project rules live in .cursor/rules/ and must use the .mdc extension. A plain my-godot-rules.md in that folder is ignored, and Cursor shows no error. If your agent seems to "forget" everything, check this first.
2. Frontmatter: three fields, four behaviours
---
description: Godot 4 API correctness - never use Godot 3 APIs
globs: **/*.gd,**/*.tscn
alwaysApply: true
---
alwaysApply: true: included in every chat. Globs are ignored.alwaysApply: false+globs: attached when a matching file is in context.alwaysApply: false+descriptiononly: the agent decides from the description.- Neither: manual, via
@rule-name.
3. What to make always-on (keep it small)
Every always-on line costs context in every request. For Godot, only three things deserve it:
- Core identity: "Godot 4.x, GDScript 2.0, never Python, never Godot 3".
- The 3 → 4 table: concrete wrong → right pairs beat vague advice.
- Workflow: plan, small step, headless check, and be honest about what was verified.
4. A minimal Godot 4 core rule you can copy
---
description: Non-negotiable Godot 4 / GDScript 2.0 rules
alwaysApply: true
---
- Godot 4.x, GDScript 2.0. Never Python syntax, never Godot 3 APIs.
- await, not yield. @export / @onready / @tool annotations.
- Type every var, param and return: func hit(dmg: int) -> void:
- Signals: health_changed.connect(_on_health_changed); health_changed.emit(v)
- KinematicBody2D is CharacterBody2D: set velocity, call move_and_slide() with no args.
- After editing a script run: godot --headless --check-only --script res://path.gd
5. Scoped rules for the details
Static typing, architecture, physics, UI, testing: give each its own .mdc with globs: **/*.gd (or tests/**/*.gd for testing). Cursor recommends keeping each rule under 500 lines. Ours are under 70.
6. Make it verifiable
Rules are context, not enforcement. The most reliable way to catch a lapse is to have the agent run the engine:
godot --headless --path . --import
godot --headless --path . --check-only --script res://scenes/player/player.gd
godot --headless --path . --quit-after 30
Gotcha: --check-only --script doesn't load autoloads, so Identifier not found: EventBus is a false positive there. The --quit-after run is the real check.
FAQ
Does Cursor read AGENTS.md too?
Yes, in the project root and in subdirectories. If you use both, keep them consistent.
Do rules affect Cursor Tab?
No. Rules apply to Agent and chat, not Tab completions.
Why is Cursor ignoring my Godot rules?
Check the file extension first. Project rules live in .cursor/rules/ and must use .mdc. A plain .md file in that folder is ignored, and Cursor shows no error.
What do alwaysApply and globs do in a .mdc rule?
alwaysApply: true includes the rule in every chat and ignores globs. alwaysApply: false with globs attaches it when a matching file is in context. With only a description, the agent decides. With neither, you attach it manually with @rule-name.
How do I check that the AI's GDScript actually works?
Have the agent run the engine: godot --headless --path . --check-only --script res://path.gd after each edit, then godot --headless --path . --quit-after 30. --check-only doesn't load autoloads, so the --quit-after run is the real check.