Skip to content

KurtGokhan/padrone

Repository files navigation

Padrone Logo

Type-safe CLI framework powered by Zod schemas

npm version npm downloads license


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 zod

Scaffold a New Project

The fastest way to get started is with padrone init:

npx padrone init my-cli
cd my-cli && bun i && bun dev

Quick 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, ansi

Features 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/padrone

Requirements

  • Node.js 18+ or Bun
  • TypeScript 5.0+ (recommended)
  • Zod (or any Standard Schema-compatible library)

License

MIT