CLI Forge vs. cleye
cleye is a declarative CLI builder with strong TypeScript support and responsive help tables.
CLI Forge strengths
- Middleware — Full middleware pipeline (example).
- Config files — Built-in loading with
extends(example). - Object options — Native
objecttype with typed nested properties (example). cleye uses JavaScript constructor functions (String,Number,Boolean) for flat options. - Env variable support — Declarative env var mapping (example).
- Documentation generation, interactive shell (example), test harness (example) — None of these exist in cleye.
Shared strengths
- Validation — Both support validation. CLI Forge has choices, conflicts, implications (example), and custom validators. cleye validates via custom type functions that combine parsing and validation in one step.
- Strict mode — Both reject unknown flags. cleye adds edit-distance suggestions for misspelled flags, which CLI Forge does not.
cleye strengths
- Responsive help — Terminal-width-aware help tables that adapt to the console size. Both tools generate help automatically, but cleye's is adaptive.
- Custom type functions — Any
(string) => Tfunction works as an option type, combining parsing and validation in one step. CLI Forge separates these intocoerceandvalidate. - Command type narrowing — Checking
argv.commandin TypeScript automatically narrows the available flags and parameters. CLI Forge achieves similar type safety through scoped command handlers.
Side-by-side example
The same CLI — a greet command with hello and goodbye subcommands — implemented in both libraries.
import { cli, command } from 'cleye';
// cleye returns a parsed argv object with command narrowing.
// Subcommands are defined with command() and passed to cli().
const argv = cli({
name: 'greet',
commands: [
command({
name: 'hello',
flags: {
name: {
type: String,
description: 'Name to greet',
default: 'World',
},
uppercase: {
type: Boolean,
description: 'Print greeting in uppercase',
default: false,
},
},
}),
command({
name: 'goodbye',
flags: {
name: {
type: String,
description: 'Name to bid farewell',
default: 'World',
},
formal: {
type: Boolean,
description: 'Use formal farewell',
default: false,
},
},
}),
],
});
if (argv.command === 'hello') {
const msg = `Hello, ${argv.flags.name}!`;
console.log(argv.flags.uppercase ? msg.toUpperCase() : msg);
} else if (argv.command === 'goodbye') {
console.log(
argv.flags.formal
? `Farewell, ${argv.flags.name}.`
: `Bye, ${argv.flags.name}!`
);
}
import { cli } from 'cli-forge';
cli('greet')
.command('hello', {
description: 'Say hello to someone',
builder: (args) =>
args
.option('name', {
type: 'string',
description: 'Name to greet',
default: 'World',
})
.option('uppercase', {
type: 'boolean',
description: 'Print greeting in uppercase',
default: false,
}),
handler: (args) => {
const msg = `Hello, ${args.name}!`;
console.log(args.uppercase ? msg.toUpperCase() : msg);
},
})
.command('goodbye', {
description: 'Say goodbye to someone',
builder: (args) =>
args
.option('name', {
type: 'string',
description: 'Name to bid farewell',
default: 'World',
})
.option('formal', {
type: 'boolean',
description: 'Use formal farewell',
default: false,
}),
handler: (args) => {
console.log(
args.formal ? `Farewell, ${args.name}.` : `Bye, ${args.name}!`
);
},
})
.forge();