Install the "gdscript-advanced" agent skill from https://github.com/jame581/GodotPrompter/tree/master/skills/gdscript-advanced into .claude/skills/gdscript-advanced/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "gdscript-advanced", then confirm the skill loads.
Claude Code copies the folder itself, the same result as the manual copy. Check what it changed before you commit it.
Type this inside Codex. $skill-installer <name> installs a curated skill from openai/skills. The installer writes to $CODEX_HOME/skills (default ~/.codex/skills). Restart Codex if the skill does not show up.
skills CLI
$ npx skills add jame581/GodotPrompter --skill gdscript-advanced -a codex
Project install goes to .agents/skills/; add -g for ~/.codex/skills/.
Install the "gdscript-advanced" agent skill from https://github.com/jame581/GodotPrompter/tree/master/skills/gdscript-advanced into .agents/skills/gdscript-advanced/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "gdscript-advanced", then confirm the skill loads.
Codex copies the folder itself, the same result as the manual copy. Check what it changed before you commit it.
skills CLI
$ npx skills add jame581/GodotPrompter --skill gdscript-advanced -a cursor
Project install goes to .agents/skills/; add -g for ~/.cursor/skills/.
Install the "gdscript-advanced" agent skill from https://github.com/jame581/GodotPrompter/tree/master/skills/gdscript-advanced into .cursor/skills/gdscript-advanced/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "gdscript-advanced", then confirm the skill loads.
Cursor copies the folder itself, the same result as the manual copy. Check what it changed before you commit it.
--scope user (default) or --scope workspace; --path is the subfolder of the repo that holds the skill; --consent skips the security confirmation prompt.
skills CLI
$ npx skills add jame581/GodotPrompter --skill gdscript-advanced -a gemini-cli
Project install goes to .agents/skills/; add -g for ~/.gemini/skills/.
Install the "gdscript-advanced" agent skill from https://github.com/jame581/GodotPrompter/tree/master/skills/gdscript-advanced into .gemini/skills/gdscript-advanced/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "gdscript-advanced", then confirm the skill loads.
Gemini CLI copies the folder itself, the same result as the manual copy. Check what it changed before you commit it.
Installs for Copilot at project scope by default; add --scope user for a personal install. Preview a skill first with gh skill preview. Needs GitHub CLI 2.90.0 or later (public preview).
skills CLI
$ npx skills add jame581/GodotPrompter --skill gdscript-advanced -a github-copilot
Project install goes to .agents/skills/; add -g for ~/.copilot/skills/.
Install the "gdscript-advanced" agent skill from https://github.com/jame581/GodotPrompter/tree/master/skills/gdscript-advanced into .github/skills/gdscript-advanced/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "gdscript-advanced", then confirm the skill loads.
GitHub Copilot copies the folder itself, the same result as the manual copy. Check what it changed before you commit it.
skills CLI
$ npx skills add jame581/GodotPrompter --skill gdscript-advanced -a opencode
OpenCode documents no install command of its own. Project install goes to .agents/skills/; add -g for ~/.config/opencode/skills/.
Install the "gdscript-advanced" agent skill from https://github.com/jame581/GodotPrompter/tree/master/skills/gdscript-advanced into .opencode/skills/gdscript-advanced/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "gdscript-advanced", then confirm the skill loads.
OpenCode copies the folder itself, the same result as the manual copy. Check what it changed before you commit it.
Facts
Skill name
gdscript-advanced
GitHub stars
792
Token cost
~3.4k tokens
SKILL.md length
1,309 words
Files
4 (incl. references)
Skills in repo
58
Repo updated
First seen
Licence
MIT
At a glance
A skill your agent uses when writing production-grade GDScript — performance idioms, metaprogramming, @tool lifecycle, async pitfalls, signal/Callable trade-offs, profiler-driven idioms, and common…
Works in 8 steps: When to reach for advanced GDScript → Performance idioms → Metaprogramming → …
SKILL.md covers 1. When to reach for advanced…, 2. Performance idioms, 3. Metaprogramming and 4. @tool lifecycle, plus 5 more sections
Instructions only: no scripts, shell commands, URLs or credentials in SKILL.md
What it does
Gdscript Advanced is an agent skill from jame581/GodotPrompter. Use when writing production-grade GDScript — performance idioms, metaprogramming, @tool lifecycle, async pitfalls, signal/Callable trade-offs, profiler-driven idioms, and common pitfalls
Its SKILL.md is about 3.4k tokens, which your agent loads only when the skill is triggered. The skill folder holds 4 other files, including reference files (for example `references/metaprogramming-recipes.md`, `references/profiler-recipes.md` and `references/tool-script-recipes.md`).
It sits in Game Development, covering Performance optimization and Game development. It works with Godot and C#. The repository describes itself as: Agentic skills framework for Godot 4.x. Domain-specific skills for AI coding agents (Claude Code, Copilot, Antigravity, Cursor). The licence is MIT.
Read from SKILL.md and the folder at commit 1e7d79d. It shows what the files ask for, not the result of running them.
Tool permissions
Pre-approves nothing: there is no allowed-tools line, so your agent's usual permission prompts apply.
From allowed-tools in the SKILL.md frontmatter.
Runs code
No scripts in the folder and no shell commands in SKILL.md (its code samples are gdscript).
From the folder's file list and the shell code blocks in SKILL.md.
Network
Links to these hosts (documentation or services it may open):
docs.godotengine.org
From URLs in SKILL.md, links to its own repository left out.
Credentials
Names no API keys, tokens, secrets or passwords.
From names ending in _API_KEY, _TOKEN, _SECRET, _KEY or _PASSWORD in SKILL.md.
Context cost
Gdscript Advanced loads about 3.4k tokens when it runs, and up to ~5.1k if it reads all its reference files. Until then it costs about 51 tokens; SKILL.md has 1,309 words of instructions outside code blocks.
Always· name and description, kept in context so the agent knows when to use it
~51
When it runs· the whole SKILL.md, loaded when a task matches
~3.4k
With references· SKILL.md plus every file in references/, read only if the agent opens them
~5.1k
Estimates: characters ÷ 4, the usual rule of thumb; real counts depend on the model's tokenizer. Scripts and assets cost tokens only if the agent reads them.
Safety
Auto-check passed
The automated check found no risky patterns in SKILL.md.
Automated static check — not a guarantee. Review scripts before installing. It scans the text of SKILL.md for risky patterns (piping downloads into a shell, reading credential files, hidden Unicode, destructive commands); files beside SKILL.md are not scanned.
Download SKILL.mdSave it as .claude/skills/gdscript-advanced/SKILL.md (or your agent's skills folder). This skill also uses 3 other files; get the full folder from GitHub.
name
gdscript-advanced
description
Use when writing production-grade GDScript — performance idioms, metaprogramming, @tool lifecycle, async pitfalls, signal/Callable trade-offs, profiler-driven idioms, and common pitfalls
GDScript Advanced
Production-grade GDScript depth — for shipping games, not for learning the language. Pair with gdscript-patterns for fundamentals.
Related skills:gdscript-patterns for language fundamentals, godot-optimization for engine-side perf work, godot-debugging for runtime diagnosis, csharp-godot for the C# alternative.
Intent: This skill is GDScript-only by design (allowlisted). C# users should read csharp-godot. Adding C# parity here would undermine the audience split.
1. When to reach for advanced GDScript
You're past gdscript-patterns when:
You're hitting a profiler bottleneck and need to know which idioms are fast
You're writing editor tools and need @tool lifecycle correctness
You're seeing coroutines that never resume or Callable lifetime bugs
You need metaprogramming (calling functions by name, dynamic dispatch) without footguns
You're shipping a real game and want to avoid the patterns that look fine but break under load
This skill assumes you already know typed parameters, @onready, await, match, and lambdas (covered in gdscript-patterns).
2. Performance idioms
Static vars and methods (Godot 4.4+) avoid per-instance overhead:
Avoid singletons-as-autoloads when a static method on a class would do.
Vector2i vs Vector2 / Vector3i vs Vector3 — integer vectors are 30-40% faster on hot paths (tile coords, grid math). Convert to float only at the rendering boundary:
gdscript
var grid_pos: Vector2i = Vector2i(8, 12) # cheap
var world_pos: Vector2 = Vector2(grid_pos) * TILE_SIZE # convert at boundary
PackedArray* over generic Array — PackedInt32Array, PackedFloat32Array, PackedVector2Array, etc. allocate contiguous memory and skip Variant boxing. Use them for buffers, vertex arrays, hot-loop accumulators.
gdscript
var positions: PackedVector3Array = PackedVector3Array()
positions.resize(1000) # one allocation
for i in 1000:
positions[i] = Vector3(i, 0, 0)
Typed Dictionary access — typed dicts (Godot 4.4+) skip the Variant unbox per read:
gdscript
var stats: Dictionary[String, int] = {}
stats["hp"] = 100 # no boxing
is_instance_valid vs null check — is_instance_valid() does an engine-side lookup; != null is a pointer compare. Prefer != null after @onready assignment; reserve is_instance_valid() for nodes that may be queue_free'd while a reference is held.
Common pitfall: _process doing if is_instance_valid(target) once per frame burns ~1µs per call — tiny per-call but multiplies fast.
3. Metaprogramming
Callable.bind, Callable.call, Callable.call_deferred give you dynamic dispatch without Object.call(name) security risks.
Binding arguments:
gdscript
var greeter: Callable = print_named.bind("Player")
greeter.call() # prints "Hello, Player"
func print_named(name: String) -> void:
print("Hello, %s" % name)
Deferred calls — run on the next frame's idle phase, useful for cross-thread or signal-storm safety:
if obj.has_method("on_damaged"):
obj.call("on_damaged", 25)
Security gotcha: Never pass obj.call(user_string, ...) where user_string comes from save files, network, or mod content without an allowlist. call("queue_free") is a free crash. Match against a known set:
gdscript
const ALLOWED_RPCS: PackedStringArray = ["take_damage", "apply_buff", "set_position"]
if user_method in ALLOWED_RPCS and obj.has_method(user_method):
obj.call(user_method, args)
Editor notifications — use _notification for editor lifecycle events (NOTIFICATION_EDITOR_PRE_SAVE, NOTIFICATION_EDITOR_POST_SAVE, NOTIFICATION_PARENTED):
gdscript
func _notification(what: int) -> void:
if what == NOTIFICATION_EDITOR_PRE_SAVE:
_bake_preview()
Common pitfall: a @tool script that calls get_tree().create_timer() at editor time. Editor has no main loop in some contexts — guard with is_editor_hint().
await suspends the function and hands control back to its caller until the signal fires. It has three trap shapes:
Trap 1 — await in _ready returns early, so the node reports ready before it is initialized:
gdscript
# BAD: the first await returns control, so `ready` is emitted and the parent's
# _ready() runs while `inventory` is still empty
func _ready() -> void:
await get_tree().create_timer(1.0).timeout
inventory = load_inventory()
Fix: finish everything other nodes read at ready time before the first await. If part of setup genuinely has to wait, set an is_initialized flag and emit an initialized signal when it completes. Dependents check the flag before awaiting, because awaiting a signal that already fired never resumes (Trap 2).
Trap 2 — Awaiting a signal that never fires suspends the coroutine forever:
gdscript
# BAD if `health_changed` never fires (e.g., entity already at full HP)
await health.health_changed
Fix: check the precondition before awaiting. When you do need to wait, race the signal against a timeout. Released Godot has no Signal.any() and no other built-in way to await several signals at once (godot-proposals#13597 proposes global any()/all()), so funnel both signals into one you own:
gdscript
signal _health_wait_finished(changed: bool)
func wait_for_health_change(timeout_sec: float) -> bool:
var timer := get_tree().create_timer(timeout_sec)
var on_changed := func(_hp: int) -> void: _health_wait_finished.emit(true)
var on_timeout := func() -> void: _health_wait_finished.emit(false)
health.health_changed.connect(on_changed)
timer.timeout.connect(on_timeout)
var changed: bool = await _health_wait_finished
if is_instance_valid(health): # freed while we waited (see Trap 3)
health.health_changed.disconnect(on_changed)
timer.timeout.disconnect(on_timeout) # or a stale timer ends the next wait early
return changed
The lambdas emit a signal rather than set a local flag: GDScript lambdas capture locals by value, so changed = true inside one never reaches the outer variable. Every awaiter of _health_wait_finished resumes on the first emit, so run one wait at a time per node.
Trap 3 — Objects freed during the wait. If the node running the coroutine is freed, the coroutine is dropped silently — no error, and nothing after the await (cleanup, a finished emit) ever runs. If the node survives but something it references is freed, touching that reference after resuming errors with "previously freed". Re-validate after every await:
gdscript
func flash(target: Node2D) -> void:
target.modulate = Color.RED
await get_tree().create_timer(0.2).timeout
if not is_instance_valid(target): # freed while we waited
return
target.modulate = Color.WHITE
6. Signal vs Callable design choices
Signal — many-to-many, decoupled, edge-triggered. Slight per-emit overhead from the connection list lookup.
Callable — one-to-one, explicit, level-triggered. Cheaper per call but tighter coupling.
Common pitfall: connecting a lambda to a signal stores the lambda's captured environment forever. If the captured object is freed, you get warnings. Disconnect explicitly in _exit_tree or use bound methods instead.
Show full SKILL.md (514 more words)Show less
7. Profiler-driven idioms
Open the Debugger → Profiler panel. The patterns that show up most often:
Profiler hot spot
Likely cause
Fix
String allocation in _process
print() / "%s" % var per frame
Pre-format outside the loop, or batch logs with a circular buffer
Object.get_node showing high self-time
Repeated $Path/Sub/Node per frame
Cache in @onready var
Signal.emit showing high call count
Per-frame signal storms (e.g., position update)
Throttle to 10 Hz, or use a polling pattern
CharacterBody.move_and_slide self-time
Many character bodies on one frame
Scale by distance from camera; use Area for cheap detection
Lambdas capture locals by value — once, when the lambda is created. Loop lambdas therefore each keep their own i, and no bind is needed. The trap runs the other way: assigning a captured local changes only the lambda's copy, which starts from the captured value again on the next call:
gdscript
var count := 0
var bump := func() -> int:
count += 1 # CONFUSABLE_CAPTURE_REASSIGNMENT warning
return count
bump.call() # 1
bump.call() # 1 again, and `count` out here is still 0
Fix: keep shared state in a member variable or a reference type — an Array, Dictionary or object is captured as the same instance:
gdscript
var state := {"count": 0}
var bump := func() -> int:
state.count += 1
return state.count # 1, then 2
@onready ordering — @onready vars are set after _init but before _ready. Children's _ready runs before parent's _ready. So:
Don't reference parent state in a child's _ready unless you're sure the parent is initialized
For cross-node setup, prefer the parent calling child.setup_with(self) from its own _ready
Static var lifecycle across scene reload — static vars on a class persist for the lifetime of the engine, not the scene. Reloading a scene does NOT reset them. If you need a per-scene singleton, use an autoload, not a static var.
Resource sharing surprises — @export var item: ItemData with the same Resource asset in two scenes shares state by reference. Mutating one mutates the other. Use item.duplicate() when each instance needs its own state.
Packed-array property setters skip element writes
⚠️ Changed in Godot 4.7: Setting an element of a packed-array property (e.g. obj.packed_prop[i] = x) no longer calls the setter for the entire packed array property. Code that relied on the setter firing for per-element writes silently breaks — reassign the whole array to trigger the setter. See the 4.7 migration guide.
gdscript
var points: PackedVector2Array:
set(value):
points = value
_rebuild_mesh()
func move_point() -> void:
points[0] = Vector2.ONE # 4.6: setter (and _rebuild_mesh) ran; 4.7+: it does NOT
var updated := points # fix: modify a copy...
updated[0] = Vector2.ONE
points = updated # ...then reassign — the setter fires
Godot 4.7+: the new CONFUSABLE_TEMPORARY_MODIFICATION warning flags modifying a temporary (discarded) value — e.g. a built-in Packed*Array property changed through a complex assignment chain or a non-const method call, where only a temporary copy changes and the property keeps its old value. Controlled by debug/gdscript/warnings/confusable_temporary_modification (default 1, warn).
Implementation Checklist
Identify which performance idiom applies (typed vectors, PackedArray, static methods)
If using metaprogramming, allowlist all dynamic method names
If @tool, guard editor vs runtime branches with Engine.is_editor_hint()
Audit await calls for signals that may never fire, _ready returning before setup finishes, and references freed during the wait
Pick signal vs Callable per the trade-off table; disconnect lambdas in _exit_tree
Profile before optimizing; match the hot-spot to the table in section 7
Audit lambdas that assign captured locals (the change never escapes the lambda), @onready ordering, static var lifecycle, Resource sharing, and packed-array property setters (Godot 4.7) for the listed pitfalls
Gdscript Advanced next to the 5 skills that share the most tags, products or categories with it. Stars are the repository's; “used in” counts other GitHub owners with a copy.
Expert patterns for simplifying 3D games to 2D including dimension reduction strategies, 2.5D fake-depth, isometric ports, camera flattening, physics conversion, 3D-to-sprite art pipeline, and…
Covers Godot 4.3+ 2D systems with GDScript and C# examples: canvas layers, draw order, TileMaps, parallax, lights and shadows, particles and custom drawing.
Covers Godot 4.3+ 3D systems such as materials, lighting, shadows, environment, global illumination, fog, LOD, occlusion culling and decals, with GDScript first and C# second.
Builds a data-driven ability system in Godot 4 from Resources and a component node, with cooldowns, buffs, stat modifiers, gameplay tags and HUD binding.
Covers Godot 4.3+ editor plugins: plugin folders, @tool scripts, the EditorPlugin lifecycle, custom inspectors, dock panels and gizmos, in GDScript and C#.
Covers animation in Godot 4.3 and later: AnimationPlayer basics, AnimationTree blend trees and state machines, sprite animation, skeleton IK and code-driven motion.
A skill your agent uses when writing production-grade GDScript — performance idioms, metaprogramming, @tool lifecycle, async pitfalls, signal/Callable trade-offs, profiler-driven idioms, and common…. Gdscript Advanced is an agent skill from jame581/GodotPrompter.
How do I install Gdscript Advanced in Claude Code?
Run `npx skills add jame581/GodotPrompter --skill gdscript-advanced -a claude-code`. Or copy the skill folder (skills/gdscript-advanced in jame581/GodotPrompter) into .claude/skills/gdscript-advanced in your project. Claude Code loads it when a task matches its description.
How do I install Gdscript Advanced in Codex?
Run `npx skills add jame581/GodotPrompter --skill gdscript-advanced -a codex`. Or copy the skill folder (skills/gdscript-advanced in jame581/GodotPrompter) into .agents/skills/gdscript-advanced in your project. Codex loads it when a task matches its description.
Can I use Gdscript Advanced in Cursor, Gemini CLI or GitHub Copilot?
Cursor, Gemini CLI, GitHub Copilot and OpenCode also load SKILL.md folders. With the skills CLI, run `npx skills add jame581/GodotPrompter --skill gdscript-advanced -a cursor` (or -a gemini-cli, github-copilot or opencode for the others). To copy it by hand, put the folder in .cursor/skills/gdscript-advanced, .gemini/skills/gdscript-advanced, .github/skills/gdscript-advanced and .opencode/skills/gdscript-advanced in your project.
What does Gdscript Advanced need to run?
SKILL.md names no scripts, command-line tools or credentials: Gdscript Advanced is instructions for the agent only.
Does Gdscript Advanced access the network?
SKILL.md names 1 domain. As links in the text: docs.godotengine.org. This is read from the text; nothing was executed.
Is Gdscript Advanced safe to install?
Our automated static check of SKILL.md found no risky patterns, such as piping downloads into a shell, reading credential files or hidden Unicode. It is not a guarantee. Review the folder before installing.
What licence does Gdscript Advanced use?
Gdscript Advanced is published under the MIT licence (the repository's licence). It allows redistribution, so the full SKILL.md is shown on this page.
How many tokens does Gdscript Advanced use?
About 3.4k tokens (SKILL.md is roughly 14k characters). Agents keep only the skill's name and description in context until a task matches; then they load SKILL.md in full. Its references folder adds about 1.7k tokens, read only when the agent opens those files.
What are the alternatives to Gdscript Advanced?
Skills that share tags, products or a category with Gdscript Advanced: Godot Performance Optimization (thedivergentai/GD-Agentic-Skills, 803 stars), Release Manager (poingstudios/godot-admob-plugin, 631 stars), Godot Admob App Open (poingstudios/godot-admob-plugin, 631 stars) and Godot Admob Banner (poingstudios/godot-admob-plugin, 631 stars). The comparison table on this page puts their stars, adoption, token cost, safety result and licence side by side.
Who maintains Gdscript Advanced?
jame581 (a GitHub user) maintains it in jame581/GodotPrompter, which has 792 GitHub stars. The repository holds 58 skills in this directory. The repository was last updated on October 6, 2026.
Source: jame581/GodotPrompter on GitHub. Facts on this page come from the repository at the commit we read; the author's words are quoted as theirs.