app · Rust · Playwright · MCP · Google Play first
app
app is a command-line tool and MCP server for getting Android apps to testers through Google Play. It registers the package, creates the Play Console listing, sets up internal testers, fetches their invitation links and installs builds on your devices, using Google's APIs where they exist and a signed-in headless browser where they don't.
app android create --name MyApp --package com.example.myapp -f phone,wear --dry-run
MyApp (com.example.myapp) [dry run]
· register planned
· create planned
· testers:phone planned
· testers:wear planned
app android invitation --name MyApp # tester links, after a release
app android accept-invitation --name MyApp && app android install --name MyApp
How each step is done
Google offers APIs for some of this and not for the rest: there is no API to create a Play app, and the testers API only takes Google Groups on closed tracks. So app uses the Android Developer Console and Play Developer APIs where it can, and a headless Chromium session that you sign in to once for the rest. Each browser flow is local to one function, so when Play's UI changes, the fix is in one place.
Credentials
The APIs use an OAuth refresh credential from a desktop OAuth client you create once; the browser steps use a Playwright storage state saved after you sign in to Play Console in a real browser. Both are plain files, so they can live in a secret store, and both can be copied to another machine over SSH without being printed. Access tokens and refreshed cookies go to a cache, so the source files never change in use.
When something is missing, app says what to run next:
app android auth status
credentials file ~/.config/app/android-auth.json (missing)
error Android OAuth credentials not found
next:
app android auth login --client-secret <desktop-oauth-client.json>
Real output from a fresh configuration, with its paths shortened.
| 0 | success |
|---|---|
| 2 | invalid input |
| 3 | configuration, including an API not enabled |
| 4 | authorisation needed; the next command is printed |
| 5 | not found |
| 6 | not ready, such as no completed release |
| 7 | busy: another command is updating this app |
| 8 | a Google API or HTTP error |
| 9 | a browser flow failed; screenshot and accessibility snapshot paths are printed |
| 10 · 11 | unsupported · timeout |
MCP
app mcp stdio exposes the same operations, from android_create to android_install. Tools that change Play state need confirmed: true unless they are a dry run, and the app-android agent skill teaches the workflow: create the app before its first internal release, then fetch the tester link and install. Configuration (account, signing key, tester lists, devices) is declarative YAML, kept apart from the secrets so a managed config in a Git checkout never attracts them.