appflight
v0.11.0
Published
Pre-submission App Store and Google Play compliance checks, with local deterministic scanning and optional AI analysis.
Maintainers
Readme
Appflight
Appflight scans iOS and Android projects for App Store and Google Play review risks before submission.
Install
Appflight requires Node.js 20.19.0 or newer.
npm install --global appflightCommands
Watch a project and rerun deterministic checks after each save:
appflight watch [dir]Run a one-shot deterministic scan:
appflight check [dir]Point [dir] at one app project. If it contains multiple independent Xcode,
Swift package, repository, or privacy-manifest roots, Appflight exits with a
clear error instead of combining them into one imaginary app.
Android checks resolve the real release model with the repository Gradle wrapper. Select flavors/modules explicitly when needed:
appflight check ./android --module :app --variant prodReleaseGradle runs offline by default; --allow-gradle-network permits dependency
resolution. This executes trusted repository build logic with your OS user's
permissions and is a different posture from iOS static reading. Read the
Android Gradle security disclosure before
enabling it in CI.
Mixed React Native/Flutter roots require --platform android|ios, or separate
commands pointed at ./android and ./ios. Appflight never combines their
rule registries.
Reports distinguish Validated, Enabled, unvalidated, and Dormant rules. Enabled, unvalidated rules run normally and their findings still trigger the configured failure threshold. “Not benchmark-validated” means precision has not yet been established against pinned real repositories at our benchmark standard; it describes our evidence, not whether the finding is correct. JSON includes per-finding rule metadata, finding validation counts, and all three rule-state counts in coverage. Scope coverage separately explains which inputs were available and which checks were not fully evaluated.
Add paid AI reasoning over findings and platform facts; iOS may also include selected, redacted code excerpts, while Android v1 includes none:
appflight login
appflight check [dir] --deepIf the signed-in account has no paid access, start Stripe Checkout directly from the terminal. Solo is the default; Team is explicit. Existing subscribers can open the non-expiring 100-analysis top-up checkout instead:
appflight upgrade
appflight upgrade --plan team
appflight upgrade --top-upOn an interactive terminal, the command opens the browser and prints the Checkout URL as a fallback. Subscription checkout waits for the live entitlement to become active; the existing CLI login works immediately after Stripe confirms the purchase, with no second website login or CLI re-login.
For a non-interactive CI run, sign in once on a trusted workstation and mint a named, revocable token for that pipeline:
appflight login
appflight token create --name "Bitrise nightly" --print-tokenStdout contains only the token. Store that single line as APPFLIGHT_TOKEN or
APPFLIGHT_API_TOKEN; do not add quotes or a Bearer prefix. Environment
credentials are read before the OS keychain, so check --deep never starts an
interactive login in CI.
CI tokens do not expire on a calendar. They are limited to running --deep and
cannot inspect the account, manage other tokens, refresh sessions, or use App
Store Connect. The server still checks the account's live paid entitlement and
quota/top-up balance on every run. Review or revoke tokens from a signed-in
workstation:
appflight token list
appflight token revoke <token-id>Create a separate named token per pipeline and revoke it immediately if it is exposed. Do not substitute a Supabase/web-session token or an internal refresh token.
Connect a project to App Store Connect, then cross-check its listing and products against local code:
appflight asc connect [dir]
appflight check [dir] --asc
appflight check [dir] --asc --deepInstall an advisory pre-push hook. Add --strict to block pushes on warnings:
appflight hook install [--strict] [dir]The default hook never blocks. Strict mode blocks only actual findings; scan
scope and other tool errors remain advisory so a configuration problem cannot
lock pushes. In a monorepo, configure one appflight check ./app-root command
per app.
Run appflight help for every option and exit-code behavior.
Free and paid
watch, plain check, and the advisory hook use the free deterministic
ruleset and require no account. check --deep and App Store Connect checks
require a signed-in, entitled account.
Privacy
Deterministic analysis runs locally. No source code or project data leaves your
machine during a free scan: source files, paths, finding text, repository
identity, and secrets are not sent. The CLI schedules a minimal anonymous,
code-free usage event by default; disable all free-path network activity with
APPFLIGHT_TELEMETRY=0 or "telemetry": false in
appflight.config.json.
The explicit --deep tier sends allowlisted deterministic findings, a facts
digest, and a small set of redacted code excerpts. App Store Connect
credentials and private keys never transit Appflight. The exact fields,
redaction steps, and opt-out behavior are documented in
What leaves your machine.
