| name | usagi-game-dev |
| description | Build, run, debug, and ship 2D pixel-art games with the Usagi engine (Lua 5.5, hot-reload, one-command export to Linux/macOS/Windows/Web). Use whenever the user mentions Usagi, the `usagi` CLI (init/dev/run/export/tools), or Usagi-specific APIs such as the `_init`/`_update`/`_draw` callbacks, `gfx.spr`, `gfx.clear`, `input.pressed`/`input.held`, `sfx.play`, `music.loop`, `usagi.save`, or `effect.screen_shake`. Also use when the user wants to make any small 2D pixel-art game and hasn't picked an engine. The skill drives a live split-screen preview loop: the agent runs the game in the background while the user watches and reports. |
Usagi game development
Usagi is a deliberately small 2D pixel-art game engine. You write Lua 5.5; the
engine (a Rust/Raylib host) gives you hot-reload, a built-in pause menu, and
one-command export to Linux/macOS/Windows/Web. Defaults are 320×180, a
16-color PICO-8 palette, and one sprites.png atlas of 16×16 cells. These
constraints are intentional — work within them instead of fighting them. There is no
ECS, no scene system, no physics, no tilemap engine: you get three callbacks and a flat
API, and you build structure yourself in plain Lua.
Three golden rules
- Discover commands at runtime — don't trust hardcoded syntax. Before running any
usagi command, confirm it with usagi --help (and usagi <command> --help for
flags). CLI verbs and flags change between releases; this skill lists the common
ones, not the authoritative set. The authoritative API for the installed version is
the project's own USAGI.md, written by usagi init.
- Mutable state lives in a Capitalized global, set in
_init. On every hot-reload
the engine re-runs your file, so any file-scope local is re-bound and loses its
value, but globals survive. Put all game state in State = {...} inside _init. The
generated .luarc.json flags stray lowercase globals on purpose — capitalize the
ones meant to persist, keep everything else local.
- You cannot see the game. The rendered window is invisible to you. Your eyes are
(a) the user — ask "what do you see?" — and (b) the stderr of the running dev
process, where Lua errors print (they also appear as a red traceback overlay
in-window). Never claim something "works" from code alone; confirm visually through
the user or a screenshot.
Setup / detection
Check it's installed: usagi --version. If missing, point the user at the official
installer (verify the URL on https://usagiengine.com if in doubt):
- macOS / Linux:
curl -fsSL https://usagiengine.com/install.sh | sh
- Windows (PowerShell):
irm https://usagiengine.com/install.ps1 | iex
It installs to ~/.usagi/bin/ (or %USERPROFILE%\.usagi\bin\) and updates PATH.
The live-preview loop (the core workflow)
This is what makes Usagi great with an agent: the user keeps the game window open
beside the chat and watches it update live while you edit code.
- Scaffold:
usagi init <name>, then read the generated main.lua and
USAGI.md — that's the real stub structure and the authoritative API for this
engine version. Don't assume; read.
- Launch dev in the background so the conversation stays responsive:
- Run
usagi dev <path> as a non-blocking / background process and keep it
running for the whole session. Do not run it in the foreground — that blocks you.
- Tell the user to place the game window next to the chat (split screen).
- Edit in small steps. Each save hot-reloads instantly into the running window
— no restart, state preserved. Make one focused change, then let the user look.
- Watch for errors. Tail the dev process's stderr; a Lua error shows there and
as the in-window red traceback. When you need visual confirmation of behavior
(not just "no error"), ask the user what they see or for a screenshot.
- Reset when needed.
F5 in the game window re-runs _init (hard reset of
State). Use it after changing initialization logic.
Fallback (harness can't background a process): ask the user to run usagi dev in
their own terminal and leave it open. You then only edit files; the user's running
process hot-reloads them and reports what they see. Everything else is identical.
Workflow phases
Keep scope tiny — one core mechanic. Usagi shines at small games.
- Discover. Ask: genre / core mechanic, controls (Usagi gives LEFT/RIGHT/UP/DOWN +
BTN1/BTN2/BTN3, plus mouse), art style, audio needs. Confirm it fits the constraints.
- Scaffold.
usagi init → read generated files → start background usagi dev.
- Prototype. Build the smallest playable thing first. Use placeholder shapes
(
gfx.rect_fill, gfx.circ_fill) for entities before any pixel art exists — draw
something, read input to move it, add a goal/score, add win/lose. Iterate live.
- Assets. Sprites go in one
sprites.png (16×16 cells, index 1 = top-left); audio
.wav in sfx/, .ogg in music/; data files in data/. You generally don't
author the PNG yourself — recommend Aseprite/Piskel and let the user supply art, or
keep placeholder shapes. usagi tools opens the TilePicker to find sprite indices.
- Polish (juice). Add feel:
effect.screen_shake, effect.hitstop,
effect.flash, effect.slow_mo, plus SFX on every meaningful action, and a
title/game-over screen (see scene pattern in references/patterns.md).
- Ship.
usagi export (all platforms) or usagi export --target web. Output lands
in export/. Confirm flags with usagi export --help.
Cheatsheet (most-used calls)
Full surface — every function and parameter — is in references/api.md. Read it when
you need anything beyond this.
function _config() return { name = "My Game", game_id = "com.you.mygame" } end
function _init() State = { x = 160, y = 90, score = 0 } end
function _update(dt) end
function _draw(dt) end
gfx.clear(gfx.COLOR_BLACK)
gfx.spr(index, x, y)
gfx.rect_fill(x, y, w, h, gfx.COLOR_RED)
gfx.text("Score: "..State.score, 4, 4, gfx.COLOR_WHITE)
if input.pressed(input.BTN1) then end
if input.held(input.LEFT) then end
State.x += State.vx * dt
effect.screen_shake(0.3, 4); effect.hitstop(0.06); effect.flash(0.1, gfx.COLOR_WHITE)
usagi.save({ score = State.score }); local s = usagi.load() or { score = 0 }
References (load on demand)
references/api.md — complete API: gfx, input, sfx, music, usagi,
effect, util, and the color/input constant tables.
references/cli.md — common CLI verbs and flags (always re-confirm with usagi --help).
references/patterns.md — reload-friendly patterns: scene switching, entity arrays,
collision, animation, save/load.
After the user upgrades the engine (usagi update), run usagi refresh inside the
project to regenerate meta/usagi.lua, .luarc.json, and USAGI.md, then re-read
USAGI.md for any API changes.
Links