Skip to content

Sidekick

A Kotlin Multiplatform debug panel for Compose apps on Android, iOS, Desktop (JVM), and Web (JS / Wasm).

Android iOS Desktop Web JS Web Wasm License Kotlin Compose

Sidekick is a debug panel composable you render in your app during development — network inspector, log viewer, preferences editor, custom screens. Your app controls when and how it's shown. In release builds, a no-op module replaces it with a passthrough composable at zero overhead.


Why Sidekick

  • One panel, many tools — built-in network inspector, log viewer, typed preferences editor, custom Composables.
  • Pluggable — implement SidekickPlugin to add anything else.
  • Zero release costcore:noop replaces the panel with a passthrough composable, and network-monitor:noop / log-monitor:noop strip the recording layer; release binaries don't contain a single byte of Sidekick UI or database code.
  • Compose Multiplatform — single UI codebase across Android, iOS, Desktop, and Web.
  • Visibility is yours to control — Sidekick renders the panel; the host app decides when to show it (FAB, shake gesture, build-type check, anything).

Built-in Plugins

Plugin What it does
Network Monitor Captures and displays all HTTP traffic via Ktor (or any client via NetworkMonitorStore).
Log Monitor Displays app logs with level filtering and search (Kermit built-in, any SDK via LogCollector).
Preferences Exposes typed settings in the panel — KSP code generation or manual DataStore bridging.
Custom Screens Wraps any Composable as a first-class debug screen.

Quick Example

@Composable
fun App() {
    val networkPlugin = remember { NetworkMonitorPlugin() }
    val plugins = remember { listOf(networkPlugin) }

    MaterialTheme {
        var sidekickVisible by remember { mutableStateOf(false) }
        Scaffold(
            floatingActionButton = {
                FloatingActionButton(onClick = { sidekickVisible = true }) {
                    Icon(Icons.Default.BugReport, contentDescription = "Open Sidekick")
                }
            },
        ) {
            Box(Modifier.fillMaxSize().padding(it)) {
                // your app content
                AnimatedVisibility(visible = sidekickVisible) {
                    Sidekick(
                        plugins = plugins,
                        actions = {
                            IconButton(onClick = { sidekickVisible = false }) {
                                Icon(Icons.Default.Close, contentDescription = "Close")
                            }
                        },
                    )
                }
            }
        }
    }
}

A FAB appears in the bottom-right corner. Tap it to open the Sidekick panel.


Ready to add Sidekick to your project? Start with Installation.


Credits

The demo app uses data from PokéAPI — a free, open RESTful Pokémon API. See pokeapi.co/about for license and usage details.