Docs menu

Docs ▸ Steam

Publishing

npx gameshipper publish --dry-run                 # check everything, upload nothing
npx gameshipper publish                           # Steam, itch.io and GitHub Releases, whichever are set up
npx gameshipper publish --to steam --branch beta  # also set the Steam build live on your beta branch
npx gameshipper publish --to github --live        # publish the GitHub release instead of leaving a draft

Set these in gameshipper.json; they're names, not secrets:

Field Example For
steam.appId 1234560 Steam: your own App ID. 480 is Valve's test app, which can't take uploads, so Steam is left out until you set it
steam.user moon_builder Steam: the account that uploads builds (or pass --steam-user)
steam.depots { "windows": 1234561 } Steam: depot IDs, when they aren't the App ID + 1, 2 and 3
itch.project moonstudio/moon-game itch.io
github.repo moonstudio/moon-game GitHub Releases (or pass --repo)

Steam. Gameshipper downloads Valve's SteamCMD into its cache (checked against a pinned SHA-256) and uploads one build with a depot per OS, from out/windows, out/mac and out/linux, with your version as its description; steam_appid.txt is never uploaded. The first time, SteamCMD asks for the password and Steam Guard code in your terminal; Gameshipper never sees them. SteamCMD runs with a HOME of its own in Gameshipper's cache, where it keeps its login, and on a Mac with a stand-in launchctl, so it never changes your Steam client's files and never loads or removes its background jobs. The build is uploaded, not set live: publish prints the link to set it live, and the launch option and Steam Cloud settings to enter once in Steamworks. --branch beta also sets it live on an existing beta branch; Valve only lets the website set the default branch live. The account needs Steamworks' Edit App Metadata and Publish App Changes To Steam permissions, and Valve recommends an account just for builds. A dry run logs in too, because Steam checks the build on its servers.

itch.io. Gameshipper downloads itch.io's butler and pushes each build to the channels windows, mac and linux, with your version. The first time, butler opens your browser to log in, and keeps the login itself; in CI, set BUTLER_API_KEY. Uploads are downloadable at once if the game's page is public: keep it in Draft to try a build first.

GitHub Releases. Needs a token in GITHUB_TOKEN (or GH_TOKEN) that can write to the repository: a fine-grained token limited to it with Contents: Read and write, or a classic token with the repo scope. Set it yourself, in your shell or the MCP server's environment; never paste it into a chat with an agent. Gameshipper never uses the gh CLI's login. It zips each build (on a Mac with ditto, so the Mac app keeps its signature however it's unzipped) and attaches them to the release v<version>, as a draft unless you pass --live. Publishing again replaces the draft's files; a published release is never changed (GITHUB_RELEASE_PUBLISHED: raise the version).

iOS and Android aren't uploaded: publish lists the steps in Xcode and Android Studio.

Code
STEAM_LOGIN_REQUIRED, ITCH_LOGIN_REQUIRED No saved login, and nobody at a terminal to log in (an agent, --json or --yes): run the command in the fix once in your own terminal. Exit code 2.
BUILD_MISSING, STEAM_TEST_APP, STEAM_DEFAULT_BRANCH, GITHUB_TOKEN_MISSING, GITHUB_AUTH_FAILED, GITHUB_REPO_NOT_FOUND, GITHUB_RELEASE_PUBLISHED Something to set or fix first; exit code 2.
STEAM_PATH_UNSUPPORTED The game folder's path has a " (or, on macOS and Linux, a \), which SteamCMD's build scripts can't hold: move or rename the folder. On a Mac it's also returned when Gameshipper's cache folder has a :: set GAMESHIPPER_CACHE to another. Exit code 2.
STEAM_UPLOAD_FAILED, STEAM_SET_LIVE_FAILED, STEAM_LOGIN_FAILED, STEAMCMD_CANT_RUN, ITCH_PUSH_FAILED, ITCH_LOGIN_FAILED, GITHUB_API_FAILED, ZIP_FAILED, TOOL_DOWNLOAD_FAILED, TOOL_CHECKSUM_MISMATCH, TOOL_UNSUPPORTED_HOST The upload or a tool failed; the message says why and the run log has the tool's output. Exit code 1.
ITCH_UPLOADS_LIVE A warning: itch.io uploads are public at once if the page is.