Kotlin CLI утилиты: пишем из консоли с нуля

Онлайн-тренажер Python для начинающих

Изучайте Python легко и без перегрузки теорией. Решайте практические задачи с автоматической проверкой, получайте подсказки на русском языке и пишите код прямо в браузере — без необходимости что-либо устанавливать.

Начать курс

Почему Kotlin — идеальный язык для CLI-утилит?

Когда речь заходит о создании консольных инструментов, многие разработчики по привычке тянутся к Python или Bash. Но если вы уже знакомы с Kotlin (а на нашем сайте pythonlib.ru мы уверены, что хороший разработчик владеет несколькими языками), то знаете, насколько этот язык лаконичен и выразителен. Создание CLI утилит на Kotlin — это не просто дань моде, а реальный способ получить быстрые, типобезопасные и кроссплатформенные инструменты.

Представьте: вы пишете консольное приложение на Kotlin, которое компилируется в JAR или нативный бинарник через GraalVM или Kotlin/Native. Оно запускается везде — от Linux-сервера до Windows-машины коллеги. При этом код получается в 2-3 раза короче, чем на Java, и намного безопаснее, чем на Python. Звучит заманчиво? Давайте разбираться.

Что нужно для старта?

Для создания Kotlin CLI вам понадобится минимум:

  • Установленный JDK 11+ (рекомендую 17 или 21)
  • IntelliJ IDEA (Community версии достаточно) или любой текстовый редактор
  • Базовое знание Kotlin (функции, классы, коллекции)
  • Gradle или Maven для сборки

Если вы еще не работали с Kotlin в консоли — не страшно. Мы пройдем путь от пустого файла до полноценной утилиты, которую можно опубликовать и использовать в CI/CD пайплайнах.

Шаг 1: Настройка проекта для CLI утилиты

Создадим простой Gradle-проект. Вот минимальный build.gradle.kts:

plugins {
    kotlin("jvm") version "1.9.22"
    application
}

application {
    mainClass.set("com.pythonlib.cli.MainKt")
}

repositories {
    mavenCentral()
}

dependencies {
    implementation("com.github.ajalt.clikt:clikt:4.2.2")
    implementation("org.jetbrains.kotlinx:kotlinx-cli:0.3.6")
}

Обратите внимание на две ключевые библиотеки: Clikt и Kotlinx CLI. Первая — самая популярная библиотека для создания CLI утилит на Kotlin. Вторая — официальное решение от JetBrains. В этой статье мы будем использовать Clikt, так как он дает больше гибкости и красивее выглядит.

Шаг 2: Пишем первую команду

Создадим файл src/main/kotlin/com/pythonlib/cli/Main.kt:

package com.pythonlib.cli

import com.github.ajalt.clikt.core.CliktCommand
import com.github.ajalt.clikt.parameters.arguments.argument
import com.github.ajalt.clikt.parameters.options.option
import com.github.ajalt.clikt.parameters.options.flag

class GreetCommand : CliktCommand(
    name = "greet",
    help = "Приветствует пользователя"
) {
    private val name: String by argument(
        help = "Имя пользователя"
    )

    private val uppercase: Boolean by option(
        "--uppercase", "-u",
        help = "Вывести имя в верхнем регистре"
    ).flag()

    override fun run() {
        val greeting = "Привет, $name!"
        if (uppercase) {
            echo(greeting.uppercase())
        } else {
            echo(greeting)
        }
    }
}

fun main(args: Array<String>) {
    GreetCommand().main(args)
}

Это простейшая Kotlin CLI утилита, которая принимает имя и опциональный флаг. Запустим:

./gradlew run --args="Алексей --uppercase"
# Вывод: ПРИВЕТ, АЛЕКСЕЙ!

Всего 30 строк кода — и у нас работающий консольный инструмент. Clikt сам генерирует справку, обрабатывает ошибки и поддерживает автодополнение для bash/zsh.

Шаг 3: Многоуровневые команды (как в Git)

Настоящие консольные приложения на Kotlin редко состоят из одной команды. Давайте сделаем утилиту для работы с файлами, которая поддерживает подкоманды:

import com.github.ajalt.clikt.core.subcommands

class FileTool : CliktCommand(
    name = "filetool",
    help = "Утилита для работы с файлами"
) {
    override fun run() {
        echo("Используйте подкоманды: count, search")
    }
}

class CountCommand : CliktCommand(
    name = "count",
    help = "Подсчитывает строки в файле"
) {
    private val file: String by argument(help = "Путь к файлу")

    override fun run() {
        val lines = java.io.File(file).readLines().size
        echo("Количество строк: $lines")
    }
}

class SearchCommand : CliktCommand(
    name = "search",
    help = "Ищет текст в файле"
) {
    private val pattern: String by argument(help = "Искомый текст")
    private val file: String by argument(help = "Путь к файлу")

    override fun run() {
        val results = java.io.File(file).readLines()
            .filter { it.contains(pattern, ignoreCase = true) }
        echo("Найдено ${results.size} совпадений:")
        results.forEach { echo(it) }
    }
}

fun main(args: Array<String>) {
    FileTool().subcommands(CountCommand(), SearchCommand()).main(args)
}

Теперь наша CLI утилита на Kotlin ведет себя как настоящий профессиональный инструмент:

./gradlew run --args="count data.txt"
./gradlew run --args="search error app.log"

Шаг 4: Продвинутые фишки Clikt

Библиотека Clikt предлагает множество возможностей, которые делают создание CLI утилит на Kotlin по-настоящему приятным. Вот несколько примеров:

Автоматическая валидация входных данных

import com.github.ajalt.clikt.parameters.types.int
import com.github.ajalt.clikt.parameters.types.file

class ValidateCommand : CliktCommand() {
    private val port: Int by option("--port", "-p")
        .int()
        .check("Порт должен быть от 1024 до 65535") { it in 1024..65535 }

    private val config: java.io.File by option("--config", "-c")
        .file(mustExist = true, canBeDir = false)

    override fun run() {
        echo("Порт: $port, конфиг: ${config.absolutePath}")
    }
}

Интерактивный режим и прогресс-бары

import com.github.ajalt.clikt.output.TermUI
import kotlinx.coroutines.delay

class ProgressCommand : CliktCommand() {
    override fun run() {
        echo("Начинаем загрузку...")
        TermUI.progress("Обработка файлов") {
            for (i in 1..100) {
                delay(50)
                this.progress = i.toDouble() / 100
            }
        }
        echo("Готово!")
    }
}

Шаг 5: Сборка нативного бинарника

Чтобы ваша Kotlin CLI утилита работала без установленной JVM

Блоги

Рекомендаций по книгам