What are ktlint's standard and experimental rule sets, and how do you opt into experimental rules safely?
answer
- Standard = stable & on; experimental = new & off
- ktlint_experimental = enabled to opt in
- Experimental rules may rename/promote/drop on upgrade
- Pin version + review diff after ktlintFormat
- Custom rule sets via RuleSetProvider JARs
basics
~20 sThe standard rule set is the stable, default set of style rules. The experimental set holds newer rules that are off by default; you turn them on in .editorconfig when you want to try them.
solid answer
~40 sktlint groups rules into **rule sets** identified by a prefix in their id: `standard:<rule>` and `experimental` rules (the experimental set). The **standard** set is enabled by default and is the stable, battle-tested baseline. The **experimental** set contains rules that are still being refined; they are **disabled by default** and you opt in with `ktlint_experimental = enabled` in `.editorconfig` (or enable individual experimental rules). Opting in safely means: enable it on a branch, run `ktlintFormat` to see the churn, review the diff, and pin your ktlint version so a future upgrade doesn't silently graduate or change a rule. Experimental rules may be promoted to standard, renamed, or removed across versions, so they shouldn't gate CI without a deliberate decision and a baseline. Third-party/custom rule sets can also be added via the plugin's `ruleSetProviders`/dependencies.
go deeper
Knows experimental rules exist and are off by default.
Can enable the experimental set in .editorconfig and explain that those rules are still evolving.
Adopts experimental rules safely (pin version, review diff, baseline) and knows custom rule sets are possible.
Sets org policy on rule-set adoption, manages upgrade/migration risk across many repos, and decides what gates CI.
## Rule sets A **rule set** is a named collection of rules. ktlint ships two first-party sets: - **Standard** (`ktlint_standard`) — the default, stable rules implementing the official Kotlin style. On unless you disable a specific rule. - **Experimental** (`ktlint_experimental`) — newer rules under evaluation. **Off by default.** They may change behavior, get renamed, be promoted into standard, or be dropped between releases. Each rule has a fully-qualified id, e.g. `standard:no-wildcard-imports`. You reference it in `.editorconfig` as `ktlint_standard_no-wildcard-imports`. ## Opting into experimental ```editorconfig [*.{kt,kts}] ktlint_experimental = enabled # enable the whole experimental set ktlint_experimental_<rule-id> = disabled # but keep one specific rule off ``` You can flip the polarity too — leave the set off and enable just one rule with `ktlint_experimental_<rule-id> = enabled` depending on version semantics; the cleanest mental model is: a rule runs only if its set and the rule itself are enabled. ## Doing it safely 1. **Pin the ktlint version** (Gradle plugin version) so behavior is reproducible. Experimental rules are the ones most likely to shift across upgrades. 2. **Enable on a branch**, run `./gradlew ktlintFormat`, and review the resulting diff — experimental rules can touch many files. 3. **Generate/refresh a baseline** if you adopt incrementally so the existing violations don't break CI immediately. 4. **Decide deliberately** before letting an experimental rule gate `ktlintCheck` in CI. ## Custom rule sets Beyond first-party sets, you can add **third-party rule sets** (custom `RuleSetProvider` JARs) for organization-specific conventions. These plug in alongside standard/experimental. ## Why the split exists The split lets the maintainers ship and iterate on new rules without forcing churn on every consumer, while keeping the default experience stable and low-friction — consistent with the anti-bikeshedding goal.
- Why pin the ktlint/plugin version when using experimental rules?Experimental rules can change, be renamed, promoted to standard, or removed across versions; pinning keeps builds reproducible and avoids surprise CI failures on upgrade.
- How would you add an organization-specific naming rule ktlint doesn't ship?Write a custom rule in a RuleSetProvider, package it as a JAR, and register it with the ktlint CLI/Gradle plugin as a custom rule set dependency.
saying these in an interview costs you the question
- Assuming experimental rules are on by default
- Enabling experimental and gating CI without reviewing churn
- Not pinning the version, then blaming 'flaky' ktlint after an upgrade
- Thinking you cannot add custom rules
- Confusing rule sets with detekt rule sets