Bryony: State Flow for Flutter
See how state flows through your Flutter app. Bryony draws your Riverpod providers, Blocs and Cubits, Provider models, GetX controllers and MobX stores, plus the widgets that use them, as one interactive graph inside VS Code. Start a debug session and the graph comes alive: nodes pulse as they rebuild and show their current value.
Why
In a large Flutter app it's hard to answer simple questions: What does this provider depend on? Who rebuilds when it changes? Which events produce which states? Why is this provider never disposed? Bryony answers them in the editor, with no code changes and no separate DevTools window.
Features
- One graph for Riverpod and Bloc. Manual providers (
Provider, StateProvider, FutureProvider, StreamProvider, NotifierProvider, AsyncNotifierProvider, StateNotifierProvider, ChangeNotifierProvider, with .autoDispose and .family), @riverpod functions and classes, Bloc, Cubit, HydratedBloc, events, states and widgets (ConsumerWidget, ConsumerState, BlocBuilder, BlocListener, context.read/watch/select).
- Provider, GetX and MobX too.
- Provider:
ChangeNotifierProvider, ListenableProvider, Provider, FutureProvider, StreamProvider, ProxyProvider and ChangeNotifierProxyProvider (including MultiProvider and .value), consumed through context.watch/read/select, Provider.of, Consumer and Selector. Each model lists the methods that call notifyListeners().
- GetX:
GetxController, GetxService and their subclasses, registered with Get.put, Get.lazyPut, Get.putAsync or bindings, used through Get.find, GetView, GetBuilder and GetX. Each controller lists its .obs/Rx fields and its workers (ever, once, debounce, interval).
- MobX: stores declared with
mixin Store (codegen class X = _X with _$X included) with their @observable, @computed and @action members, store-to-store dependencies and the widgets that use them.
- Trace anything. Click a node to light up everything upstream and downstream. Double-click to jump to the code. Search with
/, filter with chips, fit with F.
- Bloc event → state map. Each Bloc shows its handlers and which states each event emits, including handlers written as method references.
- Findings that matter, on the graph and in the Problems panel:
- dependency cycles (they throw at runtime),
- Bloc events that are never handled,
- states that are declared but never emitted,
.family providers that are never disposed (a common memory leak),
ref.read while building (it won't update),
- providers, models, controllers and stores nothing reads,
- widgets that read a Provider model nobody provides (
ProviderNotFoundException at runtime),
- models created inside
ChangeNotifierProvider.value(...) (recreated on every rebuild),
Get.find / GetView on a controller nothing registers,
- widgets that use a MobX store without an
Observer (they won't rebuild).
- Live mode. One command writes a small observer (
lib/bryony_observer.dart) for Riverpod 2, Riverpod 3, Bloc, GetX (controller created, initialised and deleted) and MobX (every observable change and action), and offers to register it in main.dart. Provider has no global hook, so Provider models appear in the graph and findings but not in live mode. While debugging, nodes pulse, show update counts, the latest value and a timeline. It prints nothing in profile or release builds.
- CodeLens above each provider, Bloc, model, controller and store: "depends on 2 · used by 5".
- Sidebar and status bar with counts and findings.
- Copy as Mermaid to paste the graph into a README, PR or wiki.
- Demo graph and a 4-step walkthrough so you can try it in a minute.
- Material 3 design that follows your VS Code light, dark or high-contrast theme.
Getting started
- Install the
.vsix: in VS Code open the Extensions view, click … → Install from VSIX…, pick bryony-1.0.1.vsix. Or run code --install-extension bryony-1.0.1.vsix.
- Open a Flutter project. A short tour opens the first time you open the graph. Replay it any time with the graduation-cap button or Bryony: Get Started.
- Press
Ctrl+Alt+G (Cmd+Alt+G on macOS) in any Dart file, or click the leaf icon in the Activity Bar.
- For live mode run Bryony: Set Up Live Mode, then start debugging.
No state management code handy? Run Bryony: Open Demo Graph.
Live mode details
The observer prints one compact JSON line per change, prefixed with [bryony], which Bryony reads from the Dart debug session. Values are cut to 300 characters. Riverpod reports a provider by its name, so providers created without name: show up as their type (for example StateProvider<int>). Run Bryony: Name Providers for Live Mode to add name: 'xProvider' to them in one undoable edit. Generated (@riverpod) providers are already named. Bloc, Cubit and GetX controllers are matched by class name. MobX events are matched by store name (_TodoStore.todos belongs to TodoStore).
Commands
| Command |
What it does |
| Bryony: Open State Flow Graph |
Opens the graph (Ctrl/Cmd+Alt+G) |
| Bryony: Show in State Flow Graph |
Focuses the provider or Bloc under the cursor (Ctrl/Cmd+Alt+Shift+G) |
| Bryony: Set Up Live Mode |
Adds the observer and wires it into main.dart |
| Bryony: Name Providers for Live Mode |
Adds name: to unnamed manual providers |
| Bryony: Copy Graph as Mermaid |
Copies the graph as a Mermaid flowchart |
| Bryony: Open Demo Graph |
Explore a sample app with simulated live events |
| Bryony: Re-scan Workspace |
Forces a full re-scan |
| Bryony: Get Started |
Opens the walkthrough |
Settings
| Setting |
Default |
|
bryony.codeLens.enabled |
true |
Dependency counts above providers, Blocs, models, controllers and stores |
bryony.diagnostics.enabled |
true |
Findings in the Problems panel |
bryony.diagnostics.showHints |
true |
Include informational findings |
bryony.scanOnType |
true |
Update while typing, not only on save |
bryony.live.openOnDebug |
false |
Open the graph when a Flutter debug session starts |
bryony.editorTitleButton |
true |
Graph button in the editor title bar for Dart files |
bryony.exclude |
[] |
Extra globs to skip, e.g. "**/test/**" |
bryony.maxFiles |
4000 |
Upper bound on scanned Dart files |
macOS and Windows
Bryony is pure TypeScript on the VS Code API. It needs no Dart SDK to draw the graph, uses vscode.Uri for every path, and reads live events from the debug adapter, so it behaves the same on macOS, Windows and Linux, in local, Remote-SSH, WSL and Dev Container setups.
Limits
Bryony uses a fast, tolerant scanner rather than the Dart analyzer, so very unusual code shapes (providers built by helper functions, Blocs created through factories in other packages) may be missed. Generated files (*.g.dart, *.freezed.dart) are skipped on purpose.
License
Proprietary. Copyright (c) 2026 Sanket Santosh Vidya Manohar. All rights reserved. Free to install and use; copying, modifying, redistributing or repackaging is not allowed. The full terms are in the LICENSE file included with the extension.
Support
Found a bug or have an idea? Open an issue at https://github.com/sanket-manohar/bryony/issues.
Flutter, Dart, Riverpod, Bloc, Provider, GetX and MobX are trademarks of their respective owners. Bryony is an independent tool and is not affiliated with or endorsed by them.
| |