Configuration and Plugins
The game-ci CLI can read options from .game-ci.yml and load plugins from command-line flags or
config. Those plugins can add engine detection, build commands, test commands, custom commands,
options, and provider-backed job execution.
Config File
The CLI looks for .game-ci.yml in the current working directory. You can also pass an explicit
config path:
game-ci --config ./ci/game-ci.yml build ./my-project
Options live under cliOptions.
cliOptions:
plugin:
- '@game-ci/orchestrator-plugin'
verbose: true
targetPlatform: StandaloneLinux64
buildsPath: dist
The config file uses the same option names as the CLI's parsed options. In practice, that means
camelCase names such as targetPlatform, providerStrategy, customImage, and buildsPath.
Plugin Sources
Plugins can provide engine detectors, build or test command handlers, custom commands, options, and provider implementations.
| Source type | Example |
|---|---|
| NPM package | --plugin @game-ci/orchestrator-plugin |
| Local file/path | --plugin ./plugins/my-plugin.ts |
| Executable | --plugin executable:./my-provider |
| GitHub shorthand | --plugin github:game-ci/example-plugin |
Direct GitHub loading is reserved for future plugin loader work. Publish the plugin to npm or use a local path for now.
Orchestrator as a Plugin
The Orchestrator ships provider implementations for the public CLI.
game-ci \
--plugin @game-ci/orchestrator-plugin \
orchestrate ./my-project \
--provider-strategy aws
You can also add the plugin to .game-ci.yml:
cliOptions:
plugins:
- '@game-ci/orchestrator-plugin'
providerStrategy: local-docker
targetPlatform: StandaloneLinux64
Then run:
game-ci orchestrate ./my-project
Provider strategies loaded through the Orchestrator plugin can also be config-defined providers:
cliOptions:
plugins:
- '@game-ci/orchestrator-plugin'
providerStrategy: config:./.game-ci/providers/local-shell.yml
Use this when YAML or JSON can describe how to call your existing provider scripts or automation APIs. See Config-defined providers.
Built-In Engine Support
The CLI includes built-in plugins for:
| Engine | Detection signal | Built-in command surface |
|---|---|---|
| Unity | ProjectSettings/ProjectVersion.txt | Engine command options |
| Godot | Godot project files | Engine command options |
| Unreal | .uproject files | Engine command options |
External plugins can add new engine support or replace command behavior without changing the CLI core.
Plugin API
A plugin exports a GameCIPlugin object. It can provide any combination of engine detectors, build
commands, test commands, option registration, providers, and an onLoad hook.
export default {
name: 'my-engine',
version: '1.0.0',
engineDetectors: [
{
name: 'my-engine',
detect(projectPath) {
return { engine: 'my-engine', engineVersion: '1.2.3' };
},
},
],
commands: [
{
engine: 'my-engine',
createCommand(command, subCommands) {
if (command === 'build') return new MyBuildCommand(command);
if (command === 'test') return new MyTestCommand(command);
return null;
},
},
],
providers: {
'my-provider': MyProvider,
},
};
Provider plugins register provider strategy names. game-ci orchestrate then creates the provider
selected by --provider-strategy. game-ci remote run and game-ci remote build are kept as
compatibility aliases for older workflows.
Provider implementations can also live outside the public CLI. The Orchestrator supports
configuration-driven providers, executable providers, and TypeScript/JavaScript provider modules.
Use the public CLI plugin API when you are adding command surface or engine behavior to game-ci
itself; use the Orchestrator provider extension points when you are changing where jobs run.
Plugin Catalog
Beyond the built-in Unity/Godot/Unreal engine plugins and the built-in Orchestrator, a growing set
of plugins add engine support and cross-cutting capabilities. steam-deploy and
runtime-test-framework are shipped and in the CLI's default load list, the same way Orchestrator
is. Everything else below is a draft - load it explicitly with --plugin @game-ci/<name> (or a
plugins: entry in .game-ci.yml) once it's real.
| Plugin | Kind | Status |
|---|---|---|
@game-ci/steam-deploy | Deploy command | Shipped. game-ci deploy steam <buildPath> - VDF generation, local/Docker SteamCMD execution. |
@game-ci/runtime-test-framework | Command | Shipped. game-ci test-runtime <buildPath> - see below for the results contract. |
@game-ci/gamemaker | Engine | Draft - registration shape only, build logic not yet implemented. |
@game-ci/rpg-maker | Engine | Draft. |
@game-ci/renpy | Engine | Draft. |
@game-ci/itch-deploy | Deploy command | Draft - mirrors steam-deploy's shape. |
@game-ci/steam-workshop | Deploy command | Draft - mods/maps via workshop_build_item.vdf, distinct from steam-deploy's full-game upload. |
@game-ci/github-release-deploy | Deploy command | Draft - mirrors steam-deploy's shape. |
@game-ci/code-signing | Command | Draft - command not yet registered in core either. |
@game-ci/crash-symbol-upload | Command | Draft - command not yet registered in core either. |
@game-ci/screen-capture | Command, GPU | Draft - command not yet registered in core either. |
@game-ci/live-show | Command | Draft - command not yet registered in core either. |
@game-ci/dedicated-server-provisioning | Command | Draft - command not yet registered in core either. |
@game-ci/anti-cheat | Options | Draft - hooks into an existing build, not a new command. |
@game-ci/pseudo-localization | Command | Draft - command not yet registered in core either. |
@game-ci/save-data-compat | Command | Draft - command not yet registered in core either. |
@game-ci/dev-tunnel | Command | Draft - command not yet registered in core either. |
"Draft" means a real, correctly-typed plugin skeleton exists (conforming to the plugin interface
above), but its actual domain logic is a documented TODO rather than an implementation - see each
plugin's own README.md under plugins/<name>/ in the game-ci/cli repo for exactly what's real
versus planned. Several of the command-based drafts also need a small core change to register their
command name with the CLI at all (the same kind of change deploy itself needed - see the PR that
added steam-deploy) before they can be invoked even once their logic is implemented.
Runtime Test Framework
game-ci test-runtime <buildPath> is a real, distinct capability from game-ci test: it launches
the actual built player your build step produced (not the Editor, and not Unity's own Test
Framework's specialized test player, which game-ci test's -runTests path uses) and reports on
whatever tests its own in-game harness ran.
game-ci test-runtime ./build/StandaloneLinux64 --timeout 60000
buildPath can point directly at the executable, or at a directory containing it - the plugin looks
for the single matching candidate (one .exe on Windows, one .app bundle on macOS, one
executable-bit file on Linux) and errors clearly if it finds none or more than one, rather than
guessing.
This plugin never runs test code itself. A game project's own in-game test harness does, against a small results contract:
The plugin launches the player with
GAME_CI_RUNTIME_TEST_MODE=1andGAME_CI_RUNTIME_TEST_RESULTS_PATH=<path>set.Your in-game harness checks for
GAME_CI_RUNTIME_TEST_MODE, runs whatever tests it wants, and writes a JSON file toGAME_CI_RUNTIME_TEST_RESULTS_PATHbefore exiting:{
"schemaVersion": 1,
"tests": [
{ "name": "player spawns at origin", "passed": true, "durationMs": 12 },
{
"name": "inventory persists across scene load",
"passed": false,
"message": "expected 3 items, got 2"
}
]
}The plugin reads that file after the process exits (or kills it and fails the run if it doesn't exit within
--timeout) and fails the CI step on anypassed: falseentry, or if the file was never written at all.
The results file, not the process exit code, is authoritative - a player that writes valid results but happens to exit non-zero for an unrelated reason still has its real test results honored.
Local Config Folder
Use config open to open the local GameCI folder:
game-ci config open
The CLI stores its user-level files under ~/.game-ci.