---
name: mable-game-assets
description: Generate game assets with the `mable` CLI — game characters, animated sprite sheets, 2D visual effects, sound effects, music and voice lines — straight into the project. Use whenever a game needs art, animation, effects or audio instead of drawing, synthesising or coding placeholders, or when a game "feels flat" and needs juice.
---

# Mable game assets

`mable` turns a short description (or one character image) into game-ready files inside the project:
a character image, a transparent sprite-sheet atlas plus an engine atlas JSON, or an MP3. Every command
writes the files, a `<id>.mable.json` sidecar (frames, fps, grid, playback hints) and an entry in
`./mable-assets.json`. Generation spends the user's Mable credits.

## Before the first call

1. `mable --version` — if missing, install: `curl -fsSL https://mable-dev-service.mable.gg/cli/install.sh | sh`.
   If `mable` is still "command not found" afterwards, call it by its full path `~/.local/bin/mable`
   (the installer adds it to PATH for new terminals only).
2. `mable whoami` — if it says not logged in, **run `mable login` yourself** (give the command up to 10
   minutes, or run it in the background). It opens the Mable sign-in page in the user's browser and prints
   the link: tell the user "I opened Mable in your browser: sign in (or create an account) and follow the
   page to Authorize", and show the link in case the tab did not open.
   The command finishes by itself once they approve and prints the credit balance.
   - If your command times out, the sign-in stays open for 10 minutes: run `mable login` again to keep
     waiting (same link), or `mable whoami` after the user says they approved.
   - If the page cannot reach this machine (you run remotely, in a sandbox or over SSH), it shows a
     one-time code starting with `mbl1.`. Ask the user to paste that code to you and run
     `mable login --code <code>`. The code only works for this login, so it is safe in chat.
   - Never ask the user for an Agent Key (`mable_agent_…`) or to paste one into chat.
   `mable credits` shows the balance; check it before a large batch and tell the user if it will not cover it.
   Charges settle within about a minute after a job finishes, so a balance read right after a job may not
   show that job yet; failed jobs are never charged and replayed jobs are not charged again.
   To report what the work cost, use `mable credits --history`: it lists each recent charge and marks the
   ones that belong to this project (other activity on the same account is shown but not counted).
3. Run commands from the project root so `assets/` and `mable-assets.json` land in the right place.

## Pick the tool

| The game needs | Command | Typical time |
| --- | --- | --- |
| A character image to animate (when the user has none) | `mable gen character --prompt "..." --id hero` → `assets/characters/hero.png` | ~30 s |
| A still object the game moves itself: coin, gem, key, hazard, crate, projectile | `mable gen prop --prompt "..." --id coin` → `assets/props/coin.png` (transparent) | ~30 s |
| A character or prop that moves (idle, run, attack, jump, open) | `mable gen sprite --image hero.png --motion "..." --state run` | 1–3 min |
| An effect: fire, explosion, slash, magic, sparkle, smoke, aura | `mable gen vfx --prompt "..." --motion "..." --state burst` | 1–3 min |
| A sound for an event: jump, hit, pickup, click, explosion | `mable gen sfx --prompt "..." --category pickup --style "..."` | ~10 s |
| Background music, a level loop, a victory stinger | `mable gen music --prompt "..." --duration 45` | ~1 min |
| Spoken lines: narration, NPC dialogue, announcer | `mable gen voice --text "..." --speaker ryan --locale en-US` | ~20 s |

Details, flags and prompt advice per kind: `mable skill show references/<kind>.md`
(`sprites.md`, `vfx.md`, `audio.md`). Read the one you need before its first call.
No character art yet? Do not skip animation and do not draw one in code: `mable gen character` first,
then animate that file with `mable gen sprite`. `gen character` always draws a full-body figure, so never
use it for objects: coins, pickups, hazards and items come from `mable gen prop`.

## Rules that save credits

- **Plan, then generate once.** List every asset the game needs (about 8 sounds at most, one music loop
  per scene, one sprite state per action) and pick one `--style` phrase shared by all sounds and music.
  Show the user the list before generating more than ~5 paid assets.
- **Rerunning a command is free and safe.** The CLI derives a stable request key, so running the exact
  same command again returns the same job (and re-downloads its files) instead of paying twice. If an
  earlier attempt failed for a temporary reason (credits topped up, provider outage), the rerun starts
  one new attempt automatically. Use `--new` only when the user wants a different variation.
- **Never probe.** No test calls with dummy prompts; every call is real and billed.
- Long jobs: add `--async` to get a job id back immediately, keep coding, then `mable job <kind> <jobId>`.
  Exit code `3` means "still running, nothing lost" — run the printed resume command later.

## Using the files

- Sprites and VFX: `<id>.webp` is a row-major transparent atlas; `<id>.atlas.json` is TexturePacker
  JSON-hash (Phaser `load.atlas`, PixiJS `Assets.load`, most engines) with the clip under `animations`.
  In plain canvas code read `columns`, `frameWidth`, `frameHeight`, `fps`, `frames` from
  `<id>.mable.json` and draw frame `i` from `(i % columns) * frameWidth, floor(i / columns) * frameHeight`.
  Never guess the grid.
- VFX with `blendMode: additive` must be drawn with additive blending (`ctx.globalCompositeOperation = "lighter"`).
- Audio: play through Web Audio or `new Audio(path)`; start audio only after the first user tap.
- Reference assets by their relative path, e.g. `const sfx = { jump: "assets/sfx/jump.mp3" }`, and
  load them from files at runtime; do not paste base64 copies into source files.
- Browsers block `file://` loading of images and audio in many cases: serve the project with any static
  server (for example `npx serve .` or `python3 -m http.server`) when testing locally.

## Output contract

Add `--json` for one line on stdout: `{"ok":…, "result_status":"succeeded|pending|failed", "data":…}`.
Exit codes: `0` done, `1` failed (see `error.code`; failed jobs are not charged), `2` bad usage,
`3` still running, `4` not logged in / key rejected. `INSUFFICIENT_CREDITS` means the user must top up
in Mable; say so plainly and stop generating.
