Arguments
Define positional arguments with types, defaults, and validation.
Arguments are positional values passed to your CLI without a flag name. They're defined as an ordered array via .args(), and Crust maps them to named, typed values.
my-cli serve 3000 localhost
# ^^^^ ^^^^^^^^^
# arg 1 arg 2Defining Arguments
Arguments are defined with the .args() method. Order matters — the first argument definition maps to the first positional value:
const cmd = new Crust("serve")
.args([
{ name: "port", type: "number", default: 3000 },
{ name: "host", type: "string", default: "localhost" },
])
.run(({ args }) => {
console.log(`Listening on ${args.host}:${args.port}`);
});Argument Properties
Each argument is an ArgDef object with properties like name, type, description, default, required, and variadic. See the ArgDef reference for the full property table.
Types
Crust supports three argument type literals:
.args([
{ name: "port", type: "number" }, // Coerced to number
{ name: "host", type: "string" }, // Kept as string
{ name: "verbose", type: "boolean" }, // Coerced to boolean
])"string"— The value is kept as-is"number"— The value is coerced to a number. Throws aPARSEerror if the value isn't a valid number"boolean"— The value is coerced to a boolean ("true"/"1"->true)
Required Arguments
Mark an argument as required to error when it's missing:
.args([
{ name: "name", type: "string", required: true },
])$ my-cli
# Error: Missing required argument "<name>"When required is true, the inferred type is guaranteed (no | undefined).
Default Values
Provide a default for optional arguments:
.args([
{ name: "port", type: "number", default: 3000 },
])When a default is set, the argument is always present in args — the inferred type is guaranteed (no | undefined).
Optional Arguments
Arguments without required or default are optional. Their type includes | undefined:
new Crust("example")
.args([
{ name: "name", type: "string" },
])
.run(({ args }) => {
args.name; // string | undefined
})Variadic Arguments
The last argument can be variadic, collecting all remaining positional values into an array:
const cmd = new Crust("copy")
.args([
{ name: "destination", type: "string", required: true },
{ name: "files", type: "string", variadic: true },
])
.run(({ args }) => {
args.destination; // string
args.files; // string[]
for (const file of args.files) {
console.log(`Copying ${file} to ${args.destination}`);
}
});my-cli /output file1.txt file2.txt file3.txtOnly the last argument can be variadic. Crust enforces this at both compile time and runtime. Placing variadic: true on a non-last argument produces a type error.
Variadic arguments with required: true error when no values are provided. Without required, an empty array is returned.
The -- Separator
Arguments after -- are collected into rawArgs and not processed as positional arguments or flags:
.run(({ args, rawArgs }) => {
// rawArgs contains everything after --
console.log("Raw args:", rawArgs);
})my-cli build -- --some-flag --passed-through
# rawArgs: ["--some-flag", "--passed-through"]This is useful for forwarding arguments to child processes.
Type Inference
Crust infers argument types from your definitions — required and default guarantee the value, otherwise it's T | undefined. Variadic arguments always return an array. See the full inference rules for all cases.