padrone 1.4.0 → 1.6.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (141) hide show
  1. package/CHANGELOG.md +115 -0
  2. package/README.md +108 -283
  3. package/dist/args-Cnq0nwSM.mjs +272 -0
  4. package/dist/args-Cnq0nwSM.mjs.map +1 -0
  5. package/dist/codegen/index.d.mts +28 -3
  6. package/dist/codegen/index.d.mts.map +1 -1
  7. package/dist/codegen/index.mjs +169 -19
  8. package/dist/codegen/index.mjs.map +1 -1
  9. package/dist/commands-B_gufyR9.mjs +514 -0
  10. package/dist/commands-B_gufyR9.mjs.map +1 -0
  11. package/dist/{completion.mjs → completion-BEuflbDO.mjs} +86 -108
  12. package/dist/completion-BEuflbDO.mjs.map +1 -0
  13. package/dist/docs/index.d.mts +22 -2
  14. package/dist/docs/index.d.mts.map +1 -1
  15. package/dist/docs/index.mjs +92 -7
  16. package/dist/docs/index.mjs.map +1 -1
  17. package/dist/errors-CL63UOzt.mjs +137 -0
  18. package/dist/errors-CL63UOzt.mjs.map +1 -0
  19. package/dist/{formatter-ClUK5hcQ.d.mts → formatter-DrvhDMrq.d.mts} +35 -6
  20. package/dist/formatter-DrvhDMrq.d.mts.map +1 -0
  21. package/dist/help-B5Kk83of.mjs +849 -0
  22. package/dist/help-B5Kk83of.mjs.map +1 -0
  23. package/dist/index-BaU3X6dY.d.mts +1178 -0
  24. package/dist/index-BaU3X6dY.d.mts.map +1 -0
  25. package/dist/index.d.mts +763 -36
  26. package/dist/index.d.mts.map +1 -1
  27. package/dist/index.mjs +3608 -1534
  28. package/dist/index.mjs.map +1 -1
  29. package/dist/mcp-BM-d0nZi.mjs +377 -0
  30. package/dist/mcp-BM-d0nZi.mjs.map +1 -0
  31. package/dist/serve-Bk0JUlCj.mjs +402 -0
  32. package/dist/serve-Bk0JUlCj.mjs.map +1 -0
  33. package/dist/stream-DC4H8YTx.mjs +77 -0
  34. package/dist/stream-DC4H8YTx.mjs.map +1 -0
  35. package/dist/test.d.mts +5 -8
  36. package/dist/test.d.mts.map +1 -1
  37. package/dist/test.mjs +5 -27
  38. package/dist/test.mjs.map +1 -1
  39. package/dist/{update-check-EbNDkzyV.mjs → update-check-CZ2VqjnV.mjs} +16 -17
  40. package/dist/update-check-CZ2VqjnV.mjs.map +1 -0
  41. package/dist/zod.d.mts +32 -0
  42. package/dist/zod.d.mts.map +1 -0
  43. package/dist/zod.mjs +50 -0
  44. package/dist/zod.mjs.map +1 -0
  45. package/package.json +20 -9
  46. package/src/cli/completions.ts +14 -11
  47. package/src/cli/docs.ts +13 -16
  48. package/src/cli/doctor.ts +213 -24
  49. package/src/cli/index.ts +28 -82
  50. package/src/cli/init.ts +12 -10
  51. package/src/cli/link.ts +22 -18
  52. package/src/cli/wrap.ts +14 -11
  53. package/src/codegen/discovery.ts +80 -28
  54. package/src/codegen/index.ts +2 -1
  55. package/src/codegen/parsers/bash.ts +179 -0
  56. package/src/codegen/schema-to-code.ts +2 -1
  57. package/src/core/args.ts +296 -0
  58. package/src/core/commands.ts +373 -0
  59. package/src/core/create.ts +268 -0
  60. package/src/{runtime.ts → core/default-runtime.ts} +70 -135
  61. package/src/{errors.ts → core/errors.ts} +22 -0
  62. package/src/core/exec.ts +259 -0
  63. package/src/core/interceptors.ts +302 -0
  64. package/src/{parse.ts → core/parse.ts} +36 -89
  65. package/src/core/program-methods.ts +301 -0
  66. package/src/core/results.ts +229 -0
  67. package/src/core/runtime.ts +246 -0
  68. package/src/core/validate.ts +247 -0
  69. package/src/docs/index.ts +124 -11
  70. package/src/extension/auto-output.ts +95 -0
  71. package/src/extension/color.ts +38 -0
  72. package/src/extension/completion.ts +49 -0
  73. package/src/extension/config.ts +262 -0
  74. package/src/extension/env.ts +101 -0
  75. package/src/extension/help.ts +192 -0
  76. package/src/extension/index.ts +43 -0
  77. package/src/extension/ink.ts +93 -0
  78. package/src/extension/interactive.ts +106 -0
  79. package/src/extension/logger.ts +214 -0
  80. package/src/extension/man.ts +51 -0
  81. package/src/extension/mcp.ts +52 -0
  82. package/src/extension/progress-renderer.ts +338 -0
  83. package/src/extension/progress.ts +299 -0
  84. package/src/extension/repl.ts +94 -0
  85. package/src/extension/serve.ts +48 -0
  86. package/src/extension/signal.ts +87 -0
  87. package/src/extension/stdin.ts +62 -0
  88. package/src/extension/suggestions.ts +114 -0
  89. package/src/extension/timing.ts +81 -0
  90. package/src/extension/tracing.ts +175 -0
  91. package/src/extension/update-check.ts +77 -0
  92. package/src/extension/utils.ts +51 -0
  93. package/src/extension/version.ts +63 -0
  94. package/src/{completion.ts → feature/completion.ts} +130 -57
  95. package/src/{interactive.ts → feature/interactive.ts} +47 -6
  96. package/src/feature/mcp.ts +387 -0
  97. package/src/{repl-loop.ts → feature/repl-loop.ts} +26 -16
  98. package/src/feature/serve.ts +438 -0
  99. package/src/feature/test.ts +262 -0
  100. package/src/{update-check.ts → feature/update-check.ts} +16 -16
  101. package/src/{wrap.ts → feature/wrap.ts} +27 -27
  102. package/src/index.ts +120 -11
  103. package/src/output/colorizer.ts +154 -0
  104. package/src/{formatter.ts → output/formatter.ts} +281 -135
  105. package/src/{help.ts → output/help.ts} +62 -15
  106. package/src/{zod.d.ts → schema/zod.d.ts} +1 -1
  107. package/src/schema/zod.ts +50 -0
  108. package/src/test.ts +2 -285
  109. package/src/types/args-meta.ts +151 -0
  110. package/src/types/builder.ts +697 -0
  111. package/src/types/command.ts +157 -0
  112. package/src/types/index.ts +59 -0
  113. package/src/types/interceptor.ts +296 -0
  114. package/src/types/preferences.ts +83 -0
  115. package/src/types/result.ts +71 -0
  116. package/src/types/schema.ts +19 -0
  117. package/src/util/dotenv.ts +244 -0
  118. package/src/{shell-utils.ts → util/shell-utils.ts} +26 -9
  119. package/src/util/stream.ts +101 -0
  120. package/src/{type-helpers.ts → util/type-helpers.ts} +23 -16
  121. package/src/{type-utils.ts → util/type-utils.ts} +99 -37
  122. package/src/util/utils.ts +51 -0
  123. package/src/zod.ts +1 -0
  124. package/dist/args-CVDbyyzG.mjs +0 -199
  125. package/dist/args-CVDbyyzG.mjs.map +0 -1
  126. package/dist/chunk-y_GBKt04.mjs +0 -5
  127. package/dist/completion.d.mts +0 -64
  128. package/dist/completion.d.mts.map +0 -1
  129. package/dist/completion.mjs.map +0 -1
  130. package/dist/formatter-ClUK5hcQ.d.mts.map +0 -1
  131. package/dist/help-CcBe91bV.mjs +0 -1254
  132. package/dist/help-CcBe91bV.mjs.map +0 -1
  133. package/dist/types-DjIdJN5G.d.mts +0 -1059
  134. package/dist/types-DjIdJN5G.d.mts.map +0 -1
  135. package/dist/update-check-EbNDkzyV.mjs.map +0 -1
  136. package/src/args.ts +0 -461
  137. package/src/colorizer.ts +0 -41
  138. package/src/command-utils.ts +0 -532
  139. package/src/create.ts +0 -1477
  140. package/src/types.ts +0 -1109
  141. package/src/utils.ts +0 -140
package/CHANGELOG.md CHANGED
@@ -1,5 +1,120 @@
1
1
  # padrone
2
2
 
3
+ ## 1.6.0
4
+
5
+ ### Minor Changes
6
+
7
+ - [`75066f9`](https://github.com/KurtGokhan/padrone/commit/75066f9e12c33a1f64c502e248fce4d4e455d0da) Thanks [@KurtGokhan](https://github.com/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.
8
+
9
+ - [`93ab85c`](https://github.com/KurtGokhan/padrone/commit/93ab85c88441e9062b2402f7d97f3d337293f2e7) Thanks [@KurtGokhan](https://github.com/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.
10
+
11
+ - [`3b7fed0`](https://github.com/KurtGokhan/padrone/commit/3b7fed06d15cc2acad04df7d919ce0f6c9b66207) Thanks [@KurtGokhan](https://github.com/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.
12
+
13
+ - [`067b9f7`](https://github.com/KurtGokhan/padrone/commit/067b9f7d695a838f0c39204c563029f8a2527675) Thanks [@KurtGokhan](https://github.com/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 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 } })`.
14
+
15
+ - [`4e7f88b`](https://github.com/KurtGokhan/padrone/commit/4e7f88bdc68b7c97f36e3546142b6ebf5f87f76e) Thanks [@KurtGokhan](https://github.com/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.
16
+
17
+ - [`aa0b568`](https://github.com/KurtGokhan/padrone/commit/aa0b568f35c2fcb97a78abf077561a914606de6f) Thanks [@KurtGokhan](https://github.com/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.
18
+
19
+ - [`91fd814`](https://github.com/KurtGokhan/padrone/commit/91fd8146c0fff0eb8c4e5f46191d1a6bf8203ecf) Thanks [@KurtGokhan](https://github.com/KurtGokhan)! - Add `padroneLogger()` and `padroneTiming()` extensions for structured logging and command execution timing.
20
+
21
+ - [`99c8cfa`](https://github.com/KurtGokhan/padrone/commit/99c8cfa298194d9632b9c784858c1695e7782acf) Thanks [@KurtGokhan](https://github.com/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()`.
22
+
23
+ - [`88c45af`](https://github.com/KurtGokhan/padrone/commit/88c45afeef123d4a3e5d5e4d359e080ddf60a154) Thanks [@KurtGokhan](https://github.com/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.
24
+
25
+ - [`8691694`](https://github.com/KurtGokhan/padrone/commit/86916947b189109e6647684d30dc06992a3909b5) Thanks [@KurtGokhan](https://github.com/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`.
26
+
27
+ - [`4343f78`](https://github.com/KurtGokhan/padrone/commit/4343f7857b6685c8e1774b4d933846cd786fe828) Thanks [@KurtGokhan](https://github.com/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.
28
+
29
+ - [`7464026`](https://github.com/KurtGokhan/padrone/commit/746402615e11262a0ff7257f41a4840c3a54143e) Thanks [@KurtGokhan](https://github.com/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.
30
+
31
+ - [`be62401`](https://github.com/KurtGokhan/padrone/commit/be624016ee6e4852ab043b15b4d525431319a168) Thanks [@KurtGokhan](https://github.com/KurtGokhan)! - Add experimental `padroneTracing()` extension for OpenTelemetry tracing. Logger automatically bridges log calls to span events when tracing is active.
32
+
33
+ ### Patch Changes
34
+
35
+ - [`dbac7ec`](https://github.com/KurtGokhan/padrone/commit/dbac7ec56a9f0c320550eef2f6b188a3741d1d4e) Thanks [@KurtGokhan](https://github.com/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.
36
+
37
+ - [`0dfae77`](https://github.com/KurtGokhan/padrone/commit/0dfae774d264d4cab092b90bb779dd3da46abaef) Thanks [@KurtGokhan](https://github.com/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.
38
+
39
+ ## 1.5.0
40
+
41
+ ### Minor Changes
42
+
43
+ - [`ef5e829`](https://github.com/KurtGokhan/padrone/commit/ef5e82931c06bbce70b6cdf3e34c179a48d04c66) Thanks [@KurtGokhan](https://github.com/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.
44
+
45
+ - [`bbb05d9`](https://github.com/KurtGokhan/padrone/commit/bbb05d9dcf4b360d7f5ae85bdd4fa6e45b68b64d) Thanks [@KurtGokhan](https://github.com/KurtGokhan)! - Add `examples` configuration to options and commands for command-line usage examples.
46
+
47
+ - [`7ff2738`](https://github.com/KurtGokhan/padrone/commit/7ff2738c146c419f4f03315ec8182af5be31d1b0) Thanks [@KurtGokhan](https://github.com/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".
48
+
49
+ - [`369ebba`](https://github.com/KurtGokhan/padrone/commit/369ebbab4dc14c1d8acfd2af01a9322f5d964e23) Thanks [@KurtGokhan](https://github.com/KurtGokhan)! - Add `group` configuration to options and commands for organized help output.
50
+
51
+ 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.
52
+
53
+ - [`3d7b282`](https://github.com/KurtGokhan/padrone/commit/3d7b28202890925e05357c9796218349b4a8410e) Thanks [@KurtGokhan](https://github.com/KurtGokhan)! - Add per-field validation during interactive prompts.
54
+
55
+ 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.
56
+
57
+ - [`1843f1f`](https://github.com/KurtGokhan/padrone/commit/1843f1f3a00714d11570c245361ab73c4049aa91) Thanks [@KurtGokhan](https://github.com/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.
58
+
59
+ - [`45ba002`](https://github.com/KurtGokhan/padrone/commit/45ba002db474e34808b64b15ebce59b289f9115b) Thanks [@KurtGokhan](https://github.com/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.
60
+
61
+ - [`ab53491`](https://github.com/KurtGokhan/padrone/commit/ab534915e3bcb5cd1c3f563f4fde740d1b91fa50) Thanks [@KurtGokhan](https://github.com/KurtGokhan)! - **BREAKING:** `eval()`, `cli()`, and `run()` no longer throw errors. Instead, they return a discriminated union with an `error` field:
62
+
63
+ - Success: `{ command, args, argsResult, result, drain() }`
64
+ - Error: `{ error, command?, args?, argsResult?, drain() }`
65
+
66
+ 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:
67
+
68
+ ```ts
69
+ const { value, error } = await program.cli().drain();
70
+ ```
71
+
72
+ New exported types: `PadroneDrainResult<T>`, `Drained<T>`.
73
+
74
+ - [`dffc5cd`](https://github.com/KurtGokhan/padrone/commit/dffc5cd36250f94cc82edae850aa34ae9916d43a) Thanks [@KurtGokhan](https://github.com/KurtGokhan)! - Add progress indicator system for commands with auto-managed spinners and manual control.
75
+
76
+ **Auto-managed progress** via `.progress()` builder method:
77
+
78
+ - `true` or `string` for simple messages, or a full config object with per-state messages
79
+ - Starts before validation, auto-succeeds/fails after execution
80
+ - Validation-phase message transitions to execution-phase message
81
+ - `spinner` option: preset name (`dots`, `line`, `arc`, `bounce`), custom `{ frames, interval }`, or `false` to disable animation
82
+ - `success`/`error` fields accept static strings, `null` to suppress, callbacks `(result) => string | null`, or `{ message, indicator }` objects for per-call icon customization
83
+
84
+ **Manual progress** via `ctx.progress` in action handlers:
85
+
86
+ - Works even without `.progress()` config — lazily creates a real indicator on first use
87
+ - Auto-stopped when execution finishes (no leaked spinners)
88
+ - No-op when the runtime has no progress factory
89
+
90
+ **Built-in terminal spinner** (`createTerminalSpinner`):
91
+
92
+ - ANSI-based spinner with pause/resume for clean output interleaving
93
+ - Customizable success/error indicator icons via `PadroneProgressOptions`
94
+ - Empty string indicators hide the icon prefix entirely
95
+ - Graceful fallback in non-TTY/CI environments
96
+
97
+ **New types**: `PadroneProgressIndicator`, `PadroneProgressConfig`, `PadroneProgressMessage`, `PadroneProgressOptions`, `PadroneSpinnerConfig`, `PadroneSpinnerPreset`
98
+
99
+ - [`6851b48`](https://github.com/KurtGokhan/padrone/commit/6851b4878ab0fc8d48f40e93c2f8924236a40165) Thanks [@KurtGokhan](https://github.com/KurtGokhan)! - Add REST server (`program.serve()`) and `mutation` command config.
100
+
101
+ - New `serve()` program method: exposes commands as HTTP endpoints with automatic OpenAPI docs (Scalar).
102
+ - New `serve` built-in CLI command: `myapp serve --port 3000`.
103
+ - Built-in endpoints: `/_health`, `/_help`, `/_schema`, `/_docs` (Scalar), `/_openapi`.
104
+ - New `mutation` option in `.configure()`: mutation commands are POST-only in serve, set `destructiveHint` in MCP, and default `needsApproval` to true in `tool()`.
105
+ - MCP: rename `endpoint` to `basePath` for consistency with serve.
106
+ - Shared utilities extracted from MCP (`collectEndpoints`, `buildInputSchema`, `serializeArgsToFlags`).
107
+
108
+ ### Patch Changes
109
+
110
+ - [`7e8f14d`](https://github.com/KurtGokhan/padrone/commit/7e8f14ddb628620f94a7c9f2e88f9417577f2b04) Thanks [@KurtGokhan](https://github.com/KurtGokhan)! - Expand boolean auto-coercion to accept `yes`/`no`/`on`/`off` (case-insensitive).
111
+
112
+ - [`a1c7072`](https://github.com/KurtGokhan/padrone/commit/a1c70724829f8cd4fb1632098f352498c87cbf2e) Thanks [@KurtGokhan](https://github.com/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.
113
+
114
+ - [`befc82e`](https://github.com/KurtGokhan/padrone/commit/befc82e39b4a1663c3ace74305dd48f9aded1a09) Thanks [@KurtGokhan](https://github.com/KurtGokhan)! - Add `.catch()` and `.finally()` methods to thenable sync results from `eval()`, `parse()`, and `cli()`
115
+
116
+ - [`81f3bbc`](https://github.com/KurtGokhan/padrone/commit/81f3bbce54940953ff32d76c620eabd6cec7322f) Thanks [@KurtGokhan](https://github.com/KurtGokhan)! - Use `node:child_process` in wrap handler instead of `Bun.spawn` for Node.js compatibility.
117
+
3
118
  ## 1.4.0
4
119
 
5
120
  ### Minor Changes
package/README.md CHANGED
@@ -2,10 +2,8 @@
2
2
  <img src="media/padrone.svg" alt="Padrone Logo" width="200" height="200" />
3
3
  </p>
4
4
 
5
- <!-- <h1 align="center">Padrone</h1> -->
6
-
7
5
  <p align="center">
8
- <strong>Create type-safe, interactive CLI apps with Zod schemas</strong>
6
+ <strong>Type-safe CLI framework powered by Zod schemas</strong>
9
7
  </p>
10
8
 
11
9
  <p align="center">
@@ -16,33 +14,26 @@
16
14
 
17
15
  ---
18
16
 
19
- ## Features
17
+ 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.
20
18
 
21
- - 🔒 **Type-safe** - Full TypeScript support with Zod schema validation
22
- - 🎯 **Fluent API** - Chain commands and arguments with a clean builder pattern
23
- - 🤖 **AI-Ready** - First-class support for Vercel AI SDK tool integration
24
- - 📚 **Auto Help** - Automatic help generation from your schema definitions
25
- - 🧩 **Nested Commands** - Support for deeply nested subcommands
26
- - 🔄 **Standard Schema** - Built on [Standard Schema](https://github.com/standard-schema/standard-schema) for maximum compatibility
27
- - 🚀 **Zero Config** - Works out of the box with sensible defaults
19
+ Built on [Standard Schema](https://github.com/standard-schema/standard-schema), so it also works with Valibot, ArkType, and others.
28
20
 
29
- ## 📦 Installation
21
+ ## Install
30
22
 
31
23
  ```bash
32
- # Using npm
33
24
  npm install padrone zod
25
+ ```
34
26
 
35
- # Using bun
36
- bun add padrone zod
27
+ ## Scaffold a New Project
37
28
 
38
- # Using pnpm
39
- pnpm add padrone zod
29
+ The fastest way to get started is with `padrone init`:
40
30
 
41
- # Using yarn
42
- yarn add padrone zod
31
+ ```bash
32
+ npx padrone init my-cli
33
+ cd my-cli && bun i && bun dev
43
34
  ```
44
35
 
45
- ## 🚀 Quick Start
36
+ ## Quick Start
46
37
 
47
38
  ```typescript
48
39
  import { createPadrone } from 'padrone';
@@ -54,320 +45,154 @@ const program = createPadrone('myapp')
54
45
  .arguments(
55
46
  z.object({
56
47
  names: z.array(z.string()).describe('Names to greet'),
57
- prefix: z
58
- .string()
59
- .optional()
60
- .describe('Prefix to use in greeting')
61
- .meta({ alias: 'p' }),
48
+ prefix: z.string().optional().describe('Prefix').meta({ flags: 'p' }),
62
49
  }),
63
50
  { positional: ['...names'] },
64
51
  )
65
52
  .action((args) => {
66
- const prefix = args?.prefix ? `${args.prefix} ` : '';
67
- args.names.forEach((name) => {
68
- console.log(`Hello, ${prefix}${name}!`);
69
- });
53
+ for (const name of args.names) {
54
+ console.log(`Hello, ${args.prefix ?? ''} ${name}!`);
55
+ }
70
56
  }),
71
57
  );
72
58
 
73
- // Run from CLI arguments
74
59
  program.cli();
75
60
  ```
76
61
 
77
- ### Running your CLI
78
-
79
62
  ```bash
80
- # Run with arguments
81
- myapp greet John Jane --prefix Mr.
82
-
83
- # Or with alias
84
63
  myapp greet John Jane -p Mr.
64
+ # Hello, Mr. John!
65
+ # Hello, Mr. Jane!
85
66
  ```
86
67
 
87
- Output:
88
- ```
89
- Hello, Mr. John!
90
- Hello, Mr. Jane!
91
- ```
92
-
93
- ## 📖 Usage Examples
94
-
95
- ### Programmatic Execution
96
-
97
- ```typescript
98
- // Run a command directly with typed arguments
99
- program.run('greet', { names: ['John', 'Jane'], prefix: 'Dr.' });
100
-
101
- // Parse CLI input without executing
102
- const parsed = program.parse('greet John --prefix Mr.');
103
- console.log(parsed.args); // { names: ['John'], prefix: 'Mr.' }
104
- ```
105
-
106
- ### API Mode
107
-
108
- Generate a typed API from your CLI program:
109
-
110
- ```typescript
111
- const api = program.api();
112
-
113
- // Call commands as functions with full type safety
114
- api.greet({ names: ['Alice', 'Bob'], prefix: 'Dr.' });
115
- ```
116
-
117
- ### Nested Commands
118
-
119
- ```typescript
120
- const program = createPadrone('weather')
121
- .command('forecast', (c) =>
122
- c
123
- .arguments(
124
- z.object({
125
- city: z.string().describe('City name'),
126
- days: z.number().optional().default(3).describe('Number of days'),
127
- }),
128
- { positional: ['city'] },
129
- )
130
- .action((args) => {
131
- console.log(`Forecast for ${args.city}: ${args.days} days`);
132
- })
133
- .command('extended', (c) =>
134
- c
135
- .arguments(
136
- z.object({
137
- city: z.string().describe('City name'),
138
- }),
139
- { positional: ['city'] },
140
- )
141
- .action((args) => {
142
- console.log(`Extended forecast for ${args.city}`);
143
- }),
144
- ),
145
- );
146
-
147
- // Run nested command
148
- program.eval('forecast extended London');
149
- ```
150
-
151
- ### Option Aliases and Metadata
68
+ ## What It Does
152
69
 
153
70
  ```typescript
154
- const program = createPadrone('app')
155
- .command('serve', (c) =>
156
- c
157
- .arguments(
158
- z.object({
159
- port: z
160
- .number()
161
- .default(3000)
162
- .describe('Port to listen on')
163
- .meta({ alias: 'p', examples: ['3000', '8080'] }),
164
- host: z
165
- .string()
166
- .default('localhost')
167
- .describe('Host to bind to')
168
- .meta({ alias: 'h' }),
169
- verbose: z
170
- .boolean()
171
- .optional()
172
- .describe('Enable verbose logging')
173
- .meta({ alias: 'v', deprecated: 'Use --debug instead' }),
174
- }),
175
- )
176
- .action((args) => {
177
- console.log(`Server running at ${args.host}:${args.port}`);
178
- }),
179
- );
180
- ```
71
+ // Multiple ways to run commands
72
+ program.cli(); // from process.argv
73
+ program.eval('greet John --prefix Mr.'); // from a string
74
+ program.run('greet', { names: ['John'], prefix: 'Mr.' }); // typed args
75
+ program.api().greet({ names: ['John'], prefix: 'Mr.' }); // as a function
181
76
 
182
- ### Environment Variables and Config Files
183
-
184
- Padrone supports loading arguments from environment variables and config files using dedicated schema methods:
185
-
186
- ```typescript
187
- const program = createPadrone('app')
188
- .command('serve', (c) =>
189
- c
190
- .arguments(
191
- z.object({
192
- port: z.number().default(3000).describe('Port to listen on'),
193
- apiKey: z.string().describe('API key for authentication'),
194
- }),
195
- )
196
- // Map environment variables to arguments
197
- .env(
198
- z
199
- .object({
200
- APP_PORT: z.coerce.number().optional(),
201
- API_KEY: z.string().optional(),
202
- })
203
- .transform((env) => ({
204
- port: env.APP_PORT,
205
- apiKey: env.API_KEY,
206
- })),
207
- )
208
- // Load config from JSON file with matching schema
209
- .configFile(
210
- 'app.config.json',
211
- z.object({
212
- port: z.number().optional(),
213
- apiKey: z.string().optional(),
214
- }),
215
- )
216
- .action((args) => {
217
- console.log(`Server running on port ${args.port}`);
218
- }),
219
- );
220
- ```
77
+ // Parse without executing
78
+ const { args } = program.parse('greet John --prefix Mr.');
221
79
 
222
- **Precedence order** (highest to lowest): CLI args > environment variables > config file
80
+ // Interactive REPL
81
+ for await (const result of program.repl()) { /* ... */ }
223
82
 
224
- ### Async Validation
83
+ // AI tool for Vercel AI SDK
84
+ const tool = program.tool();
225
85
 
226
- If your schema uses async refinements (e.g. `z.check(async ...)`), mark the command as async so that `parse()` and `cli()` return Promises:
86
+ // MCP server for AI assistants (Claude, Cursor, etc.) [experimental]
87
+ await program.mcp(); // or: myapp mcp
227
88
 
228
- ```typescript
229
- import { asyncSchema, createPadrone } from 'padrone';
89
+ // REST server with OpenAPI docs [experimental]
90
+ await program.serve(); // or: myapp serve
230
91
 
231
- const program = createPadrone('app')
232
- .command('create', (c) =>
233
- c
234
- // Option 1: brand the schema with asyncSchema()
235
- .arguments(asyncSchema(z.object({ name: z.string() }).check(async (ctx) => { /* ... */ })))
236
- // Option 2: call .async() on the builder
237
- .async()
238
- .action((args) => args.name),
239
- );
92
+ // Shell completions
93
+ const script = program.completion('zsh');
240
94
 
241
- // parse() and cli() now return Promises
242
- const result = await program.parse('create --name test');
95
+ // Help in multiple formats
96
+ program.help('greet'); // text
97
+ program.help('greet', { format: 'json' }); // json, markdown, html, ansi
243
98
  ```
244
99
 
245
- ## 🤖 AI SDK Integration
246
-
247
- Padrone provides first-class support for the [Vercel AI SDK](https://ai-sdk.dev/), making it easy to expose your CLI as an AI tool:
248
-
249
- ```typescript
250
- import { streamText } from 'ai';
251
- import { createPadrone } from 'padrone';
252
- import * as z from 'zod/v4';
253
-
254
- const weatherCli = createPadrone('weather')
255
- .command('current', (c) =>
256
- c
257
- .arguments(
258
- z.object({
259
- city: z.string().describe('City name'),
260
- }),
261
- { positional: ['city'] },
262
- )
263
- .action((args) => {
264
- return { city: args.city, temperature: 72, condition: 'Sunny' };
265
- }),
266
- );
267
-
268
- // Convert your CLI to an AI tool
269
- const result = await streamText({
270
- model: yourModel,
271
- prompt: "What's the weather in London?",
272
- tools: {
273
- weather: weatherCli.tool(),
274
- },
275
- });
276
- ```
100
+ ## Features at a Glance
277
101
 
278
- ## 📋 Auto-Generated Help
102
+ **Arguments** positional args, variadic args, short flags (`-v`), long aliases (`--dry-run`), auto kebab-case aliases, negatable booleans (`--no-verbose`).
279
103
 
280
- Padrone automatically generates help text from your Zod schemas:
104
+ **Env & Config** load from environment variables with `.extend(padroneEnv(schema))` and config files with `.extend(padroneConfig({ files, schema }))`. Precedence: CLI > stdin > env > config > defaults.
281
105
 
282
- ```typescript
283
- console.log(program.help());
284
- ```
106
+ **Interactive prompts** — auto-prompt for missing fields. Booleans become confirm, enums become select, arrays become multi-select.
285
107
 
286
- Example output:
287
- ```
288
- Usage: myapp greet [names...] [arguments]
108
+ **Progress indicators** — auto-managed spinners and progress bars with elapsed time and ETA. `.extend(padroneProgress({ message: 'Deploying...', bar: true, time: true, eta: true }))`.
289
109
 
290
- Positionals:
291
- names... Names to greet
110
+ **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.
292
111
 
293
- Arguments:
294
- -p, --prefix <string> Prefix to use in greeting
295
- -h, --help Show help
296
- ```
112
+ **Interceptors** — middleware hooks for 6 phases (start, parse, validate, execute, error, shutdown). Onion model with `next()`. Extensions register interceptors under the hood. Create your own with `defineInterceptor()`.
297
113
 
298
- ## 🔧 API Reference
114
+ **Composition** mount programs as subcommands with `.mount()`, override commands with merge semantics.
299
115
 
300
- ### `createPadrone(name)`
116
+ **Wrapping** *(experimental)* — wrap external CLI tools with `.wrap({ command: 'git', args: ['commit'] })`.
301
117
 
302
- Creates a new CLI program with the given name.
118
+ ## API
303
119
 
304
- ### Program Methods
120
+ ### Builder (define commands)
305
121
 
306
- | Method | Description |
122
+ | Method | What it does |
123
+ |--------|-------------|
124
+ | `.arguments(schema, meta?)` | Define args with Zod schema, positional config, field metadata |
125
+ | `.action(handler)` | Set handler `(args, ctx, base?) => result` |
126
+ | `.command(name, builder)` | Add subcommand (name or `[name, ...aliases]`) |
127
+ | `.context(transform?)` | Define typed context or transform inherited context |
128
+ | `.mount(name, program, options?)` | Mount another program as subcommand tree |
129
+ | `.configure(config)` | Set title, description, version, etc. |
130
+ | `.extend(padroneEnv(schema))` | Map env vars to args (composable extension) |
131
+ | `.extend(padroneConfig({ files, schema }))` | Load args from config files (composable extension) |
132
+ | `.wrap(config)` | Wrap an external CLI tool *(experimental)* |
133
+ | `.extend(padroneProgress(config?))` | Auto-managed progress indicator (extension) |
134
+ | `.intercept(interceptor)` | Register middleware interceptor (use `defineInterceptor()`) |
135
+ | `.extend(extension)` | Apply a build-time extension (bundle of config, commands, interceptors) |
136
+ | `.runtime(runtime)` | Custom I/O (for non-terminal use) |
137
+ | `.updateCheck(config?)` | Background version check |
138
+ | `.async()` | Mark as async validation |
139
+
140
+ ### Program (run commands)
141
+
142
+ | Method | What it does |
307
143
  |--------|-------------|
308
- | `.configure(config)` | Configure program properties (title, description, version) |
309
- | `.command(name, builder)` | Add a command to the program |
310
- | `.arguments(schema, meta?)` | Define arguments schema with optional positional args |
311
- | `.async()` | Mark command as async (for schemas with async validation) |
312
- | `.env(schema)` | Define schema for parsing environment variables into arguments |
313
- | `.configFile(file, schema?)` | Configure config file path(s) and schema |
314
- | `.action(handler)` | Set the command handler function |
315
- | `.cli(input?)` | Run as CLI (parses `process.argv` or input string) |
316
- | `.run(command, args?)` | Run a command programmatically |
317
- | `.parse(input?)` | Parse input without executing |
318
- | `.stringify(command?, args?)` | Convert command and arguments back to CLI string |
319
- | `.api()` | Generate a typed API object |
320
- | `.help(command?)` | Generate help text |
321
- | `.tool()` | Generate a Vercel AI SDK tool |
322
- | `.find(command)` | Find a command by name |
323
-
324
- ### Arguments Meta
325
-
326
- Use the second argument of `.arguments()` to configure positional arguments and per-argument metadata:
144
+ | `.cli(prefs?)` | Entry point parses `process.argv`, throws on errors. Pass `context` in prefs. |
145
+ | `.eval(input, prefs?)` | Parse + validate + execute string, returns errors softly. Pass `context` in prefs. |
146
+ | `.run(command, args, prefs?)` | Run by name with typed args (no validation). Pass `context` in prefs. |
147
+ | `.parse(input?)` | Parse without executing |
148
+ | `.api()` | Generate typed function API |
149
+ | `.repl(options?)` | Interactive REPL session |
150
+ | `.help(command?, prefs?)` | Generate help (text, ansi, markdown, html, json) |
151
+ | `.tool()` | Vercel AI SDK tool definition |
152
+ | `.mcp(prefs?)` | Start MCP server (HTTP or stdio) *(experimental)* |
153
+ | `.serve(prefs?)` | Start REST server with OpenAPI docs *(experimental)* |
154
+ | `.completion(shell?)` | Shell completion script |
155
+ | `.find(command)` | Look up command by path |
156
+ | `.stringify(command?, args?)` | Convert back to CLI string |
157
+
158
+ ### Zod `.meta()` fields
159
+
160
+ | Field | Example | Purpose |
161
+ |-------|---------|---------|
162
+ | `flags` | `'v'` | Single-char short flag (`-v`) |
163
+ | `alias` | `'dry-run'` | Multi-char long alias (`--dry-run`) |
164
+ | `examples` | `['8080']` | Example values in help |
165
+ | `deprecated` | `'Use --debug'` | Deprecation warning |
166
+ | `hidden` | `true` | Hide from help |
167
+ | `group` | `'Advanced'` | Group in help output |
168
+
169
+ ### Arguments meta (second param of `.arguments()`)
327
170
 
328
171
  ```typescript
329
172
  .arguments(schema, {
330
- positional: ['source', '...files', 'dest'], // '...files' is variadic
331
- fields: {
332
- verbose: { alias: 'v' },
333
- format: { deprecated: 'Use --output instead' },
334
- },
173
+ positional: ['source', '...files', 'dest'],
174
+ interactive: ['name', 'template'],
175
+ optionalInteractive: ['typescript'],
176
+ fields: { verbose: { flags: 'v' } },
177
+ stdin: 'data',
178
+ autoAlias: true, // default
335
179
  })
336
180
  ```
337
181
 
338
- ### Zod Metadata
182
+ ## Agent Skill
339
183
 
340
- Use `.meta()` on Zod schemas to provide additional CLI metadata:
341
-
342
- ```typescript
343
- z.string().meta({
344
- alias: 'p', // Short alias (-p)
345
- examples: ['value'], // Example values for help text
346
- deprecated: 'message', // Mark as deprecated
347
- hidden: true, // Hide from help output
348
- })
349
- ```
350
-
351
- ## 🤖 AI Coding Agent Skill
352
-
353
- Install the [Padrone skill](https://agentskills.io) to give your AI coding agent (Claude Code, etc.) knowledge of the Padrone API:
184
+ Give your AI coding agent knowledge of the Padrone API:
354
185
 
355
186
  ```bash
356
187
  npx skills add KurtGokhan/padrone
357
188
  ```
358
189
 
359
- ## 🛠️ Requirements
190
+ ## Requirements
360
191
 
361
192
  - Node.js 18+ or Bun
362
193
  - TypeScript 5.0+ (recommended)
363
- - Zod 3.25+ or 4.x
194
+ - Zod (or any Standard Schema-compatible library)
364
195
 
365
- ## 📄 License
196
+ ## License
366
197
 
367
- [MIT](LICENSE) © [Gokhan Kurt](https://gkurt.com)
368
-
369
- ---
370
-
371
- <p align="center">
372
- Made with ❤️ by <a href="https://gkurt.com">Gokhan Kurt</a>
373
- </p>
198
+ [MIT](LICENSE)