Getting started
@staticbolt/args-parser turns terminal input into typed, validated values. You describe your CLI once, and you get parsing, validation, help output, Markdown docs, and shell completion from that single description.
Features
- Typed and validated: every option and argument gets its type from a schema, and the parsed result is typed to match.
- Flexible syntax:
--option value,--option=value, short flags, flag coupling (-rf), and--to stop option parsing. - Repeatable options: array and set options accept
--item a --item band--item a,b. - Boolean flags: negation with
--no-verbose, with or without an explicit value. - Subcommands: each one has its own options, arguments, and handler.
- Generated help and docs: help messages, Markdown files, and completion scripts for Bash, Zsh, Fish, and PowerShell.
- Schema agnostic: works with any library that implements Standard Schema.
- Runs anywhere: Node.js, Bun, Deno, and browsers.
Install
You need a validation library alongside the parser. It must implement Standard Schema and let primitive types be optional or carry a default value.
npm install zod @staticbolt/args-parserZod is used in every example here. Valibot, Sury, and Decoders work too. See Using schemas.
Your first CLI
import { defineCLI } from "@staticbolt/args-parser";import * as z from "zod";
const cli = defineCLI({ cliName: "hello", options: { /** `--name` or `-n` */ name: { aliases: ["n"], schema: z.string().default("world"), }, },});
cli.onExecute(({ options }) => { console.log(`Hello, ${options.name}!`);});
const result = cli.run(process.argv.slice(2));if (result.error) { console.error(result.error.message);}hello # Hello, world!hello --name Sam # Hello, Sam!hello -n Sam # Hello, Sam!Three pieces do the work:
| Piece | What it does |
|---|---|
defineCLI | Describes the CLI: its name, options, arguments, and subcommands. |
onExecute | Receives the parsed values once everything validates. You can attach more than one. |
run | Parses the input, runs the matching handlers, and returns { value } or { error }. |
Option names are written as JavaScript identifiers and converted to flags: name becomes --name, and outputDir becomes --output-dir.
Handling errors
run never throws for bad input. Parsing and validation problems come back in result.error:
const result = cli.run(process.argv.slice(2));if (result.error) { console.error(result.error.message); process.exit(1);}Errors thrown inside an onExecute handler are a different matter: those propagate to the caller. If a handler is async, use runAsync so its rejection is awaited. run does not wait for handlers.
Where to go next
- Defining a CLI covers the definition object, handlers, and the result shape.
- Options and Typed arguments cover the two kinds of input.
- Parsing rules is the reference for what the parser accepts on the command line.
- Listy is a complete example CLI.