Flags
Define named flags with types, aliases, defaults, multiple values, and inheritance.
Flags are named options passed with -- (long form) or - (short form). They're defined as a record via .flags().
my-cli --port 3000 --verbose -o dist
# ^^^^^^^^^^^ ^^^^^^^^^ ^^^^^^
# flag flag shortDefining Flags
Flags are defined with the .flags() method:
const cmd = new Crust("serve")
.flags({
port: {
type: "number",
description: "Port to listen on",
default: 3000,
short: "p",
},
verbose: {
type: "boolean",
description: "Enable verbose logging",
short: "v",
},
})
.run(({ flags }) => {
console.log(`Port: ${flags.port}`); // number (has default)
console.log(`Verbose: ${flags.verbose}`); // boolean | undefined
});Flag Properties
Each flag is a FlagDef object with properties like type, description, default, required, short, aliases, multiple, and inherit. See the FlagDef reference for the full property table.
Types
Crust supports three flag type literals:
.flags({
output: { type: "string" }, // --output value (string)
port: { type: "number" }, // --port 3000 (coerced to number)
verbose: { type: "boolean" }, // --verbose (boolean toggle)
})"string"— Requires a value:--output dist"number"— Requires a value, coerced to number:--port 3000. Throws aPARSEerror if the value isn't a valid number"boolean"— Toggle flag, no value needed:--verbose
Boolean Negation
Boolean flags support --no- prefix negation:
my-cli --no-minify # flags.minify === falseThis works automatically for any boolean flag. When a boolean flag is repeated, the last occurrence wins:
my-cli --verbose --no-verbose # flags.verbose === false
my-cli --no-verbose --verbose # flags.verbose === trueUse the canonical flag name for negation (--no-verbose), not aliases like --no-v or --no-loud.
Boolean flags are toggles and do not accept explicit value assignment. Forms like --verbose=true or --verbose=false are parse errors.
Short & Aliases
Provide a single-character short form with the short property, and additional aliases with the aliases property:
.flags({
output: { type: "string", short: "o" }, // -o dist
verbose: { type: "boolean", short: "v" }, // -v
target: { type: "string", short: "t", aliases: ["T"] }, // -t or -T
})short accepts a single character for the -x short form. aliases accepts an array of additional aliases (single-char or long).
Alias collisions are caught at compile time and runtime. If an alias conflicts with another flag name or another alias, you'll get an error.
The no- prefix is reserved for boolean negation. Do not define flag names, short forms, or aliases that start with no-.
Required Flags
Mark a flag as required to error when it's missing:
.flags({
config: { type: "string", required: true },
})$ my-cli
# Error: Missing required flag "--config"Default Values
Provide a default to use when the flag isn't passed:
.flags({
port: { type: "number", default: 3000 },
format: { type: "string", default: "json" },
minify: { type: "boolean", default: true },
})When a default is set, the inferred type is guaranteed (no | undefined).
Multiple Values
Set multiple: true to collect repeated flag values into an array:
.flags({
target: {
type: "string",
multiple: true,
description: "Target platform(s)",
short: "t",
},
})my-cli --target linux-x64 --target darwin-arm64
# flags.target === ["linux-x64", "darwin-arm64"]Boolean flags with multiple: true collect each occurrence (including --no- negations) into the array:
my-cli --verbose --no-verbose --verbose
# flags.verbose === [true, false, true]You can also provide a default array:
.flags({
include: {
type: "string",
multiple: true,
default: ["src/**"],
},
})Flag Inheritance
Set inherit: true on a flag to make it available to subcommands:
const app = new Crust("my-cli")
.flags({
verbose: { type: "boolean", short: "v", inherit: true },
debug: { type: "boolean" }, // not inherited
})
.command("deploy", (cmd) =>
cmd
.flags({ env: { type: "string", required: true } })
.run(({ flags }) => {
flags.verbose; // boolean | undefined (inherited from parent)
flags.env; // string (local)
// flags.debug — not available (not inherited)
})
);Inherited flags are:
- Parsed by the subcommand's parser alongside local flags
- Typed correctly in the subcommand's handler via
EffectiveFlags<Inherited, Local> - Shown in the subcommand's help output
Local flags override inherited flags with the same key. Only flags with inherit: true are propagated — all other parent flags are excluded.
See the .sub() factory for how to use flag inheritance with the file-splitting pattern.
Unknown Flags
Crust uses strict mode for flag parsing. Unknown flags immediately produce a PARSE error:
$ my-cli --unknown-flag
# Error: Unknown flag "--unknown-flag"Type Inference
Crust infers flag types from your definitions — required and default guarantee the value, otherwise it's T | undefined. Flags with multiple: true resolve to arrays. See the full inference rules for all cases.