Couple of quick notes on working with Clikt, the Kotlin CLI library:

Using Clikt as a pure parser

If all you want is to turn command line arguments into a data class, without using the Clikt Command abstraction, you can do it as follows:

import com.github.ajalt.clikt.core.NoOpCliktCommand
import com.github.ajalt.clikt.parameters.options.option
import com.github.ajalt.clikt.parameters.options.required

fun main(vararg args: String) {
  val config: Config = CliParser.parseConfig(*args)
}

data class Config(val username: String)

class CliParser private constructor() : NoOpCliktCommand(
  name = "",
  help = "help text",
) {

  private val username: String by option(help = "the username").required()

  private fun toConfig() = Config(username = username)

  companion object {

    fun parseConfig(vararg args: String): Config =
      CliParser()
        .apply { parse(args.toList()) }
        .toConfig()
  }
}

Injecting the environment as a map

If you want to decouple Clikt from System.getenv you can do so as so:

class CliParser(
  env: Map<String, String> = System.getenv()
) : CliktCommand {

  init {
    context {
      envarReader = env::get
      autoEnvvarPrefix = "MY_APP"
    }
  }
}

Putting them together

import com.github.ajalt.clikt.core.NoOpCliktCommand
import com.github.ajalt.clikt.parameters.options.option
import com.github.ajalt.clikt.parameters.options.required

fun main(vararg args: String) {
    val config: Config = CliParser.parseConfig(*args)
}

data class Config(val username: String)

class CliParser private constructor(
  env: Map<String, String>
) : NoOpCliktCommand(
  name = "",
  help = "help text",
) {

  init {
    context {
      envarReader = env::get
      autoEnvvarPrefix = "MY_APP"
    }
  }

  private val username: String by option(help = "the username").required()

  private fun toConfig() = Config(username = username)

  companion object {

      fun parseConfig(
          args: List<String>,
          env: Map<String, String> = System.getenv(),
      ): Config =
          CliParser(env)
              .apply { parse(args) }
              .toConfig()

    fun parseConfig(
        vararg args: String,
        env: Map<String, String> = System.getenv(), 
    ): Config = parseConfig(
        args.toList(), 
        env,
    )
  }
}