# Claude Code and other agents

> Step by step, open a Moonspell game repo in Claude Code or another coding agent, ask for a game, let the agent check its own work, and know which skills assume the hosted Moonspell app.

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](https://docs.moonspell.app/start/publish-to-moonspell.md)): 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](https://docs.moonspell.app/start/quickstart.md) has the full setup; in short:

```bash
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:

```bash
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:

```text
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**

```text
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`.

```text
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.

```text
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**

```text
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.

```text
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**

```text
Use the models in assets/models/ for the player and the crates, with the
capsule and boxes as the fallback.
```

```text
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](https://docs.moonspell.app/ai/claude-code.md#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**

```text
Add a live leaderboard and "N playing now" to the title screen.
```

```text
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](https://docs.moonspell.app/backend/overview.md).

## 5. How the agent checks its work

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

| Command | What it proves |
| --- | --- |
| `npm run typecheck` | `tsc --noEmit` over the game and the engine: no type errors. It also catches misspelled SF Symbol names, which are typed. |
| `npm test` | The 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:web` | A 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 web` | The 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](https://docs.moonspell.app/platforms/ios.md) and [Android](https://docs.moonspell.app/platforms/android.md).

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 file | What it assumes | Outside the Moonspell app |
| --- | --- | --- |
| `CLAUDE.md`, **crescent-game-change**, the genre skills' checklists | `crescent export . --out /tmp/crescent-check` and `crescent doctor` as the gate; a one-paragraph summary for a player | Use `npm run typecheck`, `npm test` and `npm run export:web`. There is no `crescent doctor`. |
| **push-to-device** | `crescent push` to a Moonspell app connected to a local `crescent start` server | Does 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.md` | The game runs in the prebuilt Moonspell shell, so only the native modules compiled into it exist; `crescent catalog` lists them | The 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-art** | You 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 pass | Neither 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-game** | Sounds listed in the run's "Sounds" section or a `sounds.json` are generated after your pass | Bring your own audio files. Planning, the `ffmpeg` cleanup and the mixer wiring work as written. |
| **realtime-backend** | A gateway token (`CLOUDFLARE_API_TOKEN`), the `mila-cloudflare` MCP tools (`cloudflare_project`, `cloudflare_create`) and a resource prefix | Deploy the scaffold with Wrangler to your own Cloudflare account: [Backend](https://docs.moonspell.app/backend/overview.md). The scaffold, routes, local tests and client API are the same. |
| **playtest** | A Mac in the hosted pipeline plays `playtest.json` on a simulator and records the feed video | Nothing runs it for you. Keep the file correct so the labels stay testable; see [GDD.md and playtest.json](https://docs.moonspell.app/ai/game-design-doc.md). |
| **kingdom-game** "Device QA", `examples/README.md` | `crescent start --sim --dev` to load a game into the Moonspell app on a simulator | Use `npm run web` or a development build. |
| `npm start`, `npm run export`, `npm run push`, `npm run doctor` | These scripts call the `crescent` CLI | They 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](https://docs.moonspell.app/engine/platform-layer.md).
