cleye CLI Tool
cleye is an intuitive argv-parsing tool for Node.js CLIs. It turns a declarative options object into strongly-typed parameters and flags, auto-generates --help and --version documentation, and supports nested commands. Flag parsing is powered by type-flag.
Reference files live in ${CLAUDE_SKILL_DIR}/references/.
When NOT to use
- The user has an existing CLI on a different framework (commander, yargs, oclif, minimist) — this skill doesn't migrate, and the APIs don't translate.
- The project uses Bloomberg's Stricli — different library, non-transferable API. Use the stricli skill.
- Generic "which CLI framework should I use?" — that's a design conversation, not a cleye question.
- Non-TypeScript CLIs — cleye works in plain JS, but its core value is compile-time type inference of flags and parameters.
- Runtime debugging of an installed CLI (not developing it) — use shell/debugging tooling.
Core API surface
cleye's API is intentionally small. If something isn't listed here or in the references, assume it doesn't exist — checking the upstream repo is faster than guessing, and invented APIs compile until they don't.
This skill targets the 2.x line (cleye@latest). Check the installed version before reaching for newer options: cleye/formats needs ≥2.6 and booleanFlagNegation ≥2.3. A 3.0.0-beta.1 is published on the beta dist-tag (npm i cleye@beta) with breaking changes — if the project is on the 3.x beta, read references/v3-migration.md before trusting the shapes below.
| Entry point |
Purpose |
cli(options, callback?, argvs?) |
Parse argv from a declarative options object; returns ParsedArgv |
command(options, callback?) |
Define a subcommand; same options as cli plus name/alias |
cleye/formats |
Tree-shakable type-function helpers (oneOf, commaList, integer, float, range, url) |
Flags / Renderers / TypeFlag |
Exported types for flag objects, help renderers, and portable flag declarations |
cli() returns a ParsedArgv:
type ParsedArgv = {
_: string[] & Parameters; // positional args, named in camelCase
flags: { [flagName: string]: InferredType };
unknownFlags: { [flagName: string]: (string | boolean)[] };
command?: string; // present when commands are registered
showVersion: () => void;
showHelp: (options?: HelpOptions) => void;
};
Installation
Upstream docs are npm-first. Stay agnostic to the user's package manager — pnpm and bun work equally well.
npm i cleye
# pnpm add cleye / bun add cleye work the same way
Quick start: single-command CLI
// greet.ts
import { cli } from "cleye";
const argv = cli({
name: "greet.js",
parameters: [
"<first name>", // required
"[last name]", // optional
],
flags: {
time: {
type: String,
description: "Time of day to greet (morning or evening)",
default: "morning",
},
},
});
const name = [argv._.firstName, argv._.lastName].filter(Boolean).join(" ");
if (argv.flags.time === "morning") {
console.log(`Good morning ${name}!`);
} else {
console.log(`Good evening ${name}!`);
}
Run it:
$ node greet.js John Doe --time evening
Good evening John Doe!
Generated help (--help is handled automatically):
$ node greet.js --help
greet.js
Usage:
greet.js [flags...] <first name> [last name]
Flags:
-h, --help Show help
--time <string> Time of day to greet (morning or evening) (default: "morning")
Parameter & flag model
- Parameters (positionals) use string-format markers:
<required>, [optional], <spread...> / [spread...]. Required must precede optional; spread must be last. Access in camelCase on argv._. Full details in references/parameters.md.
- Flags map a camelCase key to a type function (
String, Number, Boolean, custom) or a descriptor object (type, alias, default, description, placeholder). Wrap the type in an array ([Number]) to accept multiple values. Full details in references/flags.md.
- Validation is done with type functions that throw on bad input. Use the ready-made helpers in
references/formats.md (cleye/formats) or write your own.
Commands
Define subcommands with command() and register them in the commands array of cli(). The active command is reported on argv.command, which narrows the parsed types. For larger CLIs, give each command its own file and handle its output in a callback. See references/commands.md.
import { cli, command } from "cleye";
const argv = cli({
name: "npm",
commands: [
command({
name: "install",
parameters: ["<package name>"],
flags: { saveDev: Boolean },
}),
],
});
// $ npm install lodash → argv.command === "install", argv._.packageName === "lodash"
Help & version
--help/-h is automatic (disable with help: false, print manually with argv.showHelp()), --version is automatic only when version is set, and help.render(nodes, renderers) plus usage/examples/description shape the document. Details in references/help.md.
Recommended workflow
Single-command CLI
cli({ name, parameters, flags }) → read argv._ / argv.flags. Pass a callback as the second argument when you prefer to keep handling co-located, and return a Promise from it to await cli(...).
Multi-command CLI
Define each command with command() (ideally one per file with its own callback), register them in commands, then branch on argv.command if you handle output centrally. See references/commands.md.
Conventions worth keeping
- Define flag keys in camelCase; cleye automatically parses the kebab-case equivalent (
--saveDev ⇄ --save-dev).
- Use
strict: true in tsconfig.json — cleye's flag/parameter inference is the whole point, and loose mode weakens it.
- Type functions throw on invalid input; never return
Error values.
- Reserve
-h/--help and --version; cleye handles them unless told otherwise.
- Enable
strictFlags to reject unknown flags (with did-you-mean suggestions); otherwise they land in argv.unknownFlags.
- Commands inherit
strictFlags and booleanFlagNegation from the parent cli() but can override them.
References
parameters.md — positional args: required/optional/spread, ordering, argv._, end-of-flags --
flags.md — flag type functions, arrays, descriptors, delimiters, boolean negation/inversion, strict flags, unknown flags
formats.md — cleye/formats helpers and custom type functions
commands.md — command(), registration, type narrowing, callbacks, aliases, option inheritance
help.md — auto docs, help options, render customization, responsive tables
examples.md — composite end-to-end patterns (multi-command, async, validation, ignoreArgv, manual showHelp)
v3-migration.md — 3.x beta breaking changes: commands record, callback/return changes, PascalCase formats, atom-based help, group(), strictCommands, CleyeExit
External
1---2name: cleye3description: Build type-safe TypeScript CLIs with the cleye argv parser. Use when the project already depends on `cleye` or the user names cleye — authoring a `cli()` call, adding typed flags/parameters, defining subcommands with `command()`, handling parsed output in a callback, using `cleye/formats` helpers (oneOf/commaList/integer/float/range/url), customizing `--help` via `help.render`, or wiring `strictFlags`/`booleanFlagNegation`. For Bloomberg's Stricli framework use the stricli skill instead; skip for commander/yargs/oclif/minimist and for generic "which CLI framework should I use?" questions.4---56# cleye CLI Tool78cleye is an intuitive argv-parsing tool for Node.js CLIs. It turns a declarative options object into strongly-typed parameters and flags, auto-generates `--help` and `--version` documentation, and supports nested commands. Flag parsing is powered by [`type-flag`](https://github.com/privatenumber/type-flag).910Reference files live in `${CLAUDE_SKILL_DIR}/references/`.1112## When NOT to use1314- The user has an existing CLI on a different framework (commander, yargs, oclif, minimist) — this skill doesn't migrate, and the APIs don't translate.15- The project uses Bloomberg's Stricli — different library, non-transferable API. Use the stricli skill.16- Generic "which CLI framework should I use?" — that's a design conversation, not a cleye question.17- Non-TypeScript CLIs — cleye works in plain JS, but its core value is compile-time type inference of flags and parameters.18- Runtime debugging of an installed CLI (not developing it) — use shell/debugging tooling.1920## Core API surface2122cleye's API is intentionally small. If something isn't listed here or in the references, assume it doesn't exist — checking the upstream repo is faster than guessing, and invented APIs compile until they don't.2324This skill targets the **2.x** line (`cleye@latest`). Check the installed version before reaching for newer options: `cleye/formats` needs ≥2.6 and `booleanFlagNegation` ≥2.3. A `3.0.0-beta.1` is published on the `beta` dist-tag (`npm i cleye@beta`) with breaking changes — if the project is on the 3.x beta, read [`references/v3-migration.md`](references/v3-migration.md) before trusting the shapes below.2526| Entry point | Purpose |27| --- | --- |28| `cli(options, callback?, argvs?)` | Parse argv from a declarative options object; returns `ParsedArgv` |29| `command(options, callback?)` | Define a subcommand; same options as `cli` plus `name`/`alias` |30| `cleye/formats` | Tree-shakable type-function helpers (`oneOf`, `commaList`, `integer`, `float`, `range`, `url`) |31| `Flags` / `Renderers` / `TypeFlag` | Exported types for flag objects, help renderers, and portable flag declarations |3233`cli()` returns a `ParsedArgv`:3435```typescript36type ParsedArgv = {37 _: string[] & Parameters; // positional args, named in camelCase38 flags: { [flagName: string]: InferredType };39 unknownFlags: { [flagName: string]: (string | boolean)[] };40 command?: string; // present when commands are registered41 showVersion: () => void;42 showHelp: (options?: HelpOptions) => void;43};44```4546## Installation4748Upstream docs are npm-first. Stay agnostic to the user's package manager — pnpm and bun work equally well.4950```bash51npm i cleye52# pnpm add cleye / bun add cleye work the same way53```5455## Quick start: single-command CLI5657```typescript58// greet.ts59import { cli } from "cleye";6061const argv = cli({62 name: "greet.js",63 parameters: [64 "<first name>", // required65 "[last name]", // optional66 ],67 flags: {68 time: {69 type: String,70 description: "Time of day to greet (morning or evening)",71 default: "morning",72 },73 },74});7576const name = [argv._.firstName, argv._.lastName].filter(Boolean).join(" ");7778if (argv.flags.time === "morning") {79 console.log(`Good morning ${name}!`);80} else {81 console.log(`Good evening ${name}!`);82}83```8485Run it:8687```sh88$ node greet.js John Doe --time evening89Good evening John Doe!90```9192Generated help (`--help` is handled automatically):9394```sh95$ node greet.js --help9697greet.js9899Usage:100 greet.js [flags...] <first name> [last name]101102Flags:103 -h, --help Show help104 --time <string> Time of day to greet (morning or evening) (default: "morning")105```106107## Parameter & flag model108109- **Parameters** (positionals) use string-format markers: `<required>`, `[optional]`, `<spread...>` / `[spread...]`. Required must precede optional; spread must be last. Access in camelCase on `argv._`. Full details in [`references/parameters.md`](references/parameters.md).110- **Flags** map a camelCase key to a type function (`String`, `Number`, `Boolean`, custom) or a descriptor object (`type`, `alias`, `default`, `description`, `placeholder`). Wrap the type in an array (`[Number]`) to accept multiple values. Full details in [`references/flags.md`](references/flags.md).111- **Validation** is done with type functions that throw on bad input. Use the ready-made helpers in [`references/formats.md`](references/formats.md) (`cleye/formats`) or write your own.112113## Commands114115Define subcommands with `command()` and register them in the `commands` array of `cli()`. The active command is reported on `argv.command`, which narrows the parsed types. For larger CLIs, give each command its own file and handle its output in a callback. See [`references/commands.md`](references/commands.md).116117```typescript118import { cli, command } from "cleye";119120const argv = cli({121 name: "npm",122 commands: [123 command({124 name: "install",125 parameters: ["<package name>"],126 flags: { saveDev: Boolean },127 }),128 ],129});130// $ npm install lodash → argv.command === "install", argv._.packageName === "lodash"131```132133## Help & version134135`--help`/`-h` is automatic (disable with `help: false`, print manually with `argv.showHelp()`), `--version` is automatic only when `version` is set, and `help.render(nodes, renderers)` plus `usage`/`examples`/`description` shape the document. Details in [`references/help.md`](references/help.md).136137## Recommended workflow138139### Single-command CLI140141`cli({ name, parameters, flags })` → read `argv._` / `argv.flags`. Pass a callback as the second argument when you prefer to keep handling co-located, and return a Promise from it to `await cli(...)`.142143### Multi-command CLI144145Define each command with `command()` (ideally one per file with its own callback), register them in `commands`, then branch on `argv.command` if you handle output centrally. See [`references/commands.md`](references/commands.md).146147## Conventions worth keeping148149- Define flag keys in **camelCase**; cleye automatically parses the kebab-case equivalent (`--saveDev` ⇄ `--save-dev`).150- Use `strict: true` in `tsconfig.json` — cleye's flag/parameter inference is the whole point, and loose mode weakens it.151- Type functions **throw** on invalid input; never return `Error` values.152- Reserve `-h`/`--help` and `--version`; cleye handles them unless told otherwise.153- Enable `strictFlags` to reject unknown flags (with did-you-mean suggestions); otherwise they land in `argv.unknownFlags`.154- Commands inherit `strictFlags` and `booleanFlagNegation` from the parent `cli()` but can override them.155156## References157158- [`parameters.md`](references/parameters.md) — positional args: required/optional/spread, ordering, `argv._`, end-of-flags `--`159- [`flags.md`](references/flags.md) — flag type functions, arrays, descriptors, delimiters, boolean negation/inversion, strict flags, unknown flags160- [`formats.md`](references/formats.md) — `cleye/formats` helpers and custom type functions161- [`commands.md`](references/commands.md) — `command()`, registration, type narrowing, callbacks, aliases, option inheritance162- [`help.md`](references/help.md) — auto docs, `help` options, `render` customization, responsive tables163- [`examples.md`](references/examples.md) — composite end-to-end patterns (multi-command, async, validation, `ignoreArgv`, manual `showHelp`)164- [`v3-migration.md`](references/v3-migration.md) — 3.x beta breaking changes: `commands` record, callback/return changes, PascalCase formats, atom-based help, `group()`, `strictCommands`, `CleyeExit`165166## External167168- [cleye GitHub](https://github.com/privatenumber/cleye)169- [`cleye` on npm](https://www.npmjs.com/package/cleye)170- [`type-flag`](https://github.com/privatenumber/type-flag) — underlying flag parser