# flashlight: an Android performance score you can run from CI, with no SDK in your app

> Flashlight measures an Android app from the outside and produces a single performance score, which is why it works on production builds without instrumenting your code. The trade is that it is Android-only, that iOS is still tracked as an issue, and that the newest release tag is from July 2024.

**bamlab/flashlight** — 📱⚡️ Lighthouse for Mobile - audits your app and gives a performance score to your Android apps (native, React Native, Flutter..). Measure performance on CLI, E2E tests, CI...

- Repository: https://github.com/bamlab/flashlight
- Website: https://docs.flashlight.dev
- Stars: 1,611 · Forks: 51
- Language: TypeScript
- License: MIT
- Published: 2026-10-16 · Updated: 2026-10-16 · Language: en
- Canonical page: https://hysenlabs.com/projects/bamlab-flashlight

## Measuring from outside is what makes production measurement possible

Flashlight generates a performance score for an Android app by aggregating different metrics. The repository description frames the scope: Android apps, whether native, React Native or Flutter, measured on the CLI, in E2E tests and in CI.

The two features that distinguish it from an in-app SDK are stated plainly at the top of the README. No setup is required in your app, and performance can be measured even on production apps.

Both of those follow from the same design choice. If the tool attaches to an APK that already exists rather than linking a library into your binary, then there is nothing to add to the build, and a release build from your store can be measured without a debug flag. That is a different contract from every APM agent, all of which need code in the app and therefore only exist in your own builds.

The scope boundary is equally explicit: iOS support is in the works and is tracked as an issue rather than shipped. For a team with both platforms, this is an Android tool today.

## Three commands, and they cover three different jobs

The CLI has three commands and they are not variations of each other.

`flashlight measure` is the quick audit with real-time measures. This is the one you run locally when you want to know where a build stands today.

`flashlight test` automates the measures with end-to-end performance testing over several iterations. Several iterations is the point: a single run of a performance tool tells you about one execution, while a repeated run is what lets you compare two builds or fail a build on a regression.

`flashlight cloud` runs the measures on real devices in the cloud and integrates with your CI setup. That last part is the operational difference. A local measurement runs on whatever machine the developer has, and a cloud run runs on a controlled device, which is what makes two builds comparable at all.

There is also a hosted path outside the CLI: you can upload an app and get its performance score back on app.flashlight.dev. For a one-off look at a build, that is faster than anything you install.

## Installing means piping a script from a URL into your shell

Installation is one command per platform. On macOS and Linux:

```bash
curl https://get.flashlight.dev | bash
```

On Windows it is the PowerShell equivalent:

```powershell
iwr https://get.flashlight.dev/windows -useb | iex
```

Both are the pipe-a-remote-script-into-your-shell pattern, which is convenient and which deserves the usual scepticism: you are executing whatever that host serves at the moment you run it, with no checksum in the command. If your organisation has a policy against that pattern, the repository is a Yarn workspace monorepo with a packages/ directory, and building the CLI from source is the alternative, at the cost of assembling the toolchain yourself.

The README itself points at docs.flashlight.dev for usage rather than documenting commands inline, which is a signal that the documentation lives outside the repository and that the CLI surface is expected to change.

## Reports are the visible output, and comparisons are what they are for

The README highlights report generation and links a specific example, a Flatlist versus Flashlist comparison report. That example is more informative than the claim, because it is the case the tool exists for: two list implementations, measured, compared.

A single aggregate score is only useful if you have something to compare it against. That is why the `test` command runs several iterations, and why a comparison report is the headline artefact rather than one number in a terminal. The natural workflow is to keep the score for the current release as a baseline, run the new build against it, and read the delta.

The topics attached to the repository describe the measurement domain: tracing, profiling, apm, monitoring, performance-testing, performance-optimization, along with android, react-native and flutter. That is a broad list, and the aggregate score is the summary of all of it rather than any single metric.

What the README does not describe is which metrics are aggregated, how they are weighted, or what score is good. A team setting up a gate on this number has to establish its own threshold, and the documentation is where to look for the metric breakdown first.

## The e2e path runs Appium against a real device farm

The package.json scripts show how the automated path actually works, and it is more informative than the README. The test:e2e script runs a binary from packages/plugins/aws-device-farm that takes an APK path, a project name, a report destination path, a test command and a test folder:

```
mkdir -p report && node packages/plugins/aws-device-farm/dist/bin.js runTest --apkPath .github/workflows/example.apk --projectName 'Flashlight-Serverless' --reportDestinationPath report --testCommand 'npx ts-node examples/e2e/appium-ci.test.ts' --testFolder .
```

Three things follow from that line. The device farm is AWS Device Farm, so running on real hardware in the cloud means an AWS dependency. The driver is Appium, invoked through ts-node, so your test script is an Appium test that launches the app and drives it. And the measure happens through a normal E2E test flow, which is why several iterations are needed: one Appium session is one sample.

The examples/ directory has cli/ and e2e/ subdirectories, so both of the two documented usage modes have runnable examples in the repository.

## A monorepo published with lerna, on a version that stopped in 2024

The repository is a Yarn workspaces monorepo with lerna for publishing. The workspaces globs are packages/*/* and examples/*, and the build compiles TypeScript across the workspace before building two specific packages, @perf-profiler/web-reporter and @perf-profiler/measure, with yarn workspace invocations.

Those two package names describe the architecture better than the README does. A measure package does the collection, and a web-reporter package renders the results, which is why the output is an HTML report rather than terminal text.

The version history is the part that needs care. The most recent releases are v0.17.3 on 2024-04-12, v0.17.4 on 2024-04-18 and v0.18.0 on 2024-07-04, and package.json still declares version 0.18.0. The last push to the repository was on 2026-10-05, so the code is being worked on without a release catching up.

For anyone planning a CI integration, that gap is the thing to resolve first. Pinning to a version published in 2024 means installing a CLI that predates the current documentation, and tracking the branch means running unreleased code in CI. The CHANGELOG.md in the repository root is where to see what has changed since v0.18.0.

The licence is MIT, with a LICENSE file, and the dependency maintenance is automated through renovate.json.

## What this is not, and the cases where it is the wrong tool

The first wrong-tool case is iOS, which is stated plainly as in the works rather than available. A cross-platform performance gate needs two tools.

The second is root-cause analysis. Flashlight aggregates metrics into a score, and a score tells you that a build is slower. It does not tell you which function is slow. If your question is why, you need a profiler, and the topics list includes profiling only because the tool collects traces. Use the score as the alarm and a profiler as the investigation.

The third is environments you cannot reach. Measurement happens by installing and driving an app, so a service with no Android client has nothing to measure here, and a build variant that cannot be distributed even internally will not work with the production-app claim.

The fourth is threshold-setting. Nothing in the README says what a good score is or how to set a gate, which means a team adopting this has to run the tool against a known-good build first and derive its own number. Without that step, the score is a curiosity rather than a check.

## Conclusion

Adopt flashlight when your team ships Android and wants a performance regression check in CI that needs no changes to the app, which is the case the no-setup claim is designed for. Do not adopt it as a cross-platform standard while iOS support is an open issue, and do not read its score as a substitute for profiling, since a single number tells you that something regressed rather than why. Verify first which device farm and test harness you will run against, because the e2e path in package.json shows Appium driving a real device rather than a local emulator.

## FAQ

### How do I install the flashlight CLI?

On macOS and Linux run `curl https://get.flashlight.dev | bash`. On Windows run `iwr https://get.flashlight.dev/windows -useb | iex` in PowerShell. Usage details are on docs.flashlight.dev rather than in the README.

### Does flashlight need code changes in my Android app?

No. The README states that no setup is required in your app and that performance can be measured even on production apps, which follows from measuring an existing APK rather than linking an SDK into your build.

### What is the difference between flashlight measure, test and cloud?

`measure` is a quick audit with real-time measures, `test` automates measures with end-to-end performance testing over several iterations, and `cloud` runs the measures on real devices in the cloud and integrates with your CI setup.

### Does flashlight support iOS?

Not yet. The README says iOS support is in the works and links the tracking issue. Coverage today is Android apps, whether native, React Native or Flutter.

### How does flashlight run end-to-end performance tests in CI?

The e2e script in package.json runs an AWS Device Farm plugin with an APK path, project name, report destination and test command, and the test command is an Appium test executed through ts-node, so a CI run launches and drives the app on real hardware.

## Sources

- [bamlab/flashlight on GitHub](https://github.com/bamlab/flashlight)
- [License: MIT](https://github.com/bamlab/flashlight/blob/main/LICENSE)
- [Project website](https://docs.flashlight.dev)
- [README](https://github.com/bamlab/flashlight/blob/main/README.md)
- [Releases](https://github.com/bamlab/flashlight/releases)

---

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