Skip to content

How Optique compares

The JavaScript and TypeScript ecosystem has many excellent command-line libraries, and most of them are good choices for a lot of tools. The point of this section is not to argue that Optique wins every time—it doesn't. It is to show concretely how Optique's combinatorial, type-first approach differs from the builder, declarative, and class-based styles you may already know, so you can tell when each fits.

Every per-library page is balanced: it shows where the other library is the better choice and where Optique is, with working code on both sides. If you are new to Optique's design philosophy, Why Optique? explains the combinator model these pages build on.

How to read these pages

Each comparison walks through the same three scenarios—the situations where Optique's model diverges most visibly from configuration- and builder-based APIs:

  1. Mutually exclusive option groups — expressing “either this whole group of options, or that one, but never a mix.”
  2. Shared option groups across subcommands — defining a set of options once and reusing it across several commands.
  3. CLI args → env vars → config file → interactive prompt — resolving a value from several sources in priority order.

For each scenario the page shows the other library's idiomatic code, then Optique's, then a short note on when each is the better tool. Optique snippets are type-checked; competitor snippets are adapted from each library's documented API. Each page then closes with a Beyond the three scenarios section weighing other dimensions—dependencies, shell completion, man-page generation, schema integration, and maturity.

The libraries

  • Commander.js — the most widely used Node.js CLI framework; mature, imperative, familiar.
  • Yargs — declarative builder with built-in env and config support and a middleware pipeline.
  • Cliffy — batteries-included framework born on Deno, with prompts and global options built in.
  • Gunshi — modern declarative library with a clean config API and a plugin system.
  • Cleye — tiny, strongly-typed flag parser that does one thing well.
  • cmd-ts — type-first, composable parser inspired by Rust's clap; Optique's closest neighbor.
  • Stricli — Bloomberg's deliberately minimal, no-magic framework.
  • oclif — Salesforce's full CLI framework with plugins, scaffolding, and command discovery.
  • Clipanion — the class-based command engine behind Yarn.

At a glance

The version each comparison targets, the API style, and how result types are obtained:

LibraryVersionAPI styleResult-type inferenceRuntimes
Optique1.2Parser combinatorsAutomatic, built inNode.js/Deno/Bun
Commander.js15Fluent builderVia extra-typings packageNode.js
Yargs18Declarative builderVia @types/yargsNode.js
Cliffy1.2Fluent builderAutomatic, built inDeno/Node.js/Bun
Gunshi0.35Declarative configAutomatic, built inNode.js/Deno/Bun
Cleye2.6Declarative configAutomatic, built inNode.js
cmd-ts0.15Composable parsersAutomatic, built inNode.js/Deno/Bun
Stricli1.2FunctionalAutomatic, built inNode.js/Bun/Deno
oclif4Class frameworkAutomatic, built inNode.js
Clipanion4 (rc)Class-basedAutomatic, built inNode.js

How each handles the three scenarios. “Native” means the library has a dedicated feature; “manual” means you write the logic yourself; “external” means a separate prompt library is required:

LibraryMutually exclusive groupsShared option groupsEnv → config → prompt fallback
Optiqueor() of groups (typed union)merge() of parsersAll three, composable
Commander.jsPairwise conflicts(); groups manualHelper fn / global optionsEnv native; config + prompt manual
YargsPairwise conflicts; groups manualHelper fn / middlewareEnv + config native; prompt external
CliffyPairwise conflicts; groups manualglobalOption inheritanceEnv native + prompt module; config manual
GunshiManual in runSpread args recordAll manual
CleyeManual after parseSpread / duplicate flagsAll manual
cmd-tsManual / custom TypeSpread args recordVia custom Type
StricliManual in handlerSpread flags recordAll manual (context injection)
oclifexclusive / exactlyOne (flags)baseFlags inheritanceEnv native; config + prompt manual
ClipanionCommand overloads / schemaBase command classEnv native; config + prompt manual

NOTE

This table summarizes; the per-library pages show the actual code and the trade-offs behind each cell. A “manual” or “external” entry is not a verdict—a lean library that stays out of your way is the right call for many tools.

Beyond the three scenarios

The scenarios above are where the parsing models diverge most, but a CLI library is more than its parser. A few other dimensions are worth weighing:

LibraryRuntime depsShell completionMan pagesSchema integration
Optique0 (core)Built in: Bash/zsh/fish/PowerShell/Nushell@optique/manZod/Valibot
Commander.js0None built inNoNo
Yargs6Built in: Bash/zshNoNo
CliffyJSR suiteBuilt in: Bash/zsh/fishNoNo
Gunshi0 (core)Plugin: Bash/zshNoNo
Cleye2NoneNoNo
cmd-ts4NoneNoCustom Type only
Stricli0 (core)Add-on: BashNoNo
oclif18Plugin: Bash/zsh/PowerShellNoNo
Clipanion1None built inNoTypanion only

A few things stand out:

  • Dependencies and footprint. Optique's core has no runtime dependencies—a trait it shares with Commander.js, Gunshi, and Stricli; Cleye and Clipanion are nearly there. Yargs, cmd-ts, and especially oclif pull in more. Optique's integration packages add dependencies only when you use them (@optique/clack brings in Clack, @optique/config the Standard Schema spec), so the base stays minimal.
  • One definition, many outputs. This is Optique's strongest structural advantage. The same parser drives argument parsing, --help, shell completion across five shells (with context-aware and async suggestions), and Unix man pages via @optique/man. Several libraries generate completion scripts, but Optique covers the most shells and is the only one here that also generates man pages.
  • Schema integration. Optique integrates Zod and Valibot as value parsers (@optique/zod, @optique/valibot) and validates config files with any Standard Schema validator (Zod, Valibot, ArkType) via @optique/config. None of the others integrate Standard Schema; cmd-ts and Clipanion ship their own validation abstractions, and the rest leave value validation to you.
  • Maturity and ecosystem. This is where the established libraries lead, and it matters. Commander.js and Yargs are ubiquitous, with enormous adoption and a deep well of examples; oclif is enterprise-proven behind the Salesforce, Heroku, and Shopify CLIs; Clipanion powers Yarn. Optique is young by comparison, so betting on a long-lived, widely-known dependency favors the incumbents.
  • Learning curve. Optique's combinator model asks you to think in composable parsers, which is less immediately familiar than the builder and declarative APIs most of these libraries offer. That investment is what buys the type inference and composition; whether it pays off depends on how much your CLI will grow.

The comparisons reflect the versions listed above, current as of June 2026. Third-party libraries evolve, so check their latest documentation if a detail matters to your decision.