argvex is a lightweight and unopinionated CLI argument parser
β just a parsing tool, not a framework
Explore the API Β»
Report a bug
Β Β Β·Β Β
Request a feature
Β Β Β·Β Β
δΈζ
You want to roll-your-own CLI, but argument parsing is such a headache?
Let argvex handle the annoying part, and nothing else.
argvex is a minimalist argument parser that stays out of your way with little to no API,
so you can keep full control, define your own rules, and avoid framework baggage.
| π Zero dependencies | One file. Fast. No tree bloat. |
| πΉοΈοΈ Control over configuration | You define behavior, types, defaults β all your choice |
| βοΈ Zero-assumptions | Everything is explicit, no coercion, no surprises. |
| π Schema-optional | Works raw out of the box, add constraints only when you need it. |
| π UNIX philosophy | Do one thing well, stay composable. |
| π TypeScript | Type definitions right out of the box. |
argvex gives you a structured view of your command-line input β flags, values,
and operands β without forcing schemas, coercion, or assumptions.
npm install argvexYou can just call argvex() to get structured process.argv output.
brewer brew espresso --size medium --shots 3 --milk none --temperature 92 --crema thickimport argvex from 'argvex'
const args = argvex()
// args -> { _: [ "brewer", "brew", "espresso" ], "size": [ "medium" ], shots: [ "3" ], milk: [ "none" ], temperature: [ "92" ], crema: [ "thick" ] }A GNU-flavoured value assign using "=" works too!
brewer brew cappuccino --size=large --shots=2 --milk=steamed --foam=thickimport argvex from 'argvex'
const args = argvex()
// args -> { _: [ "brewer", "brew", "cappuccino" ], "size": [ "large" ], shots: [ "2" ], milk: [ "steamed" ], foam: [ "thick" ] }When it comes to boolean flags, just check for their presence.
import argvex from 'argvex'
const args = argvex()
if (!!args.decaf) {
console.log("Making a decaf coffee!")
}You can use standalone short flags or use them in groups.
brewer brew americano -qs -m water -t 85import argvex from 'argvex'
const args = argvex()
// args -> { _: [ "brewer", "brew", "americano" ], "q": [], "s": [], m: [ "water" ], t: [ "85" ] }Use -- (end-of-options delimiter) to separate flags from operands that might look like flags.
brewer brew --milk oat -- --not-a-flag latteimport argvex from 'argvex'
const args = argvex()
// args -> { _: [ "brewer", "brew", "--not-a-flag", "latte" ], milk: [ "oat" ] }While you can code your own support for aliases easily,
argvex can handle those out-of-the-box if you pass a minimal schema to it.
brewer brew mocha -d -m oat -c darkimport argvex from 'argvex'
const schema = [
{ name: "decaf", alias: "d" },
{ name: "milk", alias: "m" },
{ name: "chocolate", alias: "c" }
]
const args = argvex({ schema })
// args -> { _: [ "brewer", "brew", "mocha" ], "decaf": [], milk: [ "oat" ], chocolate: [ "dark" ] }While argvex aims at being a minimalist tool, it can support most of the POSIX-flavoured syntax if you pass a schema to it.
brewer brew -dsmedium -h2 macchiatoimport argvex from 'argvex'
const schema = [
{ name: "decaf", alias: "d", arity: 0 },
{ name: "size", alias: "s", arity: 1 },
{ name: "shots", alias: "h", arity: 1 },
]
const args = argvex({ schema })
// args -> { _: [ "brewer", "brew", "macchiato" ], "decaf": [], size: [ "medium" ], shots: [ "2" ] }By default, repeating a flag will override its previous value. If you want values to accumulate instead, enable additive mode.
brewer brew flat-white --milk steamed --milk foamed --milk microfoamimport argvex from 'argvex'
const schema = [
{ name: "milk", arity: 3 },
]
const args = argvex({ schema, additive: true })
// args -> { _: [ "brewer", "brew", "flat-white" ], milk: [ "steamed", "foamed", "microfoam" ] }You may force argvex to throw an error whenever unexpected flag or value gets passed.
brewer brew cortado --size small --shots 1 --no-payimport argvex from 'argvex'
const schema = [
{ name: "size", arity: 1 },
{ name: "shots", arity: 1 },
]
const args = argvex({ schema, strict: true })
// args -> ArgvexErrorargvex doesn't try to do anything more than parsing itself, so it's up to you how you want to handle the rest.
Here are some common patterns you might find useful.
Sometimes you need to ensure certain flags are provided. You can check for their presence and throw an error if they're missing.
import argvex from 'argvex'
const args = argvex()
if (!args.temperature) {
throw new Error('You must provide "--temperature" flag first.')
}When optional flags aren't provided, you can set sensible defaults.
import argvex from 'argvex'
const args = argvex()
if (!args.milk) {
args.milk = [ "steamed" ]
}Since argvex returns all values as strings, you'll often want to convert them to the appropriate types.
import argvex from 'argvex'
const args = argvex()
if (args.temperature) {
args.temperature = args.temperature.map(temperature => parseInt(temperature, 10))
}Wrap argvex calls in try-catch to handle parsing errors gracefully.
import argvex, { ArgvexError } from 'argvex'
try {
const args = argvex({ strict: true })
// todo: process args here
} catch (error) {
if (error instanceof ArgvexError) {
console.error('Invalid command line arguments')
process.exit(1)
}
throw error
}