Sade CLI Framework
raw JSON →Sade is a lightweight and powerful JavaScript library designed for building robust command-line interface (CLI) applications for Node.js. It distinguishes itself by providing a small API surface while offering essential features such as default commands, git-like subcommands, flexible option flags with aliases, type-casting for default option values, and sophisticated handling of required versus optional arguments. Sade also includes built-in command validation and automates the generation of helpful documentation, including version and usage text. The current stable version is 1.8.1, and the package sees regular, feature-driven releases, often including patches and minor enhancements like Deno support and integrated TypeScript definitions. It aims to offer a smooth developer and user experience with minimal overhead, making it a strong alternative to more heavyweight CLI frameworks.
Common errors
error TypeError: Cannot read properties of undefined (reading 'length') ↓
sade@1.7.3 or newer. Do not rely on side effects of process.argv mutation. Access arguments and options via the action() callback parameters. error Error: Insufficient arguments! ↓
<arg>). Inform users to provide all necessary arguments, which will also be highlighted in the automatically generated help text. error Error: Unknown command: [value] ↓
--config my.js). For boolean flags, place them after the command name or ensure they are followed by a non-command argument. error TypeError: (0 , sade_1.default) is not a function ↓
import sade from 'sade'; for ESM contexts (like modern Node.js modules or bundlers) or const sade = require('sade'); for CommonJS environments. Sade supports both since v1.8.0, but context matters. Warnings
breaking Sade no longer mutates the input `process.argv` array. While this is generally good practice, older implementations that relied on side effects of `process.argv` being modified within action handlers might need adjustment. ↓
gotcha Option flags placed before the command name must now be paired with a value. Previously, Sade might have ignored these flags, but since `v1.7.1`, an unpaired flag before the command can be misinterpreted as the command itself or its value, leading to `Unknown command` errors. ↓
gotcha Sade now includes its own TypeScript definitions, and the `sade.Handler` type definition was fixed in `v1.8.1`. Users migrating from `@types/sade` should remove the `@types/sade` package to prevent type conflicts. ↓
gotcha Global options and commands are parsed and displayed in the order they are defined. Once a command is defined, you cannot add more global options or return to the global scope to define them. Ensure all program-wide configurations are set up first. ↓
Install
npm install sade yarn add sade pnpm add sade Imports
- sade wrong
const sade = require('sade')correctimport sade from 'sade' - sade.Handler wrong
import { Handler } from 'sade'; // or const handler: sade.Handler = (args, opts) => {};correctimport sade, { type Handler } from 'sade'; // or import type { Handler } from 'sade'; - sade
const sade = require('sade');
Quickstart
#!/usr/bin/env node
const sade = require('sade');
const prog = sade('my-cli');
prog
.version('1.0.5')
.option('--global, -g', 'An example global flag')
.option('-c, --config', 'Provide path to custom config', 'foo.config.js');
prog
.command('build <src> <dest>')
.describe('Build the source directory. Expects an `index.js` entry file.')
.option('-o, --output', 'Change the name of the output file', 'bundle.js')
.example('build src build --global --config my-conf.js')
.example('build app public -o main.js')
.action((src, dest, opts) => {
console.log(`> building from ${src} to ${dest}`);
console.log(`> output file: ${opts.output}`);
console.log(`> global flag: ${opts.global}`);
console.log(`> config path: ${opts.config}`);
});
prog
.command('greet <name>')
.describe('Greets the specified name.')
.option('--loud', 'Say it loudly!')
.action((name, opts) => {
const greeting = opts.loud ? `HELLO ${name.toUpperCase()}!` : `Hello ${name}!`;
console.log(greeting);
});
prog.parse(process.argv);