flutter_inspector_kit 2.5.0
flutter_inspector_kit: ^2.5.0 copied to clipboard
A multi-inspector tool integration for Flutter, bundling debugging and inspection utilities behind a single unified API.
2.5.0 #
Added #
- Hand a runtime observation to a coding agent: Log and network detail views gain a Copy prompt for AI agent action that turns the entry you are looking at into a Markdown prompt ready to paste into a coding agent. The prompt carries the event's own facts, its stack trace where one exists, and — the part that is tedious to assemble by hand — what else happened earlier on the same route. The walk backwards is bounded by the route the user was actually on, stopping at the point they entered it, rather than by a fixed time window: a page open for four seconds and one open for four minutes both yield exactly the events that belong to that visit. It opens by stating that this is an execution-time observation and not a diagnosis, and marks the captured data as untrusted, because response bodies and log messages can carry text shaped like instructions. It deliberately suggests no cause — the package has runtime facts but not your codebase, and a confidently wrong cause costs more than none.
maxTraceBackEntries(default 50) caps the walk as a fuse for long-lived pages, and when it or the end of the buffer is reached the prompt says so, so a partial history is never read as a complete one. - Network and database entries record the active route:
NetworkEntryandDatabaseEntryjoinLogEntryin carrying anactiveRoute, so every timeline entry can be attributed to the page the user was on. A request's anchor is captured when it is sent and never overwritten when it completes: the question it answers is who issued the call, and stamping the route the user had navigated to by the time the response arrived would point at an innocent page.NavigatorEntry.routeLabelis now the single source of that label's format, so an entry's anchor and a navigation event always spell the same route the same way. - Crash notifications:
FlutterInspector(showCrashNotification: true)posts a system notification when an uncaught error is captured, so a crash in a backgrounded app is noticed when it happens instead of on the next trip to the dashboard. It uses its own notification id and channel, so it never overwrites the network summary and can be silenced separately, and it is dismissible rather than ongoing. RequirescaptureUncaughtErrors: true— installing global error handlers stays your decision — and, like the network notification, is native-only. - Memory pressure lands on the timeline: When
captureLifecycleEventsis enabled, an OS memory-pressure warning is now recorded as awarning-level Console entry (Memory pressure · CheckoutPage). It is the only OOM/LMK precursor Dart can observe — the real RSS figure needs a platform channel — and as a timestamped event it interleaves with the network, navigation and database entries that came before it, so "the app just disappeared" becomes "pressure began right after that 8 MB image decode". It reuses the existing lifecycle flag rather than adding its own, because both are callbacks on a singleWidgetsBindingObserversharing one attach/detach lifecycle. Android reports it viaonTrimMemory, iOS viadidReceiveMemoryWarning; Web effectively never fires it.
2.4.0 #
Added #
- Stack traces are normalized before you read them: A Flutter stack trace is mostly framework plumbing — dozens of consecutive
package:flutter/…anddart:…frames burying the two lines of your own code that actually matter. Log detail views now show a concise stack trace by default, collapsing each run of framework-internal frames into a single[... N frames of framework internals]marker. The first and last frame of every collapsed run are deliberately kept, so the boundary between your code and the framework — the part that tells you where control crossed over — is never lost. - Asynchronous gaps are marked explicitly:
<asynchronous suspension>separators are rendered as<-- async gap -->, so a stack trace broken across anawaitreads as one causal chain instead of two unrelated fragments. - Raw / concise toggle, and explicit exports: The log detail view carries a Show raw / Show concise switch, and its share menu offers four explicit actions — Copy concise, Copy raw, Share concise and Share raw. Each exports the form named by the menu item, independently of which form is currently on screen, so a trace can be copied raw for an issue tracker while reading the concise one.
buildLogPlainTextdefaults to the concise form and acceptsisConcise: falsefor the untouched original. The raw stack trace is never mutated; normalization is purely a presentation-layer projection. - Log entries record the active route:
LogEntrygains anactiveRoutefield, populated automatically with the top-most page at the moment the log was recorded, and shown in log detail views and plain-text exports. Where a log fired is often the missing half of why it fired — an error logged fromCheckoutPageand the same error logged from a background refresh are different bugs. normalizeStackTrace,buildLogPlainTextand the entry types are now exported:FlutterInspectoralready returnedList<LogEntry>fromlogEntriesandList<TimestampedEntry>frommergedTimeline(), but neither type — nor the log formatters — was reachable throughpackage:flutter_inspector_kit/flutter_inspector_kit.dart, so code consuming those results could not name what it received. All three are now exported from the package entry point.
Fixed #
- The Console
Errorlevel chip no longer overlaps⚡ Errors only: Both filters existed and claimed to isolate failures, but only⚡ Errors onlyspanned every source — theErrorlevel chip silently constrained logs alone, so picking it hid failed network calls that the other chip kept. The redundant level chip is gone, leaving one unambiguous failure filter.
2.3.0 #
Added #
- Storage tab — browse and edit key-value stores: A new dashboard tab lists the contents of
SharedPreferences,FlutterSecureStorageand friends, with a search field over keys and values and a selector to switch between registered stores. Entries can be edited, deleted individually, or wiped in bulk, so a stale token or a stuck feature flag can be cleared on-device instead of through anadb shellor a reinstall. The tab only appears once at least one source is registered. KeyValueBrowserSource— pluggable storage adapters: Register stores throughFlutterInspector(keyValueSources: [...])orregisterKeyValueSource(...), mirroring howDatabaseBrowserSourcealready works. The package ships no implementation and takes no dependency on any storage plugin — the README carries copy-paste adapter examples forSharedPreferencesandFlutterSecureStorage, and each adapter takes an optionalnameso two stores of the same kind stay distinguishable in the selector. When a source cannot enumerate its keys (readAll()is unsupported on some platforms for secure storage), the tab surfaces a retryable error rather than an empty list, so "cannot enumerate" is never mistaken for "nothing stored".- Confirmation before every write: Edits, deletes and clear-all each require an explicit confirmation. Editing runs a type-validation step first, so a mistyped value is rejected before the confirmation dialog appears rather than after it. Clear-all names the source and the entry count it is about to wipe, and is disabled while a store is still loading — so a destructive action can never be authorised against another source's data.
- Writes are logged to the Console timeline: A successful write is recorded as an
infolog carrying the key, source and type, so a change made while debugging does not become a mystery later. Cancelled and failed writes leave no log — the audit trail only ever claims what actually landed. Old and new values are masked unless the host setsredactSensitiveData: false, since the log is shareable and a key-value source may hold secrets.
2.2.0 #
Added #
- Console search and level filtering: The Console tab now carries a search field above the timeline, matching a case-insensitive keyword against each entry's readable fields — log messages and stack traces, network URLs/methods/status codes, route names, and database tables and operations. A per-
LogLevelchip row (Verbose,Debug,Info,Warning,Error) narrows logs further, and an⚡ Errors onlychip isolates failures across types:warning/errorlogs together with failed network calls. Level chips only constrain log entries, so picking one does not silently hide network, navigation, or database events. - Jump back to the full timeline: While a filter is active, tapping any row clears every filter and scrolls the unfiltered timeline to that same entry — so a row found by searching can be read back in its surrounding context instead of in isolation.
Fixed #
- Long-press bookmarking now survives filtering: Bookmarking a row by long-press stopped working once a search or level filter was applied. Filtered rows accept long-press again, alongside the new tap-to-jump gesture.
- Search field text is cleared on jump-back: Jumping from a filtered row back to the full timeline reset the filter but left the typed keyword visible in the search field, so the UI showed an active search over unfiltered results.
2.1.0 #
Added #
- Dashboard error badges: The Console and Network tabs now show a badge with the current error count, so problems are visible without opening each tab. Badges update live as new entries arrive.
Fixed #
navigatorKeyis now declaredrequired, matching the behaviour that 2.0.0 already introduced. The parameter has been mandatory since the dashboard started routing through it, but the constructor still accepted its omission — so the failure surfaced as a dashboard that silently would not open, rather than as an error. It is now caught at compile time. Code that already passes anavigatorKeyis unaffected.- Reported package version:
FlutterInspector.versionand the header of every exported diagnostic report reported1.9.0on the 2.0.0 release. The version constant is now in sync with the published package version.
Docs #
navigatorKeywiring is now shown in both READMEs' Initialize example — previously neither did, so following them produced an inspector whose dashboard could not open. Both now also note that passing the same key toMaterialAppis required and not compiler-checkable.- The Traditional Chinese README additionally had a stale
openDashboard(context)call (an API removed in 2.0.0) and an outdated install version — both corrected. - The 2.0.0 entry below has been expanded: it described the
openDashboardsignature change but not the resultingnavigatorKeyrequirement.
2.0.0 #
BREAKING CHANGES #
-
openDashboard()no longer takes aBuildContext, andnavigatorKeybecame mandatory as a result. The dashboard now resolves its context fromnavigatorKeyinstead of receiving one at the call site, so an inspector constructed without that key cannot open the dashboard at all — magical tap, floating button, and notification tap each become a silent no-op.The constructor still accepted its omission in this release, so the requirement was enforced only at runtime, without an error explaining the failure. It is declared
requiredfrom 2.1.0 onward.Migration — pass a key to the inspector, and the same key to your
MaterialApp:final navigatorKey = GlobalKey<NavigatorState>(); final inspector = FlutterInspector(navigatorKey: navigatorKey); MaterialApp(navigatorKey: navigatorKey, /* ... */);Also drop the argument at every call site:
openDashboard(context)→openDashboard().This entry was expanded in 2.1.0. It originally read only "Removed the
BuildContextparameter … as it is no longer required for opening the inspector", which described the signature change but omitted that the context requirement had moved tonavigatorKeyrather than disappeared.
Added #
- Timeline Bookmark: Long-press any timeline entry in the Console tab to bookmark it. A push-pin indicator is displayed, and a new "Bookmarks" filter chip allows isolating bookmarked entries. Diagnostic reports now prefix bookmarked entries with a 📌 icon.
1.9.0 #
Added #
- Slow network request indicator: Network requests exceeding a configurable time threshold are now visually marked with a
🐢 SLOWindicator in the Network tab to easily spot performance bottlenecks. - Configurable slow request threshold: The threshold for marking a request as slow can now be configured via the
slowRequestThresholdparameter on theFlutterInspectorconstructor (defaults to 2 seconds).
Fixed #
- Constructor validation:
FlutterInspectornow rejects negativeslowRequestThresholdvalues.
1.8.0 #
Added #
- App lifecycle markers:
FlutterInspector(captureLifecycleEvents: true)records every app lifecycle transition (resumed/inactive/paused/detached, plushiddenon Flutter 3.13+) as aninfoConsole log, so crashes and stalled network calls can be read against whether the app was in the foreground. Each entry names the current top-most page (e.g.App lifecycle: resumed · HomePage (/home)) so repeated home/back switches stay distinguishable without cross-referencing the Navigator tab. Opt-in and disabled by default;detach()removes the observer.
Changed #
- Error rows are tinted in the merged Timeline: error-level logs and failed network calls now carry a faint red row background in the Console tab, so they're spottable while scrolling instead of relying on text colour alone. Warnings keep their orange text but stay un-tinted, so a warning-heavy app doesn't wash the whole list out.
Fixed #
- Inspector routes no longer pollute the Navigator tab: opening a detail view or bottom sheet inside the dashboard (log/network details, table rows, cell details, the export sheet) was recorded as navigation in the host app's history, so the more thoroughly you investigated, the noisier the Navigator tab became — the export sheet even wrote itself into the report it was about to produce. Every route the dashboard opens is now tagged with a shared prefix that the observer filters on. Host app navigation is untouched, including unnamed routes.
1.7.1 #
Fixed #
- Duplicate uncaught error logs:
FlutterError.onErrorandErrorWidget.builderpreviously logged the same build-crashFlutterErrorDetailstwice; an object-identity guard now dedupes them while still logging each distinct crash.
1.7.0 #
Added #
- WebView inline debugging: introduced
WebViewBridgeAdapterand injected JS bridge payload to seamlessly capture and translate a WebView'sconsole.*,window.onerror,fetch, andXMLHttpRequestactivity into the native Console and Network tabs. - First-class provenance metadata: network and log entries now include
origin(e.g.,NetworkOrigin.webviewvsNetworkOrigin.dio) andpageUrlfields, clearly distinguishing native HTTP traffic from WebView traffic in the detail views.
Fixed #
- WebView bridge reliability: capped raw bridge message size before JSON decoding to prevent memory spikes, and properly guarded
XHRresponse text reads for non-text response types.
1.6.0 #
Changed #
- Diagnostic report Timeline: the exported report's separate "Logs" section is now a chronological mixed Timeline that interleaves log, network, navigation, and database entries by timestamp (newest first), surfacing cross-layer causality at a glance. The independent Network / Navigation / Database detail sections remain below it.
- "Errors & warnings only" now filters the whole Timeline: previously the toggle restricted only the log section; it now keeps error-signal entries across the entire Timeline stream (logs plus failed/errored network calls), while the detail sections are unaffected.
Fixed #
- Timeline one-liner hardening: report one-liners are now guarded against CRLF injection and malformed-URL leaks.
1.5.0 #
Added #
- One-tap diagnostic report: the dashboard app bar now has an export action that builds a single Markdown report — device/app header, current route stack, and the log / network / navigation / database sections — and hands it to the system share sheet. Three independent filters: time window (last 5m / last 1h / all), which sources to include, and an optional "errors & warnings only" toggle for the log section (off by default). Nothing is written to disk.
DiagnosticInfoSource: optional injection point for device and app metadata (FlutterInspector(diagnosticInfoSource: ...)). This package stays free of any device-info plugin — hosts supply the values themselves, and the report header degrades toN/Awhen no source is registered. Follows the same host-injection shape asDatabaseBrowserSource.
1.4.0 #
Added #
- Network error aggregation summary: the Network tab now shows a collapsible banner above the call list that groups failed/errored requests by status code (falling back to error type for transport failures where
statusCodeisnull), with a per-group count and first/last-seen time range. Tapping a group card filters the call list down to just that error; tapping again clears the filter. The banner aggregates from the same keyword/method/status-filtered list shown below it, so counts always match what's visible.
Fixed #
- Scrollable TabBar alignment on Material 3: the dashboard's tab bar now sets
tabAlignment: TabAlignment.start, fixing tabs rendering centered/misaligned in scrollable mode under Material 3.
1.3.1 #
Changed #
- Code quality & performance optimization: Refactored major dashboard tabs (Console, Network, Navigator, Database) to eliminate large helper methods and decompose them into lightweight, specialized, and reusable private Widget classes, improving rendering efficiency.
- UI widgets consolidation: Extracted shared
DetailSection(withDetailKeyValueRow) andErrorCardwidgets to eliminate cross-file duplicate code. - Centralized log level colors: Moved log level color mapping from ConsoleTab's helper methods into a unified
LogLevelColorextension.
1.3.0 #
Added #
- Structured DioException error capture:
FlutterInspectorDioInterceptor.onErrornow preserves the machine-readableerrorType(DioExceptionType) and theerrorStackTrace(stringified stack trace) instead of discarding them. - Exception Details section: the Network detail view now displays an "Exception Details" card section for failed requests. It clearly distinguishes between transport-layer failures (where the request did not reach the server, showing
statusCode == null) and server-side responses (where the server returned an error status code). It also provides a monospace-styled, copyable stack trace for debugging. - Text export support:
buildPlainTextexports now include theError Typeand theStack Tracewhen present, improving the diagnostic value of shared logs.
1.2.1 #
Fixed #
- Console tab clear button: clearing the Console tab's merged timeline now wipes all four underlying sources (log, network, navigator, database) instead of only logs. Previously, network/navigator/database entries would reappear after clearing because they share the same buffers rendered in the Console tab's merged timeline.
1.2.0 #
Added #
- Navigator active route stack visualization: the Navigator tab now offers an "Active Stack" / "Event History" toggle. Active Stack derives the current route stack live from the recorded push/pop/replace/remove events and renders it top-first as vertical cards, with the current screen highlighted; Event History remains the original raw event log, unchanged.
1.1.0 #
Added #
- Merged cross-layer timeline: the Console tab now interleaves logs, network, navigation, and database events on a single timestamp-sorted timeline (newest first), with a filter chip per source to narrow it down. The same view is exposed programmatically via
FlutterInspector.mergedTimeline({sources}), which returnsList<TimestampedEntry>sorted bytimestampdescending. Filter with the newTimelineSourceenum (log/network/nav/db); a shareddisplayTime(HH:mm:ss.mmm) helper is available on every timeline entry. - Sensitive-data redaction: a new
redactSensitiveDataconstructor flag onFlutterInspector(defaults totrue) masks sensitive headers —Authorization,Cookie,Set-Cookie,X-Api-Key(matched case-insensitively) — with••••across every Network share/export path (copy as cURL, copy as text, system share sheet). Secure by default; passredactSensitiveData: falseto opt out. Headers shown live inside the dashboard are unaffected.
Changed #
- The Console timeline is now assembled by merging the four event buffers at render time instead of mirroring network and navigation events into the Console as separate log strings. As a result,
FlutterInspectorDioInterceptorno longer emits an extradebug-level Console log per request, andFlutterInspectorNavigatorObserverno longer mirrors route changes aswarning-level logs (both introduced in 0.2.4) — those events still appear on the merged timeline via their own buffers, without the duplicate log entries.
1.0.0 #
Added #
- Network Request Replay: You can now resend captured HTTP requests directly within the Network detail view. It replays the request locally using the same Dio client (carrying the same headers, base URL, and interceptors). Replayed requests automatically show up as new entries in the Network tab, marked with a dedicated "Replay" label.
Changed #
- Breaking Change:
FlutterInspectorconstructor no longer takes adioparameter, and does not provide a default fallback Dio. To use the Network Request Replay feature, you must explicitly pass the sourceDioinstance when creatingFlutterInspectorDioInterceptor. - Dio Interceptor Signature:
FlutterInspectorDioInterceptornow takes an optional namedsourceDioparameter (FlutterInspectorDioInterceptor(inspector, {sourceDio: dio})). Without passing thesourceDio, the "Resend" action in the Network detail view will be disabled.
0.3.1 #
Documentation #
- Refreshed the README screenshots: re-captured the database browser view and added Uncaught Error and Database Browse captures sourced from the example app.
- Removed the legacy Database (operation-log) screenshot in favor of the Database Browse capture, and re-flowed the Screenshots grid to a clean 3-column layout.
0.3.0 #
Added #
- Uncaught error capture (opt-in): pass
captureUncaughtErrors: truetoFlutterInspector(...)to capture uncaught errors fromFlutterError.onError,PlatformDispatcher.instance.onError(including unawaitedFutureerrors) andErrorWidget.builderasLogLevel.errorlogs in the Console tab. Defaults to off; when on, every hook chains/wraps the existing host handler — errors are always forwarded downstream, never swallowed. - Expandable Console error logs: tapping a Console log that carries a
stackTraceor structureddatanow opens a detail view (LogDetailView) showing the message, level, timestamp, a selectable/copyable stack trace, and the structured data — with copy/share actions. - Expandable Console rows now show a trailing chevron, matching the Network tab, so it is clear at a glance which logs open a detail view.
Fixed #
- A log carrying an empty-string
stackTraceis no longer treated as expandable, so it neither appears tappable in the Console nor renders an empty stack-trace section in the detail view.
0.2.4 #
Added #
- Network requests and responses captured by
FlutterInspectorDioInterceptorare now mirrored to the Console tab (atdebuglevel), so HTTP traffic is visible alongside other logs. FlutterInspectorNavigatorObservernow mirrors route changes (push / pop / replace / remove) to the Console tab atwarninglevel, in addition to the Navigator history.
Changed #
- Adjusted the
LogLevel.debugtext color in the Console tab to blue-grey for better visibility.
Fixed #
- Fixed the
Statusrow in the Network detail view's General section so its value aligns with the other fields (Method, URL, Duration, etc.) instead of starting at an inconsistent position.
0.2.3 #
Fixed #
- Fixed foreground notification banner on macOS where the host app
AppDelegatefailed to cast toUNUserNotificationCenterDelegate. macOS hosts must now explicitly conform and handle the callback. - Resolved a race condition during cold-starts where network notifications logged before the notifier finished initialization were lost.
- Fixed the
README.mdsetup instructions to separate iOS and macOS delegate compliance procedures.
0.2.2 #
Added #
FlutterInspectorNavigatorObservernow resolves routewidgetTypeand name natively by default.- Added support to filter out the internal
DashboardModalroute (flutter_inspector_dashboard) from the Navigator history logs to prevent UI noise. - Added a
Makefilefor automated common Flutter development tasks.
Changed #
- Refactored project directory structure: renamed internal
flutter_inspector_impl.darttoflutter_inspector.dartandintegrationsdirectory tointerceptors.
Fixed #
- Fixed a bug in the example app where null navigator context could crash the app when attempting to open the dashboard modal.
0.2.1 #
Fixed #
- Raised
diolower bound to^5.2.0to match the actual API usage (DioException), fixing the pub.dev downgrade analysis. - Restored WASM compatibility: web builds now use the browser Web Share API (
package:web) instead ofshare_plus, and the network notifier resolves to a no-op stub on web, keepingdart:ioout of the web import graph. - Dismissing the web share sheet (
AbortError) is now treated as a cancel instead of a failure, so it no longer triggers the clipboard fallback.
0.2.0 #
Added #
- Database table browser with two-level navigation (table list page and row grid view).
- Multi-direction scrolling (horizontal and vertical) in row grid view.
- Local column sorting with NULLs always sorted to the end in both directions.
- Dialog value preview and copy for individual grid cell values.
- Pagination for row grid (200 rows limit with 'Load More' button).
- Public
DatabaseBrowserSource,DatabaseTableInfo, andDatabaseTablePageclasses. FlutterInspector.registerDatabaseSourceand constructor parameterdatabaseSourcesto dynamically registry third-party databases (e.g. SQLite, ObjectBox).
Changed #
- Redesigned Database tab from chronological operation list to database table list view.
0.1.0 #
Initial release on pub.dev (package renamed from flutter_inspector to flutter_inspector_kit).
- Console, Network, Navigator, and Database inspectors behind a single unified API.
- In-app overlay FAB and full-screen Dashboard.
Diointerceptor for network traffic capture.MagicalTapwidget for gesture-based invocation.- Network notification heads-up banner: silent heads-up on Android (HIGH priority channel) and foreground banner on iOS, with automatic dismissal and visual feedback.
- Notification throttling: consecutive network calls within a 2-second window update the notification in place without re-alerting.
- Android notification channel
flutter_inspector_network_v2(HIGH importance); the legacyflutter_inspector_networkchannel is automatically deleted during upgrade. - Dio interceptor updates the pending request entry in place when its response or error arrives (no duplicate "Pending" entries);
logNetworkgained an optionalreplacesparameter and returns the stored entry.