Before you start
Get these from the person who invited you:- An account with internal access.
- The CLI and SDK tarballs,
opengamehq-cli-<version>.tgzandopengamehq-sdk-<version>.tgz. - Your origin: the
https://address the CLI signs in and uploads to. It is not opengame.io, which serves the agent guide but doesn’t take uploads yet. - A starter folder, if you want a starter and don’t have the OpenGame repository.
- Node.js 20.19, or 22.12 or later, for a starter, because that is Vite 7’s floor. A game you bring needs only the CLI’s floor, Node.js 18.17. Run
node --versionto check. - A game with
index.htmlin its build output, or a starter from the next section.
No game yet? Copy a starter
A starter is a small game withopengame.json and the SDK already set up. Pick three-vite, phaser, react or javascript. With no preference, pick three-vite, a game called Orb Run; the others share the placeholder title Target practice.
Use the install blocks below. They replace the starter’s repository-only SDK path with the tarball you downloaded. A plain npm install leaves the SDK missing without an error.
- From the repository
- From a starter folder
The starters are in the repository’s Each line runs only if the one before it worked. A wrong
templates folder. Change the first four lines before you paste the block: REPO is your copy of the repository, TARBALLS is the folder you saved the tarballs in, STARTER is the starter you picked, and GAME is a new folder for your game, which must not exist yet.REPO or STARTER, or an existing GAME, stops the block before anything is copied or installed. If only the last line fails, If a command fails covers it.*[0-9].tgz pattern skips a duplicate download such as opengamehq-sdk-0.1.0 (1).tgz. If you saved more than one version, use the newest file’s full name. npm saves the tarball’s path relative to the game folder, so if you move either one, run the npm install line again.
For other engines, Engine support links each engine’s guide, which names its starter or export recipe.
Create your preview
Pick how you want to work. Both end with the same private preview.- With an agent
- In your terminal
Open your game folder in Claude Code, Codex, Cursor or any coding agent that can run commands, and paste this prompt:The agent asks for the CLI tarball and your origin. The prompt on your origin’s
/upload page has both filled in, so you can paste that one instead.When the agent signs you in, it gives you a link and a code in two groups of four, such as KTWQ-7MHP. Open the link, type the code, then press Allow access, which stays greyed out until the code matches.You’re done when the agent gives you a preview link. Open it while signed in to the same account. The agent guide is what the agent follows.If a command fails
Find the message the CLI or npm printed, open its entry, and do what it says. Most entries start with the code that--json output reports for that error. The last two have no single code, because they cover any finding about your game and any check that failed on OpenGame’s side. The repair guide covers every finding and exit code, and For agents covers --json for scripts.
npm error code EACCES
npm error code EACCES
npm install -g couldn’t write to npm’s global folder, because your system owns that folder, not you. The CLI was not installed. Don’t rerun it with sudo. Give npm a global folder you own:npm config set is saved for later shells, and the export command is not. Add the export command to ~/.zshrc or ~/.bashrc too, so new shells find opengame.Then install the CLI again, changing the first line if you saved the tarballs somewhere other than Downloads:no matches found, or npm fails with ENOENT
no matches found, or npm fails with ENOENT
The SDK install couldn’t find the tarball, because
TARBALLS isn’t the folder you saved it in. zsh prints no matches found. In bash, npm warns that the file seems to be corrupted, then exits with ENOENT. The starter is already copied and you are in the new folder, so don’t paste the block again: set TARBALLS to the right folder and run the npm install line on its own.The OpenGame API is not available at an address
The OpenGame API is not available at an address
api_unavailable. If the address is https://opengame.io, this shell has no OPENGAME_API_URL, so the CLI used opengame.io, which doesn’t take uploads. Set it as in the terminal tab’s second step, then run the command again. If the message names your origin instead, check the address with the team.Could not reach the OpenGame API at an address
Could not reach the OpenGame API at an address
network. The same fix applies when the CLI prints The OpenGame API at and an address, then sent an answer this CLI could not read. The CLI got no answer from the address it names, or got a page it couldn’t read, such as a proxy’s sign-in page. Most often that address is wrong: a typo, or https://your-origin from the terminal tab’s second step pasted as written. Run echo "$OPENGAME_API_URL", compare it with the origin the team gave you, and set it again. If the address is right, check that you are online, and that HTTPS_PROXY is set if your network needs a proxy. Then run the command again.Run opengame login, or supply OPENGAME_TOKEN
Run opengame login, or supply OPENGAME_TOKEN
not_signed_in. You aren’t signed in on this machine. Run opengame login, open the link it prints, type the code it shows and press Allow access.Claim a handle on OpenGame, then try again
Claim a handle on OpenGame, then try again
handle_required. The account you signed in with has no handle yet, and every account that uses the CLI needs one. Claim it at opengame.io/handle, then run the command again.Uploads are not open yet
Uploads are not open yet
uploads_closed. Signing in, previewing and reading your games all work, but OpenGame isn’t taking new uploads yet. Nothing was uploaded. The message names the day uploads open when there is one; run the command again then.opengame.json already exists
opengame.json already exists
manifest_exists. The folder already has a manifest, as every starter does, so init left it alone. Skip init and edit opengame.json to change the game’s details, or run opengame pull to get changes made on the website.The checks are still running
The checks are still running
checks_pending. deploy --wait or status --watch stopped waiting after 5 minutes. Your upload is safe and OpenGame’s checks carry on. Open your deploy’s page, or run opengame status --watch to follow them.The upload did not finish
The upload did not finish
upload_interrupted. The connection dropped on every try. Your saved upload can be resumed. Keep the .opengame/ folder, check your connection and run opengame deploy . again. It resumes the same upload, or starts a fresh one if the old one has expired.A finding about your game
A finding about your game
Something in the build needs a change. Each finding names the problem, usually with a file and line, and the fix. Make the change, run
opengame check . --build, then deploy again.A check failed on OpenGame's side
A check failed on OpenGame's side
The problem is ours, and your game is fine, so don’t change it. Wait a few minutes, then run the command the error names, or the same command again.
Submit for review
When the preview plays the way you want, runopengame submit from the game folder. Each deploy makes a new release, and submit takes the newest one once its checks have finished and it is ready. If that release isn’t ready, submit stops and names the command to run. Otherwise it asks you to confirm the release, then for any jam details.
The first time you submit a game, you certify in your browser that you have the rights to everything in it. A reviewer then plays it and approves it or asks for changes. The game becomes public when the reviewer approves and publishes it. Enter a jam covers tracks, rules and following the review.
Keep building
Package your game
What goes in the folder and the manifest, and the upload limits.
Connect the SDK
Read the player, handle guests and respond to sign-in.
Add a leaderboard
Declare a board, submit scores and show results.
Update a live game
Preview a new release while players keep the published one.