How do you apply a plugin using a version catalog (libs.versions.toml) with alias(libs.plugins.x), and how is the version wired in?
answer
- [plugins] id + version.ref
- alias(libs.plugins.x)
- kebab → camelCase accessor
- shared version.ref keeps lockstep
- catalog read at settings time
basics
~10 sDefine the plugin under [plugins] in gradle/libs.versions.toml (id + version, version can reference [versions]). Then in plugins {} write alias(libs.plugins.x). Gradle generates the typesafe libs accessor and supplies the version from the catalog.
solid answer
~40 sA **version catalog** is a TOML file (conventionally `gradle/libs.versions.toml`) that centralizes dependency and plugin coordinates. Under `[plugins]` you declare each plugin with an `id` and a `version` (or `version.ref` pointing into `[versions]`). Gradle auto-generates a typesafe accessor named `libs` (the catalog's default name), so in any `build.gradle.kts` you apply the plugin with `alias(libs.plugins.springBoot)` inside `plugins {}`. The TOML key `spring-boot` maps to the accessor `libs.plugins.springBoot` (kebab/underscore segments become nested camelCase). Because the version lives in the catalog, build scripts carry no literal versions, and the same `version.ref` can be shared by a plugin and its companion dependencies — keeping, e.g., the Kotlin plugin and Kotlin stdlib in lockstep. The catalog is read very early (it's a settings-level feature), which is why it can feed the early `plugins {}` block.
code
toml · 11 lines# gradle/libs.versions.toml
[versions]
springBoot = "3.3.0"
[plugins]
spring-boot = { id = "org.springframework.boot", version.ref = "springBoot" }
# build.gradle.kts
# plugins {
# alias(libs.plugins.springBoot)
# }go deeper
Recall that you declare under [plugins] and apply with alias(libs.plugins.x).
Explain version.ref, the kebab→camelCase mapping, and why no literal version appears in scripts.
Use shared version.ref to keep plugin+library in lockstep and justify a single catalog across modules.
Treat the catalog as governance: one manifest, possibly published/shared across repos for org-wide version policy.
## What a version catalog is A **version catalog** is a single source of truth for versions, libraries, bundles, and plugins, written in TOML. By default Gradle reads `gradle/libs.versions.toml` and exposes it as the `libs` extension with typesafe, IDE-completable accessors. ```toml # gradle/libs.versions.toml [versions] kotlin = "2.0.0" springBoot = "3.3.0" [plugins] kotlin-jvm = { id = "org.jetbrains.kotlin.jvm", version.ref = "kotlin" } spring-boot = { id = "org.springframework.boot", version.ref = "springBoot" } spotless = { id = "com.diffplug.spotless", version = "6.25.0" } ``` ## Applying via alias() In the `plugins {}` block you do **not** repeat the id or version — you reference the catalog entry: ```kotlin plugins { alias(libs.plugins.kotlinJvm) alias(libs.plugins.springBoot) alias(libs.plugins.spotless) apply false // alias still supports apply false } ``` ### Name mapping rules TOML keys use `-`/`_` as segment separators; accessors turn them into nested camelCase: - `kotlin-jvm` → `libs.plugins.kotlinJvm` - `spring-boot` → `libs.plugins.springBoot` ## Why version.ref matters `version.ref` points a plugin at an entry in `[versions]`. That same `[versions]` entry can also version libraries: ```toml [libraries] kotlin-stdlib = { module = "org.jetbrains.kotlin:kotlin-stdlib", version.ref = "kotlin" } ``` Now the Kotlin **plugin** and the Kotlin **stdlib** always move together — bump `kotlin` once. ## How the version is wired into the early plugins block Catalogs are a settings-time feature: Gradle parses the TOML before scripts execute and synthesizes the `libs` accessor. That is what makes it legal to use `alias(libs.plugins.x)` inside the otherwise-restricted `plugins {}` block, where arbitrary expressions/variables are forbidden. The accessor is essentially a precomputed constant, not a runtime lookup. ## Sharing one catalog across modules The catalog declared in `settings.gradle.kts` (or the default file) is visible to **every** module, so plugin versions are defined once and applied everywhere by alias — the cleanest pattern for multi-module builds. ## Common gotcha `alias(libs.plugins.x)` is only valid for entries under **[plugins]**. Putting a plugin under `[libraries]` and aliasing it as a plugin fails. Likewise `libs.versions.kotlin` gives the version string, not something applicable as a plugin.
- How does the TOML key spring-boot become an accessor in the build script?Gradle generates a typesafe `libs` accessor where `-`/`_`-separated segments become nested camelCase: `spring-boot` → `libs.plugins.springBoot`. It is `libs.plugins.<name>` for [plugins] entries.
- Can you still use apply false with an alias?Yes. `alias(libs.plugins.x) apply false` resolves the version from the catalog without applying the plugin — useful for declaring versions at the root of a multi-project build.
- Why can alias() appear in the early plugins {} block when variables can't?Version catalogs are parsed at settings time and the `libs` accessors are generated constants, not runtime expressions, so they satisfy the block's literal-only constraint.
The catalog is like a parts manifest: build scripts order parts by name (alias) and the manifest decides the exact version everyone gets.
saying these in an interview costs you the question
- Putting the plugin under [libraries] and trying to alias it as a plugin.
- Repeating the version literal in the script even though the catalog already carries it.
- Assuming the accessor keeps the TOML's kebab-case (it becomes camelCase).