padrone
v1.9.0
Published
Create type-safe, interactive CLI apps with Zod schemas
Maintainers
Readme
Define your CLI with Zod schemas. Get type safety, validation, help generation, interactive prompts, shell completions, AI tool integration, and more — all from a single source of truth.
Built on Standard Schema, so it also works with Valibot, ArkType, and others.
Install
npm install padrone zodScaffold a New Project
The fastest way to get started is with padrone init:
npx padrone init my-cli
cd my-cli && bun i && bun devQuick Start
import { createPadrone } from 'padrone';
import * as z from 'zod/v4';
const program = createPadrone('myapp')
.command('greet', (c) =>
c
.arguments(
z.object({
names: z.array(z.string()).describe('Names to greet'),
prefix: z.string().optional().describe('Prefix').meta({ flags: 'p' }),
}),
{ positional: ['...names'] },
)
.action((args) => {
for (const name of args.names) {
console.log(`Hello, ${args.prefix ?? ''} ${name}!`);
}
}),
);
program.cli();myapp greet John Jane -p Mr.
# Hello, Mr. John!
# Hello, Mr. Jane!What It Does
// Multiple ways to run commands
program.cli(); // from process.argv
program.eval('greet John --prefix Mr.'); // from a string
program.run('greet', { names: ['John'], prefix: 'Mr.' }); // typed args
program.api().greet({ names: ['John'], prefix: 'Mr.' }); // as a function
// Parse without executing
const { args } = program.parse('greet John --prefix Mr.');
// Interactive REPL
for await (const result of program.repl()) { /* ... */ }
// AI tool for Vercel AI SDK
const tool = program.tool();
// MCP server for AI assistants (Claude, Cursor, etc.) [experimental]
await program.mcp(); // or: myapp mcp
// REST server with OpenAPI docs [experimental]
await program.serve(); // or: myapp serve
// Shell completions
const script = program.completion('zsh');
// Help in multiple formats
program.help('greet'); // text
program.help('greet', { format: 'json' }); // json, markdown, html, ansiFeatures at a Glance
Arguments — positional args, variadic args, short flags (-v), long aliases (--dry-run), auto kebab-case aliases, negatable booleans (--no-verbose), custom negation keywords (--remote → sets local to false).
Env & Config — load from environment variables with .extend(padroneEnv(schema)) and config files with .extend(padroneConfig({ files, schema })). Precedence: CLI > stdin > env > config > defaults.
Interactive prompts — auto-prompt for missing fields. Booleans become confirm, enums become select, arrays become multi-select.
Progress indicators — auto-managed spinners and progress bars with elapsed time and ETA. .extend(padroneProgress({ message: 'Deploying...', bar: true, time: true, eta: true })).
Extension-first architecture — most built-in features (help, version, REPL, color, signal handling, auto-output, stdin, config, interactive, suggestions) are implemented as extensions composed via .extend(). Any built-in can be disabled or replaced.
Interceptors — middleware hooks for 7 phases (start, parse, route, validate, execute, error, shutdown). Onion model with next(). Extensions register interceptors under the hood. Create your own with defineInterceptor().
Composition — mount programs as subcommands with .mount(), override commands with merge semantics.
Wrapping (experimental) — wrap external CLI tools with .wrap({ command: 'git', args: ['commit'] }).
API
Builder (define commands)
| Method | What it does |
|--------|-------------|
| .arguments(schema, meta?) | Define args with Zod schema, positional config, field metadata |
| .action(handler) | Set handler (args, ctx, base?) => result |
| .command(name, builder) | Add subcommand (name or [name, ...aliases]) |
| .context(transform?) | Define typed context or transform inherited context |
| .mount(name, program, options?) | Mount another program as subcommand tree |
| .configure(config) | Set title, description, version, etc. |
| .extend(padroneEnv(schema)) | Map env vars to args (composable extension) |
| .extend(padroneConfig({ files, schema })) | Load args from config files (composable extension) |
| .wrap(config) | Wrap an external CLI tool (experimental) |
| .extend(padroneProgress(config?)) | Auto-managed progress indicator (extension) |
| .intercept(interceptor) | Register middleware interceptor (use defineInterceptor()) |
| .extend(extension) | Apply a build-time extension (bundle of config, commands, interceptors) |
| .runtime(runtime) | Custom I/O (for non-terminal use) |
| .updateCheck(config?) | Background version check |
| .async() | Mark as async validation |
Program (run commands)
| Method | What it does |
|--------|-------------|
| .cli(prefs?) | Entry point — parses process.argv, throws on errors. Pass context in prefs. |
| .eval(input, prefs?) | Parse + validate + execute string, returns errors softly. Pass context in prefs. |
| .run(command, args, prefs?) | Run by name with typed args (no validation). Pass context in prefs. |
| .parse(input?) | Parse without executing |
| .api() | Generate typed function API |
| .repl(options?) | Interactive REPL session |
| .help(command?, prefs?) | Generate help (text, ansi, markdown, html, json) |
| .tool() | Vercel AI SDK tool definition |
| .mcp(prefs?) | Start MCP server (HTTP or stdio) (experimental) |
| .serve(prefs?) | Start REST server with OpenAPI docs (experimental) |
| .completion(shell?) | Shell completion script |
| .find(command) | Look up command by path |
| .stringify(command?, args?) | Convert back to CLI string |
Zod .meta() fields
| Field | Example | Purpose |
|-------|---------|---------|
| flags | 'v' | Single-char short flag (-v) |
| alias | 'dry-run' | Multi-char long alias (--dry-run) |
| negative | 'remote' | Custom negation keyword for booleans (disables --no-) |
| examples | ['8080'] | Example values in help |
| deprecated | 'Use --debug' | Deprecation warning |
| hidden | true | Hide from help |
| group | 'Advanced' | Group in help output |
Arguments meta (second param of .arguments())
.arguments(schema, {
positional: ['source', '...files', 'dest'],
interactive: ['name', 'template'],
optionalInteractive: ['typescript'],
fields: { verbose: { flags: 'v' } },
stdin: 'data',
autoAlias: true, // default
})Agent Skill
Give your AI coding agent knowledge of the Padrone API:
npx skills add KurtGokhan/padroneRequirements
- Node.js 18+ or Bun
- TypeScript 5.0+ (recommended)
- Zod (or any Standard Schema-compatible library)
