Gathering detailed insights and metrics for sade
Gathering detailed insights and metrics for sade
npm install sade
Typescript
Module System
Min. Node Version
Node Version
NPM Version
99.6
Supply Chain
98.8
Quality
75.9
Maintenance
100
Vulnerability
100
License
JavaScript (100%)
Total Downloads
421,899,921
Last Day
576,807
Last Week
3,518,010
Last Month
11,395,271
Last Year
178,414,790
1,051 Stars
113 Commits
23 Forks
9 Watching
3 Branches
6 Contributors
Minified
Minified + Gzipped
Latest Version
1.8.1
Package Id
sade@1.8.1
Unpacked Size
30.81 kB
Size
10.20 kB
File Count
6
NPM Version
8.1.0
Node Version
16.13.0
Cumulative downloads
Total Downloads
Last day
-10.5%
576,807
Compared to previous day
Last week
2%
3,518,010
Compared to previous week
Last month
-24.9%
11,395,271
Compared to previous month
Last year
17.4%
178,414,790
Compared to previous year
Smooth (CLI) Operator 🎶
Sade is a small but powerful tool for building command-line interface (CLI) applications for Node.js that are fast, responsive, and helpful!
It enables default commands, git-like subcommands, option flags with aliases, default option values with type-casting, required-vs-optional argument handling, command validation, and automated help text generation!
Your app's UX will be as smooth as butter... just like Sade's voice. 😉
$ npm install --save sade
Input:
1#!/usr/bin/env node 2 3const sade = require('sade'); 4 5const prog = sade('my-cli'); 6 7prog 8 .version('1.0.5') 9 .option('--global, -g', 'An example global flag') 10 .option('-c, --config', 'Provide path to custom config', 'foo.config.js'); 11 12prog 13 .command('build <src> <dest>') 14 .describe('Build the source directory. Expects an `index.js` entry file.') 15 .option('-o, --output', 'Change the name of the output file', 'bundle.js') 16 .example('build src build --global --config my-conf.js') 17 .example('build app public -o main.js') 18 .action((src, dest, opts) => { 19 console.log(`> building from ${src} to ${dest}`); 20 console.log('> these are extra opts', opts); 21 }); 22 23prog.parse(process.argv);
Output:
1$ my-cli --help 2 3 Usage 4 $ my-cli <command> [options] 5 6 Available Commands 7 build Build the source directory. 8 9 For more info, run any command with the `--help` flag 10 $ my-cli build --help 11 12 Options 13 -v, --version Displays current version 14 -g, --global An example global flag 15 -c, --config Provide path to custom config (default foo.config.js) 16 -h, --help Displays this message 17 18 19$ my-cli build --help 20 21 Description 22 Build the source directory. 23 Expects an `index.js` entry file. 24 25 Usage 26 $ my-cli build <src> [options] 27 28 Options 29 -o, --output Change the name of the output file (default bundle.js) 30 -g, --global An example global flag 31 -c, --config Provide path to custom config (default foo.config.js) 32 -h, --help Displays this message 33 34 Examples 35 $ my-cli build src build --global --config my-conf.js 36 $ my-cli build app public -o main.js
Define your global/program-wide version, options, description, and/or examples first.
Once you define a Command, you can't access the global-scope again.
Define all commands & options in the order that you want them to appear.
Sade will not mutate or sort your CLI for you. Global options print before local options.
Required arguments without values will error & exit
An Insufficient arguments!
error will be displayed along with a help prompt.
Don't worry about manually displaying help~!
Your help text is displayed automatically... including command-specific help text!
Automatic default/basic patterns
Usage text will always append [options]
& --help
and --version
are done for you.
Only define what you want to display!
Help text sections (example, options, etc) will only display if you provide values.
Subcommands are defined & parsed like any other command! When defining their usage
, everything up until the first argument ([foo]
or <foo>
) is interpreted as the command string.
They should be defined in the order that you want them to appear in your general --help
output.
Lastly, it is not necessary to define the subcommand's "base" as an additional command. However, if you choose to do so, it's recommended that you define it first for better visibility.
1const prog = sade('git'); 2 3// Not necessary for subcommands to work, but it's here anyway! 4prog 5 .command('remote') 6 .describe('Manage set of tracked repositories') 7 .action(opts => { 8 console.log('~> Print current remotes...'); 9 }); 10 11prog 12 .command('remote add <name> <url>', 'Demo...') 13 .action((name, url, opts) => { 14 console.log(`~> Adding a new remote (${name}) to ${url}`); 15 }); 16 17prog 18 .command('remote rename <old> <new>', 'Demo...') 19 .action((old, nxt, opts) => { 20 console.log(`~> Renaming from ${old} to ${nxt}~!`); 21 });
In certain circumstances, you may only need sade
for a single-command CLI application.
Note: Until
v1.6.0
, this made for an awkward pairing.
To enable this, you may make use of the isSingle
argument. Doing so allows you to pass the program's entire usage
text into the name
argument.
With "Single Command Mode" enabled, your entire binary operates as one command. This means that any prog.command
calls are disallowed & will instead throw an Error. Of course, you may still define a program version, a description, an example or two, and declare options. You are customizing the program's attributes as a whole.*
* This is true for multi-command applications, too, up until your first
prog.command()
call!
Example
Let's reconstruct sirv-cli
, which is a single-command application that (optionally) accepts a directory from which to serve files. It also offers a slew of option flags:
1sade('sirv [dir]', true) 2 .version('1.0.0') 3 .describe('Run a static file server') 4 .example('public -qeim 31536000') 5 .example('--port 8080 --etag') 6 .example('my-app --dev') 7 .option('-D, --dev', 'Enable "dev" mode') 8 .option('-e, --etag', 'Enable "Etag" header') 9 // There are a lot... 10 .option('-H, --host', 'Hostname to bind', 'localhost') 11 .option('-p, --port', 'Port to bind', 5000) 12 .action((dir, opts) => { 13 // Program handler 14 }) 15 .parse(process.argv);
When sirv --help
is run, the generated help text is trimmed, fully aware that there's only one command in this program:
Description
Run a static file server
Usage
$ sirv [dir] [options]
Options
-D, --dev Enable "dev" mode
-e, --etag Enable "Etag" header
-H, --host Hostname to bind (default localhost)
-p, --port Port to bind (default 5000)
-v, --version Displays current version
-h, --help Displays this message
Examples
$ sirv public -qeim 31536000
$ sirv --port 8080 --etag
$ sirv my-app --dev
Command aliases are alternative names (aliases) for a command. They are often used as shortcuts or as typo relief!
The aliased names do not appear in the general help text.
Instead, they only appear within the Command-specific help text under an "Aliases" section.
Limitations
prog.alias()
before defining any Commands (via prog.commmand()
)Example
Let's reconstruct the npm install
command as a Sade program:
1sade('npm') 2 // ... 3 .command('install [package]', 'Install a package', { 4 alias: ['i', 'add', 'isntall'] 5 }) 6 .option('-P, --save-prod', 'Package will appear in your dependencies.') 7 .option('-D, --save-dev', 'Package will appear in your devDependencies.') 8 .option('-O, --save-optional', 'Package will appear in your optionalDependencies') 9 .option('-E, --save-exact', 'Save exact versions instead of using a semver range operator') 10 // ...
When we run npm --help
we'll see this general help text:
Usage
$ npm <command> [options]
Available Commands
install Install a package
For more info, run any command with the `--help` flag
$ npm install --help
Options
-v, --version Displays current version
-h, --help Displays this message
When we run npm install --help
— or the help flag with any of install
's aliases — we'll see this command-specific help text:
Description
Install a package
Usage
$ npm install [package] [options]
Aliases
$ npm i
$ npm add
$ npm isntall
Options
-P, --save-prod Package will appear in your dependencies.
-D, --save-dev Package will appear in your devDependencies.
-O, --save-optional Package will appear in your optionalDependencies
-E, --save-exact Save exact versions instead of using a semver range operator
-h, --help Displays this message
Returns: Program
Returns your chainable Sade instance, aka your Program
.
Type: String
Required: true
The name of your Program
/ binary application.
Type: Boolean
Default: name.includes(' ');
If your Program
is meant to have only one command.
When true
, this simplifies your generated --help
output such that:
Available Commands
section$ name <command>
into the Usage
sectionFor more info, run any command with the
--help flag
textYou may customize the Usage
of your command by modifying the name
argument directly.
Please read Single Command Mode for an example and more information.
Important: Whenever
name
includes a custom usage, thenisSingle
is automatically assumed and enforced!
Create a new Command for your Program. This changes the current state of your Program.
All configuration methods (prog.describe
, prog.action
, etc) will apply to this Command until another Command has been created!
Type: String
The usage pattern for your current Command. This will be included in the general or command-specific --help
output.
Required arguments are wrapped with <
and >
characters; for example, <foo>
and <bar>
.
Optional arguments are wrapped with [
and ]
characters; for example, [foo]
and [bar]
.
All arguments are positionally important, which means they are passed to your current Command's handler
function in the order that they were defined.
When optional arguments are defined but don't receive a value, their positionally-equivalent function parameter will be undefined
.
Important: You must define & expect required arguments before optional arguments!
1sade('foo') 2 3 .command('greet <adjective> <noun>') 4 .action((adjective, noun, opts) => { 5 console.log(`Hello, ${adjective} ${noun}!`); 6 }) 7 8 .command('drive <vehicle> [color] [speed]') 9 .action((vehicle, color, speed, opts) => { 10 let arr = ['Driving my']; 11 arr.push(color ? `${color} ${vehicle}` : vehicle); 12 speed && arr.push(`at ${speed}`); 13 opts.yolo && arr.push('...YOLO!!'); 14 let str = arr.join(' '); 15 console.log(str); 16 });
1$ foo greet beautiful person 2# //=> Hello, beautiful person! 3 4$ foo drive car 5# //=> Driving my car 6 7$ foo drive car red 8# //=> Driving my red card 9 10$ foo drive car blue 100mph --yolo 11# //=> Driving my blue car at 100mph ...YOLO!!
Type: String
Default: ''
The Command's description. The value is passed directly to prog.describe
.
Type: Object
Default: {}
Type: String|Array
Optionally define one or more aliases for the current Command.
When declared, the opts.alias
value is passed directly to the prog.alias
method.
1// Program A is equivalent to Program B 2// --- 3 4const A = sade('bin') 5 .command('build', 'My build command', { alias: 'b' }) 6 .command('watch', 'My watch command', { alias: ['w', 'dev'] }); 7 8const B = sade('bin') 9 .command('build', 'My build command').alias('b') 10 .command('watch', 'My watch command').alias('w', 'dev');
Type: Boolean
Manually set/force the current Command to be the Program's default command. This ensures that the current Command will run if no command was specified.
Important: If you run your Program without a Command and without specifying a default command, your Program will exit with a
No command specified
error.
1const prog = sade('greet'); 2 3prog.command('hello'); 4//=> only runs if :: `$ greet hello` 5 6// $ greet 7//=> error: No command specified. 8 9prog.command('howdy', '', { default:true }); 10//=> runs as `$ greet` OR `$ greet howdy` 11 12// $ greet 13//=> runs 'howdy' handler 14 15// $ greet foobar 16//=> error: Invalid command
Add a description to the current Command.
Type: String|Array
The description text for the current Command. This will be included in the general or command-specific --help
output.
Internally, your description will be separated into an Array
of sentences.
For general --help
output, only the first sentence will be displayed. However, all sentences will be printed for command-specific --help
text.
Note: Pass an
Array
if you don't want internal assumptions. However, the first item is always displayed in general help, so it's recommended to keep it short.
Define one or more aliases for the current Command.
Important: An error will be thrown if:
1) the program is in Single Command Mode; or
2)prog.alias
is called before anyprog.command
.
Type: String
The list of alternative names (aliases) for the current Command.
For example, you may want to define shortcuts and/or common typos for the Command's full name.
Important: Sade does not check if the incoming
names
are already in use by other Commands or their aliases.
During conflicts, the Command with the samename
is given priority, otherwise the first Command (according to Program order) withname
as an alias is chosen.
The prog.alias()
is append-only, so calling it multiple times within a Command context will keep all aliases, including those initially passed via opts.alias
.
1sade('bin') 2 .command('hello <name>', 'Greet someone by their name', { 3 alias: ['hey', 'yo'] 4 }) 5 .alias('hi', 'howdy') 6 .alias('hola', 'oi'); 7//=> hello aliases: hey, yo, hi, howdy, hola, oi
Attach a callback to the current Command.
Type: Function
The function to run when the current Command is executed.
Its parameters are based (positionally) on your Command's usage
definition.
All options, flags, and extra/unknown values are included as the last parameter.
Note: Optional arguments are also passed as parameters & may be
undefined
!
1sade('foo') 2 .command('cp <src> <dest>') 3 .option('-f, --force', 'Overwrite without confirmation') 4 .option('-c, --clone-dir', 'Copy files to additional directory') 5 .option('-v, --verbose', 'Enable verbose output') 6 .action((src, dest, opts) => { 7 console.log(`Copying files from ${src} --> ${dest}`); 8 opts.c && console.log(`ALSO copying files from ${src} --> ${opts['clone-dir']}`); 9 console.log('My options:', opts); 10 }) 11 12// $ foo cp original my-copy -v 13//=> Copying files from original --> my-copy 14//=> My options: { _:[], v:true, verbose:true } 15 16// $ foo cp original my-copy --clone-dir my-backup 17//=> Copying files from original --> my-copy 18//=> ALSO copying files from original --> my-backup 19//=> My options: { _:[], c:'my-backup', 'clone-dir':'my-backup' }
Add an example for the current Command.
Type: String
The example string to add. This will be included in the general or command-specific --help
output.
Note: Your example's
str
will be prefixed with your Program'sname
.
Add an Option to the current Command.
Type: String
The Option's flags, which may optionally include an alias.
You may use a comma (,
) or a space (
) to separate the flags.
Note: The short & long flags can be declared in any order. However, the alias will always be displayed first.
Important: If using hyphenated flag names, they will be accessible as declared within your
action()
handler!
1prog.option('--global'); // no alias 2prog.option('-g, --global'); // alias first, comma 3prog.option('--global -g'); // alias last, space 4// etc...
Type: String
The description for the Option.
Type: String
The default value for the Option.
Flags and aliases, if parsed, are true
by default. See mri
for more info.
Note: You probably only want to define a default
value
if you're expecting aString
orNumber
value type.
If you do pass a String
or Number
value type, your flag value will be casted to the same type. See mri#options.default
for info~!
The --version
and -v
flags will automatically output the Program version.
Type: String
Default: 0.0.0
The new version number for your Program.
Note: Your Program
version
is0.0.0
until you change it.
Parse a set of CLI arguments.
Type: Array
Your Program's process.argv
input.
Important: Do not
.slice(2)
! Doing so will break parsing~!
Type: Object
Default: {}
Additional process.argv
parsing config. See mri
's options for details.
Important: These values override any internal values!
1prog 2 .command('hello') 3 .option('-f, --force', 'My flag'); 4//=> currently has alias pair: f <--> force 5 6prog.parse(process.argv, { 7 alias: { 8 f: ['foo', 'fizz'] 9 }, 10 default: { 11 abc: 123 12 } 13}); 14//=> ADDS alias pair: f <--> foo 15//=> REMOVES alias pair: f <--> force 16//=> ADDS alias pair: f <--> fizz 17//=> ADDS default: abc -> 123 (number)
Type: Function
Default: undefined
Callback to run when an unspecified option flag has been found. This is passed directly to mri
.
Your handler will receive the unknown flag (string) as its only argument.
You may return a string, which will be used as a custom error message. Otherwise, a default message is displayed.
1sade('sirv') 2 .command('start [dir]') 3 .parse(process.argv, { 4 unknown: arg => `Custom error message: ${arg}` 5 }); 6 7/* 8$ sirv start --foobar 9 10 ERROR 11 Custom error message: --foobar 12 13 Run `$ sirv --help` for more info. 14*/
Type: Boolean
Default: false
If true, Sade will not immediately execute the action
handler. Instead, parse()
will return an object of { name, args, handler }
shape, wherein the name
is the command name, args
is all arguments that would be passed to the action handler, and handler
is the function itself.
From this, you may choose when to run the handler
function. You also have the option to further modify the args
for any reason, if needed.
1let { name, args, handler } = prog.parse(process.argv, { lazy:true }); 2console.log('> Received command: ', name); 3 4// later on... 5handler.apply(null, args);
Manually display the help text for a given command. If no command name is provided, the general/global help is printed.
Your general and command-specific help text is automatically attached to the --help
and -h
flags.
Note: You don't have to call this directly! It's automatically run when you
bin --help
Type: String
Default: null
The name of the command for which to display help. Otherwise displays the general help.
MIT © Luke Edwards
No vulnerabilities found.
Reason
no dangerous workflow patterns detected
Reason
no binaries found in the repo
Reason
0 existing vulnerabilities detected
Reason
license file detected
Details
Reason
Found 3/30 approved changesets -- score normalized to 1
Reason
0 commit(s) and 0 issue activity found in the last 90 days -- score normalized to 0
Reason
detected GitHub workflow tokens with excessive permissions
Details
Reason
dependency not pinned by hash detected -- score normalized to 0
Details
Reason
no effort to earn an OpenSSF best practices badge detected
Reason
security policy file not detected
Details
Reason
project is not fuzzed
Details
Reason
branch protection not enabled on development/release branches
Details
Reason
SAST tool is not run on all commits -- score normalized to 0
Details
Score
Last Scanned on 2025-01-20
The Open Source Security Foundation is a cross-industry collaboration to improve the security of open source software (OSS). The Scorecard provides security health metrics for open source projects.
Learn More