
Kotlin Patterns
Write and refactor idiomatic Kotlin—with null safety, sealed types, coroutines, DSL builders, and Gradle Kotlin DSL—across modules, libraries, and KMP apps.
Overview
Kotlin Patterns is an agent skill most often used in Build (also Ship review) that enforces idiomatic Kotlin across null safety, sealed types, coroutines, DSLs, and Gradle Kotlin DSL.
Install
npx skills add https://github.com/affaan-m/everything-claude-code --skill kotlin-patternsWhat is this skill?
- Seven convention areas: null safety, immutability, sealed hierarchies, coroutines and Flow, extensions, DSL builders, Gr
- Sealed Result types and exhaustive when branches for API and UI outcomes
- Structured concurrency patterns for maintainable async code
- Extension functions and @DslMarker for type-safe internal APIs
- Applies to new code, reviews, refactors, and library design
- 7 key convention areas documented in How It Works
- Covers writing, reviewing, refactoring, module design, and Gradle Kotlin DSL in When to Use
Adoption & trust: 4.4k installs on skills.sh; 210k GitHub stars; 3/3 security scanners passed (skills.sh audits).
What problem does it solve?
Your Kotlin code reads like Java with nullable leaks, mutable shared state, and unstructured coroutine launches that are hard to review.
Who is it for?
Solo builders maintaining KMP apps, Kotlin libraries, or JVM services who want agent-enforced style during write and review passes.
Skip if: Teams standardizing on Swift-only or pure TypeScript stacks with no Kotlin in the repo.
When should I use this skill?
Writing new Kotlin code, reviewing Kotlin code, refactoring Kotlin, designing modules or libraries, or configuring Gradle Kotlin DSL builds.
What do I get? / Deliverables
You produce modules and APIs using sealed results, immutable models, structured concurrency, and Gradle Kotlin DSL builds that stay consistent through implementation and code review.
- Idiomatic Kotlin modules and APIs
- Refactored null-safe and immutable domain models
- Gradle Kotlin DSL snippets aligned to project structure
Recommended Skills
Journey fit
Spans multiple journey phases - primary shelf plus alternate fits below.
Language and module patterns are applied most often while implementing and structuring code in Build, even when the same rules matter again during review. Canonical shelf is backend-oriented module design, use cases, and Gradle configuration, which also feeds shared KMP layers and JVM services.
Where it fits
Define sealed Result types and Flow-backed repositories before exposing APIs to Compose UI.
Wrap third-party SDK calls in extension helpers with structured coroutine scopes.
Audit nullable chains and mutable shared state in a PR before release.
How it compares
Language and architecture conventions skill, not a test runner or deployment automation pack.
Common Questions / FAQ
Who is kotlin-patterns for?
Indie developers and small teams using Kotlin for Android, KMP, backends, or CLIs who want consistent idioms when agents generate or refactor code.
When should I use kotlin-patterns?
During Build when writing new Kotlin modules or Gradle scripts; during Ship review when refactoring nullable-heavy code; whenever designing libraries with sealed types and coroutine Flow APIs.
Is kotlin-patterns safe to install?
It supplies patterns and examples only; review the Security Audits panel on this Prism page and apply rules in your own codebase without auto-executing unknown scripts.
Workflow Chain
Then invoke: compose multiplatform patterns
SKILL.md
READMESKILL.md - Kotlin Patterns
# Kotlin Development Patterns Idiomatic Kotlin patterns and best practices for building robust, efficient, and maintainable applications. ## When to Use - Writing new Kotlin code - Reviewing Kotlin code - Refactoring existing Kotlin code - Designing Kotlin modules or libraries - Configuring Gradle Kotlin DSL builds ## How It Works This skill enforces idiomatic Kotlin conventions across seven key areas: null safety using the type system and safe-call operators, immutability via `val` and `copy()` on data classes, sealed classes and interfaces for exhaustive type hierarchies, structured concurrency with coroutines and `Flow`, extension functions for adding behaviour without inheritance, type-safe DSL builders using `@DslMarker` and lambda receivers, and Gradle Kotlin DSL for build configuration. ## Examples **Null safety with Elvis operator:** ```kotlin fun getUserEmail(userId: String): String { val user = userRepository.findById(userId) return user?.email ?: "unknown@example.com" } ``` **Sealed class for exhaustive results:** ```kotlin sealed class Result<out T> { data class Success<T>(val data: T) : Result<T>() data class Failure(val error: AppError) : Result<Nothing>() data object Loading : Result<Nothing>() } ``` **Structured concurrency with async/await:** ```kotlin suspend fun fetchUserWithPosts(userId: String): UserProfile = coroutineScope { val user = async { userService.getUser(userId) } val posts = async { postService.getUserPosts(userId) } UserProfile(user = user.await(), posts = posts.await()) } ``` ## Core Principles ### 1. Null Safety Kotlin's type system distinguishes nullable and non-nullable types. Leverage it fully. ```kotlin // Good: Use non-nullable types by default fun getUser(id: String): User { return userRepository.findById(id) ?: throw UserNotFoundException("User $id not found") } // Good: Safe calls and Elvis operator fun getUserEmail(userId: String): String { val user = userRepository.findById(userId) return user?.email ?: "unknown@example.com" } // Bad: Force-unwrapping nullable types fun getUserEmail(userId: String): String { val user = userRepository.findById(userId) return user!!.email // Throws NPE if null } ``` ### 2. Immutability by Default Prefer `val` over `var`, immutable collections over mutable ones. ```kotlin // Good: Immutable data data class User( val id: String, val name: String, val email: String, ) // Good: Transform with copy() fun updateEmail(user: User, newEmail: String): User = user.copy(email = newEmail) // Good: Immutable collections val users: List<User> = listOf(user1, user2) val filtered = users.filter { it.email.isNotBlank() } // Bad: Mutable state var currentUser: User? = null // Avoid mutable global state val mutableUsers = mutableListOf<User>() // Avoid unless truly needed ``` ### 3. Expression Bodies and Single-Expression Functions Use expression bodies for concise, readable functions. ```kotlin // Good: Expression body fun isAdult(age: Int): Boolean = age >= 18 fun formatFullName(first: String, last: String): String = "$first $last".trim() fun User.displayName(): String = name.ifBlank { email.substringBefore('@') } // Good: When as expression fun statusMessage(code: Int): String = when (code) { 200 -> "OK" 404 -> "Not Found" 500 -> "Internal Server Error" else -> "Unknown status: $code" } // Bad: Unnecessary block body fun isAdult(age: Int): Boolean { return age >= 18 } ``` ### 4. Data Classes for Value Objects Use data classes for types that primarily hold data. ```kotlin // Good: Data class with copy, equals, hashCode, toString data class CreateUserRequest( val name: String, val e