A ktlint gradle plugin
1,716
stars
1,232
commits
Kotlin
primary language
Aug 9, 2026
updated
Provides a convenient wrapper plugin over the ktlint project.
Latest plugin version: 14.2.0
This plugin creates convenient tasks in your Gradle project that run ktlint checks or do code auto format.
The plugin can be applied to any project, but only activates if that project has the kotlin plugin applied. The assumption being that you would not want to lint code you weren't compiling.
This plugin supports the following kotlin plugins:
If you know any new Kotlin plugin that is not in this list - please, open a new issue.
This plugin was written using the new API available for the Gradle script Kotlin builds. This API is available in new versions of Gradle.
Minimal supported Gradle version: 7.4
Minimal supported Kotlin version: 1.4
Minimal supported ktlint version: 0.47.1
Minimal supported Android Gradle plugin version: 4.1.0
Build script snippet for new plugin mechanism introduced in Gradle 2.1:
plugins {
id "org.jlleitschuh.gradle.ktlint" version "<current_version>"
}
repositories {
// Required to download KtLint
mavenCentral()
}
plugins {
id("org.jlleitschuh.gradle.ktlint") version "<current_version>"
}
repositories {
// Required to download KtLint
mavenCentral()
}
To configure the plugin using a version catalog, first, add the following entries to your libs.versions.toml file:
[versions]
ktlint = "<current_version>"
[plugins]
ktlint = { id = "org.jlleitschuh.gradle.ktlint", version.ref = "ktlint" }
Next, apply it to your project:
plugins {
alias(libs.plugins.ktlint)
}
repositories {
// Required to download KtLint
mavenCentral()
}
plugins {
alias(libs.plugins.ktlint)
}
repositories {
// Required to download KtLint
mavenCentral()
}
Build script snippet for use in all Gradle versions:
buildscript {
repositories {
maven {
url "https://plugins.gradle.org/m2/"
}
}
dependencies {
classpath "org.jlleitschuh.gradle:ktlint-gradle:<current_version>"
}
}
repositories {
// Required to download KtLint
mavenCentral()
}
apply plugin: "org.jlleitschuh.gradle.ktlint"
buildscript {
repositories {
maven("https://plugins.gradle.org/m2/")
}
dependencies {
classpath("org.jlleitschuh.gradle:ktlint-gradle:<current_version>")
}
}
repositories {
// Required to download KtLint
mavenCentral()
}
apply(plugin = "org.jlleitschuh.gradle.ktlint")
Optionally apply plugin to all project modules:
subprojects {
apply plugin: "org.jlleitschuh.gradle.ktlint" // Version should be inherited from parent
repositories {
// Required to download KtLint
mavenCentral()
}
// Optionally configure plugin
ktlint {
debug = true
}
}
subprojects {
apply(plugin = "org.jlleitschuh.gradle.ktlint") // Version should be inherited from parent
repositories {
// Required to download KtLint
mavenCentral()
}
// Optionally configure plugin
configure<org.jlleitschuh.gradle.ktlint.KtlintExtension> {
debug.set(true)
}
}
Plugin supports KtLint baseline with following limitations:
Run task ktlintGenerateBaseline to generate a new baseline.
To test KtLint snapshots add following configuration into project build script (latest KtLint snapshot version name you could find here):
repositories {
maven {
url 'https://oss.sonatype.org/content/repositories/snapshots'
}
}
ktlint {
version = "0.41.0-SNAPSHOT"
}
repositories {
maven("https://oss.sonatype.org/content/repositories/snapshots")
}
ktlint {
version.set("0.41.0-SNAPSHOT")
}
The version of ktlint used by default may change between patch versions of this plugin. If you don't want to inherit these changes then make sure you lock your version here. Consult the ktlint release notes for more information about the differences between ktlint versions.
You may declare the ktlint version in the ktlint extension, for example:
ktlint {
version = "1.4.0"
}
You may also declare it in ktlint-plugins.properties, which allows coordination of the ktlint version between this plugin and the intellij kotlin plugin. Example:
ktlint-version=1.0.0
All properties in the following configuration block are optional. If you don't configure these, the defaults defined in the KtlintExtension object will be used.
import org.jlleitschuh.gradle.ktlint.reporter.ReporterType
ktlint {
debug = true
verbose = true
android = false
outputToConsole = true
outputColorName = "RED"
ignoreFailures = true
enableExperimentalRules = true
additionalEditorconfigFile = file("/some/additional/.editorconfig") // not supported with ktlint 0.47+
additionalEditorconfig = [ // not supported until ktlint 0.49
"max_line_length": "20"
]
disabledRules = ["final-newline"] // not supported with ktlint 0.48+
baseline = file("my-project-ktlint-baseline.xml")
reporters {
reporter "plain"
reporter "checkstyle"
reporter "sarif"
customReporters {
"csv" {
fileExtension = "csv"
dependency = project(":project-reporters:csv-reporter")
}
"yaml" {
fileExtension = "yml"
dependency = "com.example:ktlint-yaml-reporter:1.0.0"
}
}
}
kotlinScriptAdditionalPaths {
include fileTree("scripts/")
}
filter {
exclude("**/generated/**")
include("**/kotlin/**")
}
}
dependencies {
ktlintRuleset "com.github.username:rulseset:main-SNAPSHOT"
ktlintRuleset files("/path/to/custom/rulseset.jar")
ktlintRuleset project(":chore:project-ruleset")
}
or in kotlin script:
import org.jlleitschuh.gradle.ktlint.reporter.ReporterType
configure<org.jlleitschuh.gradle.ktlint.KtlintExtension> {
version.set("0.22.0")
debug.set(true)
verbose.set(true)
android.set(false)
outputToConsole.set(true)
outputColorName.set("RED")
ignoreFailures.set(true)
enableExperimentalRules.set(true)
additionalEditorconfigFile.set(file("/some/additional/.editorconfig")) // not supported with ktlint 0.47+
additionalEditorconfig.set( // not supported until ktlint 0.49
mapOf(
"max_line_length" to "20"
)
)
disabledRules.set(setOf("final-newline")) // not supported with ktlint 0.48+
baseline.set(file("my-project-ktlint-baseline.xml"))
reporters {
reporter(ReporterType.PLAIN)
reporter(ReporterType.CHECKSTYLE)
customReporters {
register("csv") {
fileExtension = "csv"
dependency = project(":project-reporters:csv-reporter")
}
register("yaml") {
fileExtension = "yml"
dependency = "com.example:ktlint-yaml-reporter:1.0.0"
}
}
}
kotlinScriptAdditionalPaths {
include(fileTree("scripts/"))
}
filter {
exclude("**/generated/**")
include("**/kotlin/**")
}
}
dependencies {
ktlintRuleset("com.github.username:rulseset:main-SNAPSHOT")
ktlintRuleset(files("/path/to/custom/rulseset.jar"))
ktlintRuleset(project(":chore:project-ruleset"))
}
It is possible also to define different from default output directory for generated reports (by default it is "build/reports/ktlint"):
tasks.withType(org.jlleitschuh.gradle.ktlint.tasks.GenerateReportsTask) {
reportsOutputDirectory = project.layout.buildDirectory.dir("other/location/$name")
}
tasks.withType<org.jlleitschuh.gradle.ktlint.tasks.GenerateReportsTask> {
reportsOutputDirectory.set(
project.layout.buildDirectory.dir("other/location/$name")
)
}
Note: If Ktlint custom reporter creates report output file internally, for example:
class CsvReporter(
private val out: PrintStream
) : Reporter {
override fun onLintError(file: String, err: LintError, corrected: Boolean) {
val line = "$file;${err.line};${err.col};${err.ruleId};${err.detail};$corrected"
out.println(line)
File("some_other_file.txt").write(line) // <-- Here!!!
}
}
"some_other_file.txt" won't be captured as task output. This may lead to the problem, that task will always be not "UP_TO_DATE" and caching will not work.
By default, KtLint Gradle workers will use at most 256mb of heap size. For some projects it may be not enough, but it is possible to change:
tasks.withType(org.jlleitschuh.gradle.ktlint.tasks.BaseKtLintCheckTask).configureEach {
it.workerMaxHeapSize.set("512m")
}
tasks.withType<org.jlleitschuh.gradle.ktlint.tasks.BaseKtLintCheckTask> {
workerMaxHeapSize.set("512m")
}
This repository provides the following examples of how to set up this plugin:
build.gradle filesbuild.gradle.kts filesThis plugin adds following tasks to every project:
loadKtlintReporters - preloads KtLint ReportersrunKtlintCheckOverKotlinScripts - runs actual lint check over project Kotlin script filesktlintKotlinScriptCheck - generates reports and prints issues into Gradle console based on lint check found errors.
This task execution depends on loadKtlintReporters and runKtlintCheckOverKotlinScripts tasks execution outputsrunKtlintFormatOverKotlinScripts - tries to format according to the code style project Kotlin script filesktlintKotlinScriptFormat - generate reports and prints issues into Gradle console based on found non-formattable errors.
This task execution depends on loadKtlintReporters and runKtlintFormatOverKotlinScripts tasks execution outputsktlintCheck - checks all SourceSets and project Kotlin script filesktlintFormat - tries to format according to the code style all SourceSets Kotlin files and project Kotlin script filesThen for each SourceSet plugin adds following tasks:
runKtlintCheckOver[source set name]SourceSet - runs actual lint check on every Kotlin file in given SourceSetktlint[source set name]SourceSetCheck - generates reports and prints issues into Gradle console based on lint check found errors.
This task execution depends on loadKtlintReporters and runKtlintCheckOver[source set name]SourceSet tasks execution outputsrunKtlintFormatOver[source set name]SourceSet - tries to format according to the code style every Kotlin file in given SourceSetktlint[source set name]SourceSetFormat - reformats files, generates reports and prints issues into Gradle console based on found non-formattable errors.
This task execution depends on loadKtlintReporters and runKtlintFormatOver[source set name]SourceSet tasks execution outputsFollowing additional tasks are added:
addKtlintCheckGitPreCommitHook - adds Git pre-commit hook,
that runs ktlint check over staged files.addKtlintFormatGitPreCommitHook - adds Git pre-commit hook,
that runs ktlint format over staged files and adds fixed files back to commit.All these additional tasks are always added only to the root project.
Yes. Just use gradle --continue option:
$ ./gradlew --continue ktlintCheck
No. These approaches are not equivalent to how they work. The problem that the plugin may not find some of the kotlin plugins if both approaches are used in the project configuration. Especially it is related to the Android plugin.
Yes, check tasks support it. On the first run, the task will check all files in the source set, on subsequent runs it will check only added/modified files.
Format tasks do not check files incrementally.
Gradle based filtering are only working for files located inside project (subproject) folder, see https://github.com/gradle/gradle/issues/3417 To filter files outside project dir, use:
exclude { element -> element.file.path.contains("generated/") }
Ensure you are not pinning Kotlin version for "ktlint*" configurations added by plugin.
KtLint relies on Kotlin compiler to parse source files. Each version of KtLint are build using specific Kotlin version.
To exclude "ktlint*" Gradle configurations from Kotlin version pinning - use following approach:
configurations.all {
if (!name.startsWith("ktlint")) {
resolutionStrategy {
eachDependency {
// Force Kotlin to our version
if (requested.group == "org.jetbrains.kotlin") {
useVersion("1.3.72")
}
}
}
}
}
Import the settings.gradle.kts file into your IDE.
To enable the Android sample either define the ANDROID_HOME environmental variable or
add a local.properties file to the project root folder with the following content:
sdk.dir=<android-sdk-location>
Building the plugin: ./plugin/gradlew build
On how to run the current plugin snapshot check on sample projects: ./gradlew ktlintCheck
To run tests in IDEA IDE, firstly you need to run following gradle task (or after any dependency change):
$ ./plugin/gradlew -p ./plugin pluginUnderTestMetadata
Optionally you can add this step test run configuration.
Ktlint Gradle Plugin on the Gradle Plugin Registry
(top 30 of 57)
Kotlin
99.7%
A ktlint gradle plugin
1,716
stars
1,232
commits
Kotlin
primary language
Aug 9, 2026
updated
Provides a convenient wrapper plugin over the ktlint project.
Latest plugin version: 14.2.0
This plugin creates convenient tasks in your Gradle project that run ktlint checks or do code auto format.
The plugin can be applied to any project, but only activates if that project has the kotlin plugin applied. The assumption being that you would not want to lint code you weren't compiling.
This plugin supports the following kotlin plugins:
If you know any new Kotlin plugin that is not in this list - please, open a new issue.
This plugin was written using the new API available for the Gradle script Kotlin builds. This API is available in new versions of Gradle.
Minimal supported Gradle version: 7.4
Minimal supported Kotlin version: 1.4
Minimal supported ktlint version: 0.47.1
Minimal supported Android Gradle plugin version: 4.1.0
Build script snippet for new plugin mechanism introduced in Gradle 2.1:
plugins {
id "org.jlleitschuh.gradle.ktlint" version "<current_version>"
}
repositories {
// Required to download KtLint
mavenCentral()
}
plugins {
id("org.jlleitschuh.gradle.ktlint") version "<current_version>"
}
repositories {
// Required to download KtLint
mavenCentral()
}
To configure the plugin using a version catalog, first, add the following entries to your libs.versions.toml file:
[versions]
ktlint = "<current_version>"
[plugins]
ktlint = { id = "org.jlleitschuh.gradle.ktlint", version.ref = "ktlint" }
Next, apply it to your project:
plugins {
alias(libs.plugins.ktlint)
}
repositories {
// Required to download KtLint
mavenCentral()
}
plugins {
alias(libs.plugins.ktlint)
}
repositories {
// Required to download KtLint
mavenCentral()
}
Build script snippet for use in all Gradle versions:
buildscript {
repositories {
maven {
url "https://plugins.gradle.org/m2/"
}
}
dependencies {
classpath "org.jlleitschuh.gradle:ktlint-gradle:<current_version>"
}
}
repositories {
// Required to download KtLint
mavenCentral()
}
apply plugin: "org.jlleitschuh.gradle.ktlint"
buildscript {
repositories {
maven("https://plugins.gradle.org/m2/")
}
dependencies {
classpath("org.jlleitschuh.gradle:ktlint-gradle:<current_version>")
}
}
repositories {
// Required to download KtLint
mavenCentral()
}
apply(plugin = "org.jlleitschuh.gradle.ktlint")
Optionally apply plugin to all project modules:
subprojects {
apply plugin: "org.jlleitschuh.gradle.ktlint" // Version should be inherited from parent
repositories {
// Required to download KtLint
mavenCentral()
}
// Optionally configure plugin
ktlint {
debug = true
}
}
subprojects {
apply(plugin = "org.jlleitschuh.gradle.ktlint") // Version should be inherited from parent
repositories {
// Required to download KtLint
mavenCentral()
}
// Optionally configure plugin
configure<org.jlleitschuh.gradle.ktlint.KtlintExtension> {
debug.set(true)
}
}
Plugin supports KtLint baseline with following limitations:
Run task ktlintGenerateBaseline to generate a new baseline.
To test KtLint snapshots add following configuration into project build script (latest KtLint snapshot version name you could find here):
repositories {
maven {
url 'https://oss.sonatype.org/content/repositories/snapshots'
}
}
ktlint {
version = "0.41.0-SNAPSHOT"
}
repositories {
maven("https://oss.sonatype.org/content/repositories/snapshots")
}
ktlint {
version.set("0.41.0-SNAPSHOT")
}
The version of ktlint used by default may change between patch versions of this plugin. If you don't want to inherit these changes then make sure you lock your version here. Consult the ktlint release notes for more information about the differences between ktlint versions.
You may declare the ktlint version in the ktlint extension, for example:
ktlint {
version = "1.4.0"
}
You may also declare it in ktlint-plugins.properties, which allows coordination of the ktlint version between this plugin and the intellij kotlin plugin. Example:
ktlint-version=1.0.0
All properties in the following configuration block are optional. If you don't configure these, the defaults defined in the KtlintExtension object will be used.
import org.jlleitschuh.gradle.ktlint.reporter.ReporterType
ktlint {
debug = true
verbose = true
android = false
outputToConsole = true
outputColorName = "RED"
ignoreFailures = true
enableExperimentalRules = true
additionalEditorconfigFile = file("/some/additional/.editorconfig") // not supported with ktlint 0.47+
additionalEditorconfig = [ // not supported until ktlint 0.49
"max_line_length": "20"
]
disabledRules = ["final-newline"] // not supported with ktlint 0.48+
baseline = file("my-project-ktlint-baseline.xml")
reporters {
reporter "plain"
reporter "checkstyle"
reporter "sarif"
customReporters {
"csv" {
fileExtension = "csv"
dependency = project(":project-reporters:csv-reporter")
}
"yaml" {
fileExtension = "yml"
dependency = "com.example:ktlint-yaml-reporter:1.0.0"
}
}
}
kotlinScriptAdditionalPaths {
include fileTree("scripts/")
}
filter {
exclude("**/generated/**")
include("**/kotlin/**")
}
}
dependencies {
ktlintRuleset "com.github.username:rulseset:main-SNAPSHOT"
ktlintRuleset files("/path/to/custom/rulseset.jar")
ktlintRuleset project(":chore:project-ruleset")
}
or in kotlin script:
import org.jlleitschuh.gradle.ktlint.reporter.ReporterType
configure<org.jlleitschuh.gradle.ktlint.KtlintExtension> {
version.set("0.22.0")
debug.set(true)
verbose.set(true)
android.set(false)
outputToConsole.set(true)
outputColorName.set("RED")
ignoreFailures.set(true)
enableExperimentalRules.set(true)
additionalEditorconfigFile.set(file("/some/additional/.editorconfig")) // not supported with ktlint 0.47+
additionalEditorconfig.set( // not supported until ktlint 0.49
mapOf(
"max_line_length" to "20"
)
)
disabledRules.set(setOf("final-newline")) // not supported with ktlint 0.48+
baseline.set(file("my-project-ktlint-baseline.xml"))
reporters {
reporter(ReporterType.PLAIN)
reporter(ReporterType.CHECKSTYLE)
customReporters {
register("csv") {
fileExtension = "csv"
dependency = project(":project-reporters:csv-reporter")
}
register("yaml") {
fileExtension = "yml"
dependency = "com.example:ktlint-yaml-reporter:1.0.0"
}
}
}
kotlinScriptAdditionalPaths {
include(fileTree("scripts/"))
}
filter {
exclude("**/generated/**")
include("**/kotlin/**")
}
}
dependencies {
ktlintRuleset("com.github.username:rulseset:main-SNAPSHOT")
ktlintRuleset(files("/path/to/custom/rulseset.jar"))
ktlintRuleset(project(":chore:project-ruleset"))
}
It is possible also to define different from default output directory for generated reports (by default it is "build/reports/ktlint"):
tasks.withType(org.jlleitschuh.gradle.ktlint.tasks.GenerateReportsTask) {
reportsOutputDirectory = project.layout.buildDirectory.dir("other/location/$name")
}
tasks.withType<org.jlleitschuh.gradle.ktlint.tasks.GenerateReportsTask> {
reportsOutputDirectory.set(
project.layout.buildDirectory.dir("other/location/$name")
)
}
Note: If Ktlint custom reporter creates report output file internally, for example:
class CsvReporter(
private val out: PrintStream
) : Reporter {
override fun onLintError(file: String, err: LintError, corrected: Boolean) {
val line = "$file;${err.line};${err.col};${err.ruleId};${err.detail};$corrected"
out.println(line)
File("some_other_file.txt").write(line) // <-- Here!!!
}
}
"some_other_file.txt" won't be captured as task output. This may lead to the problem, that task will always be not "UP_TO_DATE" and caching will not work.
By default, KtLint Gradle workers will use at most 256mb of heap size. For some projects it may be not enough, but it is possible to change:
tasks.withType(org.jlleitschuh.gradle.ktlint.tasks.BaseKtLintCheckTask).configureEach {
it.workerMaxHeapSize.set("512m")
}
tasks.withType<org.jlleitschuh.gradle.ktlint.tasks.BaseKtLintCheckTask> {
workerMaxHeapSize.set("512m")
}
This repository provides the following examples of how to set up this plugin:
build.gradle filesbuild.gradle.kts filesThis plugin adds following tasks to every project:
loadKtlintReporters - preloads KtLint ReportersrunKtlintCheckOverKotlinScripts - runs actual lint check over project Kotlin script filesktlintKotlinScriptCheck - generates reports and prints issues into Gradle console based on lint check found errors.
This task execution depends on loadKtlintReporters and runKtlintCheckOverKotlinScripts tasks execution outputsrunKtlintFormatOverKotlinScripts - tries to format according to the code style project Kotlin script filesktlintKotlinScriptFormat - generate reports and prints issues into Gradle console based on found non-formattable errors.
This task execution depends on loadKtlintReporters and runKtlintFormatOverKotlinScripts tasks execution outputsktlintCheck - checks all SourceSets and project Kotlin script filesktlintFormat - tries to format according to the code style all SourceSets Kotlin files and project Kotlin script filesThen for each SourceSet plugin adds following tasks:
runKtlintCheckOver[source set name]SourceSet - runs actual lint check on every Kotlin file in given SourceSetktlint[source set name]SourceSetCheck - generates reports and prints issues into Gradle console based on lint check found errors.
This task execution depends on loadKtlintReporters and runKtlintCheckOver[source set name]SourceSet tasks execution outputsrunKtlintFormatOver[source set name]SourceSet - tries to format according to the code style every Kotlin file in given SourceSetktlint[source set name]SourceSetFormat - reformats files, generates reports and prints issues into Gradle console based on found non-formattable errors.
This task execution depends on loadKtlintReporters and runKtlintFormatOver[source set name]SourceSet tasks execution outputsFollowing additional tasks are added:
addKtlintCheckGitPreCommitHook - adds Git pre-commit hook,
that runs ktlint check over staged files.addKtlintFormatGitPreCommitHook - adds Git pre-commit hook,
that runs ktlint format over staged files and adds fixed files back to commit.All these additional tasks are always added only to the root project.
Yes. Just use gradle --continue option:
$ ./gradlew --continue ktlintCheck
No. These approaches are not equivalent to how they work. The problem that the plugin may not find some of the kotlin plugins if both approaches are used in the project configuration. Especially it is related to the Android plugin.
Yes, check tasks support it. On the first run, the task will check all files in the source set, on subsequent runs it will check only added/modified files.
Format tasks do not check files incrementally.
Gradle based filtering are only working for files located inside project (subproject) folder, see https://github.com/gradle/gradle/issues/3417 To filter files outside project dir, use:
exclude { element -> element.file.path.contains("generated/") }
Ensure you are not pinning Kotlin version for "ktlint*" configurations added by plugin.
KtLint relies on Kotlin compiler to parse source files. Each version of KtLint are build using specific Kotlin version.
To exclude "ktlint*" Gradle configurations from Kotlin version pinning - use following approach:
configurations.all {
if (!name.startsWith("ktlint")) {
resolutionStrategy {
eachDependency {
// Force Kotlin to our version
if (requested.group == "org.jetbrains.kotlin") {
useVersion("1.3.72")
}
}
}
}
}
Import the settings.gradle.kts file into your IDE.
To enable the Android sample either define the ANDROID_HOME environmental variable or
add a local.properties file to the project root folder with the following content:
sdk.dir=<android-sdk-location>
Building the plugin: ./plugin/gradlew build
On how to run the current plugin snapshot check on sample projects: ./gradlew ktlintCheck
To run tests in IDEA IDE, firstly you need to run following gradle task (or after any dependency change):
$ ./plugin/gradlew -p ./plugin pluginUnderTestMetadata
Optionally you can add this step test run configuration.
Ktlint Gradle Plugin on the Gradle Plugin Registry
(top 30 of 57)
Kotlin
99.7%