Gplay Preflight logo

Gplay Preflight

Community
tamtom
gplay-preflight

Offline compliance and hygiene scanning of an AAB or APK with `gplay preflight` — manifest flags, restricted permissions, 64-bit and 16 KB page alignment, listing assets, secrets, billing, privacy SDKs, target API floor, and size. Use before uploading a build, as a CI gate, or when diagnosing a Play rejection. Runs entirely offline with no credentials.

Overview

Publishertamtom
Repositorygplay-cli-skills
Skill namegplay-preflight
Stars
52
Forks
7
Bundled files
Instructions only
LicenseMIT
Links
  • Markdown instructions

    A SKILL.md file the model loads on demand, so it only costs tokens when a request actually matches.

  • Works with any LLM

    AI skills are plain Markdown, not provider-specific code, so this works with GPT, Claude, Gemini, Grok, or a local model.

  • Self-contained

    Everything the model needs lives in the instructions — no extra files to sync.

  • Open source

    Published by tamtom on GitHub. Read the source before you install it.

Installation

Install the Gplay Preflight AI skill in TypingMind to use it with any LLM, or drop it into another agent that reads SKILL.md.

1

Install in TypingMind

TypingMind installs a skill straight from its GitHub folder — it reads SKILL.md, bundles the resource files, and stores the result locally.

  1. Open the app and go to Plugins → Skills.
  2. Choose "Install from GitHub".
  3. Paste the skill folder URL below and confirm.
    https://github.com/tamtom/gplay-cli-skills/tree/main/skills/gplay-preflight
  4. Enable the skill in any chat where you want it available.
Plugins → Skills → Add skill → From GitHub URL, then paste the folder URL and press Continue.
2

Install in another agent

Any agent that reads the Agent Skills format can use this skill — copy the folder into that agent's skills directory.

Claude Code — .claude/skills
git clone --depth 1 https://github.com/tamtom/gplay-cli-skills.git /tmp/gplay-cli-skills
mkdir -p .claude/skills
cp -r /tmp/gplay-cli-skills/skills/gplay-preflight .claude/skills/gplay-preflight
Restart Claude Code after copying so it picks up the new skill.

Use it in TypingMind

Enable Gplay Preflight in any TypingMind chat and the model takes it from there. Its name and description sit in the system prompt, and the moment a request matches, the model loads the full instructions itself — you never invoke it by hand, and it costs no tokens until it is actually used.

The model loads Gplay Preflight on its own as soon as a request matches it.

Works with any AI model

AI skills are plain Markdown instructions rather than provider-specific code, so Gplay Preflight is not tied to the model it was written for. Install it once in TypingMind and use it with GPT-5, Claude, Gemini, Grok, DeepSeek, Mistral, Llama, or a local model you run yourself — all on your own API keys.

  • Loaded only when it is needed

    The system prompt carries just the name and description. The instructions are fetched on the first matching request, so an idle skill costs nothing.

  • Switch models mid-chat

    Because the skill is instructions rather than code, changing model does not break it — the next model reads the same SKILL.md.

Skill instructions

This is the SKILL.md content the model loads. Read it before installing — a skill is instructions your model will follow.

gplay preflight — offline build scanning

gplay preflight inspects a local .aab or .apk and reports findings. It makes no API calls and needs no credentials, so it works on any machine, in any CI job, before the artifact has ever touched Play.

Reach for it before gplay validate (which needs auth and hits the API) and before any upload. It catches the class of problem that Play rejects hours later, or that fails at install time on a user's device.

Preconditions

  • A built .aab or .apk on disk.
  • Nothing else. No gplay auth login, no --package, no network.

Basic usage

bash
# Scan a bundle
gplay preflight --file app-release.aab

# Also validate the store listing in the same pass
gplay preflight --file app-release.aab --listings-dir ./fastlane/metadata/android

# Machine-readable
gplay preflight --file app-release.aab --output json --pretty

# See what scanners exist
gplay preflight --list-scanners

How preflight reads the build

preflight fully decodes AndroidManifest.xml — binary AXML for APKs, aapt2 protobuf for App Bundles — so findings reflect real, typed attribute values rather than substring guesses.

This matters when you interpret results: an attribute pointing at a resource reference (for example android:debuggable="@bool/isDebug") is reported as not statically determinable, not as false. Do not read a missing finding as proof of absence in that case.

Aggressive code shrinking can rename or remove classes, so SDK detection misses are not proof an SDK is absent. Matches, however, are high confidence.

The nine scanners

Every scanner has an ID. Select with --only or exclude with --skip (comma-separated).

manifest

Manifest-level correctness and release-blocking flags.

  • android:debuggable="true" — error. Ships a debuggable build.
  • android:testOnly="true" — error. Play rejects the upload outright.
  • Component with an <intent-filter> and no android:exported on targetSdk 31+ — error. This is an install failure on Android 12+, not a warning. Launcher activities are exempt.
  • Exported <provider> with grantUriPermissions — error. Any app can reach the granted URIs.
  • Foreground service type without its matching permission on targetSdk 34+ — Android 14 throws SecurityException at runtime. A dataSync type needs FOREGROUND_SERVICE_DATA_SYNC.
  • usesCleartextTraffic="true" — warning, downgraded to info when a networkSecurityConfig is present.
  • allowBackup, requestLegacyExternalStorage, package/version sanity.

permissions

  • Restricted permissions that require a Play declaration form: SMS and Call Log groups, MANAGE_EXTERNAL_STORAGE, ACCESS_BACKGROUND_LOCATION, QUERY_ALL_PACKAGES, SYSTEM_ALERT_WINDOW, BIND_ACCESSIBILITY_SERVICE, USE_FULL_SCREEN_INTENT, SCHEDULE_EXACT_ALARM, and others. Each finding carries the Play policy documentation link.
  • Sensitive permissions that need a Data safety disclosure (info level).
  • Legacy storage: WRITE_EXTERNAL_STORAGE without maxSdkVersion on targetSdk 30+, READ_EXTERNAL_STORAGE on 33+.
  • Duplicates and deprecated permissions.

native_libs

  • Missing arm64-v8a — error. Play has required 64-bit since 2019.
  • 16 KB memory page alignment, read from real ELF program headers. Error on targetSdk 35+, warning below. Android 15 devices with 16 KB pages will not load misaligned .so files.
  • x86 without x86_64, bare armeabi.
  • Unstripped .debug_* / .symtab sections — wasted download size.
  • extractNativeLibs="true" — larger install footprint.

metadata

Requires --listings-dir. Skipped otherwise. Expects a Fastlane-style layout (<dir>/<locale>/title.txt, <dir>/<locale>/images/...).

  • Title ≤ 30, short description ≤ 80, full description ≤ 4000, release notes ≤ 500 characters — counted in runes, not bytes.
  • Real pixel dimensions: icon 512×512, feature graphic 1024×500, promo graphic 180×120, TV banner 1280×720.
  • Screenshots: min 320px per side, max 3840px, max 2:1 aspect ratio, at least 2 phone screenshots, at most 8 per form factor, max 8 MB each.

secrets

Errors: private key blocks, AWS access keys, Stripe sk_live_, GitHub tokens, Slack tokens and webhooks, SendGrid keys, Google OAuth client secrets, OpenAI/Anthropic keys, service-account JSON, shipped keystores (.jks, .keystore, .p12, .pfx, .pem, .ppk), and .git/ or .env leakage.

Warnings: Google API keys (AIza…) and JWTs.

Google API keys are a warning, not an error, on purpose. Android apps embed Maps and Firebase keys by design. The fix is restricting the key to your package name and signing certificate in Cloud Console — not removing it from the binary. Do not tell the user to delete it.

Dex bytecode is scanned too, so hardcoded string literals are caught.

billing

Third-party payment processors (Stripe, Braintree, PayPal, Adyen, Razorpay…) present in the build — a warning on its own, downgraded to info when Play Billing is also present. Also flags com.android.vending.BILLING declared with no billing implementation, and billing wrappers (RevenueCat, Adapty, Qonversion) shipped without the Play Billing Library.

privacy

Inventory of 40+ analytics, attribution, and ads SDKs (info). Reconciles the AD_ID permission: warns when an ads/tracking SDK is present on targetSdk 33+ but the permission is missing, and notes the reverse case.

policy

  • targetSdkVersion below Play's floor. Override with --min-target-sdk when Google's annual bump lands before a new gplay release.
  • Restricted services: accessibility, VPN, device admin, notification listener.
  • APK-vs-AAB upload format.

size

Download size budget (--max-size), per-dex budget (--max-dex), dex fragmentation, and a payload breakdown by bucket with the largest entries.

CI gating

bash
# Block only on hard blockers
gplay preflight --file app-release.aab --fail-on error

# Stricter: warnings fail too
gplay preflight --file app-release.aab --fail-on warning

# Narrow the gate to the scanners you care about
gplay preflight --file app-release.aab \
  --only manifest,permissions,native_libs,secrets \
  --fail-on warning

# Faster: skip the secrets scan on very large builds
gplay preflight --file app-release.aab --skip-secrets

Exit codes:

CodeMeaning
0No findings at or above --fail-on
1Findings at or above --fail-on

GitHub Actions:

yaml
- name: Offline preflight
  run: |
    gplay preflight \
      --file app/build/outputs/bundle/release/app-release.aab \
      --listings-dir fastlane/metadata/android \
      --fail-on error

JSON output

--output json emits the full report: format, package, version code and name, min/target SDK, per-scanner run status, and every finding with its check, severity, message, entry, hint, and (where one applies) a ref policy link.

bash
# Just the errors
gplay preflight --file app.aab --output json | jq '[.findings[] | select(.severity=="error")]'

# Which scanners were skipped and why
gplay preflight --file app.aab --output json | jq '.scanners[] | select(.skipped)'

Where preflight fits

ToolNeeds authScope
gplay preflightNoThe artifact itself, offline. Manifest, libs, secrets, listing files
gplay validateYesRelease readiness: local checks plus live track and listing state
gplay checks analyzeYesGoogle Checks privacy/policy analysis, server-side and async
gplay release --dry-runYesFull pipeline against a real edit, discarded before commit

Run them in that order. preflight is the cheapest and catches the most.

Agent behavior

  • Run gplay preflight --file <artifact> before any upload or release command, and report findings before proceeding.
  • Pass --listings-dir whenever a metadata directory exists — otherwise the metadata scanner is skipped and listing problems go unreported.
  • Treat error findings as blocking. Do not upload past them without the user explicitly saying to.
  • Report the hint and ref fields, not just the message. The hint says what to actually change.
  • Never advise deleting a Google API key found by the secrets scanner. Advise restricting it.
  • A missing finding is not proof of compliance when the manifest could not be decoded or the build is heavily obfuscated. Say so rather than claiming the build is clean.
  • Confirm flags with gplay preflight --help before constructing a command.
  • --only and --skip take comma-separated scanner IDs; get the current list from gplay preflight --list-scanners.

Notes

  • preflight reads the archive once and streams large entries in bounded chunks, so memory stays flat on big bundles.
  • Scanner IDs are stable; finding check names are preserved across versions for JSON consumers.
  • The policy scanner's target API floor is a constant that Google raises each August. If it looks stale, pass --min-target-sdk.

Frequently asked questions

What does the Gplay Preflight AI skill do?

Offline compliance and hygiene scanning of an AAB or APK with `gplay preflight` — manifest flags, restricted permissions, 64-bit and 16 KB page alignment, listing assets, secrets, billing, privacy SDKs, target API floor, and size. Use before uploading a build, as a CI gate, or when diagnosing a Play rejection. Runs entirely offline with no credentials.

Why use Gplay Preflight on TypingMind?

Because you install it once and use it with any model. Gplay Preflight is plain Markdown rather than provider-specific code, so the same skill runs on GPT-5, Claude, Gemini, Grok, or a local model — and you can switch model mid-chat without it breaking. TypingMind runs on your own API keys, so you pay providers directly instead of a per-seat subscription, and your skills and chats stay in your own storage.

How do I install Gplay Preflight in TypingMind?

Open Plugins → Skills → Install from GitHub in TypingMind and paste https://github.com/tamtom/gplay-cli-skills/tree/main/skills/gplay-preflight. TypingMind reads its SKILL.md and installs it as a skill you can enable per chat.

Which AI models can use Gplay Preflight?

Any model you connect in TypingMind. AI skills are plain Markdown instructions rather than provider-specific code, so GPT, Claude, Gemini, Grok, and local models can all load this skill when a request matches it.

How many AI models can I use with Gplay Preflight?

As many as you like. As long as a model supports skills, you can use Gplay Preflight with it — GPT, Claude, Gemini, Grok, DeepSeek, Mistral, Llama and more — all on TypingMind with your own API keys.

Is the Gplay Preflight AI skill free?

Yes. It is published on GitHub by tamtom under the MIT license. You only pay your own AI provider for the tokens you use.

What are AI skills?

An AI skill is a reusable instruction bundle that teaches an AI model how to do one specific task. It follows the open Agent Skills format: a SKILL.md file with a name and description, plus any scripts, templates or reference files the model may need. The model reads the instructions only when your request matches the skill, so an installed skill costs nothing until it is used.

How are AI skills different from plugins or MCP servers?

A plugin or MCP server gives a model new tools to call — code that runs somewhere and returns a result. An AI skill gives the model knowledge and process instead: how to approach a task, which steps to follow, what good output looks like. Skills are plain Markdown, so they need no server, no API key and no runtime, and they work with any model.

View all

Set up your own AI workspace now

Get notified about new features and future giveaways by subscribing to our newsletter 👇