# pipe Static state-flow analysis for Dart and Flutter apps. `pipe` maps how state moves through an app's state management and reports the breakages that make it behave worse than the code suggests: a spinner that never stops, an error the user never sees, a tap that does nothing. It is built to guide agents and reviewers on large codebases, not to score style. Every finding carries `file:line` evidence, a confidence, a severity and a remediation, and every report states how much of the project it covered. ## Coverage | State management | Support | | --- | --- | | BLoC / Cubit (`on`, `emit`, sealed, abstract, enum or freezed unions) | yes | | Single state class with a `bool loading`-style flag (`copyWith`) | yes | | Riverpod (`FutureProvider`, `StreamProvider`, `NotifierProvider`, `.family`, ...) | yes | | `provider` + `ChangeNotifier` | yes, with [limits](docs/rules.md#provider-and-changenotifier) | | C++ `enum class` state (experimental, via libclang) | [see design](docs/design.md#c-front-end-experimental) | | Firestore query inventory (`pipe queries`, no rules) | [see queries](docs/queries.md) | | Navigation, layout, theming | no | ## Quick start ```bash dart pub get tool/build_release.sh # prints the binary's path under build/ # below, `pipe` is that binary on your PATH (or `dart run bin/pipe.dart`) pipe index # can the project be analysed? pipe check # ranked findings pipe suggest # what to fix first, per file pipe guide --format agent # a brief to paste into an agent prompt pipe queries # every Firestore query, as typed records ``` In CI, accept today's findings once and fail only on new ones: ```bash pipe check . --write-baseline .pipe-baseline.json pipe check . --baseline .pipe-baseline.json --fail-on warning pipe verify . --expect-resolved # after a fix; reads .pipe-baseline.json ``` ## Rules | Rule | Meaning | | --- | --- | | `emitted-not-rendered` | A state is emitted but no UI code matches it, so the user never sees it. | | `rendered-not-emitted` | A UI branch no emitted state can reach: dead UI. | | `loading-not-reset` | An in-progress state whose failure path never resolves, so the spinner sticks. | | `loading-flag-not-reset` | The same, for a `bool loading` flag left set after an error. | | `event-without-handler` | A dispatched event with no `on`, so the interaction does nothing. | | `dead-handler` | An `on` that nothing dispatches or constructs. | | `riverpod-async-gap` | An async provider read in the UI whose error or loading state is never handled. | | `notifier-never-notifies` | A `ChangeNotifier` method changes observable state without notifying. | | `notifier-inert-consumer` | A consumed notifier that never notifies, so its consumers never rebuild. | | `provider-read-in-build` | A `Listenable` read without subscribing inside `build`, so it can render stale. | | `notifier-field-unread` | A public member of a consumed notifier that nothing reads. | | `provider-created-in-build` | A provider constructed in `build`, so its state is recreated on rebuild. | Measured precision, recall and the limits of each rule are in [docs/rules.md](docs/rules.md). ## Documentation - [Usage](docs/usage.md): commands, flags, SDK discovery, CI ratcheting, verification, fix order, agent briefs. - [Rules](docs/rules.md): what each rule claims, the evidence behind it, and how precision and recall are measured. - [Firestore queries](docs/queries.md): the query inventory, its schema and adapter config. - [Design](docs/design.md): why pipe exists, how it is built, the state-model seam, and the experimental C++ front end. - [Development](docs/development.md): building, performance, tests and hooks.