flutter_inspector
An in-app developer toolkit for Flutter. Inspect network calls, view storage, toggle feature flags, and debug your app without external tools.
The in-app developer toolkit Flutter deserves. Bring React Native's DX to Flutter.
β¨ Why flutter_inspector?
Every Flutter developer has wished for better in-app debugging tools. While Flutter DevTools is powerful, it requires USB connection, desktop access, and can't be used in production builds or shared with QA teams.
flutter_inspector solves this by providing:
- π± In-app access - No external tools needed
- π€ QA-friendly - Non-technical team members can inspect app state
- π Production-safe - Built-in guards prevent accidental release exposure
- β‘ Zero friction - Drop-in with minimal configuration
- π Extensible - Plugin architecture for custom tools
- π¨ Beautiful Dark UI - Modern, polished interface
- π± Shake to Open - Natural gesture on mobile devices
π― Features
π Network Inspector
- Intercepts HTTP/HTTPS requests and responses
- Works with both
httpandDiopackages - View request/response headers, body, and timing
- Pretty-printed JSON responses
- Search and filter by status, URL, or method
- View full request details with cURL export
πΎ Storage Viewer
- View all SharedPreferences key-value pairs
- Edit or delete storage entries in real-time
- Search functionality
- Type indicators (String, int, bool, etc.)
- Refresh to reload data
π Log Viewer
- In-app console for all your logs
- Auto-captures
debugPrint()calls - All your existing debug prints appear automatically! - Multiple log levels (debug, info, warning, error)
- Color-coded by severity
- Searchable and filterable by level
- Attach metadata to logs
- Tap to view full details
- Copy logs to clipboard
π© Feature Flags
- Toggle features on/off without rebuilding
- Perfect for A/B testing during development
- Real-time UI updates when flags change
- Conditional rendering based on flags
- Persistent across app restarts
β‘ Quick Actions
- Execute common tasks with one tap
- Clear cache, reset onboarding, trigger API calls
- Custom actions with icons and descriptions
- Loading states for async operations
- Fully customizable
π± App Info
- View app version, build number
- Device information and OS details
- Screen dimensions and pixel ratio
- Platform and locale information
π¨ Beautiful Dark Theme
- Modern, polished dark UI
- Easy on the eyes during development
- Consistent across all plugins
- Smooth animations and transitions
π³ Shake Detection
- Open panel by shaking your device
- Works on X, Y, and Z axes
- Adjustable sensitivity (1-10)
- Natural gesture for mobile development
π¦ Installation
Add to your pubspec.yaml:
dependencies:
flutter_inspector: ^0.1.0
# For network inspection
dio: ^5.7.0 # if using Dio
# Other dependencies used by DevPanel
shared_preferences: ^2.3.3 # for Storage Viewer
Run:
flutter pub get
π Quick Start
1. Initialize DevPanel
import 'package:flutter/material.dart';
import 'package:flutter_inspector/flutter_inspector.dart';
import 'package:dio/dio.dart';
// Global instances for easy access
late LogViewerPlugin logViewer;
late NetworkInspectorPlugin networkInspector;
late FeatureFlagsPlugin featureFlags;
late Dio dio;
void main() {
// IMPORTANT: Initialize bindings first
WidgetsFlutterBinding.ensureInitialized();
// Initialize plugins
logViewer = LogViewerPlugin(maxLogs: 500);
networkInspector = NetworkInspectorPlugin(maxCalls: 100);
featureFlags = FeatureFlagsPlugin(
flags: [
FeatureFlag(
key: 'dark_mode',
name: 'Dark Mode',
description: 'Enable dark theme',
isEnabled: true,
),
],
);
// Initialize DevPanel
DevPanel.init(
enableInRelease: false, // Safety: only enable in debug mode
shakeToOpen: true, // Open panel by shaking device
shakeSensitivity: 5, // 1-10, higher = more sensitive
capturePrint: true, // Auto-capture debugPrint() calls
plugins: [
AppInfoPlugin(
appName: 'My App',
version: '1.0.0',
buildNumber: '1',
),
networkInspector,
StorageViewerPlugin(),
logViewer,
featureFlags,
QuickActionsPlugin(
actions: [
QuickAction(
name: 'Clear Cache',
icon: Icons.delete_sweep,
onTap: () async {
// Your cache clearing logic
},
),
],
),
],
);
// Initialize Dio with network inspector
dio = Dio();
dio.interceptors.add(networkInspector.getDioInterceptor());
runApp(const MyApp());
}
2. Attach DevPanel to Your App
class MyApp extends StatelessWidget {
const MyApp({super.key});
@override
Widget build(BuildContext context) {
return MaterialApp(
// Use builder to attach DevPanel
builder: (context, child) => DevPanel.attach(child!),
debugShowCheckedModeBanner: false,
title: 'My App',
theme: ThemeData.dark(),
home: const HomePage(),
);
}
}
3. Add Developer Button (Optional)
AppBar(
title: Text('My App'),
actions: [
IconButton(
icon: const Icon(Icons.developer_mode),
tooltip: 'Open Dev Panel',
onPressed: () => DevPanel.show(),
),
],
)
4. Start Using!
Shake your device or tap the developer button to open the panel!
π Usage Examples
Network Inspection with Dio
final networkInspector = NetworkInspectorPlugin(maxCalls: 100);
DevPanel.init(plugins: [networkInspector]);
// Add interceptor to Dio
final dio = Dio();
dio.interceptors.add(networkInspector.getDioInterceptor());
// Make requests with custom headers and parameters
final response = await dio.get(
'https://api.example.com/posts',
queryParameters: {'userId': 1, '_limit': 5},
options: Options(
headers: {
'Authorization': 'Bearer token',
'X-Custom-Header': 'value',
},
),
);
// POST with body
await dio.post(
'https://api.example.com/posts',
data: {
'title': 'My Post',
'body': 'Content here',
'userId': 1,
},
);
// All requests are automatically captured in Network tab!
Logging
final logViewer = LogViewerPlugin(maxLogs: 500);
DevPanel.init(
capturePrint: true, // Enable auto-capture
plugins: [logViewer],
);
// Method 1: Use debugPrint (auto-captured)
debugPrint('User logged in successfully');
debugPrint('Payment amount: \$99.99');
// Method 2: Use LogViewer directly for structured logs
logViewer.log('User logged in', level: LogLevel.info);
logViewer.log(
'Payment failed',
level: LogLevel.error,
data: {
'amount': 99.99,
'reason': 'Insufficient funds',
'timestamp': DateTime.now().toIso8601String(),
},
);
// Logs appear in the Logs tab with filtering and search
Feature Flags with Real-Time Updates
final featureFlags = FeatureFlagsPlugin(
flags: [
FeatureFlag(
key: 'dark_mode',
name: 'Dark Mode',
description: 'Enable dark theme',
isEnabled: true,
),
],
);
DevPanel.init(plugins: [featureFlags]);
// In your StatefulWidget
class MyApp extends StatefulWidget {
@override
State<MyApp> createState() => _MyAppState();
}
class _MyAppState extends State<MyApp> {
@override
void initState() {
super.initState();
// Listen to feature flag changes
featureFlags.addListener(_onFlagChanged);
}
@override
void dispose() {
featureFlags.removeListener(_onFlagChanged);
super.dispose();
}
void _onFlagChanged() {
setState(() {}); // Rebuild when flags change
}
@override
Widget build(BuildContext context) {
// Check flag and switch theme in real-time
final isDarkMode = featureFlags.isFlagEnabled('dark_mode');
return MaterialApp(
theme: isDarkMode ? ThemeData.dark() : ThemeData.light(),
home: HomePage(),
);
}
}
Quick Actions
QuickActionsPlugin(
actions: [
QuickAction(
name: 'Clear Cache',
description: 'Clear all app cache',
icon: Icons.delete_sweep,
onTap: () async {
await CacheManager.clearAll();
logViewer.log('Cache cleared', level: LogLevel.info);
},
),
QuickAction(
name: 'Test API',
description: 'Make a test network request',
icon: Icons.cloud,
onTap: () async {
await dio.get('https://jsonplaceholder.typicode.com/posts/1');
},
),
QuickAction(
name: 'Reset Onboarding',
description: 'Show onboarding again',
icon: Icons.refresh,
onTap: () async {
final prefs = await SharedPreferences.getInstance();
await prefs.setBool('onboarding_complete', false);
},
),
],
)
βοΈ Configuration Options
DevPanel.init() Parameters
| Parameter | Type | Default | Description |
|---|---|---|---|
enableInRelease |
bool |
false |
Enable panel in release mode (use with caution) |
shakeToOpen |
bool |
true |
Open panel by shaking device |
shakeSensitivity |
int |
5 |
Shake sensitivity (1-10, higher = more sensitive) |
capturePrint |
bool |
true |
Auto-capture debugPrint() calls |
plugins |
List<DevPanelPlugin> |
[] |
List of plugins to enable |
theme |
DevPanelTheme? |
null |
Custom theme (currently limited) |
Plugin Options
LogViewerPlugin:
LogViewerPlugin(
maxLogs: 500, // Maximum logs to keep in memory
)
NetworkInspectorPlugin:
NetworkInspectorPlugin(
maxCalls: 100, // Maximum network calls to keep
)
π¨ UI Features
- Dark Theme: Beautiful dark interface optimized for development
- Smooth Animations: Slide-up panel with backdrop blur
- Tab Navigation: Easy switching between tools
- Search & Filter: Find what you need quickly
- Copy to Clipboard: Copy logs, values, and network data
- Empty States: Helpful messages when no data is available
- Scrollable Content: All tabs work on small mobile screens
π± Platform Support
| Platform | Supported | Notes |
|---|---|---|
| Android | β | Shake detection works on physical devices |
| iOS | β | Shake detection works on physical devices |
| Web | β | No shake detection (use button instead) |
| Desktop | β | No shake detection (use button instead) |
π Troubleshooting
Panel not opening?
- Check initialization: Make sure
DevPanel.init()is called beforerunApp() - Check release mode: Panel is disabled in release builds by default (
enableInRelease: false) - Shake not working: Try increasing
shakeSensitivityto 8-10, or use the manual button - Add
WidgetsFlutterBinding.ensureInitialized()at the start ofmain()
Prints not appearing in logs?
- Use
debugPrint()instead ofprint()- it's automatically captured - Make sure
capturePrint: trueinDevPanel.init() - Regular
print()goes directly to console in debug mode and won't be captured
Overflow errors?
The panel UI is optimized for mobile screens. If you see overflow errors, please file an issue with your device specs.
Network calls not showing?
- For Dio: Make sure you added the interceptor:
dio.interceptors.add(networkInspector.getDioInterceptor()) - For http: Use the wrapped client:
networkInspector.wrapHttpClient(http.Client())
π API Reference
DevPanel
| Method | Description |
|---|---|
DevPanel.init() |
Initialize the dev panel with configuration |
DevPanel.attach(Widget child) |
Attach panel to your app (use in MaterialApp.builder) |
DevPanel.show() |
Show the panel programmatically |
DevPanel.hide() |
Hide the panel |
DevPanel.toggle() |
Toggle panel visibility |
DevPanel.dispose() |
Clean up resources (call when app closes) |
LogViewerPlugin
logViewer.log(
String message,
{LogLevel level = LogLevel.debug, Map<String, dynamic>? data}
)
LogLevel enum: debug, info, warning, error
NetworkInspectorPlugin
// Get Dio interceptor
final interceptor = networkInspector.getDioInterceptor();
// Wrap http.Client
final client = networkInspector.wrapHttpClient(http.Client());
FeatureFlagsPlugin
// Check if flag is enabled
bool isEnabled = featureFlags.isFlagEnabled('flag_key');
// Toggle a flag programmatically
featureFlags.toggle('flag_key');
// Listen to changes
featureFlags.addListener(() {
// Rebuild UI
});
π Example App
Check out the example directory for a full demo app showcasing all features.
To run the example:
cd example
flutter pub get
flutter run
The example demonstrates:
- Network inspection with GET/POST requests
- Feature flags controlling app theme
- Logging with different levels
- Storage viewer with SharedPreferences
- Quick actions for common tasks
πΊοΈ Roadmap
Features we're considering:
Performance metrics (FPS, memory, CPU)Widget inspectorDatabase viewer (SQLite, Drift, Hive)Remote logging to external serviceCustom plugin API for third-party extensionsScreenshot/screen recording toolsExport logs/network calls to fileGraphQL supportWebSocket inspectionPush notification testing
π€ Contributing
Contributions are welcome! Please:
- Fork the repository
- Create a feature branch (
git checkout -b feature/amazing-feature) - Commit your changes (
git commit -m 'Add amazing feature') - Push to the branch (
git push origin feature/amazing-feature) - Open a Pull Request
Please read our Contributing Guidelines for more details.
π License
MIT License - see LICENSE for details.
π Acknowledgments
Inspired by:
- React Native's Debug Menu
- TanStack Query DevTools
- Flutter DevTools
- Flipper by Meta
π§ Support
- Issues: GitHub Issues
- Discussions: GitHub Discussions
- Email: your-email@example.com
β Show Your Support
If this package helps you, please give it a β on GitHub!
Made with β€οΈ for the Flutter community
Debugging should be delightful, not difficult.
Libraries
- flutter_inspector
- An in-app developer toolkit for Flutter.