Skip to main content
Version: v4 (current)

Experimental Plugins

These CLI plugins are functional but new. They're registered by default in every game-ci binary - no --plugin flag needed, and nothing extra to install - but expect rough edges, and verify against a test target (a test repo, a test itch.io channel) before pointing any of them at something real.

Deploy to a GitHub Release

@game-ci/github-release-deploy attaches a built output to a GitHub Release.

GITHUB_TOKEN=... game-ci deploy github-release ./build --repo owner/repo --tag v1.2.3

buildPath may be a single file (uploaded as-is, optionally renamed via --assetName) or a directory - every top-level file inside it is uploaded as a separate asset, named after itself. Re-running against the same tag is idempotent: an existing release for that tag is reused, and an asset that already exists on it is replaced rather than failing.

OptionDescription
--repoowner/repo. Defaults to $GITHUB_REPOSITORY.
--tagRelease tag. Required.
--releaseNotesRelease body/description.
--draftCreate the release as a draft.
--prereleaseMark the release as a prerelease.
--assetNameOverride the uploaded asset's file name (single-file buildPath only).
--targetCommitishCommit/branch to create the tag from, if it doesn't already exist.

GitLab Release support isn't included in this first version.

Deploy to itch.io

@game-ci/itch-deploy wraps itch.io's official butler push CLI.

BUTLER_API_KEY=... game-ci deploy itch ./build --user myuser --game mygame --channel windows

Requires butler already installed and on PATH (or pass --butlerPath explicitly - recommended for CI determinism). This plugin doesn't install butler for you.

OptionDescription
--useritch.io username or organization. Required.
--gameitch.io game slug. Required.
--channelChannel to push to, e.g. windows, linux, web. Required.
--butlerPathExplicit path to the butler executable.
--userVersionCustom version string shown in itch.io's build history.
--ignoreComma-separated glob patterns excluded from the push.

Publish a Steam Workshop item

@game-ci/steam-workshop uploads a Workshop item (a mod, map, or asset pack) via SteamCMD's workshop_build_item.vdf path - distinct from @game-ci/steam-deploy's full-game upload.

STEAM_USERNAME=... STEAM_PASSWORD=... game-ci deploy steam-workshop ./my-mod --appId 480 --title "My Mod"

Omit --publishedFileId to publish a new item; pass it to update an existing one.

Sign and notarize a build

@game-ci/code-signing signs (and, on macOS, notarizes and staples) a built player.

APPLE_ID=... APPLE_TEAM_ID=... APPLE_APP_SPECIFIC_PASSWORD=... game-ci \
sign ./build/Game.app --platform macos --identity "Developer ID Application: Studio Name (TEAM123)"

Windows signing goes through signtool sign instead, via --platform windows and either --certificatePath or --certificateThumbprint.

Pseudo-localization QA

@game-ci/pseudo-localization injects pseudo-loc strings pre-translation, to catch UI overflow/truncation and missing-localization bugs before real translation work starts.

game-ci pseudo-localize ./Localization

Reads a flat key→string localization table - <projectPath>/<sourceLocale>.json or .csv - and writes the pseudo-localized result to <projectPath>/<outputLocale>.<same format>. Engine-specific structured formats (e.g. Unity's binary StringTable assets) aren't supported yet.

Bevy engine support

@game-ci/bevy detects a Bevy project - a real bevy dependency in Cargo.toml, not just any Cargo project - and builds/tests it via cargo build --release/cargo test --release. Detection is automatic; point build/test at the project like you would for any other engine:

game-ci build ./my-game
game-ci test ./my-game

--target is only needed for cross-compilation (e.g. --target x86_64-pc-windows-gnu to build a Windows binary from a Linux runner) - omit it to build for the runner's own host toolchain, which is what most CI jobs want.

Detection isn't specific to Bevy - build/test inspect the project directory for every engine this way. If you need to skip that (e.g. a project whose structure confuses auto-detection, or you just want to be explicit), pass --engine=bevy to force it:

game-ci build ./my-game --engine=bevy
OptionApplies toDescription
--targetbuild, testRust target triple. Builds for the host toolchain when omitted.
--featuresbuild, testComma-separated cargo features to enable.
--lockedbuild, testFail instead of updating Cargo.lock. Default true.
--debugbuildBuild in debug mode instead of --release. Default false.
--outputPathbuildDirectory to copy the built binary into.

Cross-compilation via --target assumes the target's toolchain and any required linkers are already installed (e.g. via rustup target add, or a cross-based custom Docker image) - this plugin doesn't set that up for you. Doesn't yet resolve workspace-inherited dependencies (bevy.workspace = true) for detection - a known gap for workspace-structured projects.

Planned plugins

These are registered as structural drafts only - the command shape exists, but no domain logic is written yet, and invoking them throws. Not usable today; listed here so the roadmap is visible.

PluginWhat it will do
@game-ci/anti-cheatWrap a build with an anti-cheat SDK's own packaging step.
@game-ci/dedicated-server-provisioningProvision/deploy a built dedicated server to hosting infrastructure.
@game-ci/dev-tunnelExpose a local dev build through a public tunnel for remote playtesting.
@game-ci/gamemakerBuild a GameMaker project via Igor (needs a real licensed GameMaker install to verify against).
@game-ci/renpyBuild a Ren'Py visual novel project.
@game-ci/rpg-makerBuild an RPG Maker project (no official CLI exists yet to verify a real invocation shape against).
@game-ci/save-data-compatValidate save-data compatibility across engine/build versions.
@game-ci/screen-captureCapture gameplay footage/screenshots during an automated test run (GPU-required).

Interested in one of these? Open an issue on game-ci/cli - the plugin interface is stable, so implementing the domain logic for any of these is a scoped, self-contained contribution.