ConsolePlus

Pub Version Likes Pub Points Flutter Favorite License: MIT Platform

Console+ Logo

A floating in-app console for Flutter β€” view, filter, search & export logs while your app runs!
console_plus lets you debug on-device with a floating overlay console that captures print(), debugPrint(), and developer.log() β€” in real time.


πŸ†• Version 2.0.0 & 2.0.1 Highlights

πŸš€ Major Rewrite for Stability & Zone Safety

  • 🧭 Zone-safe initialization β€” no more β€œZone mismatch” errors.
  • πŸͺ„ Unified log capture β€” print() + debugPrint() + platform errors all logged automatically.
  • 🧩 Cleaner API β€” single ConsolePlus.initApp() entry point.
  • 🎨 Redesigned console UI β€” smoother, resizable, searchable overlay.
  • πŸ§ͺ Better Flutter Test compatibility β€” works seamlessly inside test zones.

✨ Features

βœ… Floating draggable console overlay
βœ… Logs display above your app’s UI (non-blocking)
βœ… Captures print(), debugPrint(), and developer.log()
βœ… Auto-scroll when near the bottom
βœ… Filter logs by type (INFO, WARNING, ERROR)
βœ… Keyword search for tags or text
βœ… Copy, clear, and export logs as JSON
βœ… Built-in floating 🐞 debug button
βœ… Captures FlutterError and PlatformDispatcher errors
βœ… Compatible with Flutter 3.16+ / Dart 3+


βš™οΈ Installation

Add to your pubspec.yaml:

dependencies:
  console_plus: ^2.0.1

Then fetch packages:

flutter pub get

Import it:

import 'package:console_plus/console_plus.dart';

πŸ’» Usage

Step 1 β€” Initialize ConsolePlus

Wrap your app inside ConsolePlus.initApp():

Future<void> main() async {
  await ConsolePlus.initApp(
    const MyApp(),
    interceptPrints: true,          // Capture print() and debugPrint()
    captureFlutterErrors: true,     // Capture Flutter framework errors
    capturePlatformErrors: true,    // Capture platform dispatcher errors
  );
}

🧠 This ensures WidgetsFlutterBinding and runApp() are initialized in the same zone β€” no more zone mismatch errors!

Step 2 β€” Show Floating Debug Button

FloatingDebugButton.show(context);

This shows a draggable 🐞 button that opens the console overlay.


Step 2 β€” Log Messages

Use:

DebugLogConsole.log("User logged in successfully");
DebugLogConsole.log("Missing field: email", type: LogType.warning);
DebugLogConsole.log("API request failed", type: LogType.error);

Or just use:

print("Something happened");
debugPrint("App started!");

Both are automatically captured by ConsolePlus.

Step 3 β€” Export Logs

Tap the ⬇️ Download icon in the console header to export as a .json file.

You can also programmatically call:

final json = await DebugLogConsole.exportLogs(asJson: true);

πŸŽ›οΈ Console UI

  • 🟒 Floating, draggable, and resizable window
  • πŸ” Search bar with keyword filtering
  • 🧩 Filter by log levels (Info / Warning / Error)
  • πŸ“‹ Copy, ⬇️ Export, πŸ—‘οΈ Clear logs
  • πŸ“œ Persistent scroll + multi-line selection
  • ⚑ Real-time updates powered by ValueNotifier

🧩 Example

import 'package:flutter/material.dart';
import 'package:console_plus/console_plus.dart';

Future<void> main() async {
  await ConsolePlus.initApp(
    const MyApp(),
    interceptPrints: true,
    captureFlutterErrors: true,
    capturePlatformErrors: true,
  );
}

class MyApp extends StatelessWidget {
  const MyApp({super.key});

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'ConsolePlus Demo',
      theme: ThemeData.dark(useMaterial3: true),
      home: const HomePage(),
    );
  }
}

class HomePage extends StatefulWidget {
  const HomePage({super.key});

  @override
  State<HomePage> createState() => _HomePageState();
}

class _HomePageState extends State<HomePage> {
  int counter = 0;

  @override
  void initState() {
    super.initState();
    WidgetsBinding.instance.addPostFrameCallback(
          (_) => FloatingDebugButton.show(context),
    );
  }

  void _generateLogs() {
    counter++;
    for (final type in ['Info', 'Warning', 'Error']) {
      debugPrint('D $type log #$counter');
      print('P $type log #$counter');
    }
    setState(() {});
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: const Text('ConsolePlus Demo')),
      body: Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: [
            Text('Button pressed $counter times'),
            const SizedBox(height: 20),
            ElevatedButton(
              onPressed: _generateLogs,
              child: const Text('Generate Logs'),
            ),
          ],
        ),
      ),
    );
  }
}

πŸ“‚ File Export

Format: .json

Example output:

[
  {
    "timestamp": "2025-11-08T12:30:01.345Z",
    "type": "info",
    "message": "App started"
  },
  {
    "timestamp": "2025-11-08T12:31:14.123Z",
    "type": "error",
    "message": "Network timeout"
  }
]

🧭 Upgrading from v1.x β†’ v2.0.1

Before:

void main() {
  ConsolePlus.init(MyApp());
  runApp(MyApp());
}

After (v2.0.0):

Future<void> main() async {
  await ConsolePlus.initApp(
    const MyApp(),
    interceptPrints: true,
    captureFlutterErrors: true,
    capturePlatformErrors: true,
  );
}

βœ… ConsolePlus.init() β†’ replaced with ConsolePlus.initApp() βœ… Initialization now must be awaited βœ… Zone-safe by default β€” fixes zone mismatch crashes βœ… No more manual WidgetsFlutterBinding.ensureInitialized() calls required

Contributing

PRs welcome. Keep debug-only behaviour intact. If you add native platform code, ensure release builds keep plugin inert unless explicitly enabled.


Floating Button Console Overlay Search Filter

πŸ“œ License

MIT License Β© 2025 Ashish
See the full LICENSE file for details.


πŸ’¬ Credits

Built with ❀️ by Ashish Follow for updates and Flutter dev tips!