Install any skill in seconds. Free to start, no credit card required.
Get Started Free →The cross-cutting conventions every gplay command shares — credential and package resolution, output formats, semantic exit codes, the `--dry-run`/`--confirm` safety gates, and the Edit lifecycle. Use when running or designing any gplay command, wiring gplay into CI, branching on its exit codes, or introspecting the Android Publisher API offline with `gplay schema`.
| Test case | Without → With | Effect | Δ tokens | Δ turns |
|---|---|---|---|---|
| case-02 | ✗→✓ | ▲ Improved | 9% | 0% |
| case-03 | ✗→✓ | ▲ Improved | 52% | 0% |
| case-01 | ✗→✓ | ▲ Improved | 13% | 0% |
| case-04 | ✗→✓ | ▲ Improved | 119% | 0% |
| case-06 | ✗→✓ | ▲ Improved | 95% | 0% |
This is the foundation skill: the conventions that hold for every gplay command, factored out once so the workflow skills (see the Map of skills table at the end) can reference it instead of repeating them. The normative source of truth is docs/DESIGN.md in the CLI repo; this skill summarizes it for agents and does not freeze per-command flag lists.
--help is the source of truthgplay's commands are self-describing. Confirm the current verbs, flags, and defaults from the binary, never from memory:
bashgplay --help # the whole command tree gplay <group> --help # a namespace (releases, tracks, team, …) gplay <group> <command> --help # one command, with its real flags gplay exit-codes # the semantic exit-code table
If this skill and --help ever disagree, trust --help.
gplay schema — the offline API mapWhere --help documents gplay's own surface, gplay schema introspects the underlying Android Publisher API offline (no credential, no HTTP call) from an index compiled into the binary — does a method exist, what does it send and return, what fields and enums does a type carry:
bashgplay schema --list # compact catalog: id · http · path gplay schema tracks # match across method id, REST path, type name gplay schema Track # expand a schema's fields, types, enums gplay schema edits.tracks.update # a method's request/response, one hop deep gplay schema --method PATCH # filter the method surface by HTTP verb
[experimental] (gplay v0.5.0) — confirm the surface with gplay schema --help.
Every authenticated command resolves the service-account credential in this order, highest priority first:
--service-account <path-or-inline-json> — a JSON file path or inlineJSON content. Overrides everything below.
--account <name> — a specific stored Account. Overrides env + the activeAccount.
GPLAY_SERVICE_ACCOUNT env var — a path or inline JSON.gplay auth login).Setting this up from scratch is the gplay-setup skill. Auth problems exit 10 (bad/again credential) or 11 (the service account is not invited on the app/account).
--package + project pinning)Most commands need a target package. Resolution (ADR-0004):
--package com.example.app on the command, else.gplay/config.json for the current repo.Pin once with gplay init (or gplay apps init) so day-to-day commands need no --package. Managing the registry of packages is the gplay-apps skill.
--output takes table, json, or markdown. The default is auto (ADR-0005): a human table on a terminal, JSON when piped or in CI. For machine consumption, ask for --output json explicitly — read commands pass the API payload through (ADR-0003), and write commands return the request/diff body, so a CI gate is usually one jq line. The pass-through promise is about not reshaping the API, not that every --output json is an API echo: the offline reference commands that wrap no API call — team permissions and schema — synthesize their own (gplay-owned, documented) JSON instead.
stdout is data, stderr is logs. Parse stdout; warnings, progress, and -v/--verbose flow steps go to stderr and never pollute the JSON. (Example: reviews list prints its "last 7 days only" warning to stderr.)
gplay exit-codes prints the full table. The semantic codes:
| Code | Meaning | Retry-safe | |---|---|---| | 0 | Success | — | | 1 | Generic error (fallback) | no | | 2 | CLI misuse (unknown flag/command, bad value, missing arg) | no | | 3 | A named safety flag is missing (--confirm / --grant-admin) — re-run with it | yes, with the flag | | 4 | Denied by environment policy (GPLAY_READONLY) — a mutating command was refused | no — change the environment | | 10 | Authentication failure | no | | 11 | Authorization (403 — SA not invited) | no | | 20 | Client-side validation (bad AAB, unknown locale, …) | no | | 30 | API 4xx (not found, conflict, gone, …) | no | | 40 | API 5xx (upstream unhealthy) | yes | | 50 | Network (timeout, DNS, refused) | yes | | 60 | State conflict (open edit, rate-limited, ambiguous target) | sometimes |
Agents should treat 3 as "append the named flag and re-run", 4 as "the environment forbids this write — do not retry, change the deployment", 40/50 as "back off and retry", and 2/10/11/20/30 as "fix the input, do not retry blindly".
--dry-run everywhere, --confirm for live writes--dry-run is available on write commands: it validates inputs andprints the payload/diff it would send, with no HTTP call (and usually no auth needed). Reach for it before any production-affecting write.
--confirm gates the writes that reach real users or the live store —production releases, metadata apply, compliance datasafety set — and destructive local writes like auth logout. Omitting it fails with exit 3 and names the flag (in the JSON error envelope: requires: ["confirm"]). CI=true never auto-confirms.
--grant-admin is the stronger gate for conferring admin ingplay-team.
GPLAY_READONLY=1 (truthy = enforced) is the environment-level guard foragent deployments that must only read. Because the safety flags above are advisory — an agent holding the credential can pass them itself — set this in the environment and the kernel refuses every mutating command before credential resolution and before any network call, regardless of flags, while read commands and --dry-run previews keep working. Its refusal exits 4 (denied by environment policy) — which, unlike 3, is not resolvable by adding a flag; the only fix is to change the environment.
When a write refuses for a missing flag, the message names it — that refusal is agent-resolvable (ADR-0017): re-run with the flag it asked for. The GPLAY_READONLY refusal (exit 4) is the deliberate exception: it is not agent-resolvable.
Google Play mutations run inside a transactional Edit (edits.insert → change → edits.commit). gplay offers two ways to drive it.
Implicit (the default). Each write command performs the whole three-step dance on its own: it opens its own Edit, makes the change, and commits, discarding the Edit automatically on failure. You do not manage Edit IDs by hand. --keep-edit-on-failure skips that auto-discard for debugging.
Explicit (gplay edits …, when several changes must land together). To batch multiple writes into one atomic commit, open an Edit yourself:
bashgplay edits begin # opens an Edit, pins its id to .gplay/edit-<package>.json gplay metadata apply … # these writes detect the pin and reuse the open Edit gplay releases upload … --release-notes-dir ./notes gplay edits status # local read (no auth/network): shows the open edit, or none gplay edits commit # publish everything at once, and clear the pin # gplay edits discard # …or abandon the whole batch, clearing the pin
While the pin exists, subsequent write commands reuse the open Edit instead of opening their own, so the changes commit together or not at all. In explicit mode there is no auto-commit and no auto-discard — the lifecycle is yours until you commit or discard. Notes: a project (gplay init) is required since the pin lives under .gplay/; opening a second Edit while one is pinned is refused (exit 60); if commit fails (e.g. a validation error) the Edit stays open and the pin remains — fix and re-run, or discard.
(A few surfaces sit outside the Edit model on purpose — compliance datasafety, device-tiers, recovery, orders, vitals, games, subscriptions, iap are direct writes/reads with no editId, so edits begin does not batch them; their skills call that out.)
| Surface | Skill | |---|---| | Auth onboarding | gplay-setup | | App registry + details | gplay-apps | | Releases (upload/promote/rollout) | gplay-release-flow | | Tracks + testers | gplay-tracks | | Reviews | gplay-reviews | | Store listings + images | gplay-metadata-sync | | Data Safety | gplay-compliance | | Team users + grants | gplay-team | | Managed Play private apps | gplay-customapps | | Post-launch vitals (crashes/ANRs) | gplay-vitals | | Orders (view/refund) | gplay-orders | | Play Games config (achievements/leaderboards) | gplay-games | | App recovery (bad-release remediation) | gplay-recovery | | Device tier configs | gplay-device-tiers | | Subscriptions + one-time products (catalog) | gplay-monetization |
Other measured skills in the registry, with their headline benchmark lift.