Publishing with gplay
Google Play Console is a lot of clicking. Uploading a build, filling in your store listing in every language, creating subscriptions and remembering to activate both halves of each one — all of it is web forms.
gplay is a free, open-source (MIT) command-line tool for Google Play Console. NowKit uses it, when you let it, to do those parts for you.
It's completely optional. Say no and every /kit-* command works exactly as it always has,
walking you through Play Console by hand. Nothing gets installed without asking.
Setting it up
You're offered this once, inside /kit-sign-release, when you're actually ready to upload a
build. Not during setup — it's useless until you have a Play Console account and an app created
there.
Three things happen:
- Install — one small binary (Homebrew on macOS/Linux, PowerShell on Windows, no WSL).
- Sign in — a browser opens; sign in with your Google account. The agent runs
gplay setup --auto, which creates a service account: a robot account that Google Play accepts uploads from. - Grant it access — one visit to Play Console → Users and permissions → Invite new users, pasting the robot account's email and ticking four boxes.
That's it, once, for the life of the app. Every later command just works.
Shipping a second app?
The robot account is created once per Google Cloud project, so your next app gets the same robot email — and Play refuses to invite it twice with "User already exists."
You're not inviting it again, you're editing it: Users and permissions → click the
existing …gserviceaccount.com row → App permissions → Add app → pick the new app →
tick the same four boxes → Apply → Save changes.
If you ship several apps, the Account permissions tab grants across every app on the developer account including ones you create later — one grant instead of repeating this each time. It's your own robot account on your own developer account, so the caution that applies to RevenueCat's key doesn't apply here.
The four permissions
In the App permissions tab of the invite dialog, tick:
- Releases → Release apps to testing tracks
- Releases → Release to production, exclude devices, and use Play App Signing
- Releases → Manage testing tracks and edit tester lists
- Store presence → Manage store presence
Leave everything else unticked. In particular, don't grant Admin and don't grant the financial permissions — those belong to the separate service account RevenueCat uses. Keeping them apart means no third-party dashboard ever holds a key that can publish to your production track.
Your Play Console account and your Google Cloud account don't have to be the same email. The two get connected by the invite above, not by sharing a login.
What it does for you
Uploading builds
/kit-sign-release sends the signed AAB to your testing track directly. /kit-publish-to-play's
update path — the flow you'll run for every release after the first — becomes essentially one
command instead of a walk through the console.
Creating your in-app products
The most error-prone step in the kit. Google nests a subscription inside a base plan and both
must be activated; miss one and your paywall silently shows nothing. /kit-setup-paywall now
creates the products from the plan /kit-plan-monetization wrote, activated correctly.
Product IDs are permanent. Once
premium_monthlyexists, that name is reserved forever — deleting the product doesn't free it. The kit shows you every ID and price and waits for your explicit yes before creating anything, and it never makes throwaway "test" products.
Store listing, screenshots and translations
/kit-publish-to-play pushes your title, short and full descriptions, screenshots, feature
graphic and release notes. If you ran /kit-translate-listing, every language uploads at
once — instead of pasting three fields per locale into a browser.
Staged rollouts
Something the kit couldn't do at all before. Release to a fraction of your users, watch, then ramp:
# 10% → watch → 50% → everyone
gplay rollout update --package <your.app.id> --track production --rollout 0.5
gplay rollout complete --package <your.app.id> --track production
# something's wrong
gplay rollout halt --package <your.app.id> --track production
For a first production release, 0.1 → 0.5 → complete over about a week is a sensible default.
The agent will offer it.
Per-country pricing
A flat US price prices your app out of India, Brazil and Indonesia. /kit-plan-monetization can
convert one base price into every market's local equivalent.
What it can't do
Google's API simply doesn't cover these, so they stay manual — no tool can automate them:
- Creating your Play developer account, paying the $25, identity verification
- Creating the app in Play Console (every command below needs the app to already exist)
- The whole "Set up your app" checklist — privacy policy, sign-in details, ads, content rating, target audience, data safety, government/financial/health declarations
- The Advertising ID declaration
- Submitting for review. On an app Google has never reviewed, the API refuses to send changes for review at all — it commits them as changes not sent for review — so a first release lands on the track unconfirmed and you finish it in the browser, through Dashboard → Create and publish a release (Preview and confirm → Send the release to Google for review → Publish your app). Publishing overview is empty on that path. For an app that's already live, it's the usual Publishing overview → Send app for review.
- Pre-registration (
/kit-pre-register-setupis unchanged) - Tester email lists — the API only handles Google Groups, not the console's email lists
- The AI asset declaration on the store listing's Review step — pushing a listing through the API doesn't set it, so you still answer that one in the browser
The 12-tester / 14-day closed-testing requirement is Google policy, not an API limit, so nothing changes there either.
Previewing before a write
gplay supports --dry-run on the metadata commands (sync import-listings,
sync import-images, listings update), and the kit uses it before overwriting your live store
listing.
Releases are different — there is no dry run for an upload. Before a release the kit runs:
gplay validate --package <your.app.id> --bundle app-release.aab
which is the canonical readiness report — local artifact, metadata, screenshots, release notes,
plus the remote track and listing state — and then shows you the exact upload command and waits
for your go. That gate matters more than a preview would: Play permanently burns the
versionCode in an uploaded bundle. Deleting the release afterwards does not give it back.
If something goes wrong
invalid_grant right after setup. Normal. A freshly created key takes up to a minute to
propagate through Google's auth. Wait and retry.
Your app doesn't appear. Same cause — the Play Console invite takes a moment to take effect. If it still doesn't show after a minute, check the invite went to the robot account's exact email address.
The very first upload of a brand-new app fails. Play may require the first build of an app that has never had one to go through the web console so it can enrol Play App Signing. If that happens the agent falls back to the browser for that one upload — every upload after it works through gplay.
Starting over. Your credentials live in ~/.gplay/, outside your project, so they're never
at risk of being committed. Delete that folder to reset.