Skip to content

Positionals

Positionals are the leftover inputs that were not matched by a flag or a typed argument. They are plain strings, and you get them only when allowPositionals: true.

Typed arguments are filled first, in order, and whatever is left over becomes positionals.

const cli = defineCLI({
cliName: "example",
allowPositionals: true,
arguments: {
userId: { schema: z.number(), coerce: coerce.number },
action: { schema: z.string() },
},
});
cli.onExecute(({ arguments: args, positionals }) => {
console.log(args.userId, args.action); // typed
console.log(positionals); // string[]
});
Terminal window
example 42 delete a.txt b.txt
# userId: 42, action: "delete", positionals: ["a.txt", "b.txt"]

The two modes

Setting Behavior
allowPositionals: true Typed arguments are filled first, the rest goes to positionals. No typed argument may be optional in this mode.
allowPositionals: false Every input must match a typed argument. Only the last one may be optional. Anything extra is an error.

With allowPositionals: false, an extra input fails with ParseErrorCode.PositionalArgumentNotAllowed.

Typed arguments compared to positionals

Typed arguments Positionals
Validation Validated against the schema None
Type Whatever the schema produces Always string
Order Filled left to right, strictly Everything that is left
Optional / default Controlled by the schema Never optional, never has defaults
Source The arguments field Filled automatically when allowed

Inputs that start with a dash

-- ends option parsing. Everything after it becomes a typed argument or a positional, even when it looks like a flag. For an option value that starts with a dash, use the = form.

Terminal window
listy --name=-weird -- -file.txt --not-an-option
# name: "-weird", arguments and positionals: ["-file.txt", "--not-an-option"]