@munesoft/flagx
v1.10.20
Published
Tiny CLI flag utility with superpowers. A has-flag alternative for Node.js with zero dependencies.
Maintainers
Readme
@munesoft/flagx
Tiny CLI flag utility with superpowers. A has-flag alternative that actually grows with your needs.
What is flagx?
flagx is a modern Node.js argv parser — a cli flag parser and has-flag alternative — designed to be the last flag utility you'll ever need. It's tiny, fast, and zero-dependency, but covers everything from simple boolean checks to advanced grouped flags, aliasing, type inference, and validation.
Most tools are either too simple (has-flag — booleans only) or too heavy (minimist, yargs — full parsers with baggage). flagx sits in the middle: a tiny utility that punches way above its weight class.
Simple boolean check? → One line.
Need a port number? → One line.
DB config group? → One line.
Light validation? → One line.Why flagx?
| Feature | has-flag | minimist | flagx |
|---|---|---|---|
| Boolean flags | ✅ | ✅ | ✅ |
| Value extraction | ❌ | ✅ | ✅ |
| Type inference | ❌ | ✅ | ✅ |
| Aliases | ❌ | ✅ | ✅ |
| Glob pattern matching | ❌ | ❌ | ✅ |
| Flag grouping | ❌ | ❌ | ✅ |
| Merge env/config | ❌ | ❌ | ✅ |
| Lazy + cached parse | ❌ | ❌ | ✅ |
| Light validation | ❌ | ❌ | ✅ |
| Zero dependencies | ✅ | ✅ | ✅ |
| Bundle size | ~0.1KB | ~3KB | <2KB |
Quick Start
npm install @munesoft/flagximport flagx from "@munesoft/flagx";
// That's it. One line.
if (flagx("debug")) {
console.log("debug mode on");
}Works with all standard flag styles out of the box:
node app.js --debug --port=3000 --no-verbose -f -abcExamples
Boolean check (the has-flag replacement)
import flagx from "@munesoft/flagx";
flagx("debug"); // true/false
flagx("verbose"); // true/false
flagx("prod"); // true/falseGet a value with default
const port = flagx.value("port", 3000);
const host = flagx.value("host", "localhost");Transform on read
const port = flagx.value("port", Number); // → always a number
const tags = flagx.value("tag", v => v.split(",")); // → array from stringAliases
flagx.alias({ p: "port", v: "verbose", h: "host" });
// Now -p 3000 and --port=3000 both work
const port = flagx.value("port");Pick multiple flags at once
const { port, host, debug } = flagx.pick(["port", "host", "debug"]);Multi-flag logic
flagx.hasAny(["debug", "verbose"]); // at least one
flagx.hasAll(["port", "host"]); // all requiredGlob pattern matching
// Flag: --db.host=localhost --db.port=5432 --db.ssl=true
const dbFlags = flagx.match("db.*");
// → { "db.host": "localhost", "db.port": 5432, "db.ssl": true }Grouping
// Flag: --db.host=localhost --db.port=5432
const db = flagx.group("db");
// → { host: "localhost", port: 5432 }
// Perfect for connecting to a database:
const client = new DB(db);Merge env vars or config
flagx.merge({
env: process.env,
config: { port: 3000, host: "localhost" },
});
// CLI flags always win. Env and config fill in gaps.
const port = flagx.value("port"); // from CLI, env, or configLight validation
flagx.expect({
port: "number",
debug: "boolean",
name: "string",
});
// Warns on type mismatch, throws in strict modeStrict mode
const fx = flagx({ strict: true });
fx.expect({ port: "number" }); // throws if wrong typeCommand detection
// $ node cli.js build --watch
const cmd = flagx.command(); // → "build"Flag metadata
const meta = flagx.meta("port");
// → { exists: true, value: 3000, index: 0, raw: "--port=3000" }Debug output (dev tool)
flagx.debug();
// [flagx debug] Parsed flags:
// --port 3000 (number)
// --debug true (boolean)JSON output (AI-friendly)
console.log(flagx.json());
// { "port": 3000, "debug": true }API Reference
flagx(name): boolean
Check whether a flag is present and truthy. The core has-flag-style API.
flagx("debug"); // true/falseflagx(options): api
Configure the instance. Currently supports { strict: boolean }.
flagx({ strict: true });flagx.value(name, defaultOrTransform?): any
Get a flag's value. Pass a default value or a transform function as the second argument.
flagx.value("port"); // raw value or undefined
flagx.value("port", 3000); // with default
flagx.value("port", Number); // transform: coerce to number
flagx.value("host", v => `http://${v}`); // arbitrary transformflagx.pick(keys[]): object
Extract multiple flags at once.
flagx.pick(["port", "host", "debug"]);
// → { port: 3000, host: "localhost", debug: true }flagx.all(): object
Return all parsed flags as a plain object.
flagx.all(); // → { port: 3000, debug: true, ... }flagx.hasAny(keys[]): boolean
Returns true if at least one of the keys is present and truthy.
flagx.hasAll(keys[]): boolean
Returns true only if all keys are present and truthy.
flagx.match(pattern): object
Return all flags matching a glob-style pattern (* wildcard).
flagx.match("db.*"); // → all --db.x flags
flagx.match("--no-*"); // → all negated flagsflagx.group(prefix): object
Return all flags under a prefix, with the prefix stripped from keys.
// --db.host=localhost --db.port=5432
flagx.group("db"); // → { host: "localhost", port: 5432 }flagx.meta(name): object
Return metadata about a flag.
flagx.meta("port");
// → { exists: true, value: 3000, index: 0, raw: "--port=3000" }flagx.alias(map): api
Register short-to-long aliases. Chainable.
flagx.alias({ p: "port", v: "verbose" });flagx.merge(sources): api
Merge additional flag sources. CLI args always take precedence.
flagx.merge({ env: process.env, config: loadConfig() });flagx.expect(schema): boolean
Validate flag types. Warns by default; throws in strict mode.
flagx.expect({ port: "number", debug: "boolean" });Supported types: "boolean", "number", "string", "array"
flagx.command(): string | undefined
Returns the first positional argument (typically a subcommand).
flagx.positionals(): string[]
Returns all non-flag positional arguments.
flagx.raw(): string[]
Returns the raw argv slice (everything after node script.js).
flagx.debug(): api
Prints all parsed flags with types to stdout. Dev-only tool.
flagx.json(): string
Returns all flags as a formatted JSON string.
flagx.from(argv[]): api
Override the argv source. Useful for testing.
flagx.from(["--port=3000", "--debug"]);flagx.reset(): api
Reset all state including aliases, merges, and cache.
Parsing Rules
flagx supports every common CLI flag syntax:
| Input | Result |
|---|---|
| --flag | true |
| --flag=true | true (boolean) |
| --flag=false | false (boolean) |
| --no-flag | false |
| --key=value | "value" (string) |
| --port=3000 | 3000 (number) |
| -f | true |
| -abc | a=true, b=true, c=true |
| -p 3000 | p=3000 |
| --flag --flag | [true, true] (array) |
| -- | stop parsing (rest → positionals) |
Note on space-separated values: For long flags (--key value), flagx only greedily consumes the next token when it's a typed value (number or boolean). For string values, use --key=value syntax. Short flags (-p value) always consume the next token.
Performance
flagx is built around two core principles:
Lazy parsing — argv is never touched until the first API call.
Single parse — the result is cached after the first call. Every subsequent call — flagx("x"), flagx.value("y"), flagx.all() — uses the same cached object.
100 × 1000-flag parses: ~38ms
Cached access: ~0msThis makes flagx safe to call anywhere — top of a file, in hot paths, conditionally — with no performance penalty.
Comparison
vs has-flag
has-flag does one thing: checks if a flag string exists in process.argv. No values, no types, no aliases. flagx replaces it with a superset that's still a one-liner.
vs minimist
minimist is a capable parser but is heavier (~3KB), older, and doesn't offer grouping, pattern matching, lazy parsing, merge sources, or built-in validation. flagx weighs less and does more.
vs yargs/commander
These are full CLI frameworks: help generation, command routing, middleware. If you're building a complex CLI application, they're worth it. If you just need to read flags in a script, a library, or a build tool, flagx is the right weight.
FAQ
Does flagx work in CommonJS?
Currently ESM-only (type: "module"). A CJS build can be added if needed.
Does it handle process.argv automatically?
Yes. By default it reads process.argv.slice(2). Use flagx.from([...]) to override.
Can I use it in a library (not a CLI)?
Yes. Use flagx.from(argv) with a passed-in array rather than process.argv.
Is the parse result mutable?
flagx.all() returns a shallow copy. The internal cache is not exposed directly.
What about Windows-style /flag syntax?
Not supported — flagx follows the POSIX/GNU convention used by Node.js ecosystem tools.
Keywords
cli flag parser · nodejs argv parser · command line flags javascript · has-flag alternative · minimist alternative · argv · cli · flags · parse · args
License
MIT © Munesoft
