Skip to content

Get started ​

A 5-minute walkthrough from zero to your first round-tripped Play listing.

1. Install ​

bash
npm install -g playstore-flow

Two binaries land on your PATH:

BinaryPurpose
playstoreThe CLI
playstore-mcpThe MCP server (stdio) — used by Claude Code / Cursor / other agents

Verify:

bash
playstore --help
which playstore-mcp

If you'd rather work from a checkout (handy when contributing back):

bash
git clone https://github.com/zmij/playstore-cli.git
cd playstore-cli && npm install && npm run build && npm link

2. Create a Play service account ​

Google Cloud Console → IAM & Admin → Service Accounts in the project linked to your Play Console. Create a service account, generate a JSON key, download it once (Google won't show it again).

Then in Play Console → Setup → API access, link the service account and grant it the roles you need (Release manager + Edit store listing for the full CLI surface; tighter roles work for read-only).

Note your app's package name (e.g. com.yourcompany.yourapp) from any APK / AAB you've uploaded, or from Play Console → your app → Dashboard.

See Authentication for role tuning, key rotation, and env-var overrides.

3. Drop the config file ​

The CLI looks for credentials in <repo>/.secret-stuff/ by default. Create the directory (gitignored — never commit) and the config:

yaml
# .secret-stuff/playstore-config.yaml
package_name: "com.yourcompany.yourapp"
service_account_key: "service-account.json"

Drop the JSON key next to it: .secret-stuff/service-account.json.

Different layout? Three independent env vars let you point at any directory split:

Env varDefaultWhat it points at
PLAYSTORE_SECRETS_DIR.secret-stuff/playstore-config.yaml + service-account JSON
PLAYSTORE_METADATA_DIRl10n/metadata/play/iap.yaml
PLAYSTORE_LISTINGS_DIRl10n/metadata/google/Per-language listings + screenshots + release notes

Why three knobs and not one? Play has historically split IAP YAML and listings across two directories; the CLI defaults match Lazy Sudoku's layout, but downstream users can unify by setting METADATA_DIR and LISTINGS_DIR to the same value. See the README's Configuration section.

4. Pull live state into YAML ​

Read-only — proves auth works and gives you a starting point.

bash
# Listings: per-language store copy + release notes → l10n/metadata/google/listings/<lang>.yaml
playstore listings export

# IAP catalogue: every one-time product / subscription / base plan / offer → l10n/metadata/play/iap.yaml
playstore iap export --output l10n/metadata/play/iap.yaml

Open the files. Commit them — they are now the source of truth for your store.

5. Edit + push ​

Edit a value in l10n/metadata/google/listings/en-GB.yaml — say, the short_description. Then preview before pushing:

bash
# Show what would change vs. live state
playstore listings sync --dry-run

# Push it
playstore listings sync

Same shape for IAP:

bash
playstore iap sync --dry-run
playstore iap sync

sync only patches fields that differ — your hand-edits don't overwrite the world. See Workflow for the full export → edit → sync → pull → reconcile loop, plus the iap create and iap state paths (one-time products and subscription base plans / offers have separate state lifecycles).

6. (Optional) Wire up the MCP server ​

Let Claude Code (or any MCP client) read live Play state during release prep without you leaving the terminal:

bash
# In the project directory where your secrets live
claude mcp add playstore playstore-mcp

Then ask the agent things like "show me the en-GB listing" or "what subscriptions are active?". The agent calls the same client code the CLI uses — no shelling.

See the README's MCP Server section for scope (local / project / user), other MCP clients (Cursor, Windsurf, Cline), and the working-directory + auth gotchas.

Next steps ​

  • Workflow — full export → edit → sync → pull → reconcile loop, plus iap create, iap state (activate / deactivate base plans + offers), and iap migrate-prices.
  • IAP schema — every field in iap.yaml: one-time products, subscriptions, base plans, offers, regional configs (with Money per region + new_regions fallback).
  • Listings schema — per-language listings/<lang>.yaml shape; title / short-description / full-description / release-notes length limits.
  • Play quirks — non-obvious gotchas the CLI works around (regionsVersion, monetization.* vs legacy inappproducts, edit-session discipline, batchUpdateStates for one-time purchase options, DRAFT-on-create, …).

Released under the MIT Licence. Battle-tested on Lazy Sudoku.