Reference

@hulla/args reference

Look up argument constructors, parsed result fields, parser settings, and error metadata.

On this page

Find argument constructors, parsed result fields, and parser defaults below. For a working command before the details, follow Build a greeting command.

ConstructorConfig fieldsDefault and result
flag(config)name: string, optional description: string, schema?: ZodTypeAny, long?: string | string[], short?: string | string[]Defaults to z.boolean() and derives long/short forms from name. Absent: value: false, detected: false.
option(config)Same named fields as flagDefaults to z.string(). Absent: value: undefined, detected: false.
positional(config)name: string, optional description: string, schema?: ZodTypeAnyDefaults to z.string(); consumes one unclaimed token not beginning with -.
sequence(config)name: string, optional description: string, required arguments: Positional[]No caller schema; .value maps member names to their result records. The sequence is detected only when every member matches.
infiniteSequence(config)name: string, optional description: string, optional schema: ZodArray<ZodString>Defaults to z.array(z.string()); collects remaining unclaimed non-option tokens. With none, .value is [] and detected is false.
command(config)name: string, optional description: string, alias?: string | string[], arguments?: Argument[], commands?: Command[]Declares a branch under result.commands[name]. The typed result has detected, arguments, and nested commands; aliases still use the canonical name as the result key.

All argument constructors accept a Zod schema except sequence, which uses its members’ schemas. infiniteSequence accepts an array-of-strings schema. See Validation for missing-input behavior.

The package also exports these types:

TypeScript
import type {
  ArgType,
  PossibleArguments,
  ArgumentConfig,
  CommandConfig,
  Flag,
  Option,
  Positional,
  Sequence,
  InfiniteSequence,
  Command,
  Parser,
  ArgOutput,
  ParserResult,
  ParserSettingsInit,
  ParserSettings,
  Code,
  ParserErrorConstructor,
} from '@hulla/args'

ParserResult contains argv, arguments, and commands. A nested command result contains detected, arguments, and its own commands.

Named forms and matching

For flags and options, name: 'output' accepts --output and -o. Customize the spellings with:

ConfigAccepted names
short: 'f'--output, -f
long: ['out', 'dest']--output, --out, --dest, -o

Dashes are optional in these declarations. Duplicate names or aliases fail when you create the parser.

mode: 'both' accepts long and short spellings; 'long' and 'short' limit them. sharedDash: true permits flag groups such as -qv; every configured short name must then be one character. For options, a grouped option consumes a following value, for example -vo file when v is a flag and o an option.

Each ordinary argument result has this shape:

TypeScript
{
  value: unknown,       // TypeScript infers the Zod output type
  raw: string | undefined,
  index: number,        // index in the read slice (plus nested offset); -1 when absent
  detected: boolean,
  parser: string        // parser path, e.g. "notes.add"
}

raw keeps exactly what was matched. For --output report.txt, it is '--output report.txt'; for --output=report.txt, it is '--output=report.txt'.

index points to the first matched token in the slice the parser reads. If you skip two entries with startIndex: 2, index 0 refers to the third entry of the original array. Nested commands add their offset within the same slice.

The top-level argv contains that parsed slice. It is lowercased when caseSensitive is false; use raw when you need the original text.

Omitted options and positionals have value: undefined, raw: undefined, index: -1, and detected: false. Their schemas don’t run, so a Zod .default() won’t supply a fallback.

A present option without a following value is different: it remains detected and can use the option token itself as its candidate value. Empty equals-form values skip schema validation. Use requireEquals to reject a present option without =, and check both detected and value when input is required.

Other constructors have their own empty-input behavior:

  • Flags validate false when absent and true when present.
  • infiniteSequence validates an empty array when no tokens were collected.
  • sequence returns a record per member, plus its combined raw, first index, and detected fields.

parser({ name, arguments?, commands?, settings? }) returns the parser’s name, normalized settings, and two methods: read(argv) and parse(argv).

read() selects the input from startIndex (inclusive) to stopIndex (exclusive). The defaults read the whole array. Either pass process.argv.slice(2) with those defaults, or pass the full process.argv with startIndex: 2.

SettingDefaultEffect
caseSensitivefalseMatch command and argument names without case sensitivity. Equals-form values are taken from the normalized token, so they are lowercased too; space-separated and positional values retain original casing.
mode'both'Accept long and short option/flag forms; can be 'long' or 'short'.
requireEqualsfalseRequire an option value in --name=value form.
keepOnlyDetectedfalseRemove undetected entries from the returned results; parsing and validation rules stay the same.
mergeArgsfalseLet root and selected command parsers inspect shared arguments across the command boundary. Without it, each parser sees its own command slice.
sharedDashfalseExpand grouped single-character short forms.
startIndex0First argv entry to read.
stopIndexnullExclusive end of the argv slice.

See Parser options for argv ownership and examples; see Commands for scope and merging.

ParserError extends Error and exposes message, parser, from, code, argvIndex, argumentName, and path.

Source (from)Diagnostic behavior
zodFirst issue, argvIndex: -1, empty argumentName.
parserCan identify an argv token; declaration errors can use -1.
runtimeRuntime failure details.

Treat path as diagnostic metadata. It isn’t a guaranteed argument-name lookup, and every error doesn’t have a user-supplied token index.

Parser construction can throw for duplicate/ambiguous declarations (including invalid sharedDash short-name lengths); parsing can throw on invalid schema input or unmatched/unhandled tokens. Required input is an application decision: check detected and report your own missing-value message. @hulla/args does not render help or set process exit codes. See Validation for a CLI-boundary catch example.