# castle-cli-script

Build [Castle](https://castle.xyz) games from a single Lua file.

## Install

```bash
npm install -g castle-cli-script
```

Requires Node 18+.

## Quick Start

### Create a new project

```bash
castle-script init my-game
cd my-game
```

This creates:

```
my-game/
├── main.lua           — your game script
├── castle-script.json — project config
├── CLAUDE.md          — workflow guide for Claude Code
├── API.md             — full API reference for Claude Code
└── test.mjs           — visual test script
```

### Start the web player

```bash
castle-script serve main.lua --open
```

Edit `main.lua` and the browser hot-reloads on every save.

## Writing scripts

Your Lua file has three lifecycle callbacks:

```lua
function onCreate()
  -- runs once at scene start
end

function onUpdate(dt)
  -- runs every frame; dt = delta time in seconds
end

function onDraw()
  -- runs every frame for drawing
  -- castle.draw.* only works here
end
```

### Coordinate system

The canvas is 5:7 (450×630 px). In `onDraw()`:

```
(-5, -7) ──────────────── (5, -7)   ← top
    │                          │
    │           (0, 0)          │    ← center
    │                          │
(-5,  7) ──────────────── (5,  7)   ← bottom
```

### Drawing

```lua
function onDraw()
  -- shapes
  castle.draw.setColor(1, 0.4, 0.1)
  castle.draw.circle("fill", 0, 0, 0.2)
  castle.draw.rectangle("fill", -0.3, -0.3, 0.6, 0.6)
  castle.draw.line(-0.5, 0, 0.5, 0)

  -- text
  castle.draw.setColor(1, 1, 1)
  castle.draw.text("Hello!", 0, 0, 12, "center", "middle")

  -- transforms
  castle.draw.push()
    castle.draw.translate(0.2, 0.1)
    castle.draw.rotate(math.pi / 4)
    castle.draw.rectangle("fill", -0.05, -0.05, 0.1, 0.1)
  castle.draw.pop()
end
```

See `API.md` in your project for the full API reference.

## Commands

### Local development

```
castle-script init [name]        Create a new project (default: castle-game)
castle-script serve [file]       Start the web player (default: main.lua)
  -p, --port <n>                   port to listen on (default: auto from 5000)
  --open                           open browser automatically
```

### Mobile preview

When you are logged in, `serve` streams your game live to the Castle app. Run `castle-script login` once, then `castle-script serve` — the terminal will show a mobile preview link.

While the CLI Preview screen is open on your device, you can run these commands from a separate terminal:

```
castle-script screenshot <outputPath>   Save a screenshot of the running game locally
castle-script restart                   Restart the game in the CLI Preview screen
```

From your Lua script, you can also capture screenshots at specific moments using `castle.screenshot(filename)`. The file is saved relative to your project directory by the running `serve` process. This only works from the top-level script (not actor behaviors) and only in the CLI Preview screen — it has no effect in the web player or the published game.

```lua
castle.co.start(function()
  castle.co.wait(3)
  castle.screenshot("state-after-3s.png")
end)
```

### Castle account

```
castle-script login              Log in to Castle (opens browser)
castle-script logout             Log out
castle-script whoami             Show current user
```

### Sync with Castle

```
castle-script clone <deckIdOrUrl> [outputDir]   Copy a Castle deck locally
castle-script pull [file]                        Overwrite local files from Castle
castle-script push [file]                        Publish local files to Castle
```

These commands require login.

### AI images

```
castle-script imagine <prompt> [file]   Generate an image into images/
  --name <stem>                           output filename (default: image)
  --service replicate|openai              AI backend (default: replicate)
  --draft                                 faster/cheaper model
  --style fantasy|pixel|watercolor|noir|anime
  --set-key <apiKey>                      save API key for selected service
```

Images are auto hot-reloaded by `serve`. API keys are read from `REPLICATE_API_TOKEN` / `OPENAI_API_KEY` environment variables, or saved via `--set-key`.

## With Claude Code

`CLAUDE.md`, `API.md`, and `test.mjs` are auto-generated in your project. `CLAUDE.md` gives Claude Code workflow context; `API.md` is the full draw API reference; `test.mjs` is a Playwright visual test script it can run to verify output. Open the project folder in Claude Code and ask it to build your game — it can read and edit `main.lua` directly.
