Still Debugging Flutter the Old Way? Meet DebugLens DebugLens, an on-device debugging tool for Flutter projects, has been published on pub.dev, offering developers a unified view of runtime information including network calls, logs, BLoC transitions, navigation, storage, device information, crashes, analytics, and remote config. The tool allows developers to inspect and share logs without reproducing issues, and supports overriding remote config values and app versions on the same build. DebugLens keeps all data on-device and can be integrated via a simple setup or with AI assistance. Hey, engineer Do you still do all your daily development tasks manually like coding, designing architecture, debugging, writing tests? Like most developers today, I use AI almost every day. Not to replace my work, but to speed it up. Whether it’s generating boilerplate, reviewing code, explaining unfamiliar APIs, or even integrating packages, AI has become part of my workflow. With the rise of Agentic Coding and Vibe Coding, I’ve noticed my role as a developer changing. Instead of simply writing code, I now spend more time in the following: In this article, I’ll share how, as a curious developer, I started building DebugLens as a side project to learn more about Mobile and its internals. Over time, it became more than just a learning exercise, it changed my mindset from being just a developer to becoming a builder. Eventually, I decided to publish it on pub.dev so the Flutter community could use it too. Let’s say someone from QA, Product, Business, or even another developer is using your application and discovers a bug or unusual behavior. They report it to the responsible developer. As a developer, your first instinct is to reproduce the issue by following the same steps so you can inspect the console logs or attach a debugger. Sometimes it is straightforward, but most of the time it is not. The issue could be deep within a user flow, require specific data, or only occur after a particular sequence of actions. You may even need someone to guide you through the exact steps they followed. Before you know it, you have spent hours just trying to reach the same application state instead of actually fixing the problem. DebugLens is an on device debugging tool for Flutter projects. It gives you visibility into everything that’s happening inside your application by bringing together all the important runtime information in one place, including Network Calls, Logs, BLoC Transitions, Navigation, Storage, Device Information, Crashes, Analytics, and Remote Config . Package link: https://pub.dev/packages/debug lens https://pub.dev/packages/debug lens/install The current state of your application is always available with DebugLens, so you no longer need to reproduce an issue from scratch or ask someone to walk you through the exact steps they followed. You can inspect what’s happening directly on the device, understand the application’s state, and quickly figure out the root cause, saving valuable time for everyone involved. To make debugging even faster, every service allows you to share its logs individually. You can share them with your teammates or even use them as context for your preferred AI tool to help identify the root cause. DebugLens never uploads or stores your application’s data anywhere. Everything it captures stays on the device. With DebugLens, you can quickly answer questions like: DebugLens doesn’t just help you inspect your application. It also lets you override Remote Config values and the App Version on the same build, making it easy to test feature flags, version gated behavior, and different app configurations without creating a new build. flutter pub add debug lensflutter pub get I recommend following the README and integrating each service one by one so you understand what’s happening. If you prefer, you can also let your AI tool do the integration for you. I’ve created a prompt that walks it through the setup based on your project’s requirements. Integration Prompt: https://github.com/anupam92402/DebugLens/blob/master/doc/debug lens integration.md https://github.com/anupam92402/DebugLens/blob/master/doc/debug lens integration.md The minimum setup is simply wrapping your app and adding the navigation observer: // The observer feeds Navigation; wrap mounts the bubble and the panel itself.MaterialApp navigatorObservers: DebugLens.navigatorObserver , builder: context, child = DebugLens.wrap child ?? const SizedBox.shrink , ; You can also decide when DebugLens should be enabled. A common approach is enabling it only for non-production builds. void main { // Enable DebugLens only for non-production builds. // You can also use your own flavor flag instead of kReleaseMode. DebugLens.debugLensEnabled = kReleaseMode; runApp const MyApp ;} Now, let’s explore each DebugLens service and see how it can make debugging Flutter applications significantly easier. // Captures every request/response this Dio instance makes.dio.interceptors.add DebugLensDioInterceptor ; // Optional: Disable terminal output while keeping logs in DebugLens.DebugLensLogger .printToConsole = kDebugMode;// Record informational and error logs from anywhere in your app.DebugLensLogger .i 'Signed in', name: 'auth' ;DebugLensLogger .d 'Response Failed', name: 'auth' ;DebugLensLogger .e 'Upload failed', name: 'media', error: e, stackTrace: s ; You can also configure retention limits to control how many logs and other captured records DebugLens keeps in memory during a session. // Seeds the buffer size, a tester can still raise or lower it from Settings.DebugLens.initialLimits = const DebugLensLimits logs: 5000, network: 1000 ; // Capture all BLoC and Cubit lifecycle events automatically.Bloc.observer = DebugLensBlocObserver ; If you’d like to understand how NavigatorObserver and RouteObserver work under the hood, I've written two detailed articles covering the basics, common pitfalls, and best practices: // Root navigator navigatorObservers: DebugLens.navigatorObserver ,// A nested navigator, e.g. one tab of a bottom nav bar.final observer = DebugLens.newNavigatorObserver label: 'home' ; // Register SharedPreferences and your database so DebugLens can inspect their data.DebugLens.sharedPrefsSource = = for final key in prefs.getKeys DebugLensPrefEntry key: key, value: '${prefs.get key }' , ;DebugLens.registerDatabase MyDriftAdapter db ; // Register your app's active localization strings with DebugLens.DebugLens.localeSource = = DebugLensLocaleData entries: currentLangMap, label: 'English', ; // Record notifications and deep links to inspect their payloads and routing.DebugLens.recordNotification title: message.title, body: message.body, payload: message.data, source: 'FCM', ;DebugLens.recordDeeplink uri.toString , source: 'os' ; The Services screen lets you inspect data from integrations that are specific to your app. Use the built-in adapters for Remote Config, Crash Reports, Analytics, and Performance. // Load remote config values into DebugLens during app startup.await DebugLens.instance.setRemoteConfigData { for final e in firebase.getAll .entries e.key: e.value.asString ,}, sourceLabel: 'Firebase' ;final timeout = DebugLens.instance.getInt 'api timeout seconds' ;final featureEnabled = DebugLens.instance.getBool 'new checkout enabled' ;final apiBaseUrl = DebugLens.instance.getString 'api base url' ;final discount = DebugLens.instance.getDouble 'discount percentage' ;final maxRetries = DebugLens.instance.getInt 'max retry count' ;final rawValue = DebugLens.instance.getKey 'maintenance banner' ; Capture the same crash information you send to your crash reporting service and view it instantly on the device, including the error and stack trace. This lets you investigate crashes immediately without waiting for them to appear in your crash dashboard. // Initialize crash reporting and record crashes with their stack traces.DebugLens.instance.initCrashReporting ;DebugLens.instance.recordCrash DebugLensCrashEvent error: error, stackTrace: stack, fatal: false , ; View analytics events as they are recorded, along with their parameters. This makes it easy to verify that the correct events are fired during testing without waiting for them to appear in your analytics dashboard. // Initialize analytics and record custom events with their parameters.DebugLens.instance.initAnalytics ;DebugLens.instance.recordAnalyticsEvent 'add to cart', parameters: {'sku': sku, 'price': price}, ; Record and inspect performance traces directly in DebugLens. Each trace displays its duration and any attributes you attach, making it easy to compare performance while testing on a real device. // Initialize performance monitoring and record completed performance traces.DebugLens.instance.initPerformance ;DebugLens.instance.recordTrace 'home load', stopwatch.elapsed ; // Await once at startup — this loads any override saved on a previous run.await DebugLens.instance.setAppVersion packageInfo.version ;// Read it back wherever the app shows or reports its version.Text DebugLens.instance.appVersion ; // Replaces Flutter's default red error box wherever a widget fails to build.ErrorWidget.builder = details = CustomErrorScreen details: details ; Start a Health Check session from Settings before testing a feature, running regression tests, or reproducing an issue. When you’re finished, stop the session and DebugLens generates a single report containing all crashes and error logs captured during that period, making it easy to understand what happened without manually collecting logs. // Configure the default role and tester permissions for the first app launch.DebugLens.initialRole = DebugRole.developer; // default: testerDebugLens.initialTesterAccess = { // default: {network} DebugScreen.network, DebugScreen.logs, DebugScreen.device,};DebugLens.initialTesterEnabled = false; // default: true Building DebugLens has saved me countless hours that I used to spend reproducing issues, digging through logs, and chasing problems that weren’t even the real cause. Instead of getting stuck on the same bug for hours, I can quickly understand what’s happening, fix it, and move on to solving the next problem. More importantly, DebugLens reminded me why I enjoy building software in the first place. As developers, we spend a lot of time solving problems for others, but sometimes the best projects are the ones that solve our own problems first. If it makes your life easier, there’s a good chance it will help someone else too. I hope DebugLens saves you as much time as it has saved me. If it does, I’d love to hear your feedback, feature ideas, or contributions. Happy debugging 🚀 Contributions are always welcome If you’d like to improve DebugLens, fix a bug, or add a new feature, feel free to fork the repository , make your changes, and open a Pull Request . Every contribution, big or small, is appreciated. Github: https://github.com/anupam92402/DebugLens https://github.com/anupam92402/DebugLens I hope you found this article helpful and enjoyable If you have any questions or doubts, feel free to drop them in the comments below. Also, don’t hesitate to share your thoughts or ideas — I’d love to hear them If you enjoyed this article or want to discuss more, feel free to connect with me on LinkedIn https://www.linkedin.com/in/anupam-gupta-a8440520a/ and X https://x.com/anupamg2001 . Always happy to network and share ideas with fellow developers Still Debugging Flutter the Old Way? Meet DebugLens https://blog.stackademic.com/still-debugging-flutter-the-old-way-meet-debuglens-9e769ea876ed was originally published in Stackademic https://blog.stackademic.com on Medium, where people are continuing the conversation by highlighting and responding to this story.