API
Every export of zodline — defineOptions, defineCommand, defineConfig, processConfig, ZodlineError and the types.
Everything is exported from the package root.
import {
defineCommand,
defineConfig,
defineOptions,
processConfig,
ZodlineError,
} from 'zodline';
import type {
CommandDefinition,
DefineConfig,
OptionsDefinition,
ProcessResult,
} from 'zodline';
defineOptions
function defineOptions<T extends z.ZodObject>(
schema: T,
aliases?: Record<string, string>,
): OptionsDefinition<T>;
Pairs an options schema with an alias map. Returns { schema, aliases } unchanged — the function exists to
capture T so the schema type flows into defineCommand.
schemaz.ZodObject
One key per option, in camelCase.
z.ZodObjectaliases?Record<string, string>
Maps a short flag to a schema key, e.g. { n: "name" }.
Record<string, string>const options = defineOptions(
z.object({
name: z.string().describe('Name to greet'),
loud: z.boolean().default(false).describe('Use uppercase'),
}),
{ n: 'name', l: 'loud' },
);
defineCommand
function defineCommand<TOptions, TArgs>(config: {
description?: string;
examples?: string[];
options?: TOptions;
args?: TArgs;
action: (options, args) => void | Promise<void>;
}): CommandDefinition<…>;
Describes one command. Returns its input; the generics make options and args inside action inferred
rather than any.
description?string
Shown in the help screens.
stringexamples?string[]
Example invocations, printed verbatim in the per-command help.
string[]options?OptionsDefinition
The result of defineOptions().
OptionsDefinitionargs?z.ZodType
Schema applied to the positional argument array.
z.ZodTypeaction(options, args) => void | Promise<void>
Never invoked by processConfig — you call it.
(options, args) => void | Promise<void>defineConfig
function defineConfig<TCommands>(config: DefineConfig<TCommands>): DefineConfig<TCommands>;
Collects commands and CLI metadata.
meta?{ name?: string; version?: string; description?: string }
Identity used by the help screens and --version.
{ name?: string; version?: string; description?: string }commandsRecord<string, CommandDefinition>
Keys are the names users type.
Record<string, CommandDefinition>defaultCommand?CommandDefinition
Runs when no command name is given. Never receives positional arguments.
CommandDefinitionprocessConfig
function processConfig<TCommands>(
config: DefineConfig<TCommands>,
args: string[],
): ProcessResult;
Parses and validates args, then returns the matched command with its typed options and args. Does not
call the action.
Pass process.argv.slice(2) — the array must not include the node binary or the script path.
const result = processConfig(config, process.argv.slice(2));
await result.command.action(result.options, result.args);
Control flow
Parse flags
Resolve the command
The longest run of leading positional arguments that matches a command name wins, so config set is
matched by my-cli config set. With no positional arguments, --version and --help are handled (both
exit 0), then defaultCommand, then a ZodlineError.
Per-command help
--help after a command name prints its options and exits 0.Validate
Options run through the options pipeline; positional arguments run through the args schema.
Throws
| Condition | Error |
|---|---|
No command and no defaultCommand |
ZodlineError: No command specified. |
| Unknown command | ZodlineError: Unknown command: <name> |
| Unknown option | ZodlineError: Unknown option: --<name> |
| Options schema failure | ZodError |
| Args schema failure | Error: Argument validation failed: … |
ZodlineError
class ZodlineError extends Error {
name: 'ZodlineError';
}
Thrown for parse-level problems: no command, unknown command, unknown option. Schema failures are Zod’s errors, not this one.
if (error instanceof ZodlineError) {
console.error(error.message);
process.exit(2);
}
Types
OptionsDefinition
interface OptionsDefinition<T extends z.ZodObject = z.ZodObject> {
schema: T;
aliases?: Record<string, string> | undefined;
}
CommandDefinition
interface CommandDefinition<TOptions extends z.ZodObject, TArgs extends z.ZodType | undefined> {
description?: string;
examples?: string[];
options?: OptionsDefinition<TOptions>;
args?: TArgs;
action: (
options: TOptions extends z.ZodObject ? z.infer<TOptions> : {},
args: TArgs extends z.ZodType ? z.infer<TArgs> : undefined,
) => void | Promise<void>;
}
DefineConfig
interface DefineConfig<TCommands extends Record<string, CommandDefinition>> {
meta?: {
name?: string;
version?: string;
description?: string;
};
commands: TCommands;
defaultCommand?: CommandDefinition;
}
ProcessResult
interface ProcessResult<TCommand extends CommandDefinition> {
command: TCommand;
options: z.infer<TCommand['options']['schema']>;
args: z.infer<TCommand['args']>;
}
options resolves to {} for a command without options; args resolves to undefined for a command
without an args schema.