borealis 2.0.0
borealis: ^2.0.0 copied to clipboard
In-app debugging overlay for Flutter — network inspector, logs, device info, accessibility and annotation tools in a floating panel.
Changelog #
2.0.0 — 2026-09-24 #
First public release.
- Floating debug panel overlay for Flutter apps
- Network tab — Dio request/response inspector
- Logs tab — Loggy log viewer
- Device info tab — device, OS and package data
- Rendering tab — render debug flags (slow animations, repaint rainbow, widget sizes, hitboxes)
- Annotation tab — draw notes over the app and export them
- Debug actions — buttons, inputs, toggles and selectables, global or per screen
- Custom pages — add your own tabs
- Credential headers (
Authorization,Cookie,Set-Cookie,Proxy-Authorization,X-Api-Key) are masked before capture, so they reach neither the Network tab nor its exports. Configure withredactHeadersonBorealis.initNetworkLoggerorWiretapInterceptor. redactBodyKeysmasks named keys inside request and response bodies, matched without case and applied through nested maps and lists. Empty by default.- Captured bodies are bounded. A binary body over
WiretapInterceptor.maxCapturedBodyBytes(512 KiB) is replaced with a marker stating its real size, a text body overWiretapInterceptor.maxCapturedBodyChars(512 Ki characters) is truncated with a note of its full length, and captured bodies are snapshotted so a caller that mutates a request map afterwards cannot rewrite what the panel recorded. - Log file exports are written to
borealis_exports/in the system temporary directory, and exports left by an earlier run are deleted on the next export. - A request the wiretap never sees finish — an interceptor registered after it answered the request itself — no longer occupies the store forever. After two minutes it stops outranking completed entries during eviction.
- Annotation capture reports itself as unavailable in profile and release builds, where the widget data it relies on does not exist, instead of mounting a capture layer that absorbs taps and selects nothing.
- Debug action widgets share one run discipline. A failed action now marks the
control and stays usable instead of disabling it for the session,
SelectableActionWidgettakes its colors from the theme rather than painting black on the dark panel, andInputActionWidgetkeeps the value it saved. BorealisPage.onDetachundoes whatonAttachregistered.onAttachnow runs once per page instance rather than on every rebuild of the app above the overlay, and neither runs whileBorealisSettings.enabledisfalse.Borealis.hideDebugPanel()closes the panel even when a page has pushed a screen onto it; it used to pop one route and leave the panel open.- The floating button follows the point it was grabbed by and stays on screen while dragged.
BorealisOverlaythrowsArgumentErrorfor an emptypageslist instead of asserting, which was stripped in release and failed later as aRangeError.- The Network search matches the path and query string, as the field says. It
used to match the whole URL, so
httpsmatched everything. - cURL export emits one
-Hper value of a multi-value header, rendersFormDataas-Fparts, and notes a byte body instead of pasting it as an integer array. - A JSON-labelled body that is a string is pretty-printed rather than escaped, and one that is bytes is described by size.
LogsBorealisPagetakes aneventList, and its badge, clear action and gamify popups follow it.BorealisExportCallbackis exported.ScreenActionEntryis not — it could be named but never obtained or passed.- The panel's
OverlayEntryis disposed, not just removed. - The Accessibility tab is now Rendering (
RenderingBorealisPage). It only ever held Flutter's render debug flags, and no accessibility tooling. WiretapParsedBodyno longer carries alabel. Nothing read it, and a third-partyWiretapBodyParserhad to supply one anyway.WiretapInterceptor.maxCapturedBodySizeis nowmaxCapturedBodyBytesandmaxCapturedBodyChars. One constant was compared against a byte count and a character count, so the effective cap on text depended on its alphabet.- Export actions report what they wrote.
WiretapExportUtilsreplacesLoggingUtils, which named neither its subsystem nor its job. - Fewer rebuilds: merged listenables are built once rather than per frame, the
overlay depends on the two
MediaQueryaspects it reads, the panel builds the visible tab instead of all of them, and one ticker drives every relative timestamp in the Logs tab rather than one timer per row. - Gamify hooks do nothing while the layer is off, pace themselves on a monotonic clock, and count their attachments, so one overlay being disposed no longer stops another's popups.
- Store eviction is a single resumed pass rather than a rescan per entry.
- CI measures coverage and fails below 80%.
Requires Dart 3.10 / Flutter 3.38.1 or newer.
