
Extensible on-device dev tools to inspect logs, network requests and analytics in a Material3 UI, with modular plugins, adaptive layout and zero runtime overhead when disabled.
Extensible on-device dev tools for Kotlin Multiplatform
A mini Flipper for KMP — inspect logs, network, and more with a beautiful Compose UI.
Features • Installation • Quick Start • Plugins • Custom Plugins • Documentation
| Feature | Description |
|---|---|
| 🔍 Log Inspector | Search, filter, and copy logs with syntax-highlighted JSON |
| 🌐 Network Viewer | HTTP request/response inspection with method badges |
| 📊 Analytics Tracker | Monitor analytics events in real-time |
| 🎨 Beautiful UI | Material3 design with light/dark mode support |
| 🧩 Plugin System | Extend with custom debug panels through modular dependencies |
| 📱 Adaptive Layout | Bottom sheet on phones, dialog on tablets |
| 🔌 Zero Release Overhead | Disable with a single flag — no runtime cost |
| 🍎 Multiplatform | Android, iOS, Desktop (JVM), Web (WASM) |
AEDevLens is fully modularized. Include only the plugins you need to keep your app light!
// build.gradle.kts (shared module)
kotlin {
sourceSets {
commonMain.dependencies {
// Default setup: Core UI + LogsPlugin
implementation("io.github.abdo-essam:devlens:1.0.0")
// Optional Plugins
implementation("io.github.abdo-essam:devlens-network:1.0.0")
implementation("io.github.abdo-essam:devlens-analytics:1.0.0")
}
}
}🔥 True Modularity: Worried about APK/bundle size? You can drop the
LogsPluginentirely! Just remove thedevlensdependency and importdevlens-network:1.0.0ordevlens-analytics:1.0.0directly. Because each acts completely independently and transitively exportsdevlens-coreanddevlens-ui, your app stays incredibly lightweight!
[versions]
devlens = "1.0.0"
[libraries]
devlens-core = { module = "io.github.abdo-essam:devlens", version.ref = "devlens" }
devlens-network = { module = "io.github.abdo-essam:devlens-network", version.ref = "devlens" }
devlens-analytics = { module = "io.github.abdo-essam:devlens-analytics", version.ref = "devlens" }Best called early in your platform-specific entry points (e.g. Application.onCreate for Android, or main ViewController for iOS):
DevLensSetup.init(
plugins = listOf(
LogsPlugin(), // Default built-in logs
NetworkPlugin(), // Network inspector
AnalyticsPlugin() // Analytics tracker
)
)@Composable
fun App(debugMode: Boolean) {
AEDevLensProvider(
inspector = AEDevLens.default,
enabled = debugMode, // ← disables UI overhead in release builds
uiConfig = DevLensUiConfig(
showFloatingButton = true, // Enables the 'bug' overlay button
enableLongPress = true, // Show panel on 3-finger long press
)
) {
MaterialTheme {
YourAppContent()
}
}
}Use the global static APIs corresponding to your installed plugins:
// 1. Logs API
DevLens.i("HomeScreen", "App launched!")
DevLens.e("Database", "Failed to clear cache", exception)
// 2. Network API
NetworkApi.logRequest(method = "GET", url = "https://api.example.com/users", headers = mapOf("Auth" to "Bearer 123"))
NetworkApi.logResponse(url = "https://api.example.com/users", statusCode = 200, responseBody = "{ \"count\": 2 }")
// 3. Analytics API
AnalyticsApi.logEvent("item_added_to_cart", properties = mapOf("id" to "123", "price" to "29.99"))Three ways to open the inspector:
LocalAEDevLensController.current.show()
| Module / Plugin | Class | Description |
|---|---|---|
:devlens |
LogsPlugin |
Log viewer with severity filters (ALL / VERBOSE / DEBUG / INFO / WARN / ERROR) |
:devlens-network |
NetworkPlugin |
HTTP inspector with method badges, status filtering (2xx / 4xx / 5xx) and full body view |
:devlens-analytics |
AnalyticsPlugin |
Analytics tracker separating Screens / Events with expandable properties |
Create your own debug panel (e.g., a Database Inspector or Feature Flags toggler) in 3 steps:
class FeatureFlagsPlugin : UIPlugin {
override val id = "feature_flags"
override val name = "Flags"
override val icon = Icons.Default.Flag
private val _badgeCount = MutableStateFlow<Int?>(null)
override val badgeCount: StateFlow<Int?> = _badgeCount
override fun onAttach(inspector: AEDevLens) {
// Initialize your plugin
}
@Composable
override fun Content(modifier: Modifier) {
// Your Compose UI here
LazyColumn(modifier = modifier) {
items(flags) { flag ->
FlagRow(flag)
}
}
}
}
// Install it
DevLensSetup.init(plugins = listOf(LogsPlugin(), FeatureFlagsPlugin()))📖 See the Custom Plugins Guide for the full API reference.
AEDevLens works seamlessly with your existing logging infrastructures (like Kermit or Napier). Just forward your logs to the APIs.
class DevLensKermitWriter : LogWriter() {
override fun log(severity: Severity, message: String, tag: String, throwable: Throwable?) {
DevLens.log(
severity = severity.toDevLensLogSeverity(),
tag = tag,
message = buildString {
append(message)
throwable?.let { append("\n${it.stackTraceToString()}") }
}
)
}
}📖 See the Logging Integrations Guide for more examples.
The SDK follows an encapsulated Model-Store-API-UI pattern, making plugins 100% reactive, modular, and thread-safe.
┌─────────────────────────────────────────────────┐
│ AEDevLensProvider │ Compose wrapper
│ ┌───────────────────────────────────────────┐ │
│ │ AEDevLens (Core) │ │ Plugin engine
│ │ ┌─────────┐ ┌─────────┐ ┌────────────┐ │ │
│ │ │ Logs │ │ Network │ │ Analytics │ │ │ Plugins
│ │ │ Plugin │ │ Plugin │ │ Plugin │ │ │
│ │ └────┬────┘ └────┬────┘ └─────┬──────┘ │ │
│ │ │ │ │ │ │
│ │ ┌────┴────┐ ┌────┴────┐ ┌────┴──────┐ │ │
│ │ │LogStore │ │NetStore │ │AnalyticsStore│ │ Data layer
│ │ └─────────┘ └─────────┘ └───────────┘ │ │
│ └───────────────────────────────────────────┘ │
└─────────────────────────────────────────────────┘
| Platform | Minimum Version |
|---|---|
| Android | API 24 (Android 7.0) |
| iOS | 15.0 |
| Kotlin | 2.1.10+ |
| Compose Multiplatform | 1.7.3+ |
Contributions are welcome! Please read the Contributing Guide first.
git clone https://github.com/abdo-essam/AEDevLens.git
cd AEDevLens
./gradlew build
./gradlew allTestsCopyright 2026 Abdo Essam
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Extensible on-device dev tools for Kotlin Multiplatform
A mini Flipper for KMP — inspect logs, network, and more with a beautiful Compose UI.
Features • Installation • Quick Start • Plugins • Custom Plugins • Documentation
| Feature | Description |
|---|---|
| 🔍 Log Inspector | Search, filter, and copy logs with syntax-highlighted JSON |
| 🌐 Network Viewer | HTTP request/response inspection with method badges |
| 📊 Analytics Tracker | Monitor analytics events in real-time |
| 🎨 Beautiful UI | Material3 design with light/dark mode support |
| 🧩 Plugin System | Extend with custom debug panels through modular dependencies |
| 📱 Adaptive Layout | Bottom sheet on phones, dialog on tablets |
| 🔌 Zero Release Overhead | Disable with a single flag — no runtime cost |
| 🍎 Multiplatform | Android, iOS, Desktop (JVM), Web (WASM) |
AEDevLens is fully modularized. Include only the plugins you need to keep your app light!
// build.gradle.kts (shared module)
kotlin {
sourceSets {
commonMain.dependencies {
// Default setup: Core UI + LogsPlugin
implementation("io.github.abdo-essam:devlens:1.0.0")
// Optional Plugins
implementation("io.github.abdo-essam:devlens-network:1.0.0")
implementation("io.github.abdo-essam:devlens-analytics:1.0.0")
}
}
}🔥 True Modularity: Worried about APK/bundle size? You can drop the
LogsPluginentirely! Just remove thedevlensdependency and importdevlens-network:1.0.0ordevlens-analytics:1.0.0directly. Because each acts completely independently and transitively exportsdevlens-coreanddevlens-ui, your app stays incredibly lightweight!
[versions]
devlens = "1.0.0"
[libraries]
devlens-core = { module = "io.github.abdo-essam:devlens", version.ref = "devlens" }
devlens-network = { module = "io.github.abdo-essam:devlens-network", version.ref = "devlens" }
devlens-analytics = { module = "io.github.abdo-essam:devlens-analytics", version.ref = "devlens" }Best called early in your platform-specific entry points (e.g. Application.onCreate for Android, or main ViewController for iOS):
DevLensSetup.init(
plugins = listOf(
LogsPlugin(), // Default built-in logs
NetworkPlugin(), // Network inspector
AnalyticsPlugin() // Analytics tracker
)
)@Composable
fun App(debugMode: Boolean) {
AEDevLensProvider(
inspector = AEDevLens.default,
enabled = debugMode, // ← disables UI overhead in release builds
uiConfig = DevLensUiConfig(
showFloatingButton = true, // Enables the 'bug' overlay button
enableLongPress = true, // Show panel on 3-finger long press
)
) {
MaterialTheme {
YourAppContent()
}
}
}Use the global static APIs corresponding to your installed plugins:
// 1. Logs API
DevLens.i("HomeScreen", "App launched!")
DevLens.e("Database", "Failed to clear cache", exception)
// 2. Network API
NetworkApi.logRequest(method = "GET", url = "https://api.example.com/users", headers = mapOf("Auth" to "Bearer 123"))
NetworkApi.logResponse(url = "https://api.example.com/users", statusCode = 200, responseBody = "{ \"count\": 2 }")
// 3. Analytics API
AnalyticsApi.logEvent("item_added_to_cart", properties = mapOf("id" to "123", "price" to "29.99"))Three ways to open the inspector:
LocalAEDevLensController.current.show()
| Module / Plugin | Class | Description |
|---|---|---|
:devlens |
LogsPlugin |
Log viewer with severity filters (ALL / VERBOSE / DEBUG / INFO / WARN / ERROR) |
:devlens-network |
NetworkPlugin |
HTTP inspector with method badges, status filtering (2xx / 4xx / 5xx) and full body view |
:devlens-analytics |
AnalyticsPlugin |
Analytics tracker separating Screens / Events with expandable properties |
Create your own debug panel (e.g., a Database Inspector or Feature Flags toggler) in 3 steps:
class FeatureFlagsPlugin : UIPlugin {
override val id = "feature_flags"
override val name = "Flags"
override val icon = Icons.Default.Flag
private val _badgeCount = MutableStateFlow<Int?>(null)
override val badgeCount: StateFlow<Int?> = _badgeCount
override fun onAttach(inspector: AEDevLens) {
// Initialize your plugin
}
@Composable
override fun Content(modifier: Modifier) {
// Your Compose UI here
LazyColumn(modifier = modifier) {
items(flags) { flag ->
FlagRow(flag)
}
}
}
}
// Install it
DevLensSetup.init(plugins = listOf(LogsPlugin(), FeatureFlagsPlugin()))📖 See the Custom Plugins Guide for the full API reference.
AEDevLens works seamlessly with your existing logging infrastructures (like Kermit or Napier). Just forward your logs to the APIs.
class DevLensKermitWriter : LogWriter() {
override fun log(severity: Severity, message: String, tag: String, throwable: Throwable?) {
DevLens.log(
severity = severity.toDevLensLogSeverity(),
tag = tag,
message = buildString {
append(message)
throwable?.let { append("\n${it.stackTraceToString()}") }
}
)
}
}📖 See the Logging Integrations Guide for more examples.
The SDK follows an encapsulated Model-Store-API-UI pattern, making plugins 100% reactive, modular, and thread-safe.
┌─────────────────────────────────────────────────┐
│ AEDevLensProvider │ Compose wrapper
│ ┌───────────────────────────────────────────┐ │
│ │ AEDevLens (Core) │ │ Plugin engine
│ │ ┌─────────┐ ┌─────────┐ ┌────────────┐ │ │
│ │ │ Logs │ │ Network │ │ Analytics │ │ │ Plugins
│ │ │ Plugin │ │ Plugin │ │ Plugin │ │ │
│ │ └────┬────┘ └────┬────┘ └─────┬──────┘ │ │
│ │ │ │ │ │ │
│ │ ┌────┴────┐ ┌────┴────┐ ┌────┴──────┐ │ │
│ │ │LogStore │ │NetStore │ │AnalyticsStore│ │ Data layer
│ │ └─────────┘ └─────────┘ └───────────┘ │ │
│ └───────────────────────────────────────────┘ │
└─────────────────────────────────────────────────┘
| Platform | Minimum Version |
|---|---|
| Android | API 24 (Android 7.0) |
| iOS | 15.0 |
| Kotlin | 2.1.10+ |
| Compose Multiplatform | 1.7.3+ |
Contributions are welcome! Please read the Contributing Guide first.
git clone https://github.com/abdo-essam/AEDevLens.git
cd AEDevLens
./gradlew build
./gradlew allTestsCopyright 2026 Abdo Essam
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0