# rosebud publish

URL: /docs/cli/publish

> Create a new game from a build folder or ZIP and get a play link.

```sh
rosebud publish --directory <folder> [options]
rosebud publish --zip <file> [options]
```

Each `publish` creates a new game and saves its details to the state file. To change a game you already published, use [`rosebud update`](/docs/cli/update.md).

## Options

| Option                    | Details                                                                                                               |
| ------------------------- | --------------------------------------------------------------------------------------------------------------------- |
| `--directory <folder>`    | The build folder to upload. It needs `index.html` at the top level.                                                   |
| `--zip <file>`            | A ZIP of the build, instead of `--directory`.                                                                         |
| `--title <text>`          | Up to 255 characters. `--name` is accepted as an alias.                                                               |
| `--description <text>`    | Up to 4,000 characters.                                                                                               |
| `--thumbnail <file>`      | A PNG or JPEG cover, at most 2 MiB and 4096 pixels a side.                                                            |
| `--agent-client <client>` | `claude-code`, `codex`, `cursor`, `gemini-cli`, `other` or `unknown`.                                                 |
| `--context <file>`        | A JSON file with optional details about how the game was made. See [Import a game](/docs/api/hosting/import.md#context). |
| `--state <file>`          | Where to save the game's details. Default `.rosebud/project.json`.                                                    |

Use exactly one of `--directory` and `--zip`. See [what you can upload](/docs/guides/publish-a-game.md#what-you-can-upload).

## Example

```sh
rosebud publish --directory ./dist --title 'Moon Garden' \
  --description 'Collect five glowing seeds.'
```

Without a login, the result has a private claim link:

```json
{
    "project_id": "6f1d2c8e-...",
    "play_url": "https://rosebud.ai/play/moon-garden",
    "claim_url": "https://rosebud.ai/claim#...",
    "claim_expires_at": "2026-10-27T19:04:11Z",
    "content_version": "9f2c41e0b7...",
    "state_file": ".rosebud/project.json",
    "next_action": "Claim by 2026-10-27T19:04:11Z to keep this game online for free. ..."
}
```

With an active [`rosebud login`](/docs/cli/login.md), the game goes straight into the account. The result has `claimed: true`, the `owner` and an `editor_url` instead of a claim link, and `update` works at once. If Rosebud couldn't add the game to the account, the result has the claim fields instead.

## Notes

* Unclaimed games are deleted one hour after upload. See [Claim your game](/docs/guides/claim-your-game.md).
* If the result is unknown (exit 4), the game may already exist. Don't publish again right away. The same goes for an interrupted `publish`.
* A first `publish` refused with `busy` created nothing. Run it again after `retry_after_seconds`.
* A big game can take minutes, because each media file uploads on its own. Allow the time, or run the command in the background.
* If the state file already holds a game, `publish` stops with `project_exists`. Use `update`, or pass a new `--state`.
* If your login still waits for approval, `publish` stops with `login_pending`. Approve it, or run `rosebud logout` to publish with a claim link instead.
