Skip to content

Releases: KurtGokhan/padrone

padrone@1.9.0

16 Apr 09:39
96a0c35

Choose a tag to compare

Minor Changes

  • 8114f98 Thanks @KurtGokhan! - Auto-coerce CLI string values for union types (e.g. z.union([z.boolean(), z.string()])) — --flag true now correctly passes boolean true instead of the string "true"

padrone@1.8.2

07 Apr 23:38
1aba20c

Choose a tag to compare

Patch Changes

  • 42b87eb Thanks @KurtGokhan! - Auto-output extension now automatically prints errors hapened in execution phase. Interceptor context now has a phase field to understand in which phase an error happened during error/shutdown phases.

padrone@1.8.1

07 Apr 00:07
62fca82

Choose a tag to compare

Patch Changes

  • e7c180c Thanks @KurtGokhan! - Add route phase to interceptors which will run when a command is routed to. This means it will run between parse and execute

  • 9d91f3f Thanks @KurtGokhan! - shutdown/error in interceptors can now run for command level interceptors

  • e4ae6f5 Thanks @KurtGokhan! - fix progress not getting destroyed after an error

padrone@1.8.0

06 Apr 09:17
4a430fb

Choose a tag to compare

Minor Changes

  • 7b58742 Thanks @KurtGokhan! - Add negative meta option for boolean arguments. Custom keyword(s) set the option to false and disable the default --no- prefix. Supports string, array, and empty values to only disable the prefix.

  • 07b49ae Thanks @KurtGokhan! - Add DefineCommandContext interface and defineCommand().requires() for typed interceptor context in modular commands. Commands defined with defineCommand() now have optional logger, tracing, and progress context by default. Use defineCommand().requires<T>().define(fn) for additional context requirements with compile-time validation at .command() registration.

  • e8bc2df Thanks @KurtGokhan! - Mark padroneEnv and padroneConfig as async at the type level. Extensions now return WithAsync<T> so eval() and cli() correctly return Promise when used.

  • 46cf13f Thanks @KurtGokhan! - Auto-merge interceptor context in next(). Passing next({ context: { user } }) now shallow-merges into existing context instead of replacing it. Default TContext changed from unknown to object so ctx.context is spreadable without type assertions.

Patch Changes

  • 735ffb4 Thanks @KurtGokhan! - Detect ambiguous positional arguments provided both positionally and as named options. For example, cmd val --pos1=val with positional: ['pos1', 'pos2'] now reports a validation error instead of silently overwriting.

padrone@1.7.1

02 Apr 11:36
2b11f48

Choose a tag to compare

Patch Changes

  • e15d537 Thanks @KurtGokhan! - Fix DefineCommand with default context being incompatible with parent programs that have a specific context type.

padrone@1.7.0

01 Apr 00:45
48cc0d7

Choose a tag to compare

Minor Changes

  • 3eecb40 Thanks @KurtGokhan! - Add format-aware output primitives (table, tree, list, key-value) to auto-output. Actions can use ctx.context.output.table(), .tree(), .list(), .kv() for styled output that adapts to the runtime format (ANSI, text, JSON, markdown, HTML). Declarative formatting via padroneAutoOutput({ output: 'table' }) per-command. Extract shared Styler/Layout infrastructure from help formatter into reusable styling.ts module.

  • 0a27a69 Thanks @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

28 Mar 15:09
9023eac

Choose a tag to compare

Minor Changes

  • 75066f9 Thanks @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.

  • 93ab85c Thanks @KurtGokhan! - Add typed context support. Define context with .context<T>() or .context(transform), provide it via cli(), eval(), run(), and access it in action handlers as ctx.context and in all plugin phase contexts. Subcommands inherit context from parents. .mount() accepts an optional { context } transform. New InferContext type helper.

  • 3b7fed0 Thanks @KurtGokhan! - Add typed context injection for interceptors. Interceptors can declare provided context via .provides<T>() and required context via .requires<T>() on defineInterceptor(). Action handlers see the full merged context type. .intercept() rejects interceptors whose required context is not satisfied at compile time.

  • 067b9f7 Thanks @KurtGokhan! - Add extension system with .extend() for build-time composition. Rename plugins to interceptors (.use().intercept(), PadronePluginPadroneInterceptor). Move built-in commands to composable extensions. Default builtins (help, version, repl, color, config, interactive) are applied automatically via createPadrone(). Advanced features (completion, man, mcp, serve, update-check) are opt-in extensions. Individual builtins can be disabled via createPadrone('name', { builtins: { help: false } }).

  • 4e7f88b Thanks @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.

  • aa0b568 Thanks @KurtGokhan! - Add support for Ink apps. The ink interceptor renders an Ink app as part of a command's execution, and waits for it to unmount before proceeding.

  • 91fd814 Thanks @KurtGokhan! - Add padroneLogger() and padroneTiming() extensions for structured logging and command execution timing.

  • 99c8cfa Thanks @KurtGokhan! - Add program.info for read-only access to program metadata (name, version, description, commands, etc.). Add XDG config directory support via xdg option on padroneConfig().

  • 88c45af Thanks @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 a message field (string or { validation, progress, success, error } object) with runtime-level defaults via context.

  • 8691694 Thanks @KurtGokhan! - Improve runtime agnosticism. Add terminal and exit fields to PadroneRuntime. Replace Buffer usage with Uint8Array/TextEncoder. Route scattered process.* reads through runtime abstraction. Replace all require() calls with dynamic import(). Use runtime.onSignal in serve/MCP instead of direct process.on.

  • 4343f78 Thanks @KurtGokhan! - Add signal handling support for graceful shutdown. Actions and plugins receive an AbortSignal via ctx.signal that aborts on SIGINT/SIGTERM/SIGHUP. Command results include signal and exitCode fields when interrupted. Double Ctrl+C within 2 seconds force-quits. Export new SignalError class and PadroneSignal type.

  • 7464026 Thanks @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.

  • be62401 Thanks @KurtGokhan! - Add experimental padroneTracing() extension for OpenTelemetry tracing. Logger automatically bridges log calls to span events when tracing is active.

Patch Changes

  • dbac7ec Thanks @KurtGokhan! - Add runtime to interceptor contexts. Interceptors can now access and override the runtime via ctx.runtime instead of calling getCommandRuntime(). Support next() overrides for passing modified context to downstream interceptors.

  • 0dfae77 Thanks @KurtGokhan! - Collect repeated non-array options into an array for the validator. Enables schemas like z.union([z.string(), z.array(z.string())]) to receive all values when an option is passed multiple times.

padrone@1.5.0

23 Mar 21:20
4ba1285

Choose a tag to compare

Minor Changes

  • ef5e829 Thanks @KurtGokhan! - Add asyncStream for streaming stdin as AsyncIterable. New padrone/zod entrypoint exports zodAsyncStream and jsonCodec for typed streams with per-item validation. Extract shared JSON_SCHEMA_OPTS constant across all jsonSchema.input() calls.

  • bbb05d9 Thanks @KurtGokhan! - Add examples configuration to options and commands for command-line usage examples.

  • 7ff2738 Thanks @KurtGokhan! - Collapse global commands in help output to a single summary line by default. Add --all flag to show full global commands section. Bare --detail flag now defaults to full. Rename "Built-in" section to "Global".

  • 369ebba Thanks @KurtGokhan! - Add group configuration 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 via configure({ group: 'Group Name' }). Grouped items are rendered under labeled ${group}: sections in help output, while ungrouped items remain under the default Options: / Commands: headers.

  • 3d7b282 Thanks @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.

  • 1843f1f Thanks @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. Added getCommand() and isPadroneProgram() helpers to replace direct commandSymbol usage.

  • 45ba002 Thanks @KurtGokhan! - Add built-in Model Context Protocol (MCP) server. Expose CLI commands as AI tools via mcp command or .mcp() method. Supports Streamable HTTP and stdio transports per the 2025-11-25 MCP spec.

  • ab53491 Thanks @KurtGokhan! - BREAKING: eval(), cli(), and run() no longer throw errors. Instead, they return a discriminated union with an error field:

    • 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 single Promise<{ 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>.

  • dffc5cd Thanks @KurtGokhan! - Add progress indicator system for commands with auto-managed spinners and manual control.

    Auto-managed progress via .progress() builder method:

    • true or string for 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
    • spinner option: preset name (dots, line, arc, bounce), custom { frames, interval }, or false to disable animation
    • success/error fields accept static strings, null to suppress, callbacks (result) => string | null, or { message, indicator } objects for per-call icon customization

    Manual progress via ctx.progress in 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

  • 6851b48 Thanks @KurtGokhan! - Add REST server (program.serve()) and mutation command config.

    • New serve() program method: exposes commands as HTTP endpoints with automatic OpenAPI docs (Scalar).
    • New serve built-in CLI command: myapp serve --port 3000.
    • Built-in endpoints: /_health, /_help, /_schema, /_docs (Scalar), /_openapi.
    • New mutation option in .configure(): mutation commands are POST-only in serve, set destructiveHint in MCP, and default needsApproval to true in tool().
    • MCP: rename endpoint to basePath for consistency with serve.
    • Shared utilities extracted from MCP (collectEndpoints, buildInputSchema, serializeArgsToFlags).

Patch Changes

  • 7e8f14d Thanks @KurtGokhan! - Expand boolean auto-coercion to accept yes/no/on/off (case-insensitive).

  • a1c7072 Thanks @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.

  • befc82e Thanks @KurtGokhan! - Add .catch() and .finally() methods to thenable sync results from eval(), parse(), and cli()

  • 81f3bbc Thanks @KurtGokhan! - Use node:child_process in wrap handler instead of Bun.spawn for Node.js compatibility.

padrone@1.4.0

19 Mar 11:51
7d899a4

Choose a tag to compare

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(), and parse() results always thenable (supports .then() and await)

Patch Changes

  • 79f51ae: Fix false async warning when action is async but validation is sync

padrone@1.3.0

18 Mar 15:57
026f135

Choose a tag to compare

Minor Changes

  • 6f6bfe5: Auto-generate kebab-case aliases for camelCase option names

    Options like dryRun automatically accept --dry-run on the CLI. This is enabled by default and can be disabled per-command with autoAlias: 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 alias into flags (single-char, stackable) and alias (multi-char long names)

    Breaking: PadroneFieldMeta.alias for single-character shortcuts is now flags.

    • 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-run for --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-run instead 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