kotlin-idioms

SkillAI & models

Kotlin rewards conciseness, null safety, and coroutine-based concurrency. Idiomatic Kotlin = safe, expressive, interop-aware.

Available today. Use it from your connected AI after setup.

Connect ahel once, and every AI you use reads what you have installed.

Then ask your AI: use the kotlin-idioms skill

About this capability

Comprehensive sets of standards and practices designed to elevate the capabilities of AI coding agents.

What this skill tells your AI

The instructions your AI receives, as published by irahardianto/awesome-agv in .agents/skills/kotlin-idioms/SKILL.md and read by ahel’s review.

Kotlin Idioms and Patterns

Kotlin rewards conciseness, null safety, and coroutine-based concurrency. Idiomatic Kotlin = safe, expressive, interop-aware.

Scope: Kotlin coding idioms. Test naming: .agents/rules/testing-strategy.md.

Null Safety

  1. ? for nullable types — never platform types without annotation:

    fun findById(id: String): Task?  // explicitly nullable
    fun getById(id: String): Task    // guaranteed non-null — throws if not found
    
  2. Prefer ?.let {} and ?: (Elvis) over null checks.

  3. Never !! in production — use requireNotNull with a message.

Data Classes and Sealed Types

  1. data class for DTOs and domain objects:

    data class CreateTaskRequest(val title: String, val priority: Priority)
    
  2. sealed class/sealed interface for restricted hierarchies:

    sealed interface TaskResult {
        data class Success(val task: Task) : TaskResult
        data class NotFound(val id: String) : TaskResult
        data class ValidationError(val errors: List<String>) : TaskResult
    }
    
  3. Exhaustive when with sealed types:

    when (result) {
        is TaskResult.Success -> ok(result.task)
        is TaskResult.NotFound -> notFound(result.id)
        is TaskResult.ValidationError -> badRequest(result.errors)
    }
    

Coroutines

  1. Structured concurrencycoroutineScope, supervisorScope.
  2. Never GlobalScope.launch — always scoped.
  3. Flow for reactive streams:
    fun observeTasks(): Flow<List<Task>> = flow {
        while (currentCoroutineContext().isActive) {
            emit(storage.getAll())
            delay(5.seconds)
        }
    }
    

Naming

  1. PascalCase for classes. camelCase for functions, properties.
  2. No get/set prefixes — use properties.
  3. Backtick function names only in tests: `should create task when valid`()

Testing

  1. kotest or JUnit 5 + MockK:
    @Test
    fun `create task returns task when valid`() {
        val result = service.create("Test", Priority.HIGH)
        assertThat(result.title).isEqualTo("Test")
    }
    

Formatting and Static Analysis

ToolPurposeCommand
ktlintFormattingktlint --format
detektStatic analysisdetekt --config detekt.yml
Kotlin compilerNull safetyBuilt-in

Related

  • Code Idioms and Conventions .agents/rules/code-idioms-and-conventions.md
  • Testing Strategy .agents/rules/testing-strategy.md
  • Error Handling Principles .agents/rules/error-handling-principles.md

Signals

GitHub stars
156
Forks
53
Last commit
Aug 2026
Advanced
Catalog kind
skill
Gateway key
kotlin-idioms
Source
github.com/irahardianto/awesome-agv