A version catalog moves every version number out of the build scripts into one TOML file that Gradle 19,597 finds at gradle/libs.versions.toml by convention:
[versions]
agp = "9.4.0"
kotlin = "2.4.20"
composeBom = "2026.09.00"
activity = "1.13.0"
[libraries]
activity-compose = { module = "androidx.activity:activity-compose", version.ref = "activity" }
compose-bom = { module = "androidx.compose:compose-bom", version.ref = "composeBom" }
compose-ui = { module = "androidx.compose.ui:ui" }
compose-ui-tooling = { module = "androidx.compose.ui:ui-tooling" }
compose-ui-tooling-preview = { module = "androidx.compose.ui:ui-tooling-preview" }
compose-material3 = { module = "androidx.compose.material3:material3" }
[plugins]
android-application = { id = "com.android.application", version.ref = "agp" }
kotlin-compose = { id = "org.jetbrains.kotlin.plugin.compose", version.ref = "kotlin" }Gradle generates a type-safe libs accessor from it, turning dashes into dots: compose-ui-tooling becomes libs.compose.ui.tooling, and plugins are applied with alias(libs.plugins.kotlin.compose). The Compose 234 libraries carry no version because the Compose BOM (bill of materials), added with platform(), supplies a tested set: ./gradlew :app:dependencies resolves ui to 1.12.1 and material3 to 1.4.0. Upgrading Compose is a one-line edit of composeBom; Renovate 22,612 (github.com/renovatebot/renovate (https://github.com/renovatebot/renovate 22,612 )) reads the catalog and opens upgrade pull requests. Keep aliases short, because TOML inline tables cannot span lines.