padrone 1.3.0 → 1.5.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.
- package/CHANGELOG.md +94 -0
- package/README.md +105 -284
- package/dist/{args-DFEI7_G_.mjs → args-D5PNDyNu.mjs} +46 -21
- package/dist/args-D5PNDyNu.mjs.map +1 -0
- package/dist/chunk-CjcI7cDX.mjs +15 -0
- package/dist/codegen/index.d.mts +28 -3
- package/dist/codegen/index.d.mts.map +1 -1
- package/dist/codegen/index.mjs +169 -19
- package/dist/codegen/index.mjs.map +1 -1
- package/dist/command-utils-B1D-HqCd.mjs +1117 -0
- package/dist/command-utils-B1D-HqCd.mjs.map +1 -0
- package/dist/completion.d.mts +1 -1
- package/dist/completion.d.mts.map +1 -1
- package/dist/completion.mjs +77 -29
- package/dist/completion.mjs.map +1 -1
- package/dist/docs/index.d.mts +22 -2
- package/dist/docs/index.d.mts.map +1 -1
- package/dist/docs/index.mjs +94 -7
- package/dist/docs/index.mjs.map +1 -1
- package/dist/errors-BiVrBgi6.mjs +114 -0
- package/dist/errors-BiVrBgi6.mjs.map +1 -0
- package/dist/{formatter-XroimS3Q.d.mts → formatter-DtHzbP22.d.mts} +35 -5
- package/dist/formatter-DtHzbP22.d.mts.map +1 -0
- package/dist/help-bbmu9-qd.mjs +735 -0
- package/dist/help-bbmu9-qd.mjs.map +1 -0
- package/dist/index.d.mts +32 -3
- package/dist/index.d.mts.map +1 -1
- package/dist/index.mjs +495 -267
- package/dist/index.mjs.map +1 -1
- package/dist/mcp-mLWIdUIu.mjs +379 -0
- package/dist/mcp-mLWIdUIu.mjs.map +1 -0
- package/dist/serve-B0u43DK7.mjs +404 -0
- package/dist/serve-B0u43DK7.mjs.map +1 -0
- package/dist/stream-BcC146Ud.mjs +56 -0
- package/dist/stream-BcC146Ud.mjs.map +1 -0
- package/dist/test.d.mts +1 -1
- package/dist/test.mjs +4 -15
- package/dist/test.mjs.map +1 -1
- package/dist/{types-BS7RP5Ls.d.mts → types-Ch8Mk6Qb.d.mts} +311 -63
- package/dist/types-Ch8Mk6Qb.d.mts.map +1 -0
- package/dist/{update-check-EbNDkzyV.mjs → update-check-CFX1FV3v.mjs} +2 -2
- package/dist/{update-check-EbNDkzyV.mjs.map → update-check-CFX1FV3v.mjs.map} +1 -1
- package/dist/zod.d.mts +32 -0
- package/dist/zod.d.mts.map +1 -0
- package/dist/zod.mjs +50 -0
- package/dist/zod.mjs.map +1 -0
- package/package.json +10 -2
- package/src/args.ts +76 -44
- package/src/cli/docs.ts +1 -7
- package/src/cli/doctor.ts +195 -10
- package/src/cli/index.ts +1 -1
- package/src/cli/init.ts +2 -3
- package/src/cli/link.ts +2 -2
- package/src/codegen/discovery.ts +80 -28
- package/src/codegen/index.ts +2 -1
- package/src/codegen/parsers/bash.ts +179 -0
- package/src/codegen/schema-to-code.ts +2 -1
- package/src/colorizer.ts +126 -13
- package/src/command-utils.ts +401 -23
- package/src/completion.ts +120 -47
- package/src/create.ts +483 -130
- package/src/docs/index.ts +122 -8
- package/src/formatter.ts +173 -125
- package/src/help.ts +46 -12
- package/src/index.ts +29 -1
- package/src/interactive.ts +45 -4
- package/src/mcp.ts +390 -0
- package/src/repl-loop.ts +16 -3
- package/src/runtime.ts +195 -2
- package/src/serve.ts +442 -0
- package/src/stream.ts +75 -0
- package/src/test.ts +7 -16
- package/src/type-utils.ts +28 -4
- package/src/types.ts +212 -30
- package/src/wrap.ts +23 -25
- package/src/zod.ts +50 -0
- package/dist/args-DFEI7_G_.mjs.map +0 -1
- package/dist/chunk-y_GBKt04.mjs +0 -5
- package/dist/formatter-XroimS3Q.d.mts.map +0 -1
- package/dist/help-CgGP7hQU.mjs +0 -1229
- package/dist/help-CgGP7hQU.mjs.map +0 -1
- package/dist/types-BS7RP5Ls.d.mts.map +0 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,99 @@
|
|
|
1
1
|
# padrone
|
|
2
2
|
|
|
3
|
+
## 1.5.0
|
|
4
|
+
|
|
5
|
+
### Minor Changes
|
|
6
|
+
|
|
7
|
+
- [`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.
|
|
8
|
+
|
|
9
|
+
- [`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.
|
|
10
|
+
|
|
11
|
+
- [`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".
|
|
12
|
+
|
|
13
|
+
- [`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.
|
|
14
|
+
|
|
15
|
+
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.
|
|
16
|
+
|
|
17
|
+
- [`3d7b282`](https://github.com/KurtGokhan/padrone/commit/3d7b28202890925e05357c9796218349b4a8410e) Thanks [@KurtGokhan](https://github.com/KurtGokhan)! - Add per-field validation during interactive prompts.
|
|
18
|
+
|
|
19
|
+
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.
|
|
20
|
+
|
|
21
|
+
- [`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.
|
|
22
|
+
|
|
23
|
+
- [`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.
|
|
24
|
+
|
|
25
|
+
- [`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:
|
|
26
|
+
|
|
27
|
+
- Success: `{ command, args, argsResult, result, drain() }`
|
|
28
|
+
- Error: `{ error, command?, args?, argsResult?, drain() }`
|
|
29
|
+
|
|
30
|
+
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:
|
|
31
|
+
|
|
32
|
+
```ts
|
|
33
|
+
const { value, error } = await program.cli().drain();
|
|
34
|
+
```
|
|
35
|
+
|
|
36
|
+
New exported types: `PadroneDrainResult<T>`, `Drained<T>`.
|
|
37
|
+
|
|
38
|
+
- [`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.
|
|
39
|
+
|
|
40
|
+
**Auto-managed progress** via `.progress()` builder method:
|
|
41
|
+
|
|
42
|
+
- `true` or `string` for simple messages, or a full config object with per-state messages
|
|
43
|
+
- Starts before validation, auto-succeeds/fails after execution
|
|
44
|
+
- Validation-phase message transitions to execution-phase message
|
|
45
|
+
- `spinner` option: preset name (`dots`, `line`, `arc`, `bounce`), custom `{ frames, interval }`, or `false` to disable animation
|
|
46
|
+
- `success`/`error` fields accept static strings, `null` to suppress, callbacks `(result) => string | null`, or `{ message, indicator }` objects for per-call icon customization
|
|
47
|
+
|
|
48
|
+
**Manual progress** via `ctx.progress` in action handlers:
|
|
49
|
+
|
|
50
|
+
- Works even without `.progress()` config — lazily creates a real indicator on first use
|
|
51
|
+
- Auto-stopped when execution finishes (no leaked spinners)
|
|
52
|
+
- No-op when the runtime has no progress factory
|
|
53
|
+
|
|
54
|
+
**Built-in terminal spinner** (`createTerminalSpinner`):
|
|
55
|
+
|
|
56
|
+
- ANSI-based spinner with pause/resume for clean output interleaving
|
|
57
|
+
- Customizable success/error indicator icons via `PadroneProgressOptions`
|
|
58
|
+
- Empty string indicators hide the icon prefix entirely
|
|
59
|
+
- Graceful fallback in non-TTY/CI environments
|
|
60
|
+
|
|
61
|
+
**New types**: `PadroneProgressIndicator`, `PadroneProgressConfig`, `PadroneProgressMessage`, `PadroneProgressOptions`, `PadroneSpinnerConfig`, `PadroneSpinnerPreset`
|
|
62
|
+
|
|
63
|
+
- [`6851b48`](https://github.com/KurtGokhan/padrone/commit/6851b4878ab0fc8d48f40e93c2f8924236a40165) Thanks [@KurtGokhan](https://github.com/KurtGokhan)! - Add REST server (`program.serve()`) and `mutation` command config.
|
|
64
|
+
|
|
65
|
+
- New `serve()` program method: exposes commands as HTTP endpoints with automatic OpenAPI docs (Scalar).
|
|
66
|
+
- New `serve` built-in CLI command: `myapp serve --port 3000`.
|
|
67
|
+
- Built-in endpoints: `/_health`, `/_help`, `/_schema`, `/_docs` (Scalar), `/_openapi`.
|
|
68
|
+
- New `mutation` option in `.configure()`: mutation commands are POST-only in serve, set `destructiveHint` in MCP, and default `needsApproval` to true in `tool()`.
|
|
69
|
+
- MCP: rename `endpoint` to `basePath` for consistency with serve.
|
|
70
|
+
- Shared utilities extracted from MCP (`collectEndpoints`, `buildInputSchema`, `serializeArgsToFlags`).
|
|
71
|
+
|
|
72
|
+
### Patch Changes
|
|
73
|
+
|
|
74
|
+
- [`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).
|
|
75
|
+
|
|
76
|
+
- [`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.
|
|
77
|
+
|
|
78
|
+
- [`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()`
|
|
79
|
+
|
|
80
|
+
- [`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.
|
|
81
|
+
|
|
82
|
+
## 1.4.0
|
|
83
|
+
|
|
84
|
+
### Minor Changes
|
|
85
|
+
|
|
86
|
+
- 365ad1f: Fix positional arguments and make results always thenable
|
|
87
|
+
|
|
88
|
+
- Show choices and default values in help output for positional arguments
|
|
89
|
+
- Fix type detection for optional array enum positionals (`z.array(z.enum([...])).optional()`)
|
|
90
|
+
- Coerce single values to arrays when schema expects an array type
|
|
91
|
+
- Make `cli()`, `eval()`, and `parse()` results always thenable (supports `.then()` and `await`)
|
|
92
|
+
|
|
93
|
+
### Patch Changes
|
|
94
|
+
|
|
95
|
+
- 79f51ae: Fix false async warning when action is async but validation is sync
|
|
96
|
+
|
|
3
97
|
## 1.3.0
|
|
4
98
|
|
|
5
99
|
### 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>
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
##
|
|
21
|
+
## Install
|
|
30
22
|
|
|
31
23
|
```bash
|
|
32
|
-
# Using npm
|
|
33
24
|
npm install padrone zod
|
|
25
|
+
```
|
|
34
26
|
|
|
35
|
-
|
|
36
|
-
bun add padrone zod
|
|
27
|
+
## Scaffold a New Project
|
|
37
28
|
|
|
38
|
-
|
|
39
|
-
pnpm add padrone zod
|
|
29
|
+
The fastest way to get started is with `padrone init`:
|
|
40
30
|
|
|
41
|
-
|
|
42
|
-
|
|
31
|
+
```bash
|
|
32
|
+
npx padrone init my-cli
|
|
33
|
+
cd my-cli && bun i && bun dev
|
|
43
34
|
```
|
|
44
35
|
|
|
45
|
-
##
|
|
36
|
+
## Quick Start
|
|
46
37
|
|
|
47
38
|
```typescript
|
|
48
39
|
import { createPadrone } from 'padrone';
|
|
@@ -54,320 +45,150 @@ 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
|
|
67
|
-
|
|
68
|
-
|
|
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
|
-
|
|
88
|
-
```
|
|
89
|
-
Hello, Mr. John!
|
|
90
|
-
Hello, Mr. Jane!
|
|
91
|
-
```
|
|
92
|
-
|
|
93
|
-
## 📖 Usage Examples
|
|
94
|
-
|
|
95
|
-
### Programmatic Execution
|
|
68
|
+
## What It Does
|
|
96
69
|
|
|
97
70
|
```typescript
|
|
98
|
-
//
|
|
99
|
-
program.
|
|
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
|
|
100
76
|
|
|
101
|
-
// Parse
|
|
102
|
-
const
|
|
103
|
-
console.log(parsed.args); // { names: ['John'], prefix: 'Mr.' }
|
|
104
|
-
```
|
|
105
|
-
|
|
106
|
-
### API Mode
|
|
77
|
+
// Parse without executing
|
|
78
|
+
const { args } = program.parse('greet John --prefix Mr.');
|
|
107
79
|
|
|
108
|
-
|
|
80
|
+
// Interactive REPL
|
|
81
|
+
for await (const result of program.repl()) { /* ... */ }
|
|
109
82
|
|
|
110
|
-
|
|
111
|
-
const
|
|
83
|
+
// AI tool for Vercel AI SDK
|
|
84
|
+
const tool = program.tool();
|
|
112
85
|
|
|
113
|
-
//
|
|
114
|
-
|
|
115
|
-
```
|
|
86
|
+
// MCP server for AI assistants (Claude, Cursor, etc.) [experimental]
|
|
87
|
+
await program.mcp(); // or: myapp mcp
|
|
116
88
|
|
|
117
|
-
|
|
89
|
+
// REST server with OpenAPI docs [experimental]
|
|
90
|
+
await program.serve(); // or: myapp serve
|
|
118
91
|
|
|
119
|
-
|
|
120
|
-
const
|
|
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
|
-
);
|
|
92
|
+
// Shell completions
|
|
93
|
+
const script = program.completion('zsh');
|
|
146
94
|
|
|
147
|
-
//
|
|
148
|
-
program.
|
|
95
|
+
// Help in multiple formats
|
|
96
|
+
program.help('greet'); // text
|
|
97
|
+
program.help('greet', { format: 'json' }); // json, markdown, html, ansi
|
|
149
98
|
```
|
|
150
99
|
|
|
151
|
-
|
|
100
|
+
## Features at a Glance
|
|
152
101
|
|
|
153
|
-
|
|
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
|
-
```
|
|
102
|
+
**Arguments** — positional args, variadic args, short flags (`-v`), long aliases (`--dry-run`), auto kebab-case aliases, negatable booleans (`--no-verbose`).
|
|
181
103
|
|
|
182
|
-
|
|
104
|
+
**Env & Config** — load from environment variables with `.env()` and config files with `.configFile()`. Precedence: CLI > stdin > env > config > defaults.
|
|
183
105
|
|
|
184
|
-
|
|
106
|
+
**Interactive prompts** — auto-prompt for missing fields. Booleans become confirm, enums become select, arrays become multi-select.
|
|
185
107
|
|
|
186
|
-
|
|
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
|
-
```
|
|
108
|
+
**Progress indicators** — auto-managed spinners with dynamic messages. `.progress({ progress: 'Deploying...', success: (r) => \`v${r.version}\` })`.
|
|
221
109
|
|
|
222
|
-
**
|
|
110
|
+
**Plugins** — middleware hooks for 6 phases (start, parse, validate, execute, error, shutdown). Onion model with `next()`.
|
|
223
111
|
|
|
224
|
-
|
|
112
|
+
**Composition** — mount programs as subcommands with `.mount()`, override commands with merge semantics.
|
|
225
113
|
|
|
226
|
-
|
|
114
|
+
**Wrapping** *(experimental)* — wrap external CLI tools with `.wrap({ command: 'git', args: ['commit'] })`.
|
|
227
115
|
|
|
228
|
-
|
|
229
|
-
import { asyncSchema, createPadrone } from 'padrone';
|
|
116
|
+
## API
|
|
230
117
|
|
|
231
|
-
|
|
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
|
-
);
|
|
240
|
-
|
|
241
|
-
// parse() and cli() now return Promises
|
|
242
|
-
const result = await program.parse('create --name test');
|
|
243
|
-
```
|
|
244
|
-
|
|
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
|
-
```
|
|
277
|
-
|
|
278
|
-
## 📋 Auto-Generated Help
|
|
279
|
-
|
|
280
|
-
Padrone automatically generates help text from your Zod schemas:
|
|
281
|
-
|
|
282
|
-
```typescript
|
|
283
|
-
console.log(program.help());
|
|
284
|
-
```
|
|
285
|
-
|
|
286
|
-
Example output:
|
|
287
|
-
```
|
|
288
|
-
Usage: myapp greet [names...] [arguments]
|
|
289
|
-
|
|
290
|
-
Positionals:
|
|
291
|
-
names... Names to greet
|
|
292
|
-
|
|
293
|
-
Arguments:
|
|
294
|
-
-p, --prefix <string> Prefix to use in greeting
|
|
295
|
-
-h, --help Show help
|
|
296
|
-
```
|
|
297
|
-
|
|
298
|
-
## 🔧 API Reference
|
|
299
|
-
|
|
300
|
-
### `createPadrone(name)`
|
|
118
|
+
### Builder (define commands)
|
|
301
119
|
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
|
120
|
+
| Method | What it does |
|
|
121
|
+
|--------|-------------|
|
|
122
|
+
| `.arguments(schema, meta?)` | Define args with Zod schema, positional config, field metadata |
|
|
123
|
+
| `.action(handler)` | Set handler `(args, ctx, base?) => result` |
|
|
124
|
+
| `.command(name, builder)` | Add subcommand (name or `[name, ...aliases]`) |
|
|
125
|
+
| `.mount(name, program)` | Mount another program as subcommand tree |
|
|
126
|
+
| `.configure(config)` | Set title, description, version, etc. |
|
|
127
|
+
| `.env(schema)` | Map env vars to args |
|
|
128
|
+
| `.configFile(file, schema?)` | Load args from config files |
|
|
129
|
+
| `.wrap(config)` | Wrap an external CLI tool *(experimental)* |
|
|
130
|
+
| `.progress(config?)` | Auto-managed spinner |
|
|
131
|
+
| `.use(plugin)` | Register middleware plugin |
|
|
132
|
+
| `.runtime(runtime)` | Custom I/O (for non-terminal use) |
|
|
133
|
+
| `.updateCheck(config?)` | Background version check |
|
|
134
|
+
| `.async()` | Mark as async validation |
|
|
135
|
+
|
|
136
|
+
### Program (run commands)
|
|
137
|
+
|
|
138
|
+
| Method | What it does |
|
|
307
139
|
|--------|-------------|
|
|
308
|
-
| `.
|
|
309
|
-
| `.
|
|
310
|
-
| `.
|
|
311
|
-
| `.
|
|
312
|
-
| `.
|
|
313
|
-
| `.
|
|
314
|
-
| `.
|
|
315
|
-
| `.
|
|
316
|
-
| `.
|
|
317
|
-
| `.
|
|
318
|
-
| `.
|
|
319
|
-
| `.
|
|
320
|
-
| `.
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
140
|
+
| `.cli(prefs?)` | Entry point — parses `process.argv`, throws on errors |
|
|
141
|
+
| `.eval(input, prefs?)` | Parse + validate + execute string, returns errors softly |
|
|
142
|
+
| `.run(command, args)` | Run by name with typed args (no validation) |
|
|
143
|
+
| `.parse(input?)` | Parse without executing |
|
|
144
|
+
| `.api()` | Generate typed function API |
|
|
145
|
+
| `.repl(options?)` | Interactive REPL session |
|
|
146
|
+
| `.help(command?, prefs?)` | Generate help (text, ansi, markdown, html, json) |
|
|
147
|
+
| `.tool()` | Vercel AI SDK tool definition |
|
|
148
|
+
| `.mcp(prefs?)` | Start MCP server (HTTP or stdio) *(experimental)* |
|
|
149
|
+
| `.serve(prefs?)` | Start REST server with OpenAPI docs *(experimental)* |
|
|
150
|
+
| `.completion(shell?)` | Shell completion script |
|
|
151
|
+
| `.find(command)` | Look up command by path |
|
|
152
|
+
| `.stringify(command?, args?)` | Convert back to CLI string |
|
|
153
|
+
|
|
154
|
+
### Zod `.meta()` fields
|
|
155
|
+
|
|
156
|
+
| Field | Example | Purpose |
|
|
157
|
+
|-------|---------|---------|
|
|
158
|
+
| `flags` | `'v'` | Single-char short flag (`-v`) |
|
|
159
|
+
| `alias` | `'dry-run'` | Multi-char long alias (`--dry-run`) |
|
|
160
|
+
| `examples` | `['8080']` | Example values in help |
|
|
161
|
+
| `deprecated` | `'Use --debug'` | Deprecation warning |
|
|
162
|
+
| `hidden` | `true` | Hide from help |
|
|
163
|
+
| `group` | `'Advanced'` | Group in help output |
|
|
164
|
+
|
|
165
|
+
### Arguments meta (second param of `.arguments()`)
|
|
327
166
|
|
|
328
167
|
```typescript
|
|
329
168
|
.arguments(schema, {
|
|
330
|
-
positional: ['source', '...files', 'dest'],
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
169
|
+
positional: ['source', '...files', 'dest'],
|
|
170
|
+
interactive: ['name', 'template'],
|
|
171
|
+
optionalInteractive: ['typescript'],
|
|
172
|
+
fields: { verbose: { flags: 'v' } },
|
|
173
|
+
stdin: 'data',
|
|
174
|
+
autoAlias: true, // default
|
|
335
175
|
})
|
|
336
176
|
```
|
|
337
177
|
|
|
338
|
-
|
|
178
|
+
## Agent Skill
|
|
339
179
|
|
|
340
|
-
|
|
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:
|
|
180
|
+
Give your AI coding agent knowledge of the Padrone API:
|
|
354
181
|
|
|
355
182
|
```bash
|
|
356
183
|
npx skills add KurtGokhan/padrone
|
|
357
184
|
```
|
|
358
185
|
|
|
359
|
-
##
|
|
186
|
+
## Requirements
|
|
360
187
|
|
|
361
188
|
- Node.js 18+ or Bun
|
|
362
189
|
- TypeScript 5.0+ (recommended)
|
|
363
|
-
- Zod
|
|
190
|
+
- Zod (or any Standard Schema-compatible library)
|
|
364
191
|
|
|
365
|
-
##
|
|
192
|
+
## License
|
|
366
193
|
|
|
367
|
-
[MIT](LICENSE)
|
|
368
|
-
|
|
369
|
-
---
|
|
370
|
-
|
|
371
|
-
<p align="center">
|
|
372
|
-
Made with ❤️ by <a href="https://gkurt.com">Gokhan Kurt</a>
|
|
373
|
-
</p>
|
|
194
|
+
[MIT](LICENSE)
|