Skip to content

Quick Start

You can get the library using any maven-compatible build system. Installation instructions can be found in the README.

Basic Concepts

Clikt command line interfaces are created by using property delegates inside a CliktCommand. The normal way to use Clikt is to forward argv from your main function to CliktCommand.main.

The simplest command with no parameters would look like this:

import com.github.ajalt.clikt.core.CliktCommand
import com.github.ajalt.clikt.core.main

class Hello: CliktCommand() {
    override fun run() {
        echo("Hello World!")
    }
}

fun main(args: Array<String>) = Hello().main(args)

And what it looks like to use:

$ ./hello
Hello World!

A help page is generated automatically:

$ ./hello --help
Usage: hello [<options>]

Options:
  -h, --help  Show this message and exit

Printing to Stdout and Stderr

Why does this example use echo instead of println? Although println works, it can cause problems with multi-platform support. echo uses Mordant to print, so it supports colors and detects the current terminal to make sure that colors work on the current system. You can also pass err=true to echo to print to stderr instead of stdout.

Additionally, if you use Clikt’s testing utilities, output sent to echo will be captured for testing, but output sent to println will not.

Coroutine commands with suspend functions

If you want to use coroutines in your command, you can use a SuspendingCliktCommand:

class Hello : SuspendingCliktCommand() {
    val count by option(help="Number of greetings").int().default(1)
    val name by argument()

    override suspend fun run() {
        for (i in 1..count) {
            echo("Hello $name!")
            delay(1000)
        }
    }
}

suspend fun main(args: Array<String>) = Hello().main(args)

Nesting Commands

Instances of any command can be attached to other commands, allowing arbitrary nesting of commands. For example, you could write a script to manage a database:

class Database : CliktCommand(name = "db") {
    override fun run() = Unit
}

class Init : CliktCommand() {
    override fun help(context: Context) = "Initialize the database"
    override fun run() {
        echo("Initialized the database.")
    }
}

class Drop : CliktCommand() {
    override fun help(context: Context) = "Drop the database"
    override fun run() {
        echo("Dropped the database.")
    }
}

fun main(args: Array<String>) = Database()
        .subcommands(Init(), Drop())
        .main(args)
$ ./db init
Initialized the database.

$ ./db drop
Dropped the database.
$ ./db --help
Usage: database [<options>] <command> [<args>]...

Options:
  -h, --help  Show this message and exit

Commands:
  init  Initialize the database
  drop  Drop the database

Adding Parameters

To add parameters, use the option and argument property delegates:

class Hello : CliktCommand() {
    val count by option(help="Number of greetings").int().default(1)
    val name by argument()

    override fun run() {
        for (i in 1..count) {
            echo("Hello $name!")
        }
    }
}
$ ./hello --help
Usage: hello [<options>] <name>

Options:
  --count <int>  Number of greetings
  -h, --help     Show this message and exit

Developing Command Line Applications With Gradle

When you write a command line application, you probably want to be able to run it without invoking java -jar ... every time. If you’re using Gradle, the application plugin provides a gradle task that bundles your program jars and scripts to launch them. It makes it easy to build a zip or tarball that you can distribute to your users without them needing to perform any incantations like setting up a classpath. You can see this plugin in use the in Clikt samples.

The application plugin also creates tasks that will build then run your main function directly from within gradle. You can pass command line arguments through to your app with the --args flag:

$ ./gradlew run --args="--count=3 Clikt"

A drawback to using the run gradle task is that it redirects stdout, so Clikt will not print colors or prompt for input. You can configure the Mordant terminal that Clikt uses to always print with color, but this will cause ANSI codes to be printed even if you redirect the app’s output to a file.

MyCommand().context {
    terminal = Terminal(ansiLevel = AnsiLevel.TRUECOLOR, interactive = true)
}.main(args)

Another approach is to use the installDist task provided by the plugin. This builds all the distribution scripts in your build folder, which you can then execute normally. See Clikt’s runsample script for an example of this approach.