diff --git a/README.md b/README.md
index d0bb866..0bea7c5 100644
--- a/README.md
+++ b/README.md
@@ -1,12 +1,15 @@
-
+
+
+ Native code coverage for React Native
+ A React Native library for iOS and Android that records which lines of your native code your end-to-end tests ran. Use this package to collect coverage, write LCOV, JaCoCo, and TypeScript reports, and fail CI when a report is empty.
-Code coverage for React Native — Typescript, iOS, and Android — without touching the native stuff.
-
+
+
@@ -14,136 +17,36 @@
- Install it into a dedicated test / e2e harness app (Pattern C) — never your shipping app.
-
-
-
- A TurboModule flushes real device coverage; the CLI pulls it, merges every framework's .profraw and the app binary into clean LCOV / Jacoco, and remaps your instrumented JS line-for-line back to TypeScript. Use that as a signal in your development loop or CI to gate development iterations or CI pass/fail.
-
-
-
-
-
-
+ Docs •
+ Contribute
----
-
-## Why this exists
-
-React Native is cross-platform, but your **coverage tooling stops at the JavaScript bundle**.
-
-The Objective-C++, Swift, and Kotlin that make your TurboModules actually work? That code
-runs on a device during your e2e suite and then vanishes without a trace. **iOS native
-coverage in particular is a black box** — LLVM `.profraw` files buried in a simulator
-container, `__llvm_profile` counters that never get flushed, dynamic frameworks that hide
-their own LINKEDIT sections. Nobody wants to hand-wire that.
-
-So teams don't. They ship native modules with a green checkmark that only ever proved the
-JS ran. In an agentic world where a model can rewrite your `.mm` file and swear it's tested,
-**that missing evidence is a real problem.** Coverage is the backpressure. It's how you — or
-your agent — prove the native path executed, not just the mock.
-
-`react-native-coverage` makes that evidence a one-liner: flush from the TurboModule, `rn-coverage pull`
-to merge the scattered native counters and remap your JS back to TypeScript, then `rn-coverage assert`
-to turn "did the native path actually run?" into a pass/fail signal for your dev loop or CI.
-
-No Podfile regex. No profraw archaeology. No Gradle spelunking.
-
----
-
-## Show, don't tell
-
-This repository **proves its own thesis on Codecov, live on `main`** — including the hard part, iOS.
-
-| Flag | What ran | Coverage |
-|------|----------|---------:|
-| [`e2e-ios-dynamic`](https://app.codecov.io/gh/invertase/react-native-coverage) | iOS native, dynamic frameworks (the hard case) | **90.6%** |
-| [`e2e-android`](https://app.codecov.io/gh/invertase/react-native-coverage) | Android native (Emma → Jacoco) | **81.7%** |
-| [`e2e-ios-static`](https://app.codecov.io/gh/invertase/react-native-coverage) | iOS native, static libraries | **63.1%** |
-| [`unit-js`](https://app.codecov.io/gh/invertase/react-native-coverage) | Jest unit (JS/TS) | **52.6%** |
-
-Those numbers come from an actual iOS Simulator and Android emulator running the harness apps
-under Appium — not from a mock. Browse the [`ios/` native directory on Codecov →](https://app.codecov.io/gh/invertase/react-native-coverage/tree/main/ios) yourself.
-
-**The TurboModule itself, line by line** — [`ios/Coverage.mm` on Codecov →](https://app.codecov.io/gh/invertase/react-native-coverage/blob/main/ios/Coverage.mm)
-Real Objective-C++ (`flush()`, `dumpJsCoverage`, `getTurboModule`), green where a device
-executed it, at **71.88%**:
-
-
-
-
-
-### The gap this closes
-
-[**React Native Firebase**](https://github.com/invertase/react-native-firebase) — one of the
-most-installed libraries in the ecosystem — already depends on `react-native-coverage` in its
-dedicated `tests/` app. Its Android native coverage is
-[live on Codecov](https://app.codecov.io/gh/invertase/react-native-firebase) at **65.9%** (the
-`android-native` flag), while the `ios-native` flag still reads **`0.0%`** today. That remaining
-zero — the hardest half — is exactly what this package exists to turn into a number.
-
----
-
-## Used in production by
+JavaScript coverage tools only see the JavaScript bundle. The Objective-C++, Swift, and Kotlin in your TurboModules run on the device during end-to-end tests, but no report records them. Unit tests mock those modules, so they do not record them either. A passing build can therefore ship a native change with no evidence that the change ran, including a change a coding agent wrote.
-
-
-
-
-
-
-
-
-
+> **Important:** Add this package only to a [dedicated test app](https://docs.page/invertase/react-native-coverage/coverage#dedicated-test-app), never to the app you ship. Listing it as a `devDependency` does not keep it out, because autolinking still includes the native module. That test app must run React Native's New Architecture.
-Both [**React Native Firebase**](https://github.com/invertase/react-native-firebase) and
-[**React Native Google Mobile Ads**](https://github.com/invertase/react-native-google-mobile-ads)
-flush real device coverage through the `react-native-coverage` TurboModule from their dedicated
-[Pattern C](https://docs.page/invertase/react-native-coverage/pattern-c) test apps — the same
-pattern this README describes.
+## Install
----
+**Prompt your agent:**
-## Have your agent wire it up
-
-Paste this into your coding agent (Cursor, Claude, Codex, …) **before** you touch Gradle or
-Podfiles by hand:
-
-```text
-Integrate react-native-coverage into this repo's dedicated React Native test /
-e2e harness app only (Pattern C — never the production app package.json).
-
-Constraints:
-- New Architecture / TurboModule only
-- Follow https://docs.page/invertase/react-native-coverage
-- Prefer the Expo config plugin when the harness is Expo; otherwise use the bare
- Gradle + CocoaPods Ruby helpers from the integration docs
-- Wire libraryProjectMatchers / frameworkNamePrefixes for every native library
- we need hits from
-- Add CI steps that pull coverage and fail with rn-coverage assert (exit 2)
- when hits are empty
-- Do not invent product-app install paths; keep the package out of the shipping app
-
-After install: yarn/npm add react-native-coverage in the harness, apply the plugin or
-manual hooks, prebuild / pod install as needed, then show me the exact CI commands
-to run and what green looks like.
+```txt
+Read https://docs.page/invertase/react-native-coverage/app-developers.md, and set up react-native-coverage in this project.
```
----
-
-## Install
+**Or set it up yourself** in three steps.
-Install in the **harness** (your dedicated test/e2e app), never the product app:
+### 1. Add the package to the test app
```sh
yarn add react-native-coverage
# or: npm install react-native-coverage
```
-### Expo (recommended)
+### 2. Turn coverage on in the test app's build
-Add the config plugin, then prebuild:
+Follow the path that matches the test app.
+
+**If the test app uses Expo:** add the config plugin to its `app.json` file, then generate the native projects.
```json
{
@@ -167,19 +70,11 @@ Add the config plugin, then prebuild:
npx expo prebuild
```
-### Bare React Native
-
-Apply the shipped `android/rn-coverage*.gradle` helpers and the
-`cocoapods/coverage_post_install.rb` Ruby helper as documented in
-[Android](https://docs.page/invertase/react-native-coverage/integration/android) and
-[iOS](https://docs.page/invertase/react-native-coverage/integration/ios). Copy
-`react-native-coverage.config.js.example` if you need host-specific paths.
+**If the test app does not use Expo:** apply the shipped `android/rn-coverage*.gradle` helpers and the `cocoapods/coverage_post_install.rb` helper. Use the [Android](https://docs.page/invertase/react-native-coverage/integration/android) and [iOS](https://docs.page/invertase/react-native-coverage/integration/ios) pages for where each file goes. Copy `react-native-coverage.config.js.example` if your paths differ from the defaults.
----
-
-## Prove it in CI
+### 3. Flush, pull, report, and assert
-Run your e2e suite, call `Coverage.flush()` at teardown, then:
+After your tests, call `Coverage.flush()` once, then build the reports:
```sh
# Android
@@ -188,80 +83,80 @@ rn-coverage android pull && rn-coverage android report
# iOS
rn-coverage ios pull && rn-coverage ios export && rn-coverage ios report
-# The point: empty hits must fail the job
-rn-coverage assert # exit 2 when coverage is empty
+rn-coverage assert
```
-`rn-coverage assert` is the package-owned replacement for one-off "did anything get covered?"
-shell scripts. Wire it into CI and a sabotaged or silently-broken pipeline fails loudly.
-Full CLI surface: [docs → CLI](https://docs.page/invertase/react-native-coverage/cli).
+`rn-coverage assert` exits 2 when a report is missing or empty, which fails the job.
----
+Use the [App developers](https://docs.page/invertase/react-native-coverage/app-developers) guide for both setups in full, and the [CLI](https://docs.page/invertase/react-native-coverage/reference/cli) page for every other command.
-## What you get
+## How coverage works
-| Piece | Role |
-|-------|------|
-| **TurboModule** | `flush()` — iOS LINKEDIT LLVM flush + Android Emma dump from the running app (also dumps Istanbul `global.__coverage__` when present) |
-| **CLI (`rn-coverage`)** | `android pull\|report`, `ios pull\|export\|report\|summary`, `js pull\|report`, `assert` |
-| **Expo config plugin** | Wires the Gradle helpers + the Podfile helper call (safe split) |
-| **CocoaPods Ruby helper** | Pod LLVM flags + optional dynamic-framework restore |
-| **Gradle Jacoco helpers** | `android/rn-coverage.gradle` + `android/rn-coverage-jacoco.gradle` |
-| **JS/TS coverage** | `babel-plugin-istanbul` + NYC source-map remap → TypeScript-accurate LCOV |
+Build the test app with coverage turned on, using the Expo config plugin or the Gradle and CocoaPods helpers. When the tests finish, call `Coverage.flush()` to write coverage out of the running app. Then use `rn-coverage` to build the reports and fail the job when a report is empty.
----
+| Feature | What it does |
+|---------|--------------|
+| **Expo config plugin**, or the Gradle and CocoaPods helpers | Turns native coverage on when the test app is built |
+| **TurboModule** | `flush()` writes the iOS LLVM counters and the Android Emma dump, plus Istanbul `global.__coverage__` when that data is present |
+| **CLI** (`rn-coverage`) | `pull` and `report` build the LCOV and JaCoCo files. `assert` exits 2 when those files are missing or empty |
+| **JavaScript and TypeScript coverage** | `babel-plugin-istanbul` and NYC map the instrumented bundle back to the TypeScript you edit |
-## Documentation
+## Coverage results
-Full docs live at **[docs.page/invertase/react-native-coverage](https://docs.page/invertase/react-native-coverage)**:
+This repository runs the same setup on every pull request, with its example apps on an iOS Simulator and an Android emulator under Appium. Find the reports on [Codecov](https://app.codecov.io/gh/invertase/react-native-coverage).
-- [Why native coverage](https://docs.page/invertase/react-native-coverage/why) — the problem, in full
-- [Pattern C](https://docs.page/invertase/react-native-coverage/pattern-c) — dedicated test apps only
-- **App developers:** [Expo & RN CLI integration](https://docs.page/invertase/react-native-coverage/app-developers)
-- **Library maintainers:** [unit tests + test app](https://docs.page/invertase/react-native-coverage/library-maintainers)
-- **Agents:** [quick-wire guide](https://docs.page/invertase/react-native-coverage/agents)
-- Reference: [CLI](https://docs.page/invertase/react-native-coverage/cli) · [Config](https://docs.page/invertase/react-native-coverage/config)
+
+
+
+
+
----
+Each flag is one run of the example apps:
-## Example / CI cells
+| Flag | Example app | What ran | Coverage |
+|------|-------------|----------|---------:|
+| `e2e-ios-dynamic` | `example-dynamic/` | iOS native, dynamic frameworks | 90.6% |
+| `e2e-ios-static` | `example/` | iOS native, static libraries | 63.1% |
+| `e2e-android` | `example/` | Android native (Emma to JaCoCo) | 81.7% |
+| `unit-js` | This repository | Jest unit tests, JavaScript and TypeScript | 52.6% |
-This repo's `example/` (Expo) and `example-dynamic/` (bare RN, dynamic frameworks) are the
-harness. **Appium** (WebDriverIO) drives them on every PR:
+The package also measures its own native code. Its iOS source file, [`ios/Coverage.mm`](https://app.codecov.io/gh/invertase/react-native-coverage/blob/main/ios/Coverage.mm), has 71.88% line coverage. The screenshot shows which of its lines ran. Use the [Contributing guide](./CONTRIBUTING.md) to run the example apps locally.
-| Cell | Path | Proves |
-|------|------|--------|
-| iOS **dynamic** (primary) | `example-dynamic/` | Non-zero LCOV with a real dynamic `CoverageFixture.framework` |
-| iOS **static** | `example/` | Expo staticlib merge; fixture hits still asserted |
-| Android | `example/` | Emma `.ec` → Jacoco → assert |
+
+
+
-```sh
-yarn
-yarn prepare
-yarn test # or: yarn test:coverage
-yarn e2e:ios:dynamic
-yarn e2e:ios:static
-yarn e2e:android
-node bin/rn-coverage.js --help
-```
+## Used in production
----
+-
[invertase/react-native-firebase](https://github.com/invertase/react-native-firebase)
+-
[invertase/react-native-google-mobile-ads](https://github.com/invertase/react-native-google-mobile-ads)
+
+## More information
-## Releasing
+- [Coverage](https://docs.page/invertase/react-native-coverage/coverage) — what it measures and how the pipeline works
+- Install guides for [app developers](https://docs.page/invertase/react-native-coverage/app-developers), [library maintainers](https://docs.page/invertase/react-native-coverage/library-maintainers), and [coding agents](https://docs.page/invertase/react-native-coverage/agents)
+- [CLI](https://docs.page/invertase/react-native-coverage/reference/cli) and [Configuration](https://docs.page/invertase/react-native-coverage/reference/config)
+- [Empty or missing coverage](https://docs.page/invertase/react-native-coverage/troubleshooting/empty-coverage)
-Conventional Commits + semantic-release, **manual `workflow_dispatch` only** (no
-push-to-main publish). Operator steps:
-[docs → Releasing](https://docs.page/invertase/react-native-coverage/releasing).
+## Contributing
+
+- Questions: [Discord](https://invertase.link/discord)
+- Bugs & feature requests: [Open an issue](https://github.com/invertase/react-native-coverage/issues/new/choose)
+- [Pull requests](https://github.com/invertase/react-native-coverage/pulls)
+- [Contributing guide](./CONTRIBUTING.md)
+- [Releasing](https://docs.page/invertase/react-native-coverage/releasing)
+- [Code of Conduct](https://github.com/invertase/.github/blob/main/CODE_OF_CONDUCT.md)
## License
Apache-2.0 — see [LICENSE](./LICENSE).
+---
+
-
-
-
+
+
-
- Built and maintained by Invertase.
+
+ Built and maintained by Invertase.