docs/setup/compiler-plugin.md
The Koin Compiler Plugin is the recommended approach for all new Kotlin 2.x projects. It provides auto-wiring, compile-time safety, and a cleaner DSL syntax.
The Koin Compiler Plugin is a native Kotlin Compiler Plugin (K2) that:
See Introduction to Koin Compiler Plugin for details on features and benefits.
:::tip IDE Plugin Install the Koin IDE Plugin for Android Studio & IntelliJ IDEA — code navigation between definitions and injection points, live safety checks, and dependency graph visualization. :::
First, check latest versions:
Then, in your gradle/libs.versions.toml:
[versions]
koin = "<KOIN_VERSION>"
koin-plugin = "<KOIN_PLUGIN_VERSION>"
[libraries]
koin-core = { module = "io.insert-koin:koin-core", version.ref = "koin" }
koin-annotations = { module = "io.insert-koin:koin-annotations", version.ref = "koin" }
[plugins]
koin-compiler = { id = "io.insert-koin.compiler.plugin", version.ref = "koin-plugin" }
In your settings.gradle.kts:
pluginManagement {
repositories {
mavenCentral()
gradlePluginPortal()
}
}
In your module's build.gradle.kts:
plugins {
alias(libs.plugins.koin.compiler)
}
dependencies {
implementation(libs.koin.core)
implementation(libs.koin.annotations) // For annotation support
}
:::tip
Using @KoinViewModel or @KoinWorker? Those annotations need their runtime DSL to be on the classpath:
@KoinViewModel → implementation("io.insert-koin:koin-core-viewmodel")@KoinWorker → implementation("io.insert-koin:koin-android-workmanager")The compiler will fail with a clear error naming the missing artifact if you add the annotation without its runtime — no more silent NoDefinitionFoundException at startup.
:::
[versions]
koin = "<KOIN_VERSION>"
koin-plugin = "<KOIN_PLUGIN_VERSION>"
[libraries]
koin-core = { module = "io.insert-koin:koin-core", version.ref = "koin" }
koin-annotations = { module = "io.insert-koin:koin-annotations", version.ref = "koin" }
[plugins]
koin-compiler = { id = "io.insert-koin.compiler.plugin", version.ref = "koin-plugin" }
pluginManagement {
repositories {
mavenCentral()
gradlePluginPortal()
}
}
plugins {
alias(libs.plugins.koin.compiler)
}
dependencies {
implementation(libs.koin.core)
implementation(libs.koin.annotations)
}
Import from the compiler plugin package:
import org.koin.plugin.module.dsl.*
import org.koin.dsl.module
val appModule = module {
single<Database>()
single<ApiClient>()
single<UserRepository>()
viewModel<UserViewModel>()
}
:::info
The Compiler Plugin DSL is in package org.koin.plugin.module.dsl. Classic DSL remains in org.koin.dsl.
:::
Use annotations on your classes:
@Singleton
class Database
@Singleton
class ApiClient
@Singleton
class UserRepository(
private val database: Database,
private val apiClient: ApiClient
)
@KoinViewModel
class UserViewModel(private val repository: UserRepository) : ViewModel()
@Module
@ComponentScan("com.myapp")
class AppModule
With the Compiler Plugin, use typed APIs to start Koin - no generated code needed:
@KoinApplication
@ComponentScan("com.myapp")
class MyApp
// Start Koin with typed API
startKoin<MyApp>()
// Or with additional configuration
startKoin<MyApp> {
androidContext(this@MyApplication)
printLogger()
}
Available typed APIs:
| API | Description |
|---|---|
startKoin<T>() | Start Koin globally with application T |
startKoin<T> { } | Start Koin with application T and configuration block |
koinApplication<T>() | Create isolated KoinApplication with T |
koinConfiguration<T>() | Create KoinConfiguration from T (for Compose KoinApplication, Ktor, etc.) |
Where T is a class annotated with @KoinApplication.
Loading individual modules:
You can also load @Module classes directly without @KoinApplication, using module<T>() or modules():
startKoin {
module<NetworkModule>() // Load a single module
modules(DataModule::class, CacheModule::class) // Load multiple modules
}
| API | Description |
|---|---|
module<T>() | Load a single @Module class into the KoinApplication |
modules(vararg KClass) | Load multiple @Module classes into the KoinApplication |
Where T / each KClass is a class annotated with @Module. This is useful for tests or when mixing annotation and DSL modules:
// In tests
@get:Rule
val koinTestRule = KoinTestRule.create {
module<NetworkModule>()
}
Configure the compiler plugin in your build.gradle.kts:
koinCompiler {
userLogs = true
debugLogs = false
unsafeDslChecks = true
}
| Option | Description | Default |
|---|---|---|
compileSafety | Compile-time dependency validation (A2/A3/A4) | true |
strictSafety | Force aggregator's safety pass to re-run on every build (bypasses Kotlin IC) | auto-detected on aggregator modules |
skipDefaultValues | Skip injection for parameters with Kotlin default values | true |
userLogs | Enable logs for component detection and DSL/annotation processing | false |
debugLogs | Enable verbose debug logs for internal plugin processing | false |
unsafeDslChecks | Validate that create() calls inside lambdas are the only instruction | true |
:::tip
Set userLogs = true during development to see which components are detected and processed by the plugin.
:::
The Koin Compiler Plugin provides compile-time dependency verification — validating that all your dependencies can be resolved at build time rather than failing at runtime. This is enabled by default.
koinCompiler {
compileSafety = true // Enabled by default
skipDefaultValues = true // Enabled by default
}
The plugin validates your graph at three levels: per-module (A2), full graph at startKoin<T>() (A3), and every call site (A4). See Compile-Time Safety for full details.
For projects with multiple Gradle modules:
// feature/build.gradle.kts
plugins {
alias(libs.plugins.koin.compiler)
}
dependencies {
implementation(libs.koin.core)
implementation(libs.koin.annotations)
}
// feature/src/main/kotlin/FeatureModule.kt
@Module
@ComponentScan("com.myapp.feature")
class FeatureModule
// app/build.gradle.kts
plugins {
alias(libs.plugins.koin.compiler)
}
dependencies {
implementation(project(":feature"))
implementation(libs.koin.core)
implementation(libs.koin.annotations)
}
// app/src/main/kotlin/MyModule.kt
@Module
@Configuration
class MyModule
// app/src/main/kotlin/MyApp.kt
@KoinApplication
class MyApp
class MainApplication : Application() {
override fun onCreate() {
super.onCreate()
startKoin<MyApp>()
}
}
Use @KoinApplication for the main application class with typed startup APIs.
The Compiler Plugin works with KMP projects:
// shared/build.gradle.kts
plugins {
id("org.jetbrains.kotlin.multiplatform")
alias(libs.plugins.koin.compiler)
}
kotlin {
sourceSets {
commonMain.dependencies {
implementation(libs.koin.core)
implementation(libs.koin.annotations)
}
}
}
Ensure the plugin is in your plugin repositories:
// settings.gradle.kts
pluginManagement {
repositories {
mavenCentral()
gradlePluginPortal()
}
}
The Compiler Plugin requires Kotlin 2.3.20+. Check your Kotlin version:
// build.gradle.kts
plugins {
kotlin("jvm") version "2.3.20" // Requires 2.3.20+
}
Make sure you're importing from the correct package:
// Compiler Plugin DSL
import org.koin.plugin.module.dsl.*
// Classic DSL
import org.koin.dsl.*
Like other Kotlin compiler plugins (e.g., Compose Compiler, Metro), the Koin Compiler Plugin operates at the IR level. Kotlin's incremental compilation may sometimes produce stale or inconsistent results after certain changes:
Symptoms:
NoSuchMethodError or ClassNotFoundException at runtime after refactoringWhen this typically happens:
@Single → @Factory, adding/removing @Named)@ComponentScan discovery)includes or @Configuration labelsFix: Run a clean build:
./gradlew clean build
Or in Android Studio: Build → Clean Project, then Build → Rebuild Project.
:::tip If you encounter unexpected compile safety errors after a refactor, try a clean build first. This is a known limitation of incremental compilation with compiler plugins — not specific to Koin.
For graph-level changes (DSL definitions inside module { } lambdas, classes added to @ComponentScan packages), the plugin's strictSafety option auto-enables on aggregator modules to force the full-graph safety pass to re-run each build. See strictSafety for details.
:::
If the plugin reports a missing dependency that exists in a library module, ensure:
implementation(project(":lib")), but check your task dependenciesorg.koin.plugin.module.dsl.*single { Class(get() ...) } or singleOf(::Class) with single<Class>()See the DSL Style reference above for the compile-time safe syntax.
koin-ksp-compiler)koin-ksp-compiler dependencystartKoin { modules(...) } to startKoin<MyApp>()koin-annotations library remains — only the processor changes.See Migrating from KSP to Compiler Plugin for the complete guide.