- 📝 Overview
- 💾 Installation
- 🚀 Remote Debugger Support
- ✨ Features & Usage
- ⚙️ Runtime Configuration
- 🍏 iOS Limitations
- 💭 Inspiration
- 📦 Dependency Versions
- 💡 Tips & Extras
- 📄 License
Axer is a modern, multiplatform library for advanced runtime inspection and debugging in Kotlin/Android/JVM/iOS projects. It enables you to:
- Monitor HTTP requests with deep inspection and redaction capabilities (Ktor/OkHttp supported)
- Record and inspect exceptions (both fatal and non-fatal), and customize crash handling
- View and edit Room databases in real time, run custom queries, and manage multiple DBs
- Capture and display logs, powered by Napier
- Use all these features locally or remotely via the Remote Debugger app
Axer is inspired by Chucker and KtorMonitor, LensLogger but adds multiplatform support and real-time database inspection, crashes, and logs.
Add the dependencies to your project (1.2.5 is the latest version; check Releases):
implementation("io.github.orioneee:axer:1.2.5")For production, use the no-op variant to avoid runtime overhead and source changes:
implementation("io.github.orioneee:axer-no-op:1.2.5")No-op maintains the same API, so switching in/out is seamless.
Axer now features remote debugging! You can run the Axer debugger app on your desktop, discover debuggable apps (JVM or Android) on your local network, and inspect requests, exceptions, logs, databases, and more — all remotely.
⚡️ Download the remote debugger app in the Releases section.
The standalone desktop debugger is distributed there.
⚠️ On MacOS:
If you see a warning about "unsigned" applications when launching the remote debugger, see the Opening Unsigned Applications on macOS Sequoia section below.
On your debuggable app (JVM/Android), manually start the Axer server:
// for example, in an Android Activity or ViewModel
// Also you can adjust port
Axer.runServerIfNotRunning(lifecycleScope) // has second parameter for custom port
//if you want stop server from code, you can use
Axer.stopServerIfRunning()- Note: Both debugger and debuggable device must be on the same network.
- Only one server can be runned on one device at same time (Axer uses port
53214by default), so if you want monitor multiple apps set different ports for each app or ensure only one server is running.
If your Android device is connected via ADB and you want to debug remotely from your PC avoid local network, you can forward a port using ADB:
adb forward tcp:11111 tcp:5321411111— port on your PC (you can choose any free port)53214— default port used by Axer server on the device
Now, in the Axer remote debugger app, connect to 127.0.0.1 (your local PC) and specify the chosen port (11111).
This will forward all traffic from your PC to the Axer server running on your Android device.
Also this work with emulators so you need just forawrd port, its can be the same port on pc for example
adb forward tcp:53214 tcp:53214And now you can add in axer remote debugger ip 127.0.0.1, port 53214 and use it.
- If you run Axer server on a custom port, just forward to that port instead.
- If you run the server on a custom IP (e.g., on an emulator or in a specific network setup), specify that IP in the debugger app.
Summary table:
| Scenario | Connect to (host) | Port |
|---|---|---|
| ADB port forwarding (local PC) | 127.0.0.1 | 11111 |
| Same network (Wi-Fi/LAN) | Device's IP | 53214 |
| Custom port or IP | Custom IP | (chosen) |
- Note: Both debugger and debuggable device must be on the same network.
- Only one server can be runned on one device at same time (Axer uses port
53214) so if you want monitor multiple app enshure only one server runned
Axer monitors HTTP requests and highlights important data using customizable selectors.
Supports Ktor and OkHttp out of the box.
val client = HttpClient {
install(DefaultRequest) {
contentType(ContentType.Application.Json)
if (!headers.contains("Authorization")) {
header("Authorization", "Bearer your_token_here")
}
}
install(Axer.ktorPlugin) {
requestReducer = { request ->
val redactedHeaders = request.headers.mapValues { (key, value) ->
if (key.equals("Authorization", ignoreCase = true)) "Bearer ***" else value
}
request.copy(headers = redactedHeaders)
}
responseReducer = { response ->
response.copy(
headers = response.headers.mapValues { (key, value) ->
if (key.equals("Content-Type", ignoreCase = true)) "application/json" else value
}
)
}
requestImportantSelector = { request ->
listOf("Authorization: ${request.headers["Authorization"] ?: "Not set"}")
}
responseImportantSelector = { response ->
listOf("status: ${response.status}", "content-type: ${response.headers["Content-Type"]}")
}
retentionPeriodInSeconds = 60 * 60 * 1
retentionSizeInBytes = 10 * 1024 * 1024
}
}val client = OkHttpClient.Builder()
.addInterceptor(
AxerOkhttpInterceptor.Builder()
.setRequestReducer { request ->
val redactedHeaders = request.headers.mapValues { (key, value) ->
if (key.equals("Authorization", ignoreCase = true)) "Bearer ***" else value
}
request.copy(headers = redactedHeaders)
}
.setResponseReducer { response ->
response.copy(
headers = response.headers.mapValues { (key, value) ->
if (key.equals("Content-Type", ignoreCase = true)) "application/json" else value
}
)
}
.setRequestImportantSelector { request ->
listOf("Authorization: ${request.headers["Authorization"] ?: "Not set"}")
}
.setResponseImportantSelector { response ->
listOf("status: ${response.status}", "content-type: ${response.headers["Content-Type"]}")
}
.setRetentionTime(60 * 60 * 1)
.setRetentionSize(10 * 1024 * 1024)
.build()
)
.build()Display the Axer UI in your JVM app:
fun main() = application {
AxerTrayWindow()
...
}Or manually control the window:
fun main() = application {
AxerWindows()
...
}Programmatically open the Axer UI:
Axer.openAxerUI()Integrate Axer UI directly:
AxerUIEntryPoint().Screen()Access the UI also from Android/iOS by clicking the notification (requires notification permissions).
Axer logging is powered by Napier.
-
Already use Napier?
Just install the Axer log saver:Napier.base(AxerLogSaver())
-
Don't use Napier?
Use Axer logger directly:Axer.d("App", "Test debug log") Axer.e("App", "Test error log") Axer.i("App", "Test info log") Axer.w("App", "Test warning log") Axer.v("App", "Test verbose log") Axer.wtf("App", "Test assert log")
You can also log with exceptions and control saving with
record = false.
Axer captures fatal crashes and manually recorded exceptions.
Install the error handler on your main thread:
-
Android:
class MainActivity : ComponentActivity() { override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) Axer.installErrorHandler() ... } }
-
JVM:
fun main() = application { Axer.installErrorHandler() ... }
-
iOS:
fun MainViewController(): UIViewController { Axer.installErrorHandler() ... }
Customize crash handling by overriding AxerUncaughtExceptionHandler:
open class AxerUncaughtExceptionHandler : UncaughtExceptionHandler {
// Custom implementation
}
...
Thread.setDefaultUncaughtExceptionHandler(MyUncaughtExceptionHandler())Record exceptions manually:
Axer.recordException(Exception("Test exception"))
Axer.recordAsFatal(Exception("Test fatal exception"))Axer supports live Room DB inspection and custom queries, with multiple DB support.
builder
.setDriver(AxerBundledSQLiteDriver.getInstance())
.setQueryCoroutineContext(Dispatchers.IO)
.fallbackToDestructiveMigration(false)
.build()Only required setup:
.setDriver(AxerBundledSQLiteDriver.getInstance())Enable/disable monitoring options at runtime (all enabled by default):
Axer.configure {
enableRequestMonitor = true
enableExceptionMonitor = true
enableLogMonitor = true
enableDatabaseMonitor = true
}- Stack traces are not supported.
- No support for remote debugging on iOS.
Axer is a lightweight, cross-platform HTTP logging library for Kotlin Multiplatform projects.
It’s inspired by Chucker and KtorMonitor, LensLogger with added multiplatform and Room DB inspection support.
| Dependency | Version |
|---|---|
| Kotlin | 2.2.10 |
| Compose | 1.9.0-rc01 |
| Ktor | 3.2.3 |
| Koin | 4.1.0 |
| Room | 2.7.2 |
| OkHttp | 5.1.0 |
| Napier | 2.7.1 |
| kotlinx-coroutines | 1.10.2 |
| kotlinx-serialization | 1.9.0 |
| kotlinx-datetime | 0.7.1 |
| Accompanist | 0.37.3 |
| Coil Compose | 3.3.0 |
| Navigation Compose | 2.9.0-beta04 |
| minSdk | 21 |
- For the latest desktop remote debugger, check Releases.
- You can mix and match all features or use only what you need.
- The API is intentionally minimal and consistent across platforms.
Apache License 2.0.