Skip to main content

Claude Code and other agents

This page is the engine-only path: a game repo you copied from the template, with no Moonspell account. To build with your agent and publish to the Moonspell app, start from the starter instead (Publish to the Moonspell app): its instructions already fit your machine, and the step 3 note below is not needed.

A game repo made from the template is ready for a coding agent: open it in Claude Code (or any agent that reads AGENTS.md), describe the game you want, and the agent builds it with the engine's skills and checks it with the repo's own scripts. This page walks through that, with prompts that work and the parts of the template that only make sense inside the hosted Moonspell app.

1. Get the template​

Each game is its own repo, copied from templates/crescent-game/. Quickstart has the full setup; in short:

git clone <repository-url> moonspell
cp -R moonspell/templates/crescent-game my-game
cd my-game
git init
npm install

The template has three placeholders the hosted pipeline fills in when it creates a game: __GAME_SLUG__ (the name in package.json and package-lock.json, and GAME_ID in src/engine/net/config.ts) and __GAME_TITLE__ (the first line of CLAUDE.md and AGENTS.md). Replace them with your game's slug and title, or ask the agent to do it as its first task. Commit once before the agent starts, so every change after that is a diff you can read.

2. Open it in your agent​

Claude Code. Start it in the game folder:

cd my-game
claude

Claude Code reads CLAUDE.md at the start of the session and finds the skills in .claude/skills/ by their descriptions, loading one when the task matches. You can also name one: "use the game-router skill".

Other agents. AGENTS.md holds the same instructions under the file name other agents look for. It is an exact copy of CLAUDE.md. Agents that do not load .claude/skills/ by themselves can read a skill as a file: tell the agent to read .claude/skills/game-router/SKILL.md before anything else, and to read whichever skill that file names next.

3. Tell the agent where it is running​

CLAUDE.md is written for the hosted worker: it says to check work with the crescent CLI and to finish with a message for a player. In a plain clone there is no crescent and no player (the CLI comes only with the local developer mode starter). Start your first message with a short note like this one, or keep it in a project file your agent always reads:

This game repo runs outside the Moonspell app. There is no crescent CLI,
no Moonspell app, no hosted art, sound or model generation, and no
Cloudflare gateway. Check every change with npm run typecheck, npm test and
npm run export:web instead of crescent export. Keep the GDD.md and
playtest.json habits. Commit after each playable step.

4. What to ask​

Describe the game the way you would to a friend: the genre or a game it is like, the mood, what the player does, what makes it hard. The game-router skill turns those words into a route (a module config, an example to copy, or from scratch), so you do not need to name engine pieces. These prompts match routes and skills the template has.

A new game from an idea

Make a parkour game on rooftops at night. The jumps should be hard, and I
want a best time I can beat.

The router picks foundation:character / parkour: the agent copies examples/rooftop-hop/index.tsx, follows the character-game skill, and writes GDD.md.

A drag-and-drop block puzzle that clears lines, set in space, with a daily puzzle.

Route module:puzzle: a definePuzzleGame config with pack: 'block' and daily: true, from examples/moon-blocks/, through the puzzle-game skill.

Chess against a cheeky computer opponent, three levels of difficulty.

Route kit:turns / board: the agent starts from examples/moon-chess/ and changes the rivals and their personas (docs/turns.md).

Changing a game

Make the race longer: five laps, six rivals, and make them hard to beat.

For a module game this is a config change (laps, opponents.count, opponents.speed), following car-race-game. The crescent-game-change skill tells the agent to keep every field you did not mention.

Add guards that patrol and chase me when they hear me land.

On a character game this adds bots (docs/bots.md) on the same route.

Art and sound

Use the models in assets/models/ for the player and the crates, with the
capsule and boxes as the fallback.
Plan every sound this game needs from GDD.md and wire placeholder files
through the audio mixer.

The models, sprites and cutout-art skills expect the hosted pipeline to generate the files (see What assumes the Moonspell app below). Outside it you bring the files and the agent wires them with the fallbacks those skills describe. The sound-design skill's planning, cleanup (ffmpeg) and wiring steps work anywhere.

Multiplayer and online features

Add a live leaderboard and "N playing now" to the title screen.
Let friends join my tag game in a room, with bots filling empty seats.

The realtime-backend skill copies the backend scaffold to backend/. Without a deployed backend, the same engine calls keep everything on the device (GAME_BACKEND_URL = null), so the game still works while you build. Deploying to your own Cloudflare account is on Backend.

5. How the agent checks its work​

Outside the Moonspell app these scripts in the template's package.json are the checks:

CommandWhat it proves
npm run typechecktsc --noEmit over the game and the engine: no type errors. It also catches misspelled SF Symbol names, which are typed.
npm testThe engine's unit tests (src/engine/**/*.test.ts, Node's test runner with tsx). Run it after any change in src/engine/.
npm run export:webA full static web build into dist/ (expo export --platform web). A Metro error here means the game does not open. This replaces crescent export . --out /tmp/crescent-check from CLAUDE.md.
npm run webThe Expo dev server in a browser with WebGPU. This is for you: open it, play, and tell the agent what you saw.

npm run ios and npm run android make a normal Expo development build of the game for a simulator or phone. See iOS and Android.

A save test, when the game keeps progress, runs on its own: node --import tsx --test src/game/progress.test.ts (the saves skill).

The agent cannot see or hear the game. Typecheck, tests and the export prove it builds; whether it plays well is for you to judge in the browser or on a phone. The sound-design skill says the same about audio: ask a person.

6. Work in small playable checkpoints​

The skills ask for the smallest playable version first, then one change at a time. Keep that habit outside the hosted pipeline too:

  1. One request per step: "a car that drives around a loop", then "add rivals", then "add a leaderboard".
  2. After each step the agent runs npm run typecheck and npm run export:web, and npm test when it touched src/engine/.
  3. It updates GDD.md and, when screens, labels or controls changed, playtest.json, in the same commit.
  4. It commits with a message about what changed for the player, and the route on its own line (Route: module:puzzle), as the game-router skill asks.

If a step breaks the game, git takes you back to the last commit that played.

What assumes the Moonspell app​

These skills and instructions were written for the hosted worker. They are not wrong, but their tools do not exist outside the Moonspell app.

Skill or fileWhat it assumesOutside the Moonspell app
CLAUDE.md, crescent-game-change, the genre skills' checklistscrescent export . --out /tmp/crescent-check and crescent doctor as the gate; a one-paragraph summary for a playerUse npm run typecheck, npm test and npm run export:web. There is no crescent doctor.
push-to-devicecrescent push to a Moonspell app connected to a local crescent start serverDoes not apply. Run npm run web, npm run ios or npm run android and look at it yourself.
native-now-modules and the "native is fixed" rule in CLAUDE.mdThe game runs in the prebuilt Moonspell shell, so only the native modules compiled into it exist; crescent catalog lists themThe list in references/modules.md is still the set the template's package.json pins. In your own development build you can add a native module, but then the game no longer runs inside the Moonspell app. Keep the pinned versions as they are.
models, sprites, cutout-artYou list files in ~/.crescent/models.json or ~/.crescent/sprites.json, write placeholders with ~/.crescent/helpers.cjs, and the hosted pipeline generates the real files after your passNeither the lists nor the helper exist. Put your own files at the paths (a .glb in assets/models/, a PNG sheet in assets/sprites/ with the grid you pass to createSheet), or keep the fallbacks. Any 1x1 PNG works as a sprite placeholder: the engine treats it as "not art yet" and draws your fallback.
sound-design, puzzle-game, kingdom-gameSounds listed in the run's "Sounds" section or a sounds.json are generated after your passBring your own audio files. Planning, the ffmpeg cleanup and the mixer wiring work as written.
realtime-backendA gateway token (CLOUDFLARE_API_TOKEN), the mila-cloudflare MCP tools (cloudflare_project, cloudflare_create) and a resource prefixDeploy the scaffold with Wrangler to your own Cloudflare account: Backend. The scaffold, routes, local tests and client API are the same.
playtestA Mac in the hosted pipeline plays playtest.json on a simulator and records the feed videoNothing runs it for you. Keep the file correct so the labels stay testable; see GDD.md and playtest.json.
kingdom-game "Device QA", examples/README.mdcrescent start --sim --dev to load a game into the Moonspell app on a simulatorUse npm run web or a development build.
npm start, npm run export, npm run push, npm run doctorThese scripts call the crescent CLIThey fail in a plain clone, which has no CLI. Use the scripts in the table in step 5. (The local developer mode starter includes the built CLI.)

The engine itself does not depend on the Moonspell app: where the shell is absent, the engine treats it as optional, and roomInviteUrl returns null because there is no share link. See Platform layer.