FUNC - Tiny typed CLI framework

Field Options

Field options turn command properties into CLI options. func parses the current command scope, assigns option values to the command instance, then runs the selected handler.

Flags

@Flag creates a boolean option. The property default is used when the user does not pass the flag.

import { CommandMajor, Flag, Handler } from 'func'

@CommandMajor()
export class Major {
  @Flag({ alias: 'v', description: 'Print more logs' })
  verbose = false

  @Handler()
  run() {
    console.log(this.verbose)
  }
}

my-cli --verbose and my-cli -v both set this.verbose to true.

Values

@Value creates a scalar value option. It can infer String, Number, and Boolean from TypeScript metadata. Use type when inference is not enough.

import { Command, Handler, Value } from 'func'

@Command({ name: 'serve' })
export class ServeCommand {
  @Value()
  host: string = 'localhost'

  @Value()
  port: number = 3000

  @Value({ name: 'dry-run', type: Boolean })
  dryRun = false

  @Handler()
  run() {
    console.log(this.host, this.port, this.dryRun)
  }
}

For my-cli serve --host 0.0.0.0 --port 4000, the instance receives host = '0.0.0.0' and port = 4000.

Repeated Values

@ArrayValue creates a repeated string option. Use it when the user can pass the same option multiple times.

import { ArrayValue, Command, Handler } from 'func'

@Command({ name: 'build' })
export class BuildCommand {
  @ArrayValue({ name: 'include', alias: 'i' })
  includes: string[] = []

  @Handler()
  run() {
    console.log(this.includes)
  }
}

my-cli build -i src -i tests assigns ['src', 'tests'] to this.includes.

Validation

Field validators run after option values are assigned. Validation errors are runtime-print errors, so they can be formatted by local or global error handlers.

import {
  Command,
  DependsOn,
  Enum,
  Exclusive,
  Flag,
  Handler,
  Required,
  Value,
  ValueValidate,
} from 'func'

@Command({ name: 'publish' })
export class PublishCommand {
  @Required()
  @Enum(['dev', 'prod'])
  @Value()
  target?: string

  @DependsOn(['token'])
  @Value()
  registry?: string

  @Value()
  token?: string

  @Exclusive(['json'])
  @Flag()
  table = false

  @Flag()
  json = false

  @Value()
  @ValueValidate(value => Number(value) > 0 || 'retry must be positive')
  retry: number = 1

  @Handler()
  run() {}
}
  • @Required requires a defined value.
  • @Enum restricts values to an allowed list.
  • @DependsOn requires related options when this option is explicit.
  • @Exclusive rejects conflicting explicit options.
  • @ValueValidate runs custom validation logic.

Sub-options

@SubOptions declares parse-only options for the command scope. For most typed command values, prefer field options. Use sub-options only when you intentionally want to read normalized option data from @Args().