Quick Start
This guide walks you through creating a simple CLI application with Padrone.
Scaffold with padrone init
Section titled “Scaffold with padrone init”The fastest way to start is to scaffold a new project:
npx padrone init my-clicd my-cli && bun i && bun devThis generates a ready-to-run project with a starter program. See CLI Tools for all options.
Manual Installation
Section titled “Manual Installation”Alternatively, add Padrone to an existing project:
# Using npmnpm install padrone zod
# Using bunbun add padrone zod
# Using pnpmpnpm add padrone zodCreate Your First CLI
Section titled “Create Your First CLI”Create a new file cli.ts:
import { createPadrone } from 'padrone';import * as z from 'zod/v4';
const program = createPadrone('greet') .configure({ version: '1.0.0', description: 'A friendly greeting CLI', }) .arguments( z.object({ name: z.string().describe('Name to greet'), excited: z.boolean().optional().describe('Add excitement'), }), { positional: ['name'] } ) .action((args) => { const greeting = `Hello, ${args.name}`; console.log(args.excited ? `${greeting}!` : greeting); });
program.cli();Run Your CLI
Section titled “Run Your CLI”# Run with a positional argumentbun cli.ts World# Output: Hello, World
# Run with the --excited flagbun cli.ts World --excited# Output: Hello, World!
# Show helpbun cli.ts --helpAdd Commands
Section titled “Add Commands”Most CLIs have multiple commands. Let’s add some:
import { createPadrone } from 'padrone';import * as z from 'zod/v4';
const program = createPadrone('todo') .configure({ version: '1.0.0', description: 'A simple todo CLI', }) .command('add', (c) => c .arguments( z.object({ task: z.string().describe('Task description'), priority: z.enum(['low', 'medium', 'high']).default('medium'), }), { positional: ['task'] } ) .action((args) => { console.log(`Added: ${args.task} [${args.priority}]`); }) ) .command('list', (c) => c .arguments( z.object({ all: z.boolean().optional().describe('Show completed tasks'), }) ) .action((args) => { console.log('Listing tasks...', { showAll: args.all }); }) );
program.cli();# Add a taskbun cli.ts add "Buy groceries" --priority high
# List tasksbun cli.ts list --allUse Short Flags
Section titled “Use Short Flags”Add short flags for frequently used arguments:
z.object({ verbose: z.boolean().optional().describe('Verbose output').meta({ flags: 'v' }), output: z.string().optional().describe('Output file').meta({ flags: 'o' }),})Now users can use -v instead of --verbose and -o instead of --output. Short flags are single-character and stackable: -vo out.json = -v -o out.json.
Programmatic Usage
Section titled “Programmatic Usage”You can also run commands programmatically with full type safety:
// Run a command directlyprogram.run('add', { task: 'Buy milk', priority: 'high' });
// Evaluate a command string (soft error handling)const result = program.eval('add "Buy eggs" --priority low');
// Generate a typed APIconst api = program.api();api.add({ task: 'Buy eggs', priority: 'low' });
// Parse without executingconst parsed = program.parse('add "Clean room" --priority medium');console.log(parsed.command); // 'add'console.log(parsed.args); // { task: 'Clean room', priority: 'medium' }Make It Interactive
Section titled “Make It Interactive”Add interactive prompting so users are guided through missing arguments:
const program = createPadrone('todo') .configure({ version: '1.0.0' }) .runtime({ interactive: true }) .command('add', (c) => c .arguments( z.object({ task: z.string().describe('Task description'), priority: z.enum(['low', 'medium', 'high']).default('medium').describe('Priority level'), }), { positional: ['task'], interactive: ['task'], optionalInteractive: ['priority'], } ) .action((args) => { console.log(`Added: ${args.task} [${args.priority}]`); }) );
await program.cli();Now running todo add with no arguments will prompt for the task description (text input), then offer to configure priority (select menu with low/medium/high). Prompt types are auto-detected from your Zod schema.
Next Steps
Section titled “Next Steps”- Learn about Commands & Arguments in depth
- Set up Interactive Prompting for your CLI
- Start an interactive REPL session
- Add Progress Indicators to long-running commands
- Add Interceptors & Extensions to extend command behavior
- Compose programs together with mount and override
- Integrate with AI tools (MCP (experimental), REST server (experimental), and Vercel AI SDK)
- Handle errors with Error Handling
- Test your CLI with testCli()
- Scaffold and lint with CLI Tools
- Explore the API Reference