@wentools/zli
v0.2.3
Published
Lightweight CLI builder with Zod validation and type-safe argument parsing
Downloads
760
Maintainers
Readme
@wentools/zli
Lightweight CLI builder with Zod validation and type-safe argument parsing.
Installation
npx jsr add @wentools/zli
pnpm add zod@4Features
- Type-safe arguments inferred from Zod schemas
- Flexible parsing: positional args by order OR by
--name - Short flags:
--verboseor-v - Copy-paste friendly: easy to expand from simple to multi-command scripts
- Auto-generated help text
- Pretty validation error messages
- Conflict detection for duplicate names/shorts
- Result integration for error handling
Quick Start
Simple Single Command
import { zli } from '@wentools/zli'
import { z } from 'zod'
const command = zli.c(
[
zli.p('email', z.string().email(), {
description: 'User email address',
short: 'e'
}),
zli.f('verbose', z.boolean().optional().default(false), {
description: 'Verbose output',
short: 'v'
})
],
(args) => {
console.log(args.email) // typed as string
console.log(args.verbose) // typed as boolean
},
{ description: 'Check user permissions' }
)
zli.run(command)Invocation:
# Positional
pnpm tsx script.ts [email protected]
# Named
pnpm tsx script.ts --email [email protected]
# Short flag
pnpm tsx script.ts -e [email protected]
# With flags
pnpm tsx script.ts [email protected] --verbose
# Help
pnpm tsx script.ts --helpMulti-Command Script
import { zli } from '@wentools/zli'
import { z } from 'zod'
const check = zli.c(
[zli.p('email', z.string().email())],
(args) => console.log(`Checking ${args.email}`),
{ description: 'Check user permissions' }
)
const promote = zli.c(
[zli.p('email', z.string().email())],
(args) => console.log(`Promoting ${args.email}`),
{ description: 'Promote user to admin' }
)
zli.run({
name: 'user',
description: 'User management commands',
commands: {
check,
promote
}
})Nested Command Directories
const cli = zli.d('app', {
description: 'Application CLI',
commands: {
db: zli.d('db', {
description: 'Database commands',
commands: {
migrate: zli.c([], () => console.log('Migrating...')),
seed: zli.c([], () => console.log('Seeding...')),
}
}),
version: zli.c([], () => console.log('1.0.0'))
}
})
zli.run(cli)Usage:
pnpm tsx script.ts db migrate
pnpm tsx script.ts db --help
pnpm tsx script.ts versionAPI
zli.p(name, schema, options?) - Positional Argument
Creates a positional argument that can be specified by position, --name, or -short.
zli.p('email', z.string().email(), {
short: 'e',
description: 'User email address'
})zli.f(name, schema, options?) - Flag Argument
Creates a flag argument specified with --name or -short.
zli.f('verbose', z.boolean().optional().default(false), {
short: 'v',
description: 'Enable verbose output'
})zli.c(args, handler, options?) - Command
Creates a command with arguments and handler.
zli.c(
[zli.p('name', z.string())],
async (args) => {
// Handler can be sync or async
// Can return void or Result
},
{ description: 'Command description' }
)zli.d(name, options) - Command Directory
Creates a directory of commands for hierarchical organization.
zli.d('admin', {
description: 'Admin commands',
commands: {
users: usersDirectory,
config: configCommand
}
})zli.run(input) - Execute CLI
Runs a command or command directory.
Error Handling with Results
Handlers can return Result types from @wentools/result:
import { err } from '@wentools/result'
const command = zli.c(
[zli.p('email', z.string().email())],
async (args) => {
const user = await findUser(args.email)
if (!user) {
return err('user_not_found', 'User not found')
}
console.log(`Found: ${user.name}`)
}
)If the handler returns err(), zli will:
- Log the error as JSON
- Exit with code 1
Argument Parsing Behavior
- Positional args fill slots left-to-right
- Named flags (
--nameor-short) can fill any slot - Explicit (named) overrides implicit (positional)
# These are equivalent:
script.ts [email protected]
script.ts --email [email protected]
script.ts -e [email protected]
# Override positional with flag:
script.ts [email protected] --email [email protected]
# Result: args.email = "[email protected]"License
MIT
