skip to content

How does applying a plugin in settings.gradle.kts differ from applying it in build.gradle.kts, and how does Gradle resolve a Settings plugin?

level: seniorimportance: should knowfreq 35%

answer

  1. Plugin<Settings> vs Plugin<Project>
  2. initialization vs configuration phase
  3. plugin marker artifact
  4. pluginManagement repositories
  5. can include but not register tasks

basics

~10 s

Settings plugins target the Settings object and run during initialization, before projects exist; project plugins target Project during configuration. Settings plugins are resolved through the pluginManagement repositories.

solid answer

~40 s

Applying a plugin in `settings.gradle.kts` means it implements `Plugin<Settings>` and runs in the **initialization** phase, before the project graph is built — so it can `include` subprojects, configure `dependencyResolutionManagement`, `toolchainManagement`, and `buildCache`. A plugin in `build.gradle.kts` implements `Plugin<Project>` and runs during **configuration**, shaping a single project. Resolution is the same mechanism: the `plugins {}` block resolves the plugin marker artifact through the repositories declared in `pluginManagement { repositories { ... } }` (defaulting to the Gradle Plugin Portal). The marker maps a plugin ID to an implementation coordinate. The key constraints: a Settings plugin can't touch tasks/projects (they don't exist yet), and you cannot apply the same plugin ID in both with different versions cleanly. Convention Settings plugins are often delivered as precompiled `Settings`-targeting plugins or via `includeBuild` of a build-logic build.

code

kotlin · 13 lines
kotlin
// settings.gradle.kts
pluginManagement {
    repositories { gradlePluginPortal() }
}
plugins {
    id("com.gradle.develocity") version "3.18"   // Plugin<Settings>, init phase
}
include("app", "core")

// build.gradle.kts (in :app)
plugins {
    id("java")                                    // Plugin<Project>, config phase
}

go deeper

for a junior

Know settings vs build file and that one runs before the other.

for a middle

Explain the phase difference and what each plugin type can configure.

for a senior

Describe plugin-marker resolution through pluginManagement and the precise capability boundary of a Settings plugin.

for a principal

Design org convention Settings plugins delivered via includeBuild or an internal portal, standardizing structure, catalogs, and cache policy.

## Two different extension points Gradle plugins implement `Plugin<T>`: - `Plugin<Settings>` → applied in `settings.gradle.kts`, `apply(settings)` receives the `Settings`. - `Plugin<Project>` → applied in `build.gradle.kts`, `apply(project)` receives the `Project`. The **phase** each runs in differs: - Settings file → **initialization** phase. The project graph does not exist yet. APIs available: `include`, `includeBuild`, `dependencyResolutionManagement {}`, `toolchainManagement {}`, `buildCache {}`, `enableFeaturePreview`. - Build file → **configuration** phase. The `Project` exists; you register tasks, extensions, dependencies. ## How resolution works When you write: ```kotlin plugins { id("com.gradle.develocity") version "3.18" } ``` Gradle resolves the **plugin marker artifact** `com.gradle.develocity:com.gradle.develocity.gradle.plugin:3.18`, whose POM points at the real implementation coordinate. The repositories searched are those declared in `pluginManagement { repositories { ... } }` within the *same* `settings.gradle.kts` (default: `gradlePluginPortal()`). So `pluginManagement {}` governs *where* plugins come from for both the settings `plugins {}` block and project `plugins {}` blocks. ```kotlin // settings.gradle.kts pluginManagement { repositories { gradlePluginPortal() mavenCentral() } } plugins { id("org.gradle.toolchains.foojay-resolver-convention") version "0.8.0" } ``` ## What a Settings plugin can and cannot do Can: - declare the build's structure (`include("a", "b")`), - compose builds (`includeBuild("build-logic")`), - centralize repositories/version catalogs (`dependencyResolutionManagement`), - configure build-wide features (cache, scans, toolchain resolvers). Cannot: - register tasks or configure a specific project's extensions — those objects don't exist during initialization. ## Delivering your own Settings convention plugin For org-wide standards you write a precompiled script plugin or a binary plugin targeting `Settings`, then either publish it and apply by ID, or pull it in via `includeBuild("build-logic")` and apply it in settings. This is how teams centralize toolchain, cache, and scan policy. ## Summary table | | Settings plugin | Project plugin | |---|---|---| | Implements | `Plugin<Settings>` | `Plugin<Project>` | | Applied in | `settings.gradle.kts` | `build.gradle.kts` | | Phase | initialization | configuration | | Sees | the build structure | one project | | Resolved via | pluginManagement repos | pluginManagement repos |

  • What is a plugin marker artifact and why does it exist?
    It's a small published artifact named `<id>:<id>.gradle.plugin` whose only job is to map a plugin ID + version to the real implementation coordinate, letting `plugins { id(...) }` resolve by ID.
  • Which block controls where Settings plugins are downloaded from?
    `pluginManagement { repositories { ... } }` in settings.gradle.kts; by default it uses the Gradle Plugin Portal.
  • Can a Settings plugin register a task?
    No — tasks belong to projects, which don't exist during initialization. It can only influence build structure and build-wide settings.

saying these in an interview costs you the question

  • Saying Settings plugins and Project plugins are resolved from different repository configs — both use pluginManagement.
  • Claiming a Settings plugin can configure a specific subproject's tasks directly.

context