agentsclimarketplace

Modern kotlin

Skill Heapy/kortex/plugins/kortex/skills/modern-kotlin

Agent Skills for Kotlin Development

Install
npx -y skills add Heapy/kortex --skill modern-kotlin

Assembled from the repository path, not quoted from the project. Check it against their README if it does not work.

One thing to look at

  • 3 stars3 stars. Stars are a popularity signal and not a quality one, but at this level it is likely that nobody has read this closely except its author, and you would be relying on your own review.

What its author says it does

Copied from the file, not written here

Use when writing, reviewing, or modernizing Kotlin code with recent language versions (2.0–2.4.x, including 2.4.10 and 2.4.20-Beta1), including context parameters, collection literals, guard conditions in when, multi-dollar interpolation, non-local break/continue, explicit backing fields, nested type aliases, name-based destructuring, data objects, Enum.entries, rangeUntil, unused-return-value checker, K2 smart casts, contracts, experimental -X compiler flags, and stdlib APIs such as Uuid, Base64, HexFormat, kotlin.time Instant/Clock, and atomics.

SKILL.md

13.5 KB, as published. Nobody here has run it

Modern Kotlin

Use this skill to write idiomatic Kotlin with the features added in the last four years (mid-2022 → 2026, Kotlin 1.7 → 2.4.20-Beta1) and to know exactly which compiler flag or opt-in each preview feature needs.

State as of July 2026:

  • Latest stable: 2.4.10 (July 14, 2026). EAP: 2.4.20-Beta1 (2.4.20 final planned September 2026).
  • Default language version is 2.4. K1 is gone: 2.4.0 dropped -language-version 1.9; K2 has been the only compiler since 2.0.0 (May 2024).
  • Context receivers (-Xcontext-receivers) were removed in 2.3.20 — always migrate to context parameters.

Detailed per-version notes with full stdlib/tooling changes live in references/ (linked at the bottom). Older pre-2022 features (sealed interfaces, value classes, fun interface, Duration API, …) are in references/kotlin-1.4-1.6.md.

Release timeline

VersionDateLanguage headliners
1.7.0 / 1.7.20Jun / Sep 2022K2 Alpha; builder inference, T & Any, opt-in stable; ..< and data object previews
1.8.0 / 1.8.20Dec 2022 / Apr 2023old JVM backend removed; Enum.entries preview, Base64/AutoCloseable experimental
1.9.0 / 1.9.20Jul / Nov 2023entries, data object, ..<, time API stable; K2 Beta; KMP stable
2.0.0 / 2.0.20May / Aug 2024K2 stable, smart-cast upgrades; copy() visibility migration; Uuid
2.1.0 / 2.1.20Nov 2024 / Mar 2025previews: guard conditions, non-local break/continue, $$ interpolation; atomics, Instant
2.2.0 / 2.2.20Jun / Sep 2025guards + $$ + non-local break/continue stable; context parameters preview; contracts previews
2.3.0 / 2.3.20Dec 2025 / Mar 2026return-value checker, explicit backing fields; name-based destructuring; context receivers removed
2.4.0Jun 3, 2026context parameters stable, collection literals, @IntroducedAt; K1 dropped
2.4.10Jul 14, 2026bug fixes only — current stable
2.4.20-Beta1Jun 24, 2026explicit context arguments stable; when via invokedynamic default (JVM 21+)

Stable language features (no flags needed on 2.4.x)

Context parameters — stable 2.4.0

Declare dependencies implicitly available from the calling context; parameters are named and referenced explicitly. Replaces context receivers. Preview since 2.2.0 (-Xcontext-parameters needed on 2.2–2.3 only).

interface UserService {
    fun log(message: String)
}

context(users: UserService)
fun outputMessage(message: String) = users.log("Log: $message")

context(users: UserService)
val firstUser: String get() = users.findUserById(1)

Still experimental around it: explicit context arguments at call sites (-Xexplicit-context-arguments, stable in 2.4.20-Beta1) and callable references to context functions. Docs

Explicit backing fields — stable 2.4.0

Public read-only type, private mutable storage — without the _x naming convention. Experimental in 2.3.0 behind -Xexplicit-backing-fields.

val city: StateFlow<String>
    field = MutableStateFlow("")

fun updateCity(newCity: String) {
    city.value = newCity // resolves to the MutableStateFlow field in private scope
}

Docs

Guard conditions in when — stable 2.2.0

Extra if after a branch condition (preview in 2.1.0 behind -Xwhen-guards):

when (animal) {
    is Animal.Dog -> animal.feedDog()
    is Animal.Cat if !animal.mouseHunter -> animal.feedCat()
    else -> println("Unknown animal")
}

Multi-dollar string interpolation — stable 2.2.0

$$"..." — only $$ interpolates; single $ is a literal. Perfect for JSON schema, Gradle version catalogs, regex. Preview in 2.1.0 behind -Xmulti-dollar-interpolation.

val jsonSchema = $$"""
{ "$schema": "https://json-schema.org/draft/2020-12/schema", "title": "$${title}" }
"""

Non-local break and continue — stable 2.2.0

From lambdas passed to inline functions (preview in 2.1.0 behind -Xnon-local-break-continue):

for (element in elements) {
    val v = element.nullableMethod() ?: run {
        log.warning("skipping null"); continue
    }
}

Data-flow-based when exhaustiveness — stable 2.3.0

Earlier checks and early returns count toward exhaustiveness — no redundant else (experimental in 2.2.20 behind -Xdata-flow-based-exhaustiveness):

fun getPermissionLevel(role: UserRole): Int {
    if (role == UserRole.ADMIN) return 99
    return when (role) {
        UserRole.MEMBER -> 10
        UserRole.GUEST -> 1
    } // no else needed
}

return in expression bodies — default 2.3.0

Allowed when the return type is explicit:

fun getDisplayNameOrDefault(userId: String?): String =
    getDisplayName(userId ?: return "default")

Nested type aliases — stable 2.3.0

typealias inside classes/objects/functions (Beta in 2.2.0 behind -Xnested-type-aliases); cannot capture outer type parameters.

Annotation targeting — stable 2.4.0

  • @all: meta-target applies an annotation to every applicable target of a property (@all:Email val email: String).
  • New defaulting rules: an unqualified annotation propagates to param + property (or field), not just the first applicable target. Both previewed in 2.2.0 (-Xannotation-target-all, -Xannotation-default-target).

2.1.0 stable resolution/checks

  • @SubclassOptInRequired — require opt-in to implement/extend an API.
  • Sealed-upper-bound exhaustiveness: fun <T : Result> render(result: T) = when (result) { ... } without else.
  • Generic-lambda overload resolution fixed (store("") { 1 } picks the lambda overload).

K2 smart casts — 2.0.0

All default: boolean variables capturing type checks (val isCat = animal is Cat; if (isCat) animal.purr()), is A || is B casts to the common supertype, implicit callsInPlace for inline functions, function-type val properties, smart casts propagating into catch/finally, and correct types after ++/--.

2022–2023 era (1.7–1.9), all stable since 1.9.0 or earlier

  • data object — singleton with clean toString()/equals()/hashCode() for sealed hierarchies.
  • Enum.entries — allocation-free EnumEntries<E> list replacing values(); enumEntries<T>() for reified generics (stable 2.0.0).
  • ..< (rangeUntil)in 0.0..<0.25 open-ended ranges, replacing until.
  • Definitely non-nullable T & Any (1.7.0); builder inference without flags (1.7.0); opt-in requirements stable (1.7.0); secondary constructors with bodies in value classes (1.9.0); data class + Java records interop.

Experimental and preview features (flag required on 2.4.10)

Full flag index with platform flags: references/experimental-flags.md.

Collection literals — -Xcollection-literals (2.4.0)

val shapes: MutableList<String> = ["triangle", "square", "circle"]
val fruit = ["apple", "banana"] // List<String> by default

class Row(vararg val elements: Double) {
    companion object { operator fun of(vararg elements: Double) = Row(*elements) }
}

Type comes from the expected type; custom types opt in with operator fun of. Cannot construct Java collection types. KEEP-0416.

Explicit context arguments — -Xexplicit-context-arguments (2.4.0; stable in 2.4.20-Beta1)

sendNotification(emailSender = defaultEmailSender) — pass a context argument by name, e.g. to disambiguate context-parameter overloads. KEEP-0448.

Name-based destructuring — -Xname-based-destructuring=<mode> (2.3.20)

Modes: only-syntax (new syntax only), name-mismatch (warn on positional-name mismatch), complete (parenthesized form becomes name-based). Square brackets are the new explicit positional form. Syntax-only planned stable in 2.5.

(val mail = email, val name = username) = user // by name
val [username, email] = user                   // by position

Unused return value checker — -Xreturn-value-checker=check|full (2.3.0)

Warns when a non-Unit result is silently discarded. @MustUseReturnValues scopes enforcement, @IgnorableReturnValue exempts a function; suppress one call with val _ = compute(). In 2.4.0 the returnsResultOf contract (-Xallow-returns-result-of) propagates the check through higher-order functions.

Context-sensitive resolution — -Xcontext-sensitive-resolution (2.2.0, improved 2.3.0)

Omit the type name where it is inferable (enum entries, sealed subtypes): when (problem) { CONNECTION -> ... }.

Contract extensions (2.2.20) — all with @OptIn(ExperimentalContracts::class)

  • -Xallow-contracts-on-more-functions — contracts in property accessors and specific operators; generics in contract type assertions.
  • -Xallow-condition-implies-returns-contracts(encoded != null) implies (returnsNotNull()).
  • -Xallow-holdsin-contractcondition holdsIn block for smart casts inside DSL lambdas.

Reified types in catch-Xallow-reified-type-in-catch (2.2.20)

inline fun <reified E : Throwable> handle(block: () -> Unit) { try { block() } catch (e: E) { ... } }

Other experimental

  • Compile-time constants-Xintrinsic-const-evaluation (2.4.0): const evaluation for unsigned ops, string functions, enum .name.
  • @IntroducedAt("1.1")@OptIn(ExperimentalVersionOverloading::class) (2.4.0): hidden overloads for binary compatibility when adding optional parameters.
  • when via invokedynamic-Xwhen-expressions=indy (2.2.20); default for JVM target 21+ since 2.4.20-Beta1.
  • Data class copy() visibility@ConsistentCopyVisibility / @ExposedCopyVisibility / -Xconsistent-data-class-copy-visibility (2.0.20): aligns copy() visibility with a non-public primary constructor.
  • Warning management-Xwarning-level=NAME:(error|warning|disabled) (2.2.0), -Xsuppress-warning=NAME (2.1.0), -Wextra extra checks (2.1.0).

Compiler and toolchain changes that affect code

  • 2.2.0: interface methods compile to JVM default methods by default; stable -jvm-default (enable|no-compatibility|disable) replaces -Xjvm-default. Gradle kotlinOptions {} is an error — use compilerOptions {}. REPL deprecated (-Xrepl to re-enable).
  • 2.1.0: JSpecify nullability violations are errors by default (-Xnullability-annotations=strict).
  • 2.3.0: Java 25 bytecode; -language-version 1.8 dropped. 2.4.0: Java 26; K1 fully removed.
  • 2.3.20: Kotlin/JVM builds run through the Build Tools API by default; JetBrains @Unmodifiable collections become read-only in Kotlin (warning → error in 2.5).
  • kapt runs on K2 by default since 2.2.20 (opt-out deprecated).
  • Machine-readable list of all compiler options: org.jetbrains.kotlin:kotlin-compiler-arguments-description.

Modern stdlib quick map

APISince (experimental)Stable
kotlin.uuid.Uuid2.0.202.4.0 (V4/V7 generators still experimental)
kotlin.time.Instant / Clock2.1.202.3.0
Base64 (kotlin.io.encoding)1.8.202.2.0
HexFormat (toHexString())1.9.02.2.0
Common atomics (kotlin.concurrent.atomics) + update()2.1.20 / 2.2.20experimental
AutoCloseable + use (common)1.8.202.0.0
Time API (TimeSource.Monotonic, measureTime)1.3.501.9.0
Path.walk() / visitFileTree()1.7.202.1.0
Path.copyToRecursively() / deleteRecursively()1.8.0experimental
isSorted() family, UInt.toBigInteger()2.4.0
Map fallback (getOrPutIfMissing)2.4.0experimental
StackTraceRecoverable2.4.20-Beta1experimental

Deprecated to error: toLowerCase()/toUpperCase()lowercase()/uppercase(); appendln()appendLine() (2.1.0).

References

Detailed per-version descriptions, including pre-2022 history:

Canonical upstream: What's new index · Releases · EAP · Compiler options · Components stability

Keep looking

Skills are one crate of 328,083. Ordering is by how many stacks a row turns up in, so the top of any crate is what has actually been picked rather than what has the most stars.