Godot scene plan
A workflow operating system for AI-assisted engineering. Task state, decisions, and plans live on disk as files, not in chat history, so context survives across sessions, tools, and restarts.
npx -y skills add Mozurok/fhorja.dev --skill godot-scene-planAssembled from the repository path, not quoted from the project. Check it against their README if it does not work.
2 things to look at
- 29 days oldThe repository was created 29 days ago. New is not bad, but a brand new repository carrying a familiar-sounding name is the shape a typosquat arrives in, and there has been no time for anyone else to find a problem with it.
- 6 stars6 stars. Stars are a popularity signal and not a quality one, but at this level it is likely that nobody has read this closely except its author, and you would be relying on your own review.
What its author says it does
Copied from the file, not written here
Plan the Godot scene and node structure for a 2D or 3D game feature before any GDScript is written: the scene tree, node types and responsibilities, autoloads (singletons), signal wiring, the input map, and the resources and sub-scenes to create. Produces GODOT_SCENE_PLAN.md, a design-time plan an MCP-driven editor or a human then builds against. Capability-routed and MCP-agnostic (names no specific server). Consults the per-dimension Godot reference topics. A 3D plan SHALL declare its renderer tier or it is incomplete. Use when a Godot 2D or 3D feature or screen needs its scene architecture decided before implementation. Do not use to frame whether the game idea is right (use problem-framing in its game-design mode), to slice an already-planned build (use implementation-plan), to analyze blast radius of an existing Godot project (use impact-analysis), to verify a running scene (use godot-runtime-verify), or with no active task folder (run task-init first).
SKILL.md
26.5 KB, ~6.0k tokens by cl100k_base, as published. Nobody here has run it
Act as a senior Godot engineer planning the scene and node architecture for a 2D or 3D game feature before any code is written.
Goal:
For a given game feature or screen (a player, a level, a HUD, a menu), decide the Godot scene structure: the scene tree and node types, what each node is responsible for, which autoloads (singletons) the feature needs, how nodes communicate through signals, the input map actions, and the resources and sub-scenes to create. Produce a scene plan doc at GODOT_SCENE_PLAN.md in the active task folder that an MCP-driven editor or a human can build against without re-deciding the architecture. The plan is engine-grounded and stays MCP-agnostic: it never names a specific MCP server, because the contract is the scene design, not the tool that applies it (DECISIONS D-1, D-4).
Mandatory context bootstrap (before any output):
<!-- shared:mandatory-context-bootstrap -->- Read these sections in
WORKFLOW_OPERATING_SYSTEM.mdfirst:## LLM execution contract## Editor mode policy(mode definitions only; the tool mapping table is lazy-loaded inwos/editor-mode-mappings.mdand needed only for non-Claude-Code tools)## Global output contract(including Adaptive handoff and Mode selection rule)## Cross-cutting workflow guardrails
- Bootstrap tiers (ADR-0025): the light-weight commands (
branch-commit,what-next,where-we-at,slice-closure,compact-task-memory) may skip## Editor mode policygood-fits lists and## Cross-cutting workflow guardrailssequencing heuristics, reading only the mode definitions and the core guardrail rules (routing memory, command-less input triage, official command names, material change, no-op). The full tier is measured at 9610 tokens: the combined size of the four always-readWORKFLOW_OPERATING_SYSTEM.mdsections listed above. The reduced tier is a self-declared estimate of about 3,500 tokens for the trimmed subset above; it has not been independently re-measured by the same method, and should be read as an estimate rather than a fresh figure. The same reduced tier extends to the high-frequency execution commandsimplement-approved-sliceandsync-task-state(v3 wave1 item D: the most-invoked commands pay the bootstrap most often;state-reconciledeliberately stays on the full tier, cross-artifact judgment needs the full guardrail context). - Cache-amortized layer (ADR-0006): this bootstrap floor is a cache-amortized cost, not a per-command tax paid in full on every invocation. It sits in the prompt cache for the session and is paid at write cost once per cache TTL window, then at roughly 0.1x on cached reads inside that window. Account for it separately from any per-skill Load budget (the generated
.claude/skills/<name>/SKILL.mdbody); the two are different layers and should not be summed into one figure. - Session bootstrap reuse (skip-if-unchanged; v3 wave1 item D): WHEN this same conversation already performed this bootstrap read in an earlier turn that is still VISIBLE in the current context window AND
WORKFLOW_OPERATING_SYSTEM.mdhas not changed since, the command MAY skip the re-read and cite the earlier one instead, emitting one Command transcript line:Bootstrap: reusing turn <N> read, WOS unchanged. This is a scoped exception to the context-budget re-fetch rule (wos/context-budget.md, "The re-fetch rule"), justified because the bootstrap sections are one large, static, byte-identical read repeated every turn rather than a variable tool result; the re-fetch rule still governs every other tool result without exception. VISIBLE means the bootstrap section text itself is still present and quotable in the window right now, not merely that the record of an earlier read exists. On a harness that clears, a tool result can be emptied while the record that the tool ran survives (ADR-0114); a command that finds only that record, without the section text still readable, has not satisfied VISIBLE and must re-read. Self-declared memory after a compaction never qualifies (re-read instead), and a stateless-per-turn harness is excluded. The auditable-skip rule applies: the transcript line is mandatory; a silent skip is invalid output. - Read additional sections only when relevant to this command's role.
- Read the
commands/directory command inventory to ensure command names and availability are current. - Align all routing recommendations and next-command suggestions with the current command set.
- Official next-command names only: every recommended next command (including the handoff
Run nowline) MUST be the basename of an existingcommands/<name>.mdfile in this workflow repository. Never invent names.
Required inputs:
- active task folder path
- the feature or screen to plan (one or two sentences: what it is and what it does)
- the game-design context, when available (the core loop, mechanics, and constraints from a game-design brief or from
problem-framingin its game-design mode) MECHANICS_SPEC.mdwhen it exists (the behavior contract fromimage-to-spec --gameplay, ADR-0084): the interaction, win, and lose rules the scene must realize, each tagged observed, assumed, or open- the target Godot major version, when known (the plan stays version-flexible; note 4.6+ when editor-driven on-device testing matters, per DECISIONS D-5)
- the existing project layout, for a brownfield feature (so the plan reuses existing autoloads, scenes, and the input map instead of duplicating them)
Operating rules:
-
Do not write GDScript or create scene files; this command plans the structure, it does not implement it.
-
K.2 scope note (P2-8, dogfood-wave-2 2026-07-12): this command's own artifact (
GODOT_SCENE_PLAN.md) is outside the K.2 11-file substrate scope (commands/_shared/substrate-write-protocol.md) and needs no transaction header. UpdateTASK_STATE.md's## Last completed stepafterward as ordinary operator hygiene. -
Handoff: end with the adaptive
### Handoffblock perWORKFLOW_OPERATING_SYSTEM.md## Global output contract(Mode A compact or Mode B full). -
MCP-agnostic: never name a specific MCP server in the plan. The plan is the scene design; whichever editor-control tool (or a human) applies it is out of scope (DECISIONS D-1).
-
GDScript is the default language target; note the experimental C# iOS export caveat only when the feature's language choice is genuinely open and mobile export is in scope (DECISIONS D-6).
-
No-op rule: if a valid
GODOT_SCENE_PLAN.mdalready covers this feature with no material change, do not rewrite it; return a short NO_OP note and route forward. -
Git preflight (F-9 fold, ADR-0089). Check the target game directory before planning: IF it is not a git repository (no
.git) THEN surface that as a blocking preflight and name the fix (git initplus a first commit ofproject.godot, to happen at the firstimplement-approved-sliceinvocation oncegame//project.godotactually exist, not inside this command, which runs before either file exists). The commit-evidence closure floors (ADR-0084) presuppose a repository; the dogfood behind this rule built an entire POC un-versioned and had togit initmanually at delivery time. This is a routing preflight, not an auto-init: state the gap and the one-line fix here, and do not rungit initunprompted, here or later. -
Step 1: Restate the feature and its responsibilities. One paragraph: what the feature is, what it owns, and what it explicitly does not own. Name the game-design context it serves.
-
Step 1a: Mechanic contract (mandatory; ADR-0084). Before designing the scene tree, state the mechanic contract the scene realizes. WHEN a
MECHANICS_SPEC.mdexists (fromimage-to-spec --gameplay), cite the specific rules this scene implements (the core loop, the interaction rules, the win condition, the lose condition) by their spec tag. IF a rule the scene depends on is taggedassumedoropen, or is absent from the spec, log it as an open question routed todecision-interviewand DO NOT design the scene around an assumed default. WHEN noMECHANICS_SPEC.mdexists at all (aproblem-framing --game-designordecision-interview-sourced game, a sanctioned intake path per Required Inputs below), cite the specificDECISIONS.mdD-N entries (orBRIEF.mdfields) that constitute the mechanic contract instead; the same rule applies, an assumed or missing rule in that source is still routed todecision-interview, not silently designed around. A scene plan that silently bakes in an undocumented mechanic is invalid output: the dogfood behind ADR-0084 built a whole core loop on an assumed ring mechanic that turned out wrong. Name the contract before the nodes that realize it. -
Step 1b: Screen graph (mandatory for a multi-screen game; ADR-0084). WHEN the feature belongs to a multi-screen game (menu, gameplay, score, reward, retry), specify the screen graph before the per-screen scene plans: the game states (at least a win state and a lose state) and the transitions that wire the screens together (stage complete to score to reward to next stage; a lose condition to retry). This step owns the connective flow that per-screen plans each disown; leaving it unowned is the ADR-0084 failure where the score and reward flow did not exist until a playtest surfaced it. For a single self-contained feature with no cross-screen flow, say so and skip the graph.
-
Step 2: Design the scene tree. Lay out the node hierarchy as an indented tree. For each node give its type (the Godot built-in class: in 2D
CharacterBody2D,Area2D,AnimatedSprite2D,CollisionShape2D,Camera2D,CanvasLayer,Control; in 3DCharacterBody3D,Area3D,MeshInstance3D,CollisionShape3D,Camera3D,GridMap,NavigationRegion3D) and a one-line responsibility. Prefer the smallest tree that works; do not add nodes a responsibility does not require (YAGNI). -
Step 3: Decide autoloads (singletons). List the autoloads the feature needs (e.g. a game-state store, an audio manager, an event bus) with what each holds and why a singleton is the right scope. For a brownfield feature, reuse existing autoloads rather than adding new ones; flag any new autoload as a deliberate decision. For the autoload-versus-shared-Resource choice and, when the feature persists progress, the save-state design (a save schema,
user://paths, the serialization choice, and auto-save onNOTIFICATION_APPLICATION_PAUSED), consultwos/godot-2d-architecture.mdfor a 2D target orwos/godot-3d-architecture.mdfor a 3D target. Audio ruling (recorded decision; ADR-0084): for a game with any sound, cite here the ship-with-or-without-audio decision, either an audio autoload and wired settings are in scope, or shipping silent is an explicit non-goal; "polish later" prose does not satisfy it, because the dogfood shipped inert Sound and Music toggles that controlled nothing. This plan cites the decision, it does not own it: the decision itself is adecision-interview-ownedDECISIONS.mdD-N entry (perwos/substrate-peers.md), the same routing the mechanic contract (Step 1a) already uses for an assumed or open rule. Consultwos/godot-2d-audio.mdfor the bus layout, SFX pooling, and the settings-to-mixer wiring that closes the inert-toggle gap. -
Step 4: Wire signals. For each cross-node interaction, name the emitter node, the signal, the listener, and the payload. Prefer signals over direct node references for decoupling; call out where a direct reference is the simpler correct choice. This is the scene's communication contract. When the feature has game-feel (screen shake, haptics, audio feedback), plan the feedback layer (a shake or camera autoload, a haptics call site, an audio-feedback pool) and its signal wiring here, and consult
wos/godot-mobile-interaction-and-feel.mdfor the proportional-feedback and mobile-constraint rules. A typed-Node@export(e.g.@export var target: Marker2D) assigned as a bareNodePathvalue in hand-authored.tscntext does not resolve; it silently fails at the point of use (a "Nil has no property" error far from the real cause), not at load or import time. When authoring.tscntext by hand without a live editor, plan a plainNodePathexport instead, resolved manually viaget_node()in_ready(). -
Step 5: Define the input map. List the input actions the feature needs (e.g.
move_left,jump,pause) and the device classes each must support (keyboard, touch, gamepad). For a mobile target, state the touch mapping explicitly; do not assume keyboard-only. For a 3D target, state the camera-control scheme alongside movement, and note that a desktop-leaning 3D game defaults to keyboard and gamepad rather than touch. For the mobile touch model (per-finger index tracking,TouchScreenButtonvs a Control button, the on-screen controls layer and safe area, and the mouse-versus-touch emulation decision), consultwos/godot-mobile-interaction-and-feel.md. -
Step 6: List resources and sub-scenes. Enumerate the
.tscnsub-scenes,.tresresources, and assets the feature instantiates (e.g. a reusable enemy scene, a tilemap, a particle resource), with a one-line purpose each. Mark which already exist vs which are new. Placeholder-asset policy (recorded decision; ADR-0084): when the feature uses placeholder art (colored rects, programmer sprites), cite here what is placeholder, what "final" means, and the swap trigger, so "add art later" does not become a silent permanent state and the swap stays a clean slice. As with the audio ruling above, this plan cites the decision from adecision-interview-ownedDECISIONS.mdD-N entry rather than owning it directly. Consultwos/godot-2d-asset-pipeline.mdfor a 2D target (import settings, atlas, placeholder-to-final, licensing) orwos/godot-3d-asset-pipeline.mdfor a 3D target (CC0 sourcing, the glTF and Blend import path, the per-tier texture ceiling). -
Step 7: Note dimension and platform fit. State the dimension the plan targets explicitly; it is never inferred. The plan SHALL carry the canonical declaration block shown below, in BOTH dimensions, because a floor and a check both read it and both BLOCK when it is absent or malformed (D-10 of the 2026-07-26 tier-gate task). Prose stating the dimension does not satisfy it; the block does. For a mobile target, note the viewport and aspect-ratio strategy, the renderer choice for low-end devices, and any node choice driven by the mobile target. Mark device-specific numbers as
[to confirm]rather than inventing thresholds; defer concrete budgets toperformance-budgetin its matching Godot profile.Copy this block verbatim into the plan with your values substituted.
Dimensionreads exactly2Dor3D.Renderer tieris present only WHERE the dimension is3D, and is omitted entirely for2D. Nothing else goes inside the fence, and the reason for the tier choice goes in prose OUTSIDE it. A near miss is a block, not a warning: a lowercase value, a bullet, emphasis markers, a heading, or a table row are each read as no declaration at all. Up to three spaces of leading indentation on the fence are tolerated and stripped, so the block stays legible under a numbered step; a deeper indent, a tab, a tilde fence, or a fence nested inside another fence of either character is not a declaration. A fence closes only with its own character, so a~~~never closes afence and anever closes a~~~one. Close the fence: an unterminated one, or one swallowed by an earlier unbalanced fence elsewhere in the plan (a~~~sample counts), reads as a malformed declaration rather than an absent one, and a malformed declaration is never waivable. Quoting this exemplar without declaring your own block reads the same way, so quote it in prose if you must and declare your own values for real.Dimension: 3D Renderer tier: Forward+ -
Step 7a: Declare the renderer tier (REQUIRED for a 3D target; ADR-0117 D-9). WHERE the plan targets 3D, the declaration block above SHALL carry a
Renderer tier:entry naming exactly one ofForward+,Mobile, orCompatibility, with the one-line reason in prose OUTSIDE the block rather than on the entry itself (D-10 of the 2026-07-26 tier-gate task). Prose naming a tier does not satisfy it. A 3D scene plan with no declared tier is INCOMPLETE and SHALL NOT be treated as ready to build against. The tiers differ by removed features rather than by speed, so a node or effect chosen under Forward+ has no automatic fallback on the lower tiers;wos/godot-3d-rendering-and-performance.mdcarries which features each tier drops. Two consequences to record with the tier: anything depending onRenderingDeviceis a Forward+-only path, and the iOS simulator supports only Compatibility, so a simulator check is not evidence for the shipped tier. For a 2D target this step is inert, but the declaration block is not: say in one line that no tier applies. -
Step 8: Log open questions. Architecture ambiguities that need a decision (a missing mechanic detail, an undecided autoload scope) routed to
decision-interview, and factual gaps routed totargeted-questions. -
Step 8a: Self-review the declaration block before emitting (REQUIRED; D-1 and D-10 of the 2026-07-26 tier-gate task). Before writing the file, read back the plan you are about to emit and check mechanically, not from memory: that it carries exactly one
wos-godot-declarationfenced block, that the block holds aDimension:entry reading exactly2Dor3D, and, WHERE that value is3D, that it also holds aRenderer tier:entry naming exactly one ofForward+,Mobile, orCompatibility. IF the block is absent, appears more than once, is empty, or any value is not one of those exact strings THEN the plan is INCOMPLETE: do not emit it as ready to build against, fix the block or state in the output why the tier cannot be decided yet and route that todecision-interview. This is the first of two enforcement points; the closure floor inwos/platform-runtime-floors.mdis the backstop that fires when this step is skipped. Checking your own output is the weaker of the two by design, which is why the backstop exists. -
Step 9: Write the plan. Save as
GODOT_SCENE_PLAN.md(orGODOT_SCENE_PLAN_<feature-slug>.mdwhen the task plans several features) in the active task folder.
Required output:
- Feature identity (name, what it owns, the game-design context it serves)
- The mechanic contract (Step 1a): the
MECHANICS_SPEC.mdrules the scene realizes, or the open questions routed todecision-interviewwhere a rule is assumed, open, or absent - The screen graph (Step 1b) when the feature is part of a multi-screen game (game states plus cross-screen transitions), or an explicit note that the feature is self-contained
- The generated
GODOT_SCENE_PLAN.md(the scene tree, autoloads with the audio ruling, signals, input map, resources and sub-scenes with the placeholder-asset policy, thewos-godot-declarationfenced block carryingDimension:and, when the dimension is 3D,Renderer tier:, the platform fit notes, and the tier reason in prose outside the block) - Reused vs new (existing autoloads/scenes/input actions reused; new ones added, each as a deliberate decision)
- Open questions and their routing
- Recommended next command
Claim grounding (active epistemic humility)
<!-- shared:claim-grounding -->Claim grounding (active epistemic humility). This block governs what you may assert and how you record it. It is keyed to the substrate section you are writing, not to which command is running, and it is INERT on any output that writes none of the claim-bearing sections below. Full contract and rationale: wos/active-epistemic-humility.md.
-
When this applies. This block fires ONLY while you are writing a claim-bearing substrate section:
TASK_STATE.md ## Current known facts,## Risks to watch,## Observations,## Active files in scope,## Canonical decisions;DECISIONS.md ## Locked decisions;IMPLEMENTATION_PLAN.md ## Current gaps,## Risks and mitigations;IMPACT_ANALYSIS.md;EXTERNAL_RESEARCH.md;REFERENCES.md; or any section whose content is a statement a later command or a human decision will act on. WHEN your output writes none of these, this block imposes nothing: skip it and proceed. This is the D-13 inert clause; a fully-grounded or claim-free output pays nothing. -
The unit is the load-bearing claim. A load-bearing claim is one a downstream command or a human decision consumes. A passing aside is not load-bearing; a statement someone will act on is. Apply the rest of this block per load-bearing claim, not per sentence.
-
Ground it or abstain. Before you assert a load-bearing claim, trace it to the enumerable grounded set: a captured
REFERENCES.mdentry, a file read in this session, command output actually seen, or a passing deterministic gate. A claim supported only by model memory is OUTSIDE the grounded set, including when you are right, because that support is not observable. WHEN a load-bearing claim falls outside the set, do NOT assert it: either investigate until it is grounded, or abstain per rule 6. -
Status records provenance, never confidence. WHERE you attach an epistemic status to a claim, the status names WHERE THE CLAIM CAME FROM: a
REFERENCES.mdentry title, a file path plus line, or the gate output it came from. It SHALL NOT express a degree of certainty. Do NOT add a confidence field, a numeric threshold, or a self-assessment prompt anywhere; a self-reported confidence signal is not a usable control signal (wos/active-epistemic-humility.mdPart 1.3). A status whose referent slot is empty is read as UNKNOWN, not as a weak yes. -
Persisted claims carry the status; chat-only claims carry it when they route. Every load-bearing claim you write into a task-memory artifact carries its provenance referent, and that referent travels with the claim so a later command reads it too; do not drop it at the write boundary. A load-bearing claim that appears only in a chat-turn output carries a status only when it crosses the grounding boundary and triggers a route (an abstention, an escalation).
-
Abstain as a routed continuation, never a bare refusal. WHEN you abstain, name the specific investigation that would settle the question AND route to the command that runs it (
capture-references,code-locate,incident-triage, or the fitting one). A withholding that stalls the work is invalid output. Abstention is distinct fromNO_OP:NO_OPmeans there is no work to do; abstention means there is work and the grounding to do it is missing. -
An unfired gate is not evidence. The absence of a fired check does not mean grounding existed. Do not read silence here as a pass.
Standard output layout (required)
<!-- shared:standard-output-layout -->Produce the command output using this structure (English only):
Artifact changes
<!-- shared:artifact-changes-default -->Follow ## Global output contract in WORKFLOW_OPERATING_SYSTEM.md for APPLIED / PROPOSED / SKIP rules.
Command transcript
<!-- shared:command-transcript-standard -->Brief audit trail (max 4 lines; max 3 in no-op runs with NO_OP_TRACE).
Handoff
<!-- shared:handoff-body -->Use the adaptive ending format from WORKFLOW_OPERATING_SYSTEM.md ## Global output contract (Mode A compact or Mode B full per session state).
Definition of done (command output)
- The emitted plan carries exactly one
wos-godot-declarationfenced block withDimension:reading2Dor3D, plusRenderer tier:naming one ofForward+,Mobile,Compatibilitywhen the dimension is3D, and the tier reason in prose OUTSIDE the block. A plan satisfying every other bullet without this one still blocks at closure, which is why it is stated here and not only in Step 8a. - The scene tree names a Godot node type and a one-line responsibility for every node, and is the smallest tree that satisfies the feature.
- Autoloads, signals, the input map, and resources/sub-scenes are each addressed; reused-vs-new is explicit for a brownfield feature.
- The mandatory Mechanic contract (Step 1a) is present: every mechanic the scene realizes is cited from
MECHANICS_SPEC.md, or an assumed, open, or missing rule is routed todecision-interview; a scene designed around an undocumented assumed mechanic is invalid output (ADR-0084). For a multi-screen game the screen graph (Step 1b) specifies the win and lose states and the cross-screen transitions. For a game with sound the audio ruling is recorded; for a game with placeholder art the placeholder-asset policy is recorded (ADR-0084); "polish later" prose satisfies neither. - The plan names no specific MCP server (MCP-agnostic, DECISIONS D-1) and invents no device-specific performance numbers (deferred to
performance-budget). GODOT_SCENE_PLAN.mdis written in Agent mode (or PROPOSED in Ask/Plan mode per ADR-0001).- Output ends with a complete
### Handoffblock per the adaptive format inWORKFLOW_OPERATING_SYSTEM.md## Global output contract. - Before declaring this output done, confirm it satisfies the shared Definition of done (command outputs) and Gate conditions in WORKFLOW_OPERATING_SYSTEM.md.
Quality bar: A Godot engineer (or an MCP-driven editor) reading the plan should be able to build the scene without re-deciding the node types, the signal wiring, or the input map. Prefer the smallest correct scene tree over a clever one.
<!-- cache-breakpoint -->What ships with it
Read from the repository
Just SKILL.md. No reference files, no scripts.