Smooth CLI operator for building command-line applications with subcommands, options, and automated help text generation.
—
Action handler system for command execution, argument parsing, and lazy evaluation support.
Attach callback handlers to commands that execute when the command is invoked.
/**
* Attach callback handler to current command
* @param {function} handler - Command handler function
* @returns {Sade} Chainable instance
*/
action(handler);
/**
* Command handler function signature
* @param {...*} args - Positional arguments based on command usage pattern
* @param {object} opts - Parsed options and flags
*/
type Handler = (...args: any[], opts: object) => any;Parameters:
handler (function, required): Callback function executed when command runs
undefined if not providedUsage Examples:
// Basic command handler
prog.command('greet <name>')
.action((name, opts) => {
console.log(`Hello, ${name}!`);
});
// Handler with optional arguments
prog.command('serve [dir] [port]')
.option('-w, --watch', 'Watch for changes')
.action((dir = '.', port = 3000, opts) => {
console.log(`Serving ${dir} on port ${port}`);
if (opts.watch) console.log('Watching for changes...');
});
// Handler with multiple required arguments
prog.command('copy <src> <dest>')
.option('-f, --force', 'Overwrite existing files')
.action((src, dest, opts) => {
console.log(`Copying ${src} to ${dest}`);
console.log('Options:', opts);
// opts = { _: [], force: true/false, f: true/false }
});Parse command line arguments and execute the appropriate command handler.
/**
* Parse command line arguments and execute appropriate handler
* @param {string[]} arr - Command line arguments (typically process.argv)
* @param {object} [opts] - Parsing configuration options
* @returns {void|LazyOutput} Void (executes handler) or LazyOutput if opts.lazy = true
*/
parse(arr, opts);
interface ParseOptions {
/** Return execution info instead of running handler */
lazy?: boolean;
/** Additional flag aliases */
alias?: Record<string, string | string[]>;
/** Additional default values */
default?: Record<string, any>;
/** Handler for unknown flags */
unknown?: (flag: string) => string | void;
}
interface LazyOutput {
/** Command name that was matched */
name: string;
/** Handler function to execute */
handler: Handler;
/** Arguments array to pass to handler */
args: any[];
}Parameters:
arr (string[], required): Command line arguments array (usually process.argv)opts (object, optional): Parsing configuration optionsBasic Usage:
// Standard usage - executes handler immediately
prog.parse(process.argv);
// With custom arguments (for testing)
prog.parse(['node', 'script.js', 'build', 'src', 'dist', '--watch']);Use lazy parsing to defer command execution and gain control over when handlers run.
Usage Examples:
// Get execution information without running
const result = prog.parse(process.argv, { lazy: true });
console.log('Command:', result.name);
console.log('Arguments:', result.args);
// Execute later (optionally modify args first)
result.handler.apply(null, result.args);
// Or with modified arguments
const modifiedArgs = result.args.map(arg =>
typeof arg === 'string' ? arg.toUpperCase() : arg
);
result.handler.apply(null, modifiedArgs);Override or extend option parsing behavior with custom configuration.
Alias Override:
prog.command('build')
.option('-f, --force', 'Force build');
// Override aliases at parse time
prog.parse(process.argv, {
alias: {
f: ['foo', 'fizz'], // -f now maps to --foo and --fizz instead of --force
v: ['verbose'] // Add new -v -> --verbose alias
}
});Default Value Override:
prog.command('start')
.option('-p, --port', 'Server port', 3000);
// Override defaults at parse time
prog.parse(process.argv, {
default: {
port: 8080, // Override default port
env: 'development' // Add new default value
}
});Unknown Flag Handling:
prog.parse(process.argv, {
unknown: (flag) => {
if (flag.startsWith('--experimental-')) {
return; // Allow experimental flags without error
}
return `Unknown flag: ${flag}. Did you mean --help?`;
}
});
// Example output:
// $ my-cli build --typo
// ERROR: Unknown flag: --typo. Did you mean --help?Sade follows specific rules for parsing arguments and options.
Argument Order and Types:
prog.command('deploy <env> [version] [region]')
.option('-f, --force', 'Force deployment')
.option('--timeout', 'Deployment timeout', 300)
.action((env, version, region, opts) => {
// env: always provided (required)
// version: string or undefined (optional)
// region: string or undefined (optional)
// opts: { force: boolean, timeout: number, ... }
});
// Examples:
// $ my-cli deploy prod
// → env='prod', version=undefined, region=undefined
// $ my-cli deploy prod v1.2.0
// → env='prod', version='v1.2.0', region=undefined
// $ my-cli deploy prod v1.2.0 us-east-1 --force
// → env='prod', version='v1.2.0', region='us-east-1', opts.force=trueOptions Object Structure:
prog.command('build')
.option('-w, --watch', 'Watch mode')
.option('-o, --output', 'Output file', 'dist.js')
.action((opts) => {
console.log(opts);
// {
// _: [], // Remaining arguments
// w: true, // Short flag alias
// watch: true, // Long flag name
// o: 'custom.js', // Short flag alias with value
// output: 'custom.js' // Long flag name with value
// }
});Parse method handles various error conditions and provides helpful error messages.
Common Errors:
unknown option)Error Examples:
// Insufficient arguments
// $ my-cli copy file1
// ERROR: Insufficient arguments!
// Run `$ my-cli copy --help` for more info.
// Invalid command
// $ my-cli invalid-command
// ERROR: Invalid command: invalid-command
// Run `$ my-cli --help` for more info.
// No command (multi-command mode)
// $ my-cli
// ERROR: No command specified.
// Run `$ my-cli --help` for more info.The parse method follows a specific execution flow:
Install with Tessl CLI
npx tessl i tessl/npm-sade