Releases: KurtGokhan/padrone
padrone@1.9.0
Minor Changes
8114f98Thanks @KurtGokhan! - Auto-coerce CLI string values for union types (e.g.z.union([z.boolean(), z.string()])) —--flag truenow correctly passes booleantrueinstead of the string"true"
padrone@1.8.2
Patch Changes
42b87ebThanks @KurtGokhan! - Auto-output extension now automatically prints errors hapened in execution phase. Interceptor context now has aphasefield to understand in which phase an error happened during error/shutdown phases.
padrone@1.8.1
Patch Changes
-
e7c180cThanks @KurtGokhan! - Addroutephase to interceptors which will run when a command is routed to. This means it will run between parse and execute -
9d91f3fThanks @KurtGokhan! - shutdown/error in interceptors can now run for command level interceptors -
e4ae6f5Thanks @KurtGokhan! - fix progress not getting destroyed after an error
padrone@1.8.0
Minor Changes
-
7b58742Thanks @KurtGokhan! - Addnegativemeta option for boolean arguments. Custom keyword(s) set the option tofalseand disable the default--no-prefix. Supports string, array, and empty values to only disable the prefix. -
07b49aeThanks @KurtGokhan! - AddDefineCommandContextinterface anddefineCommand().requires()for typed interceptor context in modular commands. Commands defined withdefineCommand()now have optionallogger,tracing, andprogresscontext by default. UsedefineCommand().requires<T>().define(fn)for additional context requirements with compile-time validation at.command()registration. -
e8bc2dfThanks @KurtGokhan! - MarkpadroneEnvandpadroneConfigas async at the type level. Extensions now returnWithAsync<T>soeval()andcli()correctly returnPromisewhen used. -
46cf13fThanks @KurtGokhan! - Auto-merge interceptor context innext(). Passingnext({ context: { user } })now shallow-merges into existing context instead of replacing it. DefaultTContextchanged fromunknowntoobjectsoctx.contextis spreadable without type assertions.
Patch Changes
735ffb4Thanks @KurtGokhan! - Detect ambiguous positional arguments provided both positionally and as named options. For example,cmd val --pos1=valwithpositional: ['pos1', 'pos2']now reports a validation error instead of silently overwriting.
padrone@1.7.1
Patch Changes
e15d537Thanks @KurtGokhan! - FixDefineCommandwith default context being incompatible with parent programs that have a specific context type.
padrone@1.7.0
Minor Changes
-
3eecb40Thanks @KurtGokhan! - Add format-aware output primitives (table, tree, list, key-value) to auto-output. Actions can usectx.context.output.table(),.tree(),.list(),.kv()for styled output that adapts to the runtime format (ANSI, text, JSON, markdown, HTML). Declarative formatting viapadroneAutoOutput({ output: 'table' })per-command. Extract shared Styler/Layout infrastructure from help formatter into reusablestyling.tsmodule. -
0a27a69Thanks @KurtGokhan! - Add printf-style format specifiers (%s,%d,%i,%f,%j,%o,%O,%%) to the logger extension, following WHATWG Console Standard conventions.
padrone@1.6.0
Minor Changes
-
75066f9Thanks @KurtGokhan! - Improve "Did you mean?" suggestions for typos in commands and options. Return multiple matches (up to 3), add prefix/substring matching for inputs longer than 3 characters, and include--prefix in option suggestions. Suggestions are now included in soft-mode validation errors too. -
93ab85cThanks @KurtGokhan! - Add typed context support. Define context with.context<T>()or.context(transform), provide it viacli(),eval(),run(), and access it in action handlers asctx.contextand in all plugin phase contexts. Subcommands inherit context from parents..mount()accepts an optional{ context }transform. NewInferContexttype helper. -
3b7fed0Thanks @KurtGokhan! - Add typed context injection for interceptors. Interceptors can declare provided context via.provides<T>()and required context via.requires<T>()ondefineInterceptor(). Action handlers see the full merged context type..intercept()rejects interceptors whose required context is not satisfied at compile time. -
067b9f7Thanks @KurtGokhan! - Add extension system with.extend()for build-time composition. Rename plugins to interceptors (.use()→.intercept(),PadronePlugin→PadroneInterceptor). Move built-in commands to composable extensions. Default builtins (help, version, repl, color, config, interactive) are applied automatically viacreatePadrone(). Advanced features (completion, man, mcp, serve, update-check) are opt-in extensions. Individual builtins can be disabled viacreatePadrone('name', { builtins: { help: false } }). -
4e7f88bThanks @KurtGokhan! - Respect terminal width in help output. Default and choices metadata now appear inline with descriptions when space allows, and long descriptions wrap aligned to the description column. -
aa0b568Thanks @KurtGokhan! - Add support for Ink apps. Theinkinterceptor renders an Ink app as part of a command's execution, and waits for it to unmount before proceeding. -
91fd814Thanks @KurtGokhan! - AddpadroneLogger()andpadroneTiming()extensions for structured logging and command execution timing. -
99c8cfaThanks @KurtGokhan! - Addprogram.infofor read-only access to program metadata (name, version, description, commands, etc.). Add XDG config directory support viaxdgoption onpadroneConfig(). -
88c45afThanks @KurtGokhan! - Add elapsed time (time: true) and ETA (eta: true) to progress indicators. ETA is calculated from numeric progress updates and counts down between updates. Move progress messages into amessagefield (string or{ validation, progress, success, error }object) with runtime-level defaults via context. -
8691694Thanks @KurtGokhan! - Improve runtime agnosticism. Addterminalandexitfields toPadroneRuntime. ReplaceBufferusage withUint8Array/TextEncoder. Route scatteredprocess.*reads through runtime abstraction. Replace allrequire()calls with dynamicimport(). Useruntime.onSignalin serve/MCP instead of directprocess.on. -
4343f78Thanks @KurtGokhan! - Add signal handling support for graceful shutdown. Actions and plugins receive anAbortSignalviactx.signalthat aborts on SIGINT/SIGTERM/SIGHUP. Command results includesignalandexitCodefields when interrupted. Double Ctrl+C within 2 seconds force-quits. Export newSignalErrorclass andPadroneSignaltype. -
7464026Thanks @KurtGokhan! - Reject unknown options for commands without.arguments(). Previously, commands without a schema accepted all options silently. Now they infer an empty object and error on unknown options. -
be62401Thanks @KurtGokhan! - Add experimentalpadroneTracing()extension for OpenTelemetry tracing. Logger automatically bridges log calls to span events when tracing is active.
Patch Changes
-
dbac7ecThanks @KurtGokhan! - Addruntimeto interceptor contexts. Interceptors can now access and override the runtime viactx.runtimeinstead of callinggetCommandRuntime(). Supportnext()overrides for passing modified context to downstream interceptors. -
0dfae77Thanks @KurtGokhan! - Collect repeated non-array options into an array for the validator. Enables schemas likez.union([z.string(), z.array(z.string())])to receive all values when an option is passed multiple times.
padrone@1.5.0
Minor Changes
-
ef5e829Thanks @KurtGokhan! - AddasyncStreamfor streaming stdin asAsyncIterable. Newpadrone/zodentrypoint exportszodAsyncStreamandjsonCodecfor typed streams with per-item validation. Extract sharedJSON_SCHEMA_OPTSconstant across alljsonSchema.input()calls. -
bbb05d9Thanks @KurtGokhan! - Addexamplesconfiguration to options and commands for command-line usage examples. -
7ff2738Thanks @KurtGokhan! - Collapse global commands in help output to a single summary line by default. Add--allflag to show full global commands section. Bare--detailflag now defaults tofull. Rename "Built-in" section to "Global". -
369ebbaThanks @KurtGokhan! - Addgroupconfiguration to options and commands for organized help output.Options can be grouped via
fields: { myField: { group: 'Group Name' } }in argument metadata. Commands can be grouped viaconfigure({ group: 'Group Name' }). Grouped items are rendered under labeled${group}:sections in help output, while ungrouped items remain under the defaultOptions:/Commands:headers. -
3d7b282Thanks @KurtGokhan! - Add per-field validation during interactive prompts.When a user provides an invalid value for an interactive field, the prompt now immediately validates it against the schema and re-prompts with a warning message instead of deferring all errors until after all prompts complete. This applies to both required and optional interactive fields.
-
1843f1fThanks @KurtGokhan! - Lazily initialize commands defined with callbacks. Builder functions passed to.command()are now deferred until the command is routed to, avoiding upfront construction of unused commands. Features that need the full command tree (help, MCP, serve, docs, completion, REPL) resolve all commands eagerly. AddedgetCommand()andisPadroneProgram()helpers to replace directcommandSymbolusage. -
45ba002Thanks @KurtGokhan! - Add built-in Model Context Protocol (MCP) server. Expose CLI commands as AI tools viamcpcommand or.mcp()method. Supports Streamable HTTP and stdio transports per the 2025-11-25 MCP spec. -
ab53491Thanks @KurtGokhan! - BREAKING:eval(),cli(), andrun()no longer throw errors. Instead, they return a discriminated union with anerrorfield:- Success:
{ command, args, argsResult, result, drain() } - Error:
{ error, command?, args?, argsResult?, drain() }
Added
drain()method to all command results. It flattens the result into a singlePromise<{ value } | { error }>that never throws — resolving Promises, collecting iterables into arrays, and catching errors:const { value, error } = await program.cli().drain();
New exported types:
PadroneDrainResult<T>,Drained<T>. - Success:
-
dffc5cdThanks @KurtGokhan! - Add progress indicator system for commands with auto-managed spinners and manual control.Auto-managed progress via
.progress()builder method:trueorstringfor simple messages, or a full config object with per-state messages- Starts before validation, auto-succeeds/fails after execution
- Validation-phase message transitions to execution-phase message
spinneroption: preset name (dots,line,arc,bounce), custom{ frames, interval }, orfalseto disable animationsuccess/errorfields accept static strings,nullto suppress, callbacks(result) => string | null, or{ message, indicator }objects for per-call icon customization
Manual progress via
ctx.progressin action handlers:- Works even without
.progress()config — lazily creates a real indicator on first use - Auto-stopped when execution finishes (no leaked spinners)
- No-op when the runtime has no progress factory
Built-in terminal spinner (
createTerminalSpinner):- ANSI-based spinner with pause/resume for clean output interleaving
- Customizable success/error indicator icons via
PadroneProgressOptions - Empty string indicators hide the icon prefix entirely
- Graceful fallback in non-TTY/CI environments
New types:
PadroneProgressIndicator,PadroneProgressConfig,PadroneProgressMessage,PadroneProgressOptions,PadroneSpinnerConfig,PadroneSpinnerPreset -
6851b48Thanks @KurtGokhan! - Add REST server (program.serve()) andmutationcommand config.- New
serve()program method: exposes commands as HTTP endpoints with automatic OpenAPI docs (Scalar). - New
servebuilt-in CLI command:myapp serve --port 3000. - Built-in endpoints:
/_health,/_help,/_schema,/_docs(Scalar),/_openapi. - New
mutationoption in.configure(): mutation commands are POST-only in serve, setdestructiveHintin MCP, and defaultneedsApprovalto true intool(). - MCP: rename
endpointtobasePathfor consistency with serve. - Shared utilities extracted from MCP (
collectEndpoints,buildInputSchema,serializeArgsToFlags).
- New
Patch Changes
-
7e8f14dThanks @KurtGokhan! - Expand boolean auto-coercion to acceptyes/no/on/off(case-insensitive). -
a1c7072Thanks @KurtGokhan! - Improve help output formatting: options now display flags first, then names, type, and description in aligned columns. Metadata (deprecated, default, choices, examples, env, config) is shown on separate indented lines. -
befc82eThanks @KurtGokhan! - Add.catch()and.finally()methods to thenable sync results fromeval(),parse(), andcli() -
81f3bbcThanks @KurtGokhan! - Usenode:child_processin wrap handler instead ofBun.spawnfor Node.js compatibility.
padrone@1.4.0
Minor Changes
-
365ad1f: Fix positional arguments and make results always thenable
- Show choices and default values in help output for positional arguments
- Fix type detection for optional array enum positionals (
z.array(z.enum([...])).optional()) - Coerce single values to arrays when schema expects an array type
- Make
cli(),eval(), andparse()results always thenable (supports.then()andawait)
Patch Changes
- 79f51ae: Fix false async warning when action is async but validation is sync
padrone@1.3.0
Minor Changes
-
6f6bfe5: Auto-generate kebab-case aliases for camelCase option names
Options like
dryRunautomatically accept--dry-runon the CLI. This is enabled by default and can be disabled per-command withautoAlias: false. Auto-aliases are shown as the primary name in help text when available.// --dry-run automatically resolves to dryRun .arguments(z.object({ dryRun: z.boolean() })) // Disable auto-aliases .arguments(z.object({ dryRun: z.boolean() }), { autoAlias: false })
-
07cbf35: Split option
aliasintoflags(single-char, stackable) andalias(multi-char long names)Breaking:
PadroneFieldMeta.aliasfor single-character shortcuts is nowflags.flags: single-char short flags used with single dash (-v,-o file). Stackable:-abc=-a -b -c.alias: multi-char alternative long names used with double dash (--dry-runfor--dryRun).
Migration
- { fields: { verbose: { alias: 'v' } } } + { fields: { verbose: { flags: 'v' } } }
- z.string().meta({ alias: ['v'] }) + z.string().meta({ flags: ['v'] })
Multi-char aliases remain as
alias:{ fields: { dryRun: { alias: "dry-run"; } } }
-
186c2be: Improve help output formatting
- Use bracket convention for option types:
<type>for required,[type]for optional, nothing for booleans - Show kebab-case alias as primary name when available (e.g.
--dry-runinstead of--dryRun) - Move choices and default values after the description
- Show array item types (e.g.
[string[]]instead of[array] (repeatable)) - Hide empty default values (empty strings and arrays)
- Cap description alignment at 32 characters
- Show
(stdin)marker on arguments that accept stdin input - Show
--no-negation hint only when relevant (boolean options defaulting to true) - Remove
[no-]prefix from individual boolean options
- Use bracket convention for option types: