# RevylAI/greenlight: an offline pre-submission scanner for App Store and Google Play review rules

> Greenlight is a Go CLI that checks app source, privacy manifests, Android manifests and IPA/APK/AAB binaries against Apple's Review Guidelines and Google Play's Developer Program Policies. Everything static runs offline with no account; runtime flow verification is a separate, account-backed tier.

**RevylAI/greenlight** — Pre-submission compliance scanner for the Apple App Store and Google Play. Scans code, privacy manifests, Android manifests, and IPA/APK/AAB binaries against the review guidelines. Offline, no account.

- Repository: https://github.com/RevylAI/greenlight
- Website: https://revyl.com
- Stars: 2,440 · Forks: 147
- Language: Go
- License: MIT
- Published: 2026-09-28 · Updated: 2026-09-28 · Language: en
- Canonical page: https://hysenlabs.com/projects/revylai-greenlight

## What greenlight checks before you submit

App review rejections rarely come from a bug. They come from a rule you did not know applied to you: a private API call, an ad SDK without App Tracking Transparency, an account creation screen with no deletion path, a target API level that has already fallen behind Google Play's distribution schedule. Greenlight's job is to surface those before a reviewer does.

The README frames it as "Know before you submit" and describes the input surface plainly: source code, privacy manifests, Android manifests and Gradle builds, IPA binaries, and App Store Connect metadata. The audience is mobile teams, including React Native and Expo projects, since codescan explicitly covers Swift, Objective-C, React Native and Expo source. It is a CLI, not a dashboard, and it is aimed at whoever owns the release checklist.

## How the scanners work and where findings come from

The core command is `preflight`, which the README says "Runs every applicable scanner in parallel." Five scanners are listed, each with its own input type: metadata reads app.json and Info.plist; codescan runs 24 rules over roughly 60 patterns; privacy inspects PrivacyInfo.xcprivacy completeness, Required Reason APIs and tracking SDKs against ATT; playscan covers Google Play policy, target API deadline, restricted permissions, foreground service types and Play Billing version; ipa inspects the binary's Info.plist keys, launch storyboard, icons, app size and framework privacy manifests.

Two design details matter more than the rule count. First, every finding cites the rule it comes from, so a report is traceable to a guideline section rather than to a heuristic. Second, rules that describe a project-level fact "report once for the whole project rather than once per file that triggers them," which keeps output readable on large codebases. If a repo contains both Android and iOS projects, both are picked up in one pass.

Severity is split four ways. CRITICAL means rejection or install failure is near-certain; HIGH covers a published deadline, a required declaration, or a check that fails at runtime; WARN and INFO are advisory. Only the top two fail a CI gate.

## Installing greenlight and running a first preflight

Three install paths are documented. Homebrew is the macOS route, Go installs from source, and the Makefile builds a local binary. Pick one.

```bash
# Homebrew (macOS)
brew install revylai/tap/greenlight

# Go
go install github.com/RevylAI/greenlight/cmd/greenlight@latest

# Build from source
git clone https://github.com/RevylAI/greenlight.git
cd greenlight && make build
# Binary at: build/greenlight
```

The source build places the binary at `build/greenlight`; `make build` passes a version string via `-ldflags "-X main.version=$(VERSION)"`, where VERSION falls back to `git describe` output or the literal `dev`.

With the binary on your PATH, point preflight at a project directory. The README's first example is the whole-project scan with no uploads:

```bash
greenlight preflight /path/to/your/project
```

If you have a built iOS artifact, add `--ipa` so the binary scanner runs too:

```bash
greenlight preflight . --ipa build.ipa
```

For CI, `--exit-code` makes the process exit non-zero on CRITICAL and HIGH. The README notes it also trips on a scanner that crashed, "so an incomplete scan never reports as a pass." Machine-readable output comes from `--format json`, or `--format sarif --output greenlight.sarif` if your code scanning dashboard consumes SARIF.

Android artifacts get their own entry points, and the built-artifact modes read the merged manifest rather than the source manifest:

```bash
greenlight playscan --apk app-release.apk
greenlight playscan --aab app-release.aab
greenlight playscan . --exit-code
```

## The runtime tier, and why a static scan is not proof

The README is direct about the ceiling of static analysis: "A static scan can only prove a flow exists." Codescan can see that a Restore Purchases call exists somewhere in the source. It cannot see that tapping the button dead-ends on a real device.

`greenlight verify` covers that gap for three flows: account deletion, restore purchases, and Sign in with Apple. It runs them on a cloud device and fails the build if any dead-ends. This tier is powered by Revyl and needs a free account, so it is the one part of the tool that is not offline. The same targeting flags apply to `preflight --verify` and the standalone command: `--artifact`, `--build-name`, `--device-model`, `--os-version`, `--var`.

```bash
greenlight preflight . --verify --build-name "My App" \
  --var email=qa@acme.com --var password=secret --exit-code
```

That split is the honest architecture here. Rules that can be decided from files stay local; rules that need a running app leave the machine. Teams that cannot send builds to a third party lose the verify tier entirely, and no amount of local scanning replaces it.

## Where greenlight gives you a false sense of safety

The clearest limitation is the one the README states itself: existence is not behaviour. A codebase can contain a deletion path that crashes, and codescan will be satisfied.

There are narrower gaps. The privacy scanner checks PrivacyInfo.xcprivacy completeness and Required Reason API declarations, but the README does not claim it validates that your declared reasons match how the API is actually used. The crypto rules are signal-based: a wallet triggers a WARN because it needs an Organization account, and an exchange or on-ramp SDK is HIGH because it "usually needs licensing or a legal opinion." Those are pointers to a human decision, not answers.

It is also the wrong tool for anything outside the two mobile stores. A web app, a desktop app, or an internal enterprise distribution has no App Store or Play policy surface for these scanners to read. And if your release process is already gated by a human compliance reviewer with a checklist, greenlight duplicates part of that work rather than replacing it. The README does not document a rollback or undo path for a scan run, which matters little for a read-only scanner but is worth knowing before you wire it into a pipeline.

## Greenlight versus a general static analysis stack

The obvious alternative is running a general linter or SAST tool over the same code. Semgrep, for example, lets you write custom rules and is not tied to any store's policy. The difference in approach is the rule source. A general SAST tool knows about code patterns you describe; greenlight ships rules derived from Apple's Review Guidelines and Google Play's Developer Program Policies, and each finding links the policy page or guideline section it came from. That is why `playscan` can flag a target API deadline or a Play Billing Library version that loses support, which no generic linter will tell you.

The trade-off runs the other way too. A general SAST tool covers languages and frameworks greenlight does not, and it does not go stale when a store updates a deadline. If your concern is injection flaws or dependency risk rather than review rejection, greenlight is the wrong category of tool. The two can coexist: SARIF output means greenlight findings can land in the same pipeline as your existing scanner.

## Maintenance, licence and what a scan run costs you

The repository is MIT licensed, so you can vendor it, fork it, or ship it inside an internal toolchain, subject to the usual attribution terms. Nothing here is legal advice; read the LICENSE file and the licence text of the Go dependencies in go.mod if you redistribute a build.

Maintenance signals are mixed but current: the last push was on 2026-08-05, and the two releases in the repository are v0.1.0 on 2026-02-11 and v0.2.0 on 2026-07-28. The repository is not archived. There is no stated support window, and no documented migration path between releases, so pinning a version and reading the release notes before upgrading is the only guidance the README supports.

Upgrade cost is mostly rule freshness, not code. Store policies move on fixed dates, and the README already names some: target API 36 for new apps and updates from August 31, 2026, Play Billing v7 and below losing support on the same date with no direct v7 to v9 upgrade path, and a July 2026 change to `READ_CALL_LOG` permitted uses. A version of greenlight that predates a policy change will not know about it. The install path is cheap (`go install ...@latest` or a Homebrew upgrade), but the scan results are only as current as the binary.

## Conclusion

Adopt greenlight if you ship iOS or Android releases and want the static checks (private API use, ATT, Restore Purchases, target API deadlines, restricted permissions) wired into CI before submission. Skip it if you expect a static scan to prove a user flow works end to end, or if you need a hosted dashboard rather than a CLI. Verify first that your project layout is one the scanners actually read: metadata, codescan, privacy, playscan and ipa each look at specific files, and the README does not document rollback or an undo path for a scan run.

## FAQ

### Does greenlight upload my source code or app binary?

The README states the static scanners run with no account, no uploads and no network. The exception is the `verify` tier, which runs flows on a cloud device, is powered by Revyl, and needs a free account.

### What does greenlight's exit code mean in CI?

The `--exit-code` flag makes the process exit non-zero on CRITICAL and HIGH findings. The README also notes it trips on a crashed scanner, so an incomplete scan never reports as a pass.

### Can greenlight scan an Android app bundle or APK directly?

Yes. `greenlight playscan --apk app-release.apk` and `greenlight playscan --aab app-release.aab` run against the built artifact, and the README says this reads the merged manifest.

### Does greenlight check both iOS and Android in one run?

The README states that Android and iOS projects in one repository are both picked up, so a cross-platform app is checked against both stores in a single pass.

## Sources

- [License: MIT](https://github.com/RevylAI/greenlight/blob/main/LICENSE)
- [Project website](https://revyl.com)
- [README](https://github.com/RevylAI/greenlight/blob/main/README.md)
- [Releases](https://github.com/RevylAI/greenlight/releases)
- [RevylAI/greenlight on GitHub](https://github.com/RevylAI/greenlight)

---

Hysen Labs editorial analysis, written from the project's own repository and release notes. Cite the canonical page: https://hysenlabs.com/projects/revylai-greenlight
