or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

arguments.mdconfiguration-sources.mdcore-commands.mdexceptions.mdindex.mdoptions.mdparameter-groups.mdparameter-types.mdshell-completion.mdtesting-utilities.md

options.mddocs/

0

# Options

1

2

Declarative option parsing with type conversion, validation, and default values. Options are declared as delegated properties with a fluent API for configuration.

3

4

## Capabilities

5

6

### Option Declaration

7

8

Create options using the `option()` function with support for multiple names, help text, environment variables, and completion.

9

10

```kotlin { .api }

11

/**

12

* Create an option

13

* @param names Option names (e.g., "-v", "--verbose")

14

* @param help Help text for the option

15

* @param metavar Placeholder for option value in help

16

* @param hidden Hide option from help

17

* @param helpTags Extra help formatter information

18

* @param envvar Environment variable name

19

* @param valueSourceKey Key for value source lookup

20

* @param completionCandidates Completion candidates

21

*/

22

fun CliktCommand.option(

23

vararg names: String,

24

help: String = "",

25

metavar: String? = null,

26

hidden: Boolean = false,

27

helpTags: Map<String, String> = emptyMap(),

28

envvar: String? = null,

29

valueSourceKey: String? = null,

30

completionCandidates: CompletionCandidates? = null

31

): RawOption

32

```

33

34

**Usage Examples:**

35

36

```kotlin

37

class MyCommand : CliktCommand() {

38

// Basic option

39

private val verbose by option("-v", "--verbose", help = "Enable verbose output")

40

41

// Option with environment variable

42

private val apiKey by option("--api-key", envvar = "API_KEY", help = "API key")

43

44

// Hidden option

45

private val debug by option("--debug", hidden = true, help = "Debug mode")

46

}

47

```

48

49

### Type Conversion

50

51

Convert option values to specific types with built-in converters.

52

53

```kotlin { .api }

54

/**

55

* Convert option value using custom conversion function

56

*/

57

inline fun <InT : Any, ValueT : Any> NullableOption<InT, InT>.convert(

58

metavar: String,

59

completionCandidates: CompletionCandidates? = null,

60

crossinline conversion: ValueConverter<InT, ValueT>

61

): NullableOption<ValueT, ValueT>

62

63

inline fun <InT : Any, ValueT : Any> NullableOption<InT, InT>.convert(

64

crossinline metavar: (Context) -> String,

65

completionCandidates: CompletionCandidates? = null,

66

crossinline conversion: ValueConverter<InT, ValueT>

67

): NullableOption<ValueT, ValueT>

68

69

/** Convert to Int */

70

fun RawOption.int(): NullableOption<Int, Int>

71

72

/** Convert to Long */

73

fun RawOption.long(): NullableOption<Long, Long>

74

75

/** Convert to Float */

76

fun RawOption.float(): NullableOption<Float, Float>

77

78

/** Convert to Double */

79

fun RawOption.double(): NullableOption<Double, Double>

80

81

/** Convert to Boolean */

82

fun RawOption.boolean(): NullableOption<Boolean, Boolean>

83

84

/** Convert to Enum */

85

fun <T : Enum<T>> RawOption.enum(): NullableOption<T, T>

86

87

/** Convert using choice map */

88

fun <T : Any> RawOption.choice(choices: Map<String, T>): NullableOption<T, T>

89

90

/** Convert using string choices */

91

fun RawOption.choice(vararg choices: String): NullableOption<String, String>

92

```

93

94

**Usage Examples:**

95

96

```kotlin

97

class MyCommand : CliktCommand() {

98

// Numeric options

99

private val port by option("--port", help = "Port number").int().default(8080)

100

private val timeout by option("--timeout", help = "Timeout in seconds").double()

101

102

// Enum option

103

enum class LogLevel { DEBUG, INFO, WARN, ERROR }

104

private val logLevel by option("--log-level").enum<LogLevel>().default(LogLevel.INFO)

105

106

// Choice option

107

private val format by option("--format").choice("json", "xml", "yaml").default("json")

108

109

// Custom conversion

110

private val date by option("--date").convert("DATE") { LocalDate.parse(it) }

111

}

112

```

113

114

### Value Processing

115

116

Process option values with defaults, validation, and multiple value handling.

117

118

```kotlin { .api }

119

/** Provide default value */

120

fun <T : Any> NullableOption<T, T>.default(value: T): OptionDelegate<T>

121

122

/** Provide lazy default value */

123

fun <T : Any> NullableOption<T, T>.defaultLazy(value: () -> T): OptionDelegate<T>

124

125

/** Mark option as required */

126

fun <T : Any> NullableOption<T, T>.required(): OptionDelegate<T>

127

128

/** Accept multiple values */

129

fun <T : Any> NullableOption<T, T>.multiple(): OptionDelegate<List<T>>

130

131

/** Convert multiple values to Set */

132

fun <T : Any> OptionDelegate<List<T>>.unique(): OptionDelegate<Set<T>>

133

134

/** Accept exactly 2 values */

135

fun <T : Any> NullableOption<T, T>.pair(): NullableOption<Pair<T, T>, T>

136

137

/** Accept exactly 3 values */

138

fun <T : Any> NullableOption<T, T>.triple(): NullableOption<Triple<T, T, T>, T>

139

```

140

141

**Usage Examples:**

142

143

```kotlin

144

class MyCommand : CliktCommand() {

145

// Default values

146

private val host by option("--host").default("localhost")

147

private val port by option("--port").int().default(8080)

148

149

// Lazy default

150

private val timestamp by option("--timestamp").defaultLazy { Instant.now().toString() }

151

152

// Required option

153

private val apiKey by option("--api-key").required()

154

155

// Multiple values

156

private val includes by option("--include").multiple()

157

private val tags by option("--tag").multiple().unique()

158

159

// Paired values

160

private val coordinates by option("--coord").int().pair()

161

162

override fun run() {

163

echo("Host: $host:$port")

164

echo("Includes: $includes")

165

echo("Coordinates: $coordinates")

166

}

167

}

168

```

169

170

### Validation

171

172

Validate option values with custom validators and built-in checks.

173

174

```kotlin { .api }

175

/**

176

* Validate option value

177

* @param validator Custom validation function

178

*/

179

fun <T> NullableOption<T, T>.validate(validator: OptionValidator<T>): NullableOption<T, T>

180

181

/**

182

* Check option value with boolean condition

183

* @param message Error message if check fails

184

* @param validator Boolean check function

185

*/

186

fun <T> NullableOption<T, T>.check(

187

message: String,

188

validator: (T) -> Boolean

189

): NullableOption<T, T>

190

```

191

192

**Usage Examples:**

193

194

```kotlin

195

class MyCommand : CliktCommand() {

196

// Custom validation

197

private val port by option("--port").int().validate {

198

require(it in 1..65535) { "Port must be between 1 and 65535" }

199

}

200

201

// Boolean check

202

private val percentage by option("--percentage").int().check("Must be 0-100") {

203

it in 0..100

204

}

205

206

// Multiple validations

207

private val email by option("--email")

208

.check("Must contain @") { "@" in it }

209

.check("Must end with .com") { it.endsWith(".com") }

210

}

211

```

212

213

### Special Option Types

214

215

Special option types for common CLI patterns.

216

217

```kotlin { .api }

218

/** Boolean flag option (no value) */

219

fun RawOption.flag(default: Boolean = false): OptionDelegate<Boolean>

220

221

/** Count option occurrences */

222

fun RawOption.counted(): OptionDelegate<Int>

223

224

/** Switch option with choices */

225

fun <T> RawOption.switch(choices: Map<String, T>): OptionDelegate<T?>

226

227

/** Version option that prints version and exits */

228

fun CliktCommand.versionOption(

229

version: String,

230

names: Set<String> = setOf("-V", "--version"),

231

help: String = "Show the version and exit",

232

message: String = version

233

): Unit

234

```

235

236

**Usage Examples:**

237

238

```kotlin

239

class MyCommand : CliktCommand() {

240

// Flag option

241

private val verbose by option("-v", "--verbose", help = "Verbose output").flag()

242

243

// Counted option

244

private val verbosity by option("-v", "--verbose", help = "Increase verbosity").counted()

245

246

// Switch option

247

private val mode by option("--mode").switch(

248

mapOf(

249

"--dev" to "development",

250

"--prod" to "production",

251

"--test" to "testing"

252

)

253

)

254

255

// Version option

256

init {

257

versionOption("1.0.0")

258

}

259

260

override fun run() {

261

if (verbose) echo("Verbose mode enabled")

262

echo("Verbosity level: $verbosity")

263

echo("Mode: $mode")

264

}

265

}

266

```

267

268

### Eager Options

269

270

Options that are processed before normal parameter parsing.

271

272

```kotlin { .api }

273

/**

274

* Create eager option that processes before normal parsing

275

*/

276

fun CliktCommand.eagerOption(

277

vararg names: String,

278

help: String = "",

279

hidden: Boolean = false,

280

helpTags: Map<String, String> = emptyMap()

281

): EagerOption

282

283

abstract class EagerOption : Option {

284

/** Process the option value */

285

abstract fun process(context: Context, value: String)

286

}

287

```

288

289

## Option Interfaces

290

291

```kotlin { .api }

292

/**

293

* Base option interface

294

*/

295

interface Option {

296

/** A name representing the values for this option that can be displayed to the user */

297

fun metavar(context: Context): String?

298

299

/** The description of this option, usually a single line */

300

fun optionHelp(context: Context): String

301

302

/** The names that can be used to invoke this option */

303

val names: Set<String>

304

305

/** Names that can be used for a secondary purpose, like disabling flag options */

306

val secondaryNames: Set<String>

307

308

/** The min and max number of values that must be given to this option */

309

val nvalues: IntRange

310

311

/** If true, this option should not appear in help output */

312

val hidden: Boolean

313

314

/** Extra information about this option to pass to the help formatter */

315

val helpTags: Map<String, String>

316

317

/** Optional set of strings to use when the user invokes shell autocomplete */

318

val completionCandidates: CompletionCandidates

319

320

/** Optional explicit key to use when looking this option up from a ValueSource */

321

val valueSourceKey: String?

322

323

/** If true, this option can be specified without a name e.g. `-2` instead of `-o2` */

324

val acceptsNumberValueWithoutName: Boolean

325

326

/** If true, the presence of this option will halt parsing immediately */

327

val eager: Boolean

328

329

/** If false, invocations must be of the form `--foo=1` or `-f1` */

330

val acceptsUnattachedValue: Boolean

331

332

/** Information about this option for the help output */

333

fun parameterHelp(context: Context): HelpFormatter.ParameterHelp.Option?

334

335

/** Called after this command's argv is parsed to transform and store the option's value */

336

fun finalize(context: Context, invocations: List<Invocation>)

337

338

/** Called after all parameters have been finalized to perform validation */

339

fun postValidate(context: Context)

340

}

341

342

/**

343

* Option property delegate interface

344

*/

345

interface OptionDelegate<T> : GroupableOption, ReadOnlyProperty<ParameterHolder, T>, PropertyDelegateProvider<ParameterHolder, ReadOnlyProperty<ParameterHolder, T>> {

346

/** The value for this option */

347

val value: T

348

349

/** Implementations must call ParameterHolder.registerOption */

350

override operator fun provideDelegate(

351

thisRef: ParameterHolder,

352

property: KProperty<*>

353

): ReadOnlyProperty<ParameterHolder, T>

354

355

override fun getValue(thisRef: ParameterHolder, property: KProperty<*>): T = value

356

}

357

358

/**

359

* Raw unprocessed option

360

*/

361

interface RawOption : Option

362

363

/**

364

* Option that may have null value

365

*/

366

interface NullableOption<out T, ValueT> : Option

367

368

/**

369

* Option with processed values

370

*/

371

interface OptionWithValues<ValueT, EachT, AllT> : Option

372

373

/**

374

* Flag option for boolean values

375

*/

376

interface FlagOption : Option

377

378

/**

379

* Eager option processed before normal parsing

380

*/

381

abstract class EagerOption : Option {

382

abstract fun process(context: Context, value: String)

383

}

384

```

385

386

## Type Aliases

387

388

```kotlin { .api }

389

typealias ValueConverter<InT, ValueT> = OptionTransformContext.(InT) -> ValueT

390

typealias OptionValidator<T> = OptionTransformContext.(T) -> Unit

391

```