flying-fox-cli
v1.0.0
Published
Zero-dependency CLI toolkit — arg parsing, colors, spinner, logger, table, box, progress bar
Maintainers
Readme
flying-fox-cli
Zero-dependency CLI toolkit for Node.js.
Argument parsing, ANSI colors, spinner, progress bar, table, box, logger, prompts, help printer — everything you need to build a polished CLI.
npm install flying-fox-clicolors
import { colors } from 'flying-fox-cli';
console.log(colors.green('✔ Done'));
console.log(colors.red('✖ Failed'));
console.log(colors.bold(colors.cyan('flying-fox-cli')));
console.log(colors.dim('loading…'));
console.log(colors.bgBlue(colors.white(' INFO ')));
// Strip ANSI from any string
colors.strip('\x1B[32mhello\x1B[0m') // 'hello'Styles: bold dim italic underline inverse strikethrough
Foreground: black red green yellow blue magenta cyan white gray
brightRed brightGreen brightYellow brightBlue brightMagenta brightCyan brightWhite
Background: bgBlack bgRed bgGreen bgYellow bgBlue bgMagenta bgCyan bgWhite
parseArgs
import { parseArgs } from 'flying-fox-cli';
// node build.js --output dist --watch --port 3000 -v
const args = parseArgs(process.argv.slice(2), {
boolean: ['watch', 'verbose'],
number: ['port'],
string: ['output'],
alias: { v: 'verbose', o: 'output', p: 'port' },
default: { port: 8080, output: 'dist' },
});
args._ // ['build.js'] ← positional args
args.output // 'dist'
args.watch // true
args.port // 3000 (number)
args.verbose // true (from -v)Supports: --flag, --flag=value, --no-flag, -abc (combined shorts), -- separator.
log
import { log } from 'flying-fox-cli';
log.info('Server started on :3000');
log.success('Build complete');
log.warn('Deprecated API used');
log.error('Connection refused');
log.debug('Cache miss for key=user:42'); // only when DEBUG=1
log.print('raw output');
log.br(); // blank linespinner
import { spinner } from 'flying-fox-cli';
const spin = spinner('Fetching data…');
spin.start();
try {
await fetchData();
spin.succeed('Data fetched'); // ✔ Data fetched
} catch (err) {
spin.fail(`Failed: ${err.message}`); // ✖ Failed: …
}Methods: start() · stop() · update(text) · succeed(text?) · fail(text?) · warn(text?)
progress
import { progress } from 'flying-fox-cli';
const bar = progress(100, { width: 40 });
for (let i = 0; i <= 100; i++) {
bar.update(i);
await sleep(20);
}
bar.done();
// ████████████████████░░░░░░░░░░░░░░░░░░░░ 52% (52/100)Custom template:
const bar = progress(files.length, {
template: (pct, bar, cur, tot) => `${bar} ${cur}/${tot} files`,
});table
import { table } from 'flying-fox-cli';
console.log(table([
['Alice', '32', 'admin'],
['Bob', '28', 'user'],
['Carol', '41', 'user'],
], {
headers: ['Name', 'Age', 'Role'],
align: ['left', 'right', 'left'],
}));┌───────┬─────┬───────┐
│ Name │ Age │ Role │
├───────┼─────┼───────┤
│ Alice │ 32 │ admin │
│ Bob │ 28 │ user │
│ Carol │ 41 │ user │
└───────┴─────┴───────┘Also accepts objects: table([{ name: 'Alice', age: 32 }, …], { headers: ['Name', 'Age'] })
box
import { box, colors } from 'flying-fox-cli';
console.log(box('Deployment complete!\nVersion 2.1.0', {
title: 'Success',
style: 'round',
borderColor: colors.green,
}));╭─ Success ────────────╮
│ │
│ Deployment complete! │
│ Version 2.1.0 │
│ │
╰──────────────────────╯Styles: single double round bold
prompt / confirm / select
import { prompt, confirm, select } from 'flying-fox-cli';
const name = await prompt('Your name: ');
const proceed = await confirm('Continue?', true); // default yes
const env = await select('Deploy to:', ['staging', 'production', 'preview']);printHelp / exitWith
import { printHelp, exitWith, parseArgs } from 'flying-fox-cli';
const args = parseArgs();
if (args.help) {
printHelp({
name: 'deploy',
version: '1.0.0',
description: 'Deploy your app to the cloud',
usage: 'deploy <env> [options]',
commands: {
'up': 'Deploy the stack',
'down': 'Tear down the stack',
'logs': 'Stream live logs',
},
options: {
'--env, -e': 'Target environment',
'--dry-run': 'Preview changes without applying',
'--verbose, -v': 'Verbose output',
'--help, -h': 'Show this help',
},
});
process.exit(0);
}
if (!args._[0]) exitWith('Missing <env> argument');String utilities
import { truncate, pad, wordWrap } from 'flying-fox-cli';
truncate('Hello, world!', 8) // 'Hello, …'
truncate('Hello, world!', 8, '...') // 'Hello...'
pad('hi', 10) // 'hi '
pad('hi', 10, 'right') // ' hi'
pad('hi', 10, 'center') // ' hi '
wordWrap('The quick brown fox jumps over the lazy dog', 20)
// 'The quick brown fox\njumps over the lazy\ndog'Complete example
import {
parseArgs, log, spinner, progress,
table, box, confirm, printHelp, exitWith, colors,
} from 'flying-fox-cli';
const args = parseArgs(process.argv.slice(2), {
boolean: ['dry-run', 'help'],
alias: { h: 'help' },
});
if (args.help) {
printHelp({
name: 'my-cli', version: '1.0.0',
usage: 'my-cli <command>',
commands: { build: 'Build the project', deploy: 'Deploy to production' },
options: { '--dry-run': 'Preview only', '--help, -h': 'Show help' },
});
process.exit(0);
}
const [command] = args._;
if (!command) exitWith('No command specified');
const ok = await confirm(`Run ${colors.cyan(command)}?`);
if (!ok) process.exit(0);
const spin = spinner(`Running ${command}…`);
spin.start();
await new Promise(r => setTimeout(r, 1000));
spin.succeed('Done!');
console.log(box(`${command} completed successfully`, { style: 'round', borderColor: colors.green }));CommonJS
const { parseArgs, log, spinner, colors } = require('flying-fox-cli');License
MIT
