| name | cleye |
| description | cleye CLI development tool — argv parsing with typed parameters, flags, commands, and auto-generated help. Use when building Node.js CLI scripts with cleye or when the user imports `cli` or `command` from `cleye`. |
cleye
Quick Patterns
| Task | Pattern |
|---|
| Basic CLI | cli({ name, parameters, flags }) |
| Named command | command({ name, parameters, flags }, callback) |
| Register commands | cli({ commands: [cmd1, cmd2] }) |
| Async callback | await cli({ ... }, async (argv) => { ... }) |
| Raw argv | cli({ ... }, callback, process.argv.slice(2)) |
Parameters
Positional arguments mapped to named properties on argv._.
| Format | Description |
|---|
<name> | Required |
[name] | Optional |
<name...> | Required spread (1+) |
[name...] | Optional spread (0+) |
-- | End-of-flags separator |
const argv = cli({
parameters: ['<required>', '[optional]', '[rest...]']
})
argv._.required
argv._.optional
argv._.rest
argv._['--']
Multi-word names use camelCase on argv._: '<first name>' → argv._.firstName.
Flags
const argv = cli({
flags: {
verbose: Boolean,
output: {
type: String,
alias: 'o',
default: 'dist',
description: 'Output directory',
placeholder: '<path>'
},
count: {
type: [Number],
alias: 'n'
}
}
})
argv.flags.verbose
argv.flags.output
argv.flags.count
Flag name is camelCase; parsed from kebab-case CLI input (--output-dir → outputDir).
Delimiters — =, :, and . all work as value separators:
--flag=value --flag:value --flag.value
Use : when the value itself contains = (e.g. --define:KEY=VALUE).
Counting flags — use [Boolean] and check .length:
cli({
flags: {
verbose: {
type: [Boolean],
alias: 'v'
}
}
})
Optional value — custom type returns true when no value is given:
const OptionalString = (value: string) => value || true
cli({ flags: { tag: OptionalString } })
Boolean Flag Negation
By default, set a boolean flag to false using the = operator:
--verbose=false
--verbose false
To also support the --no-<flag> convention, enable booleanFlagNegation (additive — =false still works):
cli({
flags: { verbose: Boolean },
booleanFlagNegation: true
})
Commands inherit booleanFlagNegation from the parent cli() but can override it.
Strict Flags
cli({
flags: { foo: Boolean },
strictFlags: true
})
Commands inherit strictFlags but can override it.
Commands
export const installCommand = command({
name: 'install',
alias: ['i', 'add'],
parameters: ['<package name>'],
flags: { saveDev: Boolean }
}, (argv) => {
argv._.packageName
argv.flags.saveDev
})
cli({
name: 'npm',
version: '1.0.0',
commands: [installCommand]
})
When a command is matched, argv.command narrows the type for type-safe branching.
Help & Version
cli({
name: 'my-script',
version: '1.2.3',
help: {
description: 'Does things',
usage: 'my-script [flags] <file>',
examples: ['my-script foo.txt', 'my-script --output=dist foo.txt'],
version: '1.2.3'
}
})
Tip: import name, version, and description from package.json to avoid keeping them in sync manually:
import { name, version, description } from './package.json' with { type: 'json' }
cli({
name,
version,
help: { description }
})
Custom Flag Types
Any function (value: string) => T works as a flag type — the return type is inferred.
const Port = (value: string) => {
const n = Number(value)
if (!Number.isInteger(n) || n < 1 || n > 65_535) { throw new Error(`Invalid port: ${value}`) }
return n
}
const sizes = ['small', 'medium', 'large'] as const
const Size = (v: string) => {
if (!(sizes as readonly string[]).includes(v)) { throw new Error(`Expected: ${sizes.join(', ')}`) }
return v as typeof sizes[number]
}
const List = (v: string) => v.split(',')
cli({ flags: { data: JSON.parse } })
const Env = (v: string): Record<string, string | true> => {
const [k, value] = v.split('=')
return { [k]: value ?? true }
}
cli({ flags: { env: [Env] } })
Type Helpers (cleye/formats)
cleye/formats ships composable, tree-shakable type-function helpers. Import only what you need.
import {
oneOf, commaList, integer, float, range, url
} from 'cleye/formats'
oneOf('a', 'b', 'c') — infers 'a' | 'b' | 'c'; throws if the value is not in the list.
commaList(itemType) — splits "a,b,c" → T[]; trims whitespace; composes with other helpers (e.g. commaList(integer())).
integer() — base-10 integer; throws on floats/non-numeric.
float() — finite float; throws on Infinity/non-numeric.
range(min, max) — returns (input: string) => number; validates input parses to a number in [min, max].
url() — parses with new URL(); returns a URL object (not a string).
Help Customization
cli({
help: {
render(nodes, renderers) {
nodes.push('\nDocs: https://example.com')
renderers.flagOperator = () => '='
return renderers.render(nodes)
}
}
})
Default renderers: /src/render-help/renderers.ts.
ignoreArgv
cli({
ignoreArgv(type, flagOrArgv, value) {
if (type === 'unknown-flag') { return true }
}
})
type: 'known-flag' | 'unknown-flag' | 'argument'
Return Type
type ParsedArgv = {
_: string[] & Parameters
flags: { [name: string]: InferredType }
unknownFlags: { [name: string]: (string | boolean)[] }
showVersion: () => void
showHelp: (options?: HelpOptions) => void
}
TypeScript Exports
import type { Flags, Renderers, TypeFlag } from 'cleye'
| Type | Use |
|---|
Flags | Type for the flags option object |
Renderers | Help renderer class type for help.render customization |
TypeFlag | Re-export from type-flag for portable type declarations |