CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/npm-stricli--core

Build complex CLIs with type safety and no dependencies

Overview
Eval results
Files

flag-parameters.mddocs/

Flag Parameters

Type-safe flag definitions supporting boolean, counter, enum, and parsed types with optional, required, and variadic variants.

Quick Reference

flags: {
  // Boolean
  verbose: { kind: "boolean", brief: "Verbose output", default: false },
  dryRun: { kind: "boolean", brief: "Dry run", optional: true },
  
  // Counter (repeatable)
  verbosity: { kind: "counter", brief: "Verbosity level" },
  
  // Enum (string literals)
  env: { kind: "enum", values: ["dev", "prod"], brief: "Environment", default: "dev" },
  
  // Parsed (custom type)
  port: { kind: "parsed", parse: numberParser, brief: "Port", default: "3000" },
  timeout: { kind: "parsed", parse: numberParser, brief: "Timeout", optional: true },
  
  // Variadic
  files: { kind: "parsed", parse: String, variadic: true, brief: "Files" },
  tags: { kind: "parsed", parse: String, variadic: ",", brief: "Tags", optional: true }
},
aliases: { v: "verbose", e: "env", p: "port" }

Flag Types

Boolean Flags

On/off toggles with optional negation syntax.

// Required with default
verbose: {
  kind: "boolean",
  brief: "Enable verbose output",
  default: false  // optional, defaults to false
}

// Optional
dryRun: {
  kind: "boolean",
  brief: "Perform dry run",
  optional: true
}

Usage: --verbose, --no-verbose, --dry-run

Counter Flags

Increment with each occurrence.

verbosity: {
  kind: "counter",
  brief: "Increase verbosity (-v, -vv, -vvv)"
}

Usage: -v (1), -vv (2), -vvv (3), --verbosity --verbosity (2)

Enum Flags

Predefined set of string values.

// Single value
env: {
  kind: "enum",
  values: ["dev", "staging", "prod"],
  brief: "Target environment",
  default: "dev"  // optional
}

// Variadic (multiple values)
features: {
  kind: "enum",
  values: ["auth", "api", "ui"],
  brief: "Enabled features",
  variadic: true  // or "," for comma-separated
}

Usage: --env prod, --features auth --features api, --features auth,api,ui

Parsed Flags

Custom parser for any type.

// Single value with default
port: {
  kind: "parsed",
  parse: numberParser,
  brief: "Server port",
  default: "3000"
}

// Optional
timeout: {
  kind: "parsed",
  parse: (input) => parseInt(input, 10),
  brief: "Timeout in seconds",
  optional: true
}

// Variadic
files: {
  kind: "parsed",
  parse: String,
  variadic: true,
  brief: "Input files",
  proposeCompletions: async () => await readdir(".")  // optional
}

Flag Properties

Common:

  • kind: "boolean" | "counter" | "enum" | "parsed"
  • brief: string (description)
  • optional: boolean (makes flag optional, undefined if not provided)
  • default: string (for parsed/enum) | boolean (for boolean) - conflicts with optional
  • placeholder: string (custom placeholder in usage line)
  • hidden: boolean (hide from help text)

Parsed-specific:

  • parse: InputParser<T, CONTEXT>
  • variadic: boolean | string (true or separator like ",")
  • inferEmpty: boolean (if flag specified without value, use "")
  • proposeCompletions: (partial: string) => string[] | Promise<string[]>

Enum-specific:

  • values: readonly T[]
  • variadic: boolean | string

Type Safety & Type Inference

TypedFlagParameter Type

Generic type for defining flag parameters with full type inference. Automatically infers the appropriate flag type based on TypeScript types.

/**
 * Definition of a flag parameter
 * Properties vary based on type T:
 * - boolean types -> BooleanFlagParameter
 * - number types -> CounterFlagParameter or ParsedFlagParameter
 * - string literal unions -> EnumFlagParameter
 * - arrays -> Variadic flags
 * - undefined in union -> Optional flags
 */
type TypedFlagParameter<T, CONTEXT extends CommandContext = CommandContext> =
  undefined extends T
    ? TypedFlagParameter_Optional<NonNullable<T>, CONTEXT>
    : TypedFlagParameter_Required<T, CONTEXT>;

FlagParametersForType Type

Mapped type defining flags for each named parameter in type T. Transforms TypeScript interface into flag parameter definitions.

/**
 * Definition of flags for each named parameter
 * Transforms TypeScript interface into flag parameter definitions
 */
type FlagParametersForType<T, CONTEXT extends CommandContext = CommandContext> = {
  readonly [K in keyof T]-?: TypedFlagParameter<T[K], CONTEXT>;
};

Usage Example:

import { FlagParametersForType, buildCommand } from "@stricli/core";

// Define flags type
interface MyFlags {
  verbose: boolean;
  output?: string;
  count: number;
  mode: "fast" | "slow";
}

// Type-safe flag parameters
const flagParams: FlagParametersForType<MyFlags> = {
  verbose: {
    kind: "boolean",
    brief: "Enable verbose mode"
  },
  output: {
    kind: "parsed",
    parse: (s) => s,
    brief: "Output file path",
    optional: true
  },
  count: {
    kind: "counter",
    brief: "Repeat count"
  },
  mode: {
    kind: "enum",
    values: ["fast", "slow"],
    brief: "Processing mode",
    default: "fast"
  }
};

const command = buildCommand({
  func: async function(flags: MyFlags) {
    // flags is fully typed!
    if (flags.verbose) {
      this.process.stdout.write("Verbose mode\n");
    }
  },
  parameters: {
    flags: flagParams
  },
  docs: {
    brief: "My command"
  }
});

TypedCommandFlagParameters Type

Typed definitions for all flag parameters with optional aliases mapping.

/**
 * Typed definitions for all flag parameters
 */
interface TypedCommandFlagParameters<
  FLAGS extends BaseFlags,
  CONTEXT extends CommandContext
> {
  /** Typed definitions for all flag parameters */
  readonly flags: FlagParametersForType<FLAGS, CONTEXT>;

  /** Object that aliases single characters to flag names */
  readonly aliases?: Aliases<keyof FLAGS & string>;
}

/** Root constraint for all flag type parameters */
type BaseFlags = Readonly<Record<string, unknown>>;

Aliases

Object mapping single-character aliases to flag names. Limited to single letters a-g, i-z, A-Z (h is reserved).

/**
 * Object mapping single-character aliases to flag names
 * Limited to single letters a-g, i-z, A-Z (h is reserved)
 */
type Aliases<T> = Readonly<Partial<Record<AvailableAlias, T>>>;

type AvailableAlias = Exclude<
  | "a" | "b" | "c" | "d" | "e" | "f" | "g"
  | "i" | "j" | "k" | "l" | "m" | "n" | "o" | "p" | "q" | "r"
  | "s" | "t" | "u" | "v" | "w" | "x" | "y" | "z"
  | "A" | "B" | "C" | "D" | "E" | "F" | "G"
  | "I" | "J" | "K" | "L" | "M" | "N" | "O" | "P" | "Q" | "R"
  | "S" | "T" | "U" | "V" | "W" | "X" | "Y" | "Z",
  "h"
>;

Usage Example:

parameters: {
  flags: { verbose, output, force },
  aliases: { v: "verbose", o: "output", f: "force" }
}

// Usage: -v -o file.txt -f
// Usage: -vof file.txt  (combined)
// Usage: --verbose --output file.txt --force

Complete Example

interface DeployFlags {
  environment: "dev" | "staging" | "prod";
  verbose: boolean;
  dryRun?: boolean;
  timeout?: number;
  replicas: number;
  services: readonly string[];
  tags?: readonly string[];
}

const deployCommand = buildCommand({
  func: async function(flags: DeployFlags) {
    this.process.stdout.write(`Deploying to ${flags.environment}\n`);
    this.process.stdout.write(`Services: ${flags.services.join(", ")}\n`);
    if (flags.dryRun) {
      this.process.stdout.write("DRY RUN\n");
      return;
    }
  },
  parameters: {
    flags: {
      environment: { kind: "enum", values: ["dev", "staging", "prod"], brief: "Environment", default: "dev" },
      verbose: { kind: "boolean", brief: "Verbose logging", default: false },
      dryRun: { kind: "boolean", brief: "Dry run mode", optional: true },
      timeout: { kind: "parsed", parse: numberParser, brief: "Timeout (seconds)", optional: true },
      replicas: { kind: "counter", brief: "Replicas (specify multiple times)" },
      services: { kind: "parsed", parse: String, variadic: true, brief: "Services to deploy" },
      tags: { kind: "parsed", parse: String, variadic: ",", optional: true, brief: "Tags (comma-separated)" }
    },
    aliases: { e: "environment", v: "verbose", d: "dryRun", t: "timeout", r: "replicas" }
  },
  docs: { brief: "Deploy services" }
});

// Usage:
// myapp -e prod -v -rrr --services api --services web
// myapp --environment staging --dry-run --timeout 300 --services api
// myapp --tags v2.0,stable --services api --services web

Related

  • Parameter Parsers
  • Positional Parameters

Install with Tessl CLI

npx tessl i tessl/npm-stricli--core

docs

application.md

commands-and-routing.md

configuration-and-context.md

documentation-and-help.md

error-handling.md

exit-codes.md

flag-parameters.md

index.md

parameter-parsers.md

positional-parameters.md

text-and-localization.md

tile.json