CLI app helper that simplifies building command-line interfaces in Node.js with automatic argument parsing and flag handling
npx @tessl/cli install tessl/npm-meow@13.2.0Meow is a CLI app helper that simplifies building command-line interfaces in Node.js. It automatically parses command-line arguments and flags, converts flags to camelCase format, provides built-in support for version and help text output, handles flag negation with --no- prefix, and includes advanced features like flag validation, multiple value support, and required flag detection.
npm install meowimport meow from 'meow';Import with types for TypeScript:
import meow, { type Options, type Result, type FlagType } from 'meow';For CommonJS:
const meow = require('meow');#!/usr/bin/env node
import meow from 'meow';
const cli = meow(`
Usage
$ foo <input>
Options
--rainbow, -r Include a rainbow
Examples
$ foo unicorns --rainbow
🌈 unicorns 🌈
`, {
importMeta: import.meta,
flags: {
rainbow: {
type: 'boolean',
shortFlag: 'r'
}
}
});
/*
{
input: ['unicorns'],
flags: {rainbow: true},
unnormalizedFlags: {rainbow: true, r: true},
pkg: {...},
help: '...',
showHelp: [Function],
showVersion: [Function]
}
*/
console.log('Input:', cli.input);
console.log('Flags:', cli.flags);Main function that processes command-line arguments and returns a parsed result object.
/**
* Parse command-line arguments with help text and options
* @param helpMessage - Help text to display with --help
* @param options - Configuration options for parsing
* @returns Parsed CLI result object
*/
function meow<Flags extends AnyFlags>(
helpMessage: string,
options?: Options<Flags>
): Result<Flags>;
/**
* Parse command-line arguments with options only
* @param options - Configuration options for parsing
* @returns Parsed CLI result object
*/
function meow<Flags extends AnyFlags>(options?: Options<Flags>): Result<Flags>;Configure argument flags with various options and validation rules.
interface Flag<PrimitiveType extends FlagType, Type, IsMultiple = false> {
/** Type of value: 'string' | 'boolean' | 'number' */
readonly type?: PrimitiveType;
/** Limit valid values to predefined choices */
readonly choices?: Type extends unknown[] ? Type : Type[];
/** Default value when flag is not specified */
readonly default?: Type;
/** Single character alias for the flag */
readonly shortFlag?: string;
/** Alternative names for the flag */
readonly aliases?: string[];
/** Allow multiple values (creates array) */
readonly isMultiple?: IsMultiple;
/** Determine if flag is required (boolean or function) */
readonly isRequired?: boolean | IsRequiredPredicate;
}Flag Usage Examples:
// String flag with choices and aliases
flags: {
unicorn: {
type: 'string',
choices: ['rainbow', 'cat', 'unicorn'],
default: 'rainbow',
shortFlag: 'u',
aliases: ['unicorns']
}
}
// Multiple boolean flag
flags: {
verbose: {
type: 'boolean',
isMultiple: true,
shortFlag: 'v'
}
}
// Required flag with dynamic requirement
flags: {
output: {
type: 'string',
isRequired: (flags, input) => {
return flags.format === 'file';
}
}
}Configure parsing behavior, help text, and validation rules.
interface Options<Flags extends AnyFlags> {
/** Required import.meta object for package.json discovery */
readonly importMeta: ImportMeta;
/** Flag definitions object */
readonly flags?: Flags;
/** Description shown above help text (default: package.json description) */
readonly description?: string | false;
/** Help text content (supports template literals) */
readonly help?: string | false;
/** Version string override (default: package.json version) */
readonly version?: string | false;
/** Automatically show help on --help flag */
readonly autoHelp?: boolean;
/** Automatically show version on --version flag */
readonly autoVersion?: boolean;
/** Custom package.json object */
readonly pkg?: Record<string, unknown>;
/** Custom arguments array (default: process.argv.slice(2)) */
readonly argv?: readonly string[];
/** Auto-infer argument types from values */
readonly inferType?: boolean;
/** Default value for undefined boolean flags */
readonly booleanDefault?: boolean | null | undefined;
/** Allow unknown flags (default: true) */
readonly allowUnknownFlags?: boolean;
/** Allow parent flags (default: true) */
readonly allowParentFlags?: boolean;
/** Number of spaces for help text indentation (default: 2) */
readonly helpIndent?: number;
/** @deprecated Hard rejection for unhandled promises */
readonly hardRejection?: boolean;
}The parsed CLI result with input, flags, and utility functions.
interface Result<Flags extends AnyFlags> {
/** Non-flag arguments array */
input: string[];
/** Flags converted to camelCase excluding aliases */
flags: CamelCasedProperties<TypedFlags<Flags>> & Record<string, unknown>;
/** Flags converted to camelCase including aliases */
unnormalizedFlags: TypedFlags<Flags> & Record<string, unknown>;
/** The package.json object */
pkg: PackageJson;
/** Formatted help text */
help: string;
/** Show help text and exit with code (default: 2) */
showHelp: (exitCode?: number) => never;
/** Show version text and exit */
showVersion: () => void;
}All TypeScript type definitions for comprehensive type safety.
/** Supported flag value types */
type FlagType = 'string' | 'boolean' | 'number';
/** Callback function to determine if a flag is required during runtime */
type IsRequiredPredicate = (
flags: Readonly<Record<string, any>>,
input: readonly string[]
) => boolean;
/** Type-safe flags object with proper inference based on flag definitions */
type TypedFlags<Flags extends Record<string, any>> = {
[F in keyof Flags]: Flags[F] extends {isMultiple: true}
? Flags[F] extends {type: 'string'}
? string[]
: Flags[F] extends {type: 'number'}
? number[]
: Flags[F] extends {type: 'boolean'}
? boolean[]
: unknown[]
: Flags[F] extends {type: 'string'}
? string
: Flags[F] extends {type: 'number'}
? number
: Flags[F] extends {type: 'boolean'}
? boolean
: unknown
};Error Examples:
// Unknown flag error
$ my-cli --unknown-flag
// Output: Unknown flag --unknown-flag
// Process exits with code 2
// Missing required flag
flags: {
output: {
type: 'string',
isRequired: true
}
}
$ my-cli
// Output: Missing required flag --output
// Process exits with code 2
// Invalid choice error
flags: {
format: {
type: 'string',
choices: ['json', 'yaml', 'xml']
}
}
$ my-cli --format csv
// Output: Unknown value for flag --format: csv. Value must be one of: [json, yaml, xml]
// Process exits with code 2Advanced Configuration Example:
import meow from 'meow';
const cli = meow({
importMeta: import.meta,
description: 'My awesome CLI tool',
help: `
Usage
$ my-tool <command> [options]
Commands
build Build the project
test Run tests
Options
--config, -c Configuration file path
--verbose, -v Enable verbose output (can be used multiple times)
--dry-run Show what would be done without executing
--no-cache Disable caching
`,
flags: {
config: {
type: 'string',
shortFlag: 'c',
default: './config.json'
},
verbose: {
type: 'boolean',
shortFlag: 'v',
isMultiple: true
},
dryRun: {
type: 'boolean',
default: false
},
cache: {
type: 'boolean',
default: true
}
},
booleanDefault: undefined,
allowUnknownFlags: false,
helpIndent: 4
});
// Advanced booleanDefault behavior example
const cli2 = meow({
importMeta: import.meta,
booleanDefault: undefined, // Exclude undefined boolean flags from result
flags: {
rainbow: {
type: 'boolean',
default: true, // This takes precedence over booleanDefault
shortFlag: 'r'
},
unicorn: {
type: 'boolean',
default: false, // This takes precedence over booleanDefault
shortFlag: 'u'
},
sparkles: {
type: 'boolean' // Will be excluded if not provided
}
}
});
// $ my-cli --rainbow
// Result: { flags: { rainbow: true, unicorn: false } }
// Note: sparkles is excluded since it wasn't provided and booleanDefault is undefined