name: project-scaffold description: | Generate a new Godot game project with standardized ECS structure and tooling. Use when starting a new game: "create a project", "set up a new game", "scaffold", "initialize", "new project", "start building", "let's make it". Triggers after game-planner produces a confirmed plan, or when the user provides a game name + genre directly. Even for simple requests like "make me a new Godot project", use this skill to ensure proper ECS structure. Creates directory structure, project.godot, CLAUDE.md, gecs World setup, addon stubs, and template source files based on the game plan or user input.
Project Scaffold
$ARGUMENTS
Generate a new Godot game project with GodotMaker's ECS architecture.
Read templates from this skill's templates/ directory, fill {{placeholders}}
with values from the game plan or user input, and write results to the target.
Step 1 — Gather Variables
If a confirmed Game Plan exists in the conversation (from game-planner), extract variables from it. Otherwise, ask the user for game name and genre at minimum — use genre defaults for everything else.
| Variable | Source | Default |
|---|---|---|
{{game_name}} |
user input, snake_case, used as directory name | required |
{{game_title}} |
user input or Title Case of game_name | required |
{{genre}} |
Game Plan "Genre" or user | "platformer" |
{{perspective}} |
Fixed framework target | "2D" |
{{viewport_width}} |
genre defaults table | 1280 |
{{viewport_height}} |
genre defaults table | 720 |
{{rendering_method}} |
fixed 2D renderer | "gl_compatibility" |
{{root_node_type}} |
fixed 2D root | "Node2D" |
{{camera_type}} |
fixed 2D camera | "Camera2D" |
{{game_description}} |
Game Plan summary or one-line from user | genre name + " game" |
Genre defaults:
| Genre | Viewport | Gravity | Input Actions |
|---|---|---|---|
| Platformer | 1280x720 | 980.0 | move_left, move_right, jump |
| Top-down | 1280x720 | none | move_up, move_down, move_left, move_right |
| Puzzle | 1280x720 | none | select, confirm, cancel |
| Endless runner | 720x1280 | 980.0 | jump |
Step 2 — Create Directory Structure
Create the project root and all subdirectories:
{{game_name}}/
├── project.godot
├── CLAUDE.md
├── .gitignore
├── src/
│ ├── components/ # C_ prefixed component scripts
│ ├── systems/ # NameSystem scripts
│ ├── entities/ # Entity scene definitions
│ └── ui/ # UI scenes and scripts
├── scenes/
│ ├── main.tscn # Entry point scene
│ └── game_world.tscn # Gameplay scene with camera
├── test/
│ └── test_example.gd # gdUnit4 test template
├── e2e/
│ └── conftest.py # E2E test config (GODOT_PROJECT = "..")
├── assets/
│ ├── sprites/
│ ├── audio/
│ ├── fonts/
│ └── ui/
├── references/ # Scene reference images (generated by /gm-asset)
└── addons/ # gecs + gdUnit4 + godot_e2e installed here
.tscn Generation Rules
When writing .tscn files (from templates or manually), follow these rules strictly:
- No UID references — use
res://path/to/script.gdpaths, neveruid://xxx. UID references fail in headless/CI environments becauseuid_cache.bincannot be rebuilt. - load_steps formula —
load_steps = ext_resource_count + sub_resource_count + 1. Count carefully; mismatch causes parse errors. - parent attribute required — only the root
[node]omitsparent. Every other node MUST haveparent="."(direct child of root) orparent="path/to/parent". - World node setup — always set
system_nodes_root = NodePath(".")andentity_nodes_root = NodePath(".")when using SystemGroups.
Step 3 — Fill Templates
Read each template from templates/, replace all {{placeholders}}, write output.
Remove any template comments (lines starting with ; TEMPLATE:) from the output.
| Template | Output Path | Notes |
|---|---|---|
project.godot.tmpl |
project.godot |
Must be valid Godot ConfigFile |
claude.md.tmpl |
CLAUDE.md |
Fill game info + ECS reference |
gitignore.tmpl |
.gitignore |
Use as-is, no placeholders |
main_scene.tmpl |
scenes/main.tscn |
Use a 2D root node |
world_scene.tmpl |
scenes/game_world.tscn |
Use 2D node + camera types; gameplay scene gets a World child node added during /gm-build |
test_example.tmpl |
test/test_example.gd |
Replace {{GameNamePascal}} |
component.tmpl |
src/components/c_example.gd |
Example stub |
system.tmpl |
src/systems/example_system.gd |
Example stub |
gecs World setup
gecs v7.1.0 ships class_name World in addons/gecs/ecs/world.gd. The
canonical scene-node pattern:
- Add a
Nodechild to your gameplay scene withscript = res://addons/gecs/ecs/world.gd, namedWorld, withsystem_nodes_root = NodePath("Systems")andentity_nodes_root = NodePath("Entities"). - The main scene script wires it up:
@onready var world: World = $WorldthenECS.world = worldin_ready(). - Drive systems via
world.process(delta, "gameplay")/world.process(delta, "physics")from_process/_physics_process.
Scaffold leaves the World node out — gameplay scene structure is filled in
during /gm-build. See the gecs skill for the full World API.
Game Plan ECS stubs
If the Game Plan includes an ECS Architecture section with components and systems:
- Components: for each planned component (e.g.,
C_Velocity), create a file insrc/components/based oncomponent.tmpl. Fill the class name and add@exportvars from the plan. - Systems: for each planned system (e.g.,
MovementSystem), create a file insrc/systems/based onsystem.tmpl. Fill the class name andquery()with the required components. - World: register systems by adding them as children of the gameplay
scene's
Worldnode — see "gecs World setup" above for the full pattern.
Step 4 — Genre Adaptations
After writing base template files, apply genre-specific modifications to project.godot:
Platformer / Endless runner (gravity games):
- Add
[physics]section:2d/default_gravity=980.0 - Add
[input]section with move + jump actions
Top-down:
- No
[physics]section - Add
[input]section with 4-directional movement
For input action serialization format, read references/project_settings.md
— it has the exact Object() syntax and key code table.
Step 5 — Post-Scaffold Steps
After all files are written, tell the user what to do next:
Deploy GodotMaker skills to the new project:
bash <godotmaker_repo>/shell/publish.sh {{game_name}}/This copies skills to
.claude/skills/, createsgodotmaker.yaml(prompts for Godot executable path on first run), and creates.godotmaker/config.yamlwith default project settings.Install addons — pick the row matching your Godot version from the active runtime's
config/addon_versions.json(the source of truth for repo, tag, and install path), then install addon-only directories:- gecs ->
addons/gecs/ - gdUnit4 ->
addons/gdUnit4/ - godot_e2e ->
addons/godot_e2e/
tools/check_project.py --e2eand the gm-* skills expect those exact paths (notegdUnit4/is capital U — matches the upstream repo layout). Seereferences/addons.mdfor the step-by-step installation contract.- gecs ->
Register godot-mcp for runtime debugging:
claude mcp add godot -e GODOT_PATH="<godot_path>" -- npx @coding-solo/godot-mcpVerify with headless-build:
godot --headless --quit 2>&1
Report
After scaffold completes, output:
- Project path (absolute)
- File tree listing
- Checklist of pending post-scaffold steps
What This Skill Does NOT Do
- Does not implement game logic — only creates the starting structure
- Does not install addons — provides instructions in references/addons.md
- Does not run game-planner — expects a plan or minimal user input already
- Does not deploy skills — that is publish.sh's job