| name | kmp-gradle-doctor |
| description | Diagnose and fix Kotlin Multiplatform Gradle, source-set, dependency, Android target, Compose plugin, KGP/AGP, testing, static-analysis, and CI issues. |
KMP Gradle Doctor
Set $PLUGIN_ROOT ($env:PLUGIN_ROOT in PowerShell; same path suffix) once: host plugin-root variable when defined (Claude Code: PLUGIN_ROOT="$CLAUDE_PLUGIN_ROOT"), else this plugin root's absolute path. Bundled commands use it.
Use for KMP build failures; Gradle DSL changes; plugin version alignment; target declarations; source-set hierarchy; Android-KMP plugin migration; dependency placement; KSP/KAPT; detekt/ktlint; Compose compiler; CI; test task selection.
Diagnosis Flow
- Read:
settings.gradle(.kts)
- root/module
build.gradle(.kts)
gradle/libs.versions.toml
gradle.properties
gradle/wrapper/gradle-wrapper.properties
- Run:
python3 "$PLUGIN_ROOT/scripts/kmp_inspector.py" --root <project-root>
- Classify modules:
- KMP library
- Android app shell
- pure Android library
- iOS Xcode app
- desktop/web/server app
- convention plugin or build logic
- Find smallest failing task. Avoid
clean unless cache state is suspected.
- Check official docs for current DSL/version-sensitive guidance before edits.
- If the failure looks host-specific on macOS/iOS, separate project diagnosis from environment diagnosis. Use
kdoctor only if installed or explicitly approved to install; scope: host/toolchain readiness.
Environment Triage
Use project static inspection first. Then consider host diagnostics when symptoms include Xcode selection, CocoaPods/Ruby, Android Studio plugin, JDK/JAVA_HOME, simulator, or iOS Gradle task failures unrelated to source changes.
Useful checks:
xcode-select -p
xcodebuild -version
java -version
./gradlew -version
kdoctor -v
Do not install/update KDoctor, CocoaPods, Ruby, Xcode, Android Studio, JDKs, or SDK tools unless the user explicitly asked for environment setup.
Build Governance
Medium/large KMP projects: inspect whether repeated configuration is centralized.
- Prefer included-build
build-logic/ or buildSrc/ convention plugins when many modules repeat setup.
- Prefer version catalogs for plugin/dependency coordinates.
- Prefer central
pluginManagement and dependencyResolutionManagement in settings.
- Avoid ad hoc repositories in module build files.
- Keep stack-specific choices (DI, database, obfuscation, codegen, publishing) opt-in by module role.
Source-Set Rules
- Prefer default hierarchy template when the target combination is covered.
- Manual
dependsOn() edges can disable the default hierarchy template; keep them only for real non-default sharing needs.
- Declare targets before source-set references.
- Place dependencies in narrowest valid source sets:
- shared/target-published libraries:
commonMain
- Android-only artifacts:
androidMain
- iOS-only bindings:
iosMain or exact native source set
- JVM/Desktop-only artifacts:
jvmMain or named desktop source set
- Before moving to
commonMain, verify every configured target publishes the artifact.
Android-KMP Rules
Android-targeting KMP library modules on modern AGP:
- Prefer
com.android.kotlin.multiplatform.library.
- Keep Android config in
kotlin { android { ... } }.
- Do not use a top-level
android {} block after Android-KMP library plugin migration.
- Android-KMP library plugin is single-variant: no
buildTypes or productFlavors in that module.
- Enable only used features:
androidResources { enable = true } if Android resources or Compose resources need Android resource processing.
withJava() for Java sources.
- host/device test builders for Android tests.
localDependencySelection for variant-rich Android library consumption.
- For Compose preview tooling in Android-KMP library modules, verify current workaround before using debug-only configurations.
Build And Test Commands
Prefer the narrowest proof:
./gradlew :shared:compileKotlinMetadata
./gradlew :shared:compileKotlinIosSimulatorArm64
./gradlew :shared:jvmTest
./gradlew :shared:allTests
./gradlew :androidApp:assembleDebug
./gradlew :desktopApp:run
Task names vary by module/target; use ./gradlew :module:tasks --all when uncertain.
Static Analysis
- detekt often needs explicit KMP source-set inputs/config; do not assume root
detekt checks all commonMain, iosMain, and androidMain code.
- Type-resolution can explode runtime in large KMP monorepos; prefer scoped tasks; avoid enabling all Android variants unless required.
- KSP must match Kotlin versions; verify compatibility before bumping KGP or KSP.
- KAPT is modern Android/KMP migration risk; prefer KSP or isolate legacy processors.
- For published KMP libraries, check whether Kotlin ABI validation is configured or intentionally skipped.
- If a module exposes many
api(...) dependencies, review whether public surface is too broad.
CI Pattern
- Split jobs by cost/platform: common/JVM tests first on Linux; Android builds on Linux; iOS simulator/Apple framework checks on macOS.
- Use official Gradle setup action and one shared Java/Gradle setup path.
- Upload test reports/platform artifacts.
- Keep signing, notarization, and store publishing separate from ordinary PR validation.