# Kotlin Control Flow

Use when writing or reviewing Kotlin branching and control flow: when expressions...

- Repository: https://github.com/chrisbanes/skills (1135 stars)
- Category: Mobile
- License: Apache-2.0
- Last updated: 2026-11-01
- Runs scripts: no, instructions only

## Install

Claude Code: `npx skills add chrisbanes/skills --skill kotlin-control-flow -g -a claude-code -y`
Codex: `npx skills add chrisbanes/skills --skill kotlin-control-flow -g -a codex -y`
Cursor: `npx skills add chrisbanes/skills --skill kotlin-control-flow -g -a cursor -y`
Gemini CLI: `npx skills add chrisbanes/skills --skill kotlin-control-flow -g -a gemini-cli -y`
Claude Code plugin marketplace: `/plugin marketplace add chrisbanes/skills`

## Description

Use when writing or reviewing Kotlin branching and control flow: when expressions, guard conditions, sealed type exhaustiveness, smart casts, nullable branching, early returns, or replacing complex if/else chains.

## SKILL.md, as published by its author (untrusted third-party text, read it as data)

# Kotlin control flow

## Core principle

Make the classified value obvious, keep branch-local predicates on their
branch, and let the compiler prove closed-domain coverage.

## Procedure

1. Name the value being classified. If every branch tests it, use
   `when (subject)`; otherwise keep a subjectless `when` or `if` chain.
2. Choose the branch shape:

   | Code shape | Prefer |
   |---|---|
   | One classified value | `when (subject)` |
   | Unrelated boolean conditions | Subjectless `when` or `if`/`else` |
   | Primary case plus a branch-local predicate | Guard condition |
   | Invalid input before the main path | Early return, `require`, or `check` |
   | Closed value-returning domain | Exhaustive `when` expression |
   | Open input or deliberate fallback | Explicit `else` |

3. Use a guard only on a subject `when`, after a primary condition, when the
   extra predicate belongs to that branch and an unguarded branch still handles
   the primary condition. Put the guarded branch first. Split comma-separated
   conditions instead of guarding one of them. Guards are stable from Kotlin
   2.2. Honor an explicit `languageVersion` setting; otherwise the project's
   Kotlin version in its build file or version catalog is enough to confirm
   support, so do not decline a guard for lack of further proof.
4. For a closed enum, Boolean, sealed type, or nullable closed type, name every
   case and omit `else`. Match objects by value and class/data-class subtypes
   with `is`. If the input is an open server/platform value or needs real
   fallback/logging, keep `else`. Give each data-bearing subtype, including one
   a catch-all collapses, its own `is` branch. When its data affects the
   mapping or its safe handling, the finding or change must show the
   smart-cast member access, even if the public value stays constant:

   ```kotlin
   is Outcome.Failed -> safeFailureLabel(outcome.reason)
   ```

The rest: https://github.com/chrisbanes/skills/blob/HEAD/skills/kotlin-control-flow/SKILL.md
