@cli-forge/parser

v1.10.0npmGitHub
npm install @cli-forge/parser

A type-safe argument parser for Node.js with full TypeScript inference.

This is the low-level parsing engine that powers cli-forge. Use this package directly if you need fine-grained control over argument parsing without the higher-level command management features.

Installation

npm install @cli-forge/parser

Quick Start

import { parser } from '@cli-forge/parser';

const args = parser()
  .option('name', { type: 'string', required: true })
  .option('port', { type: 'number', default: 3000 })
  .option('verbose', { type: 'boolean', alias: ['v'] })
  .parse(['--name', 'my-app', '--port', '8080', '-v']);

// args is fully typed:
// { name: string; port: number; verbose: boolean }
console.log(args.name);    // 'my-app'
console.log(args.port);    // 8080
console.log(args.verbose); // true

Features

  • Full TypeScript inference - Types accumulate as you chain .option() calls
  • Multiple option types - string, number, boolean, array, object
  • Value sources - CLI args, environment variables, config files, defaults
  • Validation - choices, validate, required, conflicts, implies
  • Config file support - JSON/YAML with inheritance via extends
  • Coercion - Transform values during parsing

Option Types

String

parser().option('name', {
  type: 'string',
  description: 'User name',
  default: 'anonymous',
});

Number

parser().option('port', {
  type: 'number',
  description: 'Port number',
  default: 3000,
});

Boolean

parser().option('verbose', {
  type: 'boolean',
  alias: ['v'],
  description: 'Enable verbose output',
});
// Supports: --verbose, --verbose true, --no-verbose

Array

parser().option('files', {
  type: 'array',
  items: 'string',
  description: 'Input files',
});
// Supports: --files a b c, --files a,b,c, --files a --files b

Object

parser().option('config', {
  type: 'object',
  properties: {
    host: { type: 'string', default: 'localhost' },
    port: { type: 'number', required: true },
    ssl: { type: 'boolean' },
  },
});
// Supports: --config.host example.com --config.port 443 --config.ssl

Positional Arguments

parser()
  .positional('input', { type: 'string', required: true })
  .positional('output', { type: 'string' })
  .parse(['input.txt', 'output.txt']);

Validation

Choices

parser().option('level', {
  type: 'string',
  choices: ['debug', 'info', 'warn', 'error'],
});

Custom Validation

parser().option('port', {
  type: 'number',
  validate: (value) => {
    if (value < 1 || value > 65535) {
      throw new Error('Port must be between 1 and 65535');
    }
    return true;
  },
});

Conflicts and Implies

parser()
  .option('quiet', { type: 'boolean' })
  .option('verbose', {
    type: 'boolean',
    conflicts: ['quiet'],
  })
  .option('output', {
    type: 'string',
    implies: { format: 'json' },
  });

Environment Variables

parser().option('apiKey', {
  type: 'string',
  env: 'API_KEY',
});
// Will read from process.env.API_KEY if --apiKey not provided

Configuration Files

parser()
  .configFile('myapp.config.json')
  .option('port', { type: 'number' })
  .parse([]);

Config files support inheritance:

{
  "extends": "./base-config.json",
  "port": 8080
}

Coercion

Transform values during parsing:

parser().option('date', {
  type: 'string',
  coerce: (value) => new Date(value),
});

Type Inference

The parser tracks types as options are added:

const p = parser()
  .option('name', { type: 'string' })        // { name?: string }
  .option('port', { type: 'number' })        // { name?: string; port?: number }
  .option('required', { type: 'string', required: true }); // { name?: string; port?: number; required: string }
  • cli-forge - High-level CLI builder with commands, middleware, and documentation generation

Documentation

Full documentation available at: https://craigory.dev/cli-forge/

License

ISC

API EXPORTS

Functions

chainfunction

Applies a series of functions to an initial value, passing the result of each function to the next. Used to convert code that looks like: ```typescript const a = addB(addC({ a: 'a' })); ``` to: ```typescript const a = chain({ a: 'a' }, addB, addC); ``` See [composable-options](/examples/composable-options) for an example of how this can be used.

detectLocalefunction

Detects the current locale from the system. Uses Intl.DateTimeFormat to determine the user's locale.

fromCamelCaseToDashedfunction
fromCamelOrDashedCaseToConstCasefunction
fromDashedToCamelCasefunction
getBinfunction
getEnvironmentProviderfunction

Return the current global EnvironmentProvider.

getEnvKeyfunction
getFileSystemProviderfunction

Return the current global FileSystemProvider.

hideBinfunction
isArrayOptionConfigfunction
isBooleanOptionConfigfunction
isNumberOptionConfigfunction
isObjectOptionConfigfunction
isOneOfOptionConfigfunction
isStringOptionConfigfunction
makeComposableOptionfunction

A composition helper to be used with chain.

parserfunction

Small helper function to create a new parser instance.

readDefaultValuefunction
resolveLocalizedTextfunction

Resolves a localized text value from a dictionary.

setEnvironmentProviderfunction

Replace the global EnvironmentProvider. Call before parsing to redirect all env-var reads/writes.

setFileSystemProviderfunction

Replace the global FileSystemProvider. Call before parsing to redirect all file-system operations.

supportsNegationfunction

Check if a config supports boolean-like negation (--no-flag). True for boolean options and oneOf options containing a boolean valueType.

tryParseValuefunction

Types

AliasConfigtype
ArrayOptionConfigtype

Configuration for array options. Arrays are parsed from comma separated, space separated, or multiple values. e.g. `--foo a b c`, `--foo a,b,c`, or `--foo a --foo b --foo c`

BaseTypetype

Map an option config to its base TypeScript type. Uses structural typing to avoid circular imports.

BooleanOptionConfigtype
CommonOptionConfigtype
Defaulttype
DefaultValueWithDescriptiontype
DefaultValueWithFactorytype
EnvOptionConfigtype

Defines the option configuration passed to ArgvParser.env.

Expandtype

Force TypeScript to fully expand a type. This helps with deferred type evaluation in recursive types.

ExpandDeeptype

Deeply expand a type, including nested objects.

InferChoicetype

Infer the choice type from an option config. Choices can be an array (including readonly) or a function returning an array.

InferCoercetype

Infer the coerced type. If coerce function exists, use its return type. Otherwise fall back to the provided fallback type. Uses optional property matching `coerce?:` to handle configs where coerce is defined as optional (like ObjectOptionConfig). Special handling: - [R] extends [never]: When coerce is missing/undefined, R infers as never - R extends undefined: When coerce explicitly returns undefined

Internaltype
InternalOptionConfigtype
LocalizationDictionarytype

Localization dictionary type for translating option keys and other text. Each key maps to an object with a "default" value and optional locale-specific translations.

LocalizationFunctiontype

Localization function type for custom translation logic. This allows integration with existing localization libraries like i18next.

MakeUndefinedPropertiesOptionaltype

Makes properties whose type includes `undefined` optional. This allows omitting properties like `{ foo?: string | undefined }` from object literals instead of requiring `{ foo: undefined }`. Uses `Pick` to avoid producing empty `{}` intersection members in TypeDoc output. When one side has no matching keys, `Pick<T, never>` collapses to `{}` inside a two-part `& {}` — the mapped type wrapper `{ [K in keyof ...]: ... }` forces TypeScript to flatten the intersection into a single object type, eliminating the empty half entirely and keeping tooltips clean.

NumberArrayOptionConfigtype
NumberOptionConfigtype
ObjectOptionConfigtype
ObjectValueTypetype

Compute the full value type for an object option.

OneOfArrayValueTypetype
OneOfBooleanValueTypetype
OneOfNumberValueTypetype
OneOfOptionConfigtype

Configuration for a `oneOf` option that accepts multiple value types. Each entry in `valueTypes` defines a type the option can accept. At parse time, non-boolean parsers are tried in array order; boolean is always tried last (but has exclusive claim on bare flags, negation, and the literals `true`/`false`).

OneOfStringValueTypetype
OneOfValueTypeEntrytype

A single entry in the `valueTypes` array.

OptionConfigtype

Configures an option for the parser. See subtypes for more information. - StringOptionConfig - NumberOptionConfig - ArrayOptionConfig - BooleanOptionConfig - OneOfOptionConfig

OptionConfigToTypetype

Converts an OptionConfig to the TypeScript type for the parsed value. Uses shared type resolution logic from type-resolution.ts.

ParsedArgstype

Base type for parsed arguments.

ParserOptionstype

Extra options for the parser

PlainDefaultValuetype
ResolveOneOfEntrytype

Resolve the TypeScript type for a single valueTypes entry. Forces distribution so each union member is resolved independently. Without this, InferChoice from one entry can swallow other entries.

ResolveOneOfValueTypestype

Resolve the union type for the entire `valueTypes` tuple. Maps each entry to its resolved type and produces a union.

ResolveOptionTypetype

Resolve a single option config to its final type. Priority: choices > coerce > base type For array options, choices narrow the element type rather than replacing the entire type. e.g. `{ type: 'array', items: 'string', choices: ['a', 'b'] as const }` resolves to `('a' | 'b')[]`, not `'a' | 'b'`.

ResolvePropertiestype

Resolve all properties of an object option to their types. Each property becomes its resolved type, wrapped with optional handling. Special case: when TProperties is `any` (from `OptionConfig<any, any, any, any>`), we return `unknown` to avoid creating an index signature that would hide the actual properties inferred from the value.

StringArrayOptionConfigtype
StringOptionConfigtype
UnknownOptionConfigtype

An OptionConfig with generic parameters set for maximum compatibility. Uses `any` for all type parameters to allow maximum assignability.

WithOptionaltype

Wrap a resolved type with undefined if the option is optional. Required options or options with defaults are never undefined. Uses `'key' extends keyof TConfig` instead of `TConfig extends { key: unknown }` to properly detect OPTIONAL properties. The latter check fails for optional properties because `{ default?: X }` doesn't guarantee `default` exists.