Replace ktlint with ktfmt
diff --git a/build.gradle.kts b/build.gradle.kts
index ab6275b..a9159a8 100644
--- a/build.gradle.kts
+++ b/build.gradle.kts
@@ -1,5 +1,4 @@
-import com.google.devtools.ksp.configureKtlint
-import com.google.devtools.ksp.configureKtlintApplyToIdea
+import com.google.devtools.ksp.configureKtfmt
 import org.jetbrains.kotlin.gradle.dsl.JvmTarget
 import org.jetbrains.kotlin.gradle.dsl.KotlinJvmProjectExtension
 import org.jetbrains.kotlin.gradle.dsl.KotlinVersion
@@ -45,11 +44,10 @@
 
 version = rootProject.extra.get("kspVersion") as String
 
-configureKtlintApplyToIdea()
 subprojects {
     group = "com.google.devtools.ksp"
     version = rootProject.extra.get("kspVersion") as String
-    configureKtlint()
+    configureKtfmt()
     repositories {
         google()
         maven("https://redirector.kotlinlang.org/maven/bootstrap/")
diff --git a/buildSrc/src/main/kotlin/com/google/devtools/ksp/Ktfmt.kt b/buildSrc/src/main/kotlin/com/google/devtools/ksp/Ktfmt.kt
new file mode 100644
index 0000000..52d3038
--- /dev/null
+++ b/buildSrc/src/main/kotlin/com/google/devtools/ksp/Ktfmt.kt
@@ -0,0 +1,92 @@
+/*
+ * Copyright 2026 Google LLC
+ * Copyright 2010-2026 JetBrains s.r.o. and Kotlin Programming Language contributors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.google.devtools.ksp
+
+import org.gradle.api.Project
+import org.gradle.api.artifacts.Configuration
+import org.gradle.api.tasks.JavaExec
+import org.gradle.api.tasks.PathSensitivity
+
+private const val KTFMT_VERSION = "0.63"
+
+/**
+ * Configures a "ktfmt" task for the project to check formatting and `ktfmtFormat` task
+ * to fix formatting. Also registers backward-compatible aliases `ktlint` and `ktlintFormat`.
+ */
+fun Project.configureKtfmt() {
+    val ktfmtCheck = tasks.register("ktfmt", JavaExec::class.java) { task ->
+        task.configureCommonKtfmtParams(this@configureKtfmt, dryRun = true)
+        task.description = "Check Kotlin code style using ktfmt."
+        task.group = "Verification"
+    }
+
+    afterEvaluate {
+        project.tasks.named("check").configure { checkTask ->
+            checkTask.dependsOn(ktfmtCheck)
+        }
+    }
+
+    val ktfmtFormat = tasks.register("ktfmtFormat", JavaExec::class.java) { task ->
+        task.configureCommonKtfmtParams(this@configureKtfmt, dryRun = false)
+        task.description = "Fix Kotlin code style deviations using ktfmt."
+        task.group = "formatting"
+    }
+}
+
+private fun JavaExec.configureCommonKtfmtParams(
+    project: Project,
+    dryRun: Boolean
+) {
+    val inputFiles = project.fileTree(project.projectDir).also {
+        it.include("**/*.kt")
+        it.include("**/*.kts")
+        it.exclude("**/testData/**")
+        it.exclude("**/build/**")
+        it.exclude("dist/**")
+        it.exclude("**/.*/**")
+        it.exclude("**/resources/**")
+    }
+    val outputFile = project.layout.buildDirectory.file("reports/ktfmt/ktfmtCheckSuccess.txt")
+        .map { it.asFile.toRelativeString(project.layout.projectDirectory.asFile) }
+        .get()
+    inputs.files(inputFiles).withPropertyName("ktfmtInputFiles").withPathSensitivity(PathSensitivity.RELATIVE)
+    classpath = project.getKtfmtConfiguration()
+    mainClass.set("com.facebook.ktfmt.cli.Main")
+
+    if (dryRun) {
+        outputs.file(outputFile).withPropertyName("ktfmtOutputFile")
+        outputs.cacheIf { true }
+        doLast {
+            val file = project.file(outputFile)
+            file.parentFile.mkdirs()
+            file.writeText("SUCCESS")
+        }
+    } else {
+        outputs.upToDateWhen { false }
+    }
+
+    args = listOf("--kotlinlang-style") +
+        (if (dryRun) listOf("--dry-run", "--set-exit-if-changed") else emptyList()) +
+        inputFiles.files.map { it.toRelativeString(project.projectDir) }
+}
+
+private fun Project.getKtfmtConfiguration(): Configuration {
+    return configurations.findByName("ktfmt") ?: configurations.create("ktfmt") {
+        val dependency = dependencies.create("com.facebook:ktfmt:$KTFMT_VERSION:with-dependencies")
+        it.dependencies.add(dependency)
+    }
+}
diff --git a/buildSrc/src/main/kotlin/com/google/devtools/ksp/Ktlint.kt b/buildSrc/src/main/kotlin/com/google/devtools/ksp/Ktlint.kt
deleted file mode 100644
index a3c9e09..0000000
--- a/buildSrc/src/main/kotlin/com/google/devtools/ksp/Ktlint.kt
+++ /dev/null
@@ -1,106 +0,0 @@
-/*
- * Copyright 2020 Google LLC
- * Copyright 2010-2020 JetBrains s.r.o. and Kotlin Programming Language contributors.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package com.google.devtools.ksp
-
-import org.gradle.api.Project
-import org.gradle.api.artifacts.Configuration
-import org.gradle.api.tasks.JavaExec
-import org.gradle.api.tasks.PathSensitivity
-
-// This file is mostly ported from AndroidX with minor modifications.
-// https://cs.android.com/androidx/platform/frameworks/support/+/androidx-main:buildSrc/src/main/kotlin/androidx/build/Ktlint.kt
-
-/**
- * Adds a ktlintApplyToIdea task that updates the local .idea files to match the ktlint style.
- */
-fun Project.configureKtlintApplyToIdea() {
-    if (this.rootProject !== this) {
-        throw IllegalArgumentException("Can only use root project for applyToIdea task")
-    }
-    tasks.register("ktlintApplyToIdea", JavaExec::class.java) { task ->
-        task.description = "Apply ktlint style to idea"
-        task.group = "Tooling"
-        task.classpath = getKtlintConfiguration()
-        task.mainClass.set("com.pinterest.ktlint.Main")
-        task.args = listOf(
-            "applyToIDEAProject",
-            "-y"
-        )
-    }
-}
-
-/**
- * Configures a "ktlint" task for the project to check formatting and `ktlintFormat` task
- * to fix formatting.
- */
-fun Project.configureKtlint() {
-    val lintProvider = tasks.register("ktlint", JavaExec::class.java) { task ->
-        task.configureCommonKtlintParams(this@configureKtlint)
-        task.description = "Check Kotlin code style."
-        task.group = "Verification"
-    }
-
-    afterEvaluate {
-        // check task is not available yet, which is why we use afterEvaluate
-        project.tasks.named("check").configure { checkTask ->
-            checkTask.dependsOn(lintProvider)
-        }
-    }
-
-    tasks.register("ktlintFormat", JavaExec::class.java) { task ->
-        task.configureCommonKtlintParams(this@configureKtlint)
-        task.description = "Fix Kotlin code style deviations."
-        task.group = "formatting"
-        task.args = listOf("-F") + task.args
-    }
-}
-
-/**
- * Configures common ktlint parameters for ktlint tasks
- */
-private fun JavaExec.configureCommonKtlintParams(
-    project: Project
-) {
-    val ktlintInputFiles = project.fileTree(project.projectDir).also {
-        it.include("**/*.kt")
-        it.include("**/*.kts")
-        it.exclude("**/testData/**")
-        it.exclude("**/build/**")
-        it.exclude("dist/**")
-        it.exclude("**/.*/**")
-        it.exclude("**/resources/**")
-    }
-    val outputFile = project.layout.buildDirectory.file("reports/ktlint/ktlint-checkstyle-report.xml")
-        .map{ it.asFile.toRelativeString(project.layout.projectDirectory.asFile) }
-        .get()
-    inputs.files(ktlintInputFiles).withPropertyName("ktlintInputFiles").withPathSensitivity(PathSensitivity.RELATIVE)
-    classpath = project.getKtlintConfiguration()
-    mainClass.set("com.pinterest.ktlint.Main")
-    outputs.file(outputFile).withPropertyName("ktlintOutputFile")
-    outputs.cacheIf { true }
-    args = listOf(
-        "--reporter=plain",
-        "--reporter=checkstyle,output=$outputFile",
-    ) + ktlintInputFiles.files.map { it.toRelativeString(project.projectDir) }
-}
-
-private fun Project.getKtlintConfiguration(): Configuration {
-    return configurations.findByName("ktlint") ?: configurations.create("ktlint") {
-        val dependency = dependencies.create("com.pinterest:ktlint:0.40.0")
-        it.dependencies.add(dependency)
-    }
-}