CLI Forge vs. cleye

cleye is a declarative CLI builder with strong TypeScript support and responsive help tables.

CLI Forge strengths

Shared strengths

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) => T function works as an option type, combining parsing and validation in one step. CLI Forge separates these into coerce and validate.
  • Command type narrowing — Checking argv.command in 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();

Back to comparison overview · View all framework examples