From personal-skills
Use when setting up or refactoring Android Gradle build logic — convention plugins, composite builds, version catalogs, and shared build configuration across modules.
How this skill is triggered — by the user, by Claude, or both
Slash command
/personal-skills:android-gradle-logicThe summary Claude sees in its skill listing — used to decide when to auto-load this skill
Centralise build logic in reusable Convention Plugins instead of copy-pasting `build.gradle.kts` configuration across modules.
Centralise build logic in reusable Convention Plugins instead of copy-pasting build.gradle.kts configuration across modules.
root/
├── build-logic/
│ ├── convention/
│ │ ├── src/main/kotlin/
│ │ │ ├── AndroidApplicationConventionPlugin.kt
│ │ │ ├── AndroidLibraryConventionPlugin.kt
│ │ │ └── AndroidComposeConventionPlugin.kt
│ │ └── build.gradle.kts
│ └── settings.gradle.kts
├── gradle/
│ └── libs.versions.toml
├── app/
│ └── build.gradle.kts ← just: plugins { alias(libs.plugins.myapp.android.application) }
├── feature/home/
│ └── build.gradle.kts ← just: plugins { alias(libs.plugins.myapp.android.library) }
└── settings.gradle.kts
build-logic as a Composite Build// settings.gradle.kts
pluginManagement {
includeBuild("build-logic")
repositories {
google()
mavenCentral()
gradlePluginPortal()
}
}
dependencyResolutionManagement {
repositoriesMode.set(RepositoriesMode.FAIL_ON_PROJECT_REPOS)
repositories {
google()
mavenCentral()
}
}
build-logic/settings.gradle.kts// build-logic/settings.gradle.kts
dependencyResolutionManagement {
repositories {
google()
mavenCentral()
}
versionCatalogs {
create("libs") {
from(files("../gradle/libs.versions.toml"))
}
}
}
rootProject.name = "build-logic"
include(":convention")
build-logic/convention/build.gradle.ktsplugins {
`kotlin-dsl`
}
dependencies {
compileOnly(libs.android.gradlePlugin)
compileOnly(libs.kotlin.gradlePlugin)
compileOnly(libs.ksp.gradlePlugin)
}
gradlePlugin {
plugins {
register("androidApplication") {
id = "myapp.android.application"
implementationClass = "AndroidApplicationConventionPlugin"
}
register("androidLibrary") {
id = "myapp.android.library"
implementationClass = "AndroidLibraryConventionPlugin"
}
register("androidCompose") {
id = "myapp.android.compose"
implementationClass = "AndroidComposeConventionPlugin"
}
}
}
// AndroidApplicationConventionPlugin.kt
import com.android.build.api.dsl.ApplicationExtension
import org.gradle.api.Plugin
import org.gradle.api.Project
import org.gradle.kotlin.dsl.configure
class AndroidApplicationConventionPlugin : Plugin<Project> {
override fun apply(target: Project) {
with(target) {
pluginManager.apply("com.android.application")
pluginManager.apply("org.jetbrains.kotlin.android")
extensions.configure<ApplicationExtension> {
compileSdk = 35
defaultConfig {
minSdk = 26
targetSdk = 35
}
}
extensions.configure<org.jetbrains.kotlin.gradle.dsl.KotlinAndroidProjectExtension> {
jvmToolchain(21)
}
}
}
}
// AndroidLibraryConventionPlugin.kt
import com.android.build.api.dsl.LibraryExtension
import org.gradle.api.Plugin
import org.gradle.api.Project
import org.gradle.kotlin.dsl.configure
class AndroidLibraryConventionPlugin : Plugin<Project> {
override fun apply(target: Project) {
with(target) {
pluginManager.apply("com.android.library")
pluginManager.apply("org.jetbrains.kotlin.android")
extensions.configure<LibraryExtension> {
compileSdk = 35
defaultConfig.minSdk = 26
}
extensions.configure<org.jetbrains.kotlin.gradle.dsl.KotlinAndroidProjectExtension> {
jvmToolchain(21)
}
}
}
}
// AndroidComposeConventionPlugin.kt
import com.android.build.api.dsl.CommonExtension
import org.gradle.api.Plugin
import org.gradle.api.Project
import org.gradle.kotlin.dsl.getByType
class AndroidComposeConventionPlugin : Plugin<Project> {
override fun apply(target: Project) {
with(target) {
pluginManager.apply("org.jetbrains.kotlin.plugin.compose")
val extension = extensions.getByType<CommonExtension<*, *, *, *, *, *>>()
extension.buildFeatures.compose = true
}
}
}
# gradle/libs.versions.toml
[plugins]
myapp-android-application = { id = "myapp.android.application", version = "unspecified" }
myapp-android-library = { id = "myapp.android.library", version = "unspecified" }
myapp-android-compose = { id = "myapp.android.compose", version = "unspecified" }
// app/build.gradle.kts
plugins {
alias(libs.plugins.myapp.android.application)
alias(libs.plugins.myapp.android.compose)
alias(libs.plugins.hilt)
alias(libs.plugins.ksp)
}
android {
namespace = "com.example.app"
defaultConfig.applicationId = "com.example.app"
defaultConfig.versionCode = 1
defaultConfig.versionName = "1.0"
}
dependencies {
implementation(projects.feature.home)
implementation(libs.hilt.android)
ksp(libs.hilt.compiler)
}
// feature/home/build.gradle.kts
plugins {
alias(libs.plugins.myapp.android.library)
alias(libs.plugins.myapp.android.compose)
}
android.namespace = "com.example.feature.home"
The feature module's build file is now just 5 lines. All common configuration lives in the convention plugins.
The convention plugin examples above target AGP 8. AGP 9 changes several things that hit build logic directly: it drops the standalone org.jetbrains.kotlin.android plugin (Kotlin is built into com.android.application / com.android.library), removes BaseExtension and the old variant APIs (applicationVariants → androidComponents { onVariants { … } }), moves kotlinOptions {} to a top-level kotlin { compilerOptions { … } }, and makes kapt incompatible (migrate to KSP). Any convention plugin that touches these needs updating.
Defer to the dedicated migration skills for the mechanics rather than duplicating the steps here: Google's agp-9-upgrade for pure-Android projects, JetBrains' kotlin-tooling-agp9-migration for KMP, and this repo's gradle-build-performance skill for the kapt → KSP step.
build-logic included as a composite build in root settings.gradle.ktscompileSdk, minSdk, Java toolchain defined once in plugins — not in each modulebuild-logic itself resolves dependencies from the root version catalognpx claudepluginhub w0lzard/wolzard-s-marketplace --plugin personal-skillsBuilds a throwaway prototype to answer a design question about UI appearance or state/logic behavior. Guides you through two branches: interactive terminal app for logic validation, or multiple UI variations for visual exploration.