Parameters
Define typed flags and positional arguments for commands.
Contents
- Type Inference
- Flag Kinds
- Parsed Flags
- Enum Flags
- Boolean Flags
- Counter Flags
- Common Flag Variants
- Flag Aliases
- Positional Arguments
- Practical Patterns
Type Inference
Stricli infers parameter configuration from the TypeScript function signature and flag types you provide.
Use strict: true in tsconfig.json whenever possible. Upstream docs strongly recommend it because optionality and parameter inference rely on strict TypeScript behavior.
Flag Kinds
Stricli currently supports four flag kinds:
parsedenumbooleancounter
There is no separate kind: "variadic". Variadic behavior is configured on supported flag kinds with variadic.
Parsed Flags
Use kind: "parsed" when a flag should parse string input into a custom type.
import { buildCommand, numberParser } from "@stricli/core";
interface Flags {
readonly port?: number;
}
export const serveCommand = buildCommand({
docs: {
brief: "Start the server",
},
parameters: {
flags: {
port: {
kind: "parsed",
parse: numberParser,
brief: "Port to bind",
placeholder: "port",
optional: true,
default: "3000",
},
},
},
func(this, flags: Flags) {
const port = flags.port ?? 3000;
this.process.stdout.write(`Listening on ${port}\n`);
},
});
Important details:
defaultfor parsed flags is a raw string, not the already-parsed valueparsecan be sync or asyncoptional: truemust match the flag type being optional
Enum Flags
Use kind: "enum" when valid values are known string literals.
interface Flags {
readonly format: "json" | "yaml" | "toml";
}
flags: {
format: {
kind: "enum",
values: ["json", "yaml", "toml"] as const,
brief: "Output format",
default: "json"
}
}
Enum flags:
- validate inputs against
values - show choices in help output
- feed values into completion proposals automatically
Boolean Flags
Use kind: "boolean" for on/off flags.
interface Flags {
readonly quiet?: boolean;
}
flags: {
quiet: {
kind: "boolean",
brief: "Suppress normal output",
optional: true,
withNegated: true
}
}
Notes:
- when
withNegatedis omitted ortrue, Stricli supports a negated flag like--noQuiet - scanner/documentation case style may display that as
--no-quiet - use
withNegated: falseif the negated form is not desirable
Counter Flags
Use kind: "counter" when repeated appearances should increment a number.
interface Flags {
readonly verbose: number;
}
flags: {
verbose: {
kind: "counter",
brief: "Increase verbosity"
}
}
aliases: {
V: "verbose"
}
Typical usage:
my-cli -V
my-cli -VV
my-cli -VVV
Common Flag Variants
Optional
If the TypeScript flag property is optional or nullable in a way Stricli recognizes, the flag config should include optional: true.
interface Flags {
readonly host?: string;
}
flags: {
host: {
kind: "parsed",
parse: String,
brief: "Host to connect to",
optional: true
}
}
Do not rely on undocumented "all flags are optional" behavior. Current Stricli typing expects optionality to be explicit.
Defaults
Defaults depend on the flag kind:
parsed: string or string array for variadic parsed flagsenum: enum value or enum value array for variadic enum flagsboolean: boolean
flags: {
region: {
kind: "parsed",
parse: String,
brief: "Target region",
optional: true,
default: "eu-west-1"
}
}
Variadic
Variadic flags collect multiple values into an array.
interface Flags {
readonly include?: readonly string[];
}
flags: {
include: {
kind: "parsed",
parse: String,
brief: "Glob(s) to include",
optional: true,
variadic: true
}
}
This accepts repeated flags:
my-cli --include src --include test
You can also provide a separator string:
include: {
kind: "parsed",
parse: String,
brief: "Glob(s) to include",
optional: true,
variadic: ","
}
This accepts comma-separated input:
my-cli --include src,test,docs
inferEmpty
Parsed flags can distinguish between --flag and --flag value by inferring an empty string when no explicit value is provided.
flags: {
message: {
kind: "parsed",
parse: String,
brief: "Optional message",
optional: true,
inferEmpty: true
}
}
Hidden Flags
Hidden flags do not appear in normal help or standard completion proposals.
flags: {
debugToken: {
kind: "parsed",
parse: String,
brief: "Internal debug token",
optional: true,
hidden: true
}
}
Users can still reveal hidden flags with --helpAll.
Flag Aliases
Aliases are defined in parameters.aliases.
parameters: {
flags: {
output: {
kind: "parsed",
parse: String,
brief: "Output file",
optional: true
}
},
aliases: {
o: "output"
}
}
Rules:
- aliases are single characters
- aliases can be batched, such as
-abc - reserve
-h,-H, and-vas described in upstream docs
Positional Arguments
Stricli supports two positional modes:
tuple- fixed shapearray- repeated values of one shape
Tuple Positionals
Use kind: "tuple" for a fixed ordered argument list.
positional: {
kind: "tuple",
parameters: [
{
brief: "Source path",
parse: String,
placeholder: "source"
},
{
brief: "Destination path",
parse: String,
placeholder: "dest"
}
]
}
Command implementation:
func(this, flags, source: string, dest: string) {
this.process.stdout.write(`Copying ${source} to ${dest}\n`);
}
Array Positionals
Use kind: "array" for a repeated positional value.
positional: {
kind: "array",
parameter: {
brief: "Input file",
parse: String,
placeholder: "file"
}
}
Command implementation:
func(this, flags, ...files: string[]) {
this.process.stdout.write(`Received ${files.length} file(s)\n`);
}
Practical Patterns
Cross-Argument Validation
Use command logic for constraints that Stricli does not model directly.
func(this, flags) {
const selected = [flags.create, flags.update, flags.remove].filter(Boolean);
if (selected.length !== 1) {
throw new Error("Choose exactly one of --create, --update, or --remove");
}
}
Camel Case + Kebab Case
Use camelCase in TypeScript and enable app-level scanning when you want users to type kebab-case flags.
const app = buildApplication(routes, {
name: "my-cli",
scanner: {
caseStyle: "allow-kebab-for-camel",
},
});
Then dryRun can be passed as --dry-run.