@alcyone-labs/arg-parser 1.0.0 → 1.1.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 (76) hide show
  1. package/README.md +844 -45
  2. package/dist/examples/fuzzy-demo.d.ts +8 -0
  3. package/dist/examples/fuzzy-demo.d.ts.map +1 -0
  4. package/dist/examples/fuzzy-test-example.d.ts +8 -0
  5. package/dist/examples/fuzzy-test-example.d.ts.map +1 -0
  6. package/dist/examples/fzf-search-cli.d.ts +8 -0
  7. package/dist/examples/fzf-search-cli.d.ts.map +1 -0
  8. package/dist/examples/getting-started.d.ts +27 -0
  9. package/dist/examples/getting-started.d.ts.map +1 -0
  10. package/dist/examples/mcp-preset-transports.d.ts +19 -0
  11. package/dist/examples/mcp-preset-transports.d.ts.map +1 -0
  12. package/dist/examples/simple-cli.d.ts +26 -0
  13. package/dist/examples/simple-cli.d.ts.map +1 -0
  14. package/dist/examples/v1.1.0-showcase.d.ts +16 -0
  15. package/dist/examples/v1.1.0-showcase.d.ts.map +1 -0
  16. package/dist/examples/with-env-example.d.ts +3 -0
  17. package/dist/examples/with-env-example.d.ts.map +1 -0
  18. package/dist/index-6G9StDO_.js +6445 -0
  19. package/dist/index-6G9StDO_.js.map +1 -0
  20. package/dist/index-CqU7Fj3C.cjs +6444 -0
  21. package/dist/index-CqU7Fj3C.cjs.map +1 -0
  22. package/dist/index-Dx_q1msW.js +4682 -0
  23. package/dist/index-Dx_q1msW.js.map +1 -0
  24. package/dist/index.cjs +1704 -60
  25. package/dist/index.cjs.map +1 -1
  26. package/dist/index.min.mjs +1628 -484
  27. package/dist/index.min.mjs.map +1 -1
  28. package/dist/index.mjs +1660 -59
  29. package/dist/index.mjs.map +1 -1
  30. package/dist/src/ArgParser.d.ts +156 -0
  31. package/dist/src/ArgParser.d.ts.map +1 -0
  32. package/dist/{ArgParser.d.ts → src/ArgParserBase.d.ts} +20 -13
  33. package/dist/src/ArgParserBase.d.ts.map +1 -0
  34. package/dist/{FlagManager.d.ts → src/FlagManager.d.ts} +1 -1
  35. package/dist/src/FlagManager.d.ts.map +1 -0
  36. package/dist/src/fuzzy-test-cli.d.ts +5 -0
  37. package/dist/src/fuzzy-test-cli.d.ts.map +1 -0
  38. package/dist/src/fuzzy-tester.d.ts +101 -0
  39. package/dist/src/fuzzy-tester.d.ts.map +1 -0
  40. package/dist/src/index.d.ts +7 -0
  41. package/dist/src/index.d.ts.map +1 -0
  42. package/dist/src/mcp-integration.d.ts +31 -0
  43. package/dist/src/mcp-integration.d.ts.map +1 -0
  44. package/dist/src/types.d.ts +154 -0
  45. package/dist/src/types.d.ts.map +1 -0
  46. package/dist/sse-B5Jf_YpG.cjs +121 -0
  47. package/dist/sse-B5Jf_YpG.cjs.map +1 -0
  48. package/dist/sse-BDL3h2Ll.js +121 -0
  49. package/dist/sse-BDL3h2Ll.js.map +1 -0
  50. package/dist/sse-DSjLfGFo.js +107 -0
  51. package/dist/sse-DSjLfGFo.js.map +1 -0
  52. package/dist/stdio-Cf19UQO7.js +70 -0
  53. package/dist/stdio-Cf19UQO7.js.map +1 -0
  54. package/dist/stdio-DESvSONI.cjs +94 -0
  55. package/dist/stdio-DESvSONI.cjs.map +1 -0
  56. package/dist/stdio-DLOResWr.js +94 -0
  57. package/dist/stdio-DLOResWr.js.map +1 -0
  58. package/dist/streamableHttp-DXIdDSbF.js +342 -0
  59. package/dist/streamableHttp-DXIdDSbF.js.map +1 -0
  60. package/dist/streamableHttp-DsXlAnqJ.cjs +456 -0
  61. package/dist/streamableHttp-DsXlAnqJ.cjs.map +1 -0
  62. package/dist/streamableHttp-Vd4Qsgko.js +456 -0
  63. package/dist/streamableHttp-Vd4Qsgko.js.map +1 -0
  64. package/dist/types-DSxPEImy.cjs +943 -0
  65. package/dist/types-DSxPEImy.cjs.map +1 -0
  66. package/dist/types-DdsPVLQ5.js +846 -0
  67. package/dist/types-DdsPVLQ5.js.map +1 -0
  68. package/dist/types-DpK81FWv.js +944 -0
  69. package/dist/types-DpK81FWv.js.map +1 -0
  70. package/package.json +18 -7
  71. package/dist/ArgParser.d.ts.map +0 -1
  72. package/dist/FlagManager.d.ts.map +0 -1
  73. package/dist/index.d.ts +0 -2
  74. package/dist/index.d.ts.map +0 -1
  75. package/dist/types.d.ts +0 -91
  76. package/dist/types.d.ts.map +0 -1
package/README.md CHANGED
@@ -2,37 +2,75 @@
2
2
 
3
3
  ArgParser is a powerful and flexible library for building command-line interfaces (CLIs) in TypeScript and JavaScript. It helps you define, parse, validate, and handle command-line arguments and sub-commands in a structured, type-safe way.
4
4
 
5
- Whether you're building a simple script or a complex nested CLI application, ArgParser provides the tools to create robust and user-friendly interfaces.
5
+ Whether you're building a simple script, a complex nested CLI application, or an MCP (Model Context Protocol) server, ArgParser provides the tools to create robust and user-friendly interfaces with minimal boilerplate.
6
6
 
7
- ## TODOs
7
+ ## What's New in v1.1.0
8
8
 
9
- ### Features
9
+ ### **Major Features**
10
10
 
11
- - [] Publish as an open-source library
12
- - [] Upgrade to Zod/V4
13
- - [] Add support for locales / translations
14
- - [] (potentially) support for async type function to enable more flexibility (but at the cost of a potentially much larger issue surface)
15
- - [] (potentially) add support for fully typed parsed output, this has proven very challenging
11
+ - **MCP (Model Context Protocol) Integration**: Transform any CLI into an MCP server with multiple transport support. Run MCP servers with stdio, SSE, and HTTP transports simultaneously, including streamable HTTP.
12
+ - **System Flags**: Built-in `--s-debug-print`, `--s-with-env`, `--s-save-to-env`, and `--s-enable-fuzzy` for enhanced debugging, configuration, and testing
13
+ - **Environment Loading**: Load configuration from `.env`, `.yaml`, `.json`, and `.toml` files
14
+ - **Enhanced Debugging**: Comprehensive runtime debugging and configuration export tools
16
15
 
17
- ### (known) Bugs / DX improvement points
16
+ ### **Quick Start with MCP**
18
17
 
19
- - [] When a flag with `flagOnly: false` is going to consume a value that appears like a valid flag from the set, raise the appropriate warning
20
- - [] When a flag with `allowMultiple: false` and `flagOnly: true` is passed multiple times (regardless of the options, for example "-1" and later "--one", both being valid), raise the correct error
18
+ ```typescript
19
+ import { ArgParser } from "@alcyone-labs/arg-parser";
20
+
21
+ const cli = ArgParser.withMcp({
22
+ appName: "My CLI Tool",
23
+ appCommandName: "my-tool",
24
+ description: "A powerful CLI that can also run as an MCP server",
25
+ handler: async (ctx) => ({ result: "success", args: ctx.args }),
26
+ })
27
+ .addFlags([
28
+ { name: "input", options: ["--input", "-i"], type: "string", mandatory: true },
29
+ { name: "verbose", options: ["--verbose", "-v"], type: "boolean", flagOnly: true },
30
+ ])
31
+ .addMcpSubCommand("serve", {
32
+ name: "my-mcp-server",
33
+ version: "1.1.0",
34
+ description: "Expose this CLI as an MCP server",
35
+ }, {
36
+ // Optional: Configure default transports (CLI flags take precedence)
37
+ defaultTransports: [
38
+ { type: "stdio" },
39
+ { type: "sse", port: 3001, host: "0.0.0.0" }
40
+ ]
41
+ });
42
+
43
+ // Use as CLI: my-tool --input data.txt --verbose
44
+ // Use as MCP server with defaults: my-tool serve
45
+ // Use as MCP server with CLI override: my-tool serve --transport sse --port 3002
46
+ // Use with multiple transports: my-tool serve --transports '[{"type":"stdio"},{"type":"sse","port":3001}]'
47
+ ```
21
48
 
22
49
  ## Features
23
50
 
24
- - **Type Safety:** Define expected argument types (string, number, boolean, array, custom functions) and get type-safe parsed results.
25
- - **Optionally Complex Dynamic Types** Provide a method to trigger arbitrary logic when a flag is encountered and return the output to the parsed flag.
26
- - **Declarative API:** Configure your CLI structure, flags, and sub-commands using a clear, declarative syntax.
27
- - **Automatic Help Generation:** Generate comprehensive and contextual help text based on your parser configuration.
28
- - **Hierarchical Commands:** Easily define nested sub-commands to create complex command structures (e.g., `git commit`, `docker container ls`).
29
- - **Handler Execution:** Associate handler functions with commands and have them executed automatically upon successful parsing (or manually control execution).
30
- - **Validation:** Define custom validation rules for flag values.
31
- - **Conditional Requirements:** Make flags mandatory based on the presence or values of other arguments.
32
- - **Default Values:** Specify default values for flags if they are not provided on the command line.
33
- - **Flag Inheritance:** Share common flags between parent and child commands with an intuitive inheritance mechanism.
34
- - **Error Handling:** Built-in, user-friendly error reporting for common parsing issues, with an option to handle errors manually.
35
- - **Debugging Tools:** Easily inspect your parser's configuration for complex setups.
51
+ ### **Core CLI Features**
52
+ - **Type Safety:** Define expected argument types (string, number, boolean, array, custom functions) and get type-safe parsed results
53
+ - **Declarative API:** Configure your CLI structure, flags, and sub-commands using a clear, declarative syntax
54
+ - **Automatic Help Generation:** Generate comprehensive and contextual help text based on your parser configuration
55
+ - **Hierarchical Commands:** Easily define nested sub-commands to create complex command structures (e.g., `git commit`, `docker container ls`)
56
+ - **Handler Execution:** Associate handler functions with commands and have them executed automatically upon successful parsing
57
+ - **Validation:** Define custom validation rules for flag values with enum support and custom validators
58
+ - **Conditional Requirements:** Make flags mandatory based on the presence or values of other arguments
59
+ - **Default Values:** Specify default values for flags if they are not provided on the command line
60
+ - **Flag Inheritance:** Share common flags between parent and child commands with an intuitive inheritance mechanism
61
+ - **Error Handling:** Built-in, user-friendly error reporting for common parsing issues, with an option to handle errors manually
62
+
63
+ ### **MCP Integration (v1.1.0+)**
64
+ - **Automatic MCP Server Creation:** Transform any CLI into an MCP server with a single method call
65
+ - **Multiple Transport Support:** Run stdio, SSE, and HTTP transports simultaneously on different ports
66
+ - **Type-Safe Tool Generation:** Automatically generate MCP tools with Zod schema validation from CLI definitions
67
+ - **Flexible Configuration:** Support for single transport or complex multi-transport JSON configurations
68
+
69
+ ### **System & Configuration Features (v1.1.0+)**
70
+ - **Environment Loading:** Load configuration from `.env`, `.yaml`, `.json`, and `.toml` files with `--s-with-env`
71
+ - **Configuration Export:** Save current configuration to various formats with `--s-save-to-env`
72
+ - **Advanced Debugging:** Runtime debugging with `--s-debug` and configuration inspection with `--s-debug-print`
73
+ - **CLI Precedence:** Command line arguments always override file configuration
36
74
 
37
75
  ## Installation
38
76
 
@@ -50,8 +88,91 @@ bun add @alcyone-labs/arg-parser
50
88
  deno install npm:@alcyone-labs/arg-parser
51
89
  ```
52
90
 
91
+ ### **For MCP Integration (Optional)**
92
+
93
+ If you plan to use MCP server features, install the additional dependencies:
94
+
95
+ ```bash
96
+ pnpm add @modelcontextprotocol/sdk express
97
+ # or
98
+ npm install @modelcontextprotocol/sdk express
99
+ ```
100
+
101
+ **Note:** MCP dependencies are optional and only required if you use `ArgParser` with MCP features or MCP-related functionality.
102
+
103
+ ## Runtime Compatibility
104
+
105
+ ArgParser is fully compatible with multiple JavaScript runtimes:
106
+
107
+ ### **BunJS**
108
+ ```bash
109
+ # Run TypeScript directly
110
+ bun your-cli.ts --flag value
111
+
112
+ # Or compile and run
113
+ bun build your-cli.ts --outdir ./dist
114
+ bun ./dist/your-cli.js --flag value
115
+ ```
116
+
117
+ ### **Node.js**
118
+ ```bash
119
+ # Using tsx for TypeScript
120
+ npx tsx your-cli.ts --flag value
121
+
122
+ # Using ts-node
123
+ npx ts-node your-cli.ts --flag value
124
+
125
+ # Or compile and run
126
+ npx tsc your-cli.ts
127
+ node your-cli.js --flag value
128
+ ```
129
+
130
+ ### **Deno**
131
+ ```bash
132
+ # Run with required permissions
133
+ deno run --unstable-sloppy-imports --allow-read --allow-write --allow-env your-cli.ts --flag value
134
+
135
+ # Or use the provided deno.json configuration for easier task management
136
+ deno task example:simple-cli --env production --port 8080
137
+ ```
138
+
139
+ ### **Using Built Artifacts**
140
+
141
+ After building your project with `pnpm build` (or your preferred build tool), you can use the compiled JavaScript files directly:
142
+
143
+ ```bash
144
+ # CommonJS (Node.js)
145
+ node dist/index.cjs
146
+
147
+ # ES Modules (Node.js with "type": "module" in package.json)
148
+ node dist/index.mjs
149
+
150
+ # Minified ES Modules (production)
151
+ node dist/index.min.mjs
152
+
153
+ # Import in your own projects
154
+ const { ArgParser } = require('./dist/index.cjs'); // CommonJS
155
+ import { ArgParser } from './dist/index.mjs'; // ES Modules
156
+
157
+ # Example: Using built artifacts in production
158
+ node -e "
159
+ const { ArgParser } = require('./dist/index.cjs');
160
+ const cli = new ArgParser({
161
+ appName: 'Production CLI',
162
+ handler: (ctx) => console.log('Production ready!', ctx.args)
163
+ }).addFlags([
164
+ { name: 'env', options: ['--env'], type: 'string', mandatory: true, description: 'Environment' }
165
+ ]);
166
+ cli.parse(['--env', 'production']);
167
+ "
168
+ ```
169
+
170
+ All examples in this repository work seamlessly across all three runtimes, ensuring maximum compatibility for your CLI applications.
171
+
53
172
  ## Basic Usage
54
173
 
174
+ ### **Standard CLI Usage**
175
+
55
176
  Here's a simple example demonstrating how to define flags and parse arguments:
56
177
 
57
178
  ```typescript
@@ -61,13 +182,15 @@ const parser = new ArgParser({
61
182
  appName: "Data Processor",
62
183
  appCommandName: "data-proc", // Used in help text and error messages
63
184
  description: "A tool for processing data phases",
64
- // By default, if a handler is set, it will be executed after successful parsing.
65
- // Set handler: () => { ... } here for a root command handler.
185
+ handler: async (ctx) => {
186
+ console.log("Processing data with phase:", ctx.args.phase);
187
+ return { success: true, phase: ctx.args.phase };
188
+ },
66
189
  }).addFlags([
67
190
  {
68
191
  name: "phase",
69
192
  options: ["--phase"],
70
- type: String, // Use native types or typeof string equivalents ("string", "number", "boolean", etc.)
193
+ type: "string", // Use "string", "number", "boolean", or native types
71
194
  mandatory: true,
72
195
  enum: ["chunking", "pairing", "analysis"],
73
196
  description: "Processing phase to execute",
@@ -76,36 +199,133 @@ const parser = new ArgParser({
76
199
  name: "batch",
77
200
  options: ["-b", "--batch-number"],
78
201
  type: "number",
79
- mandatory: (args) => args.phase !== "analysis", // Mandatory based on another flag's value
202
+ mandatory: (args) => args.phase !== "analysis", // Conditional requirement
80
203
  defaultValue: 0,
81
204
  description: "Batch number (required except for analysis phase)",
82
205
  },
83
206
  {
84
207
  name: "verbose",
85
- options: ["-v"],
208
+ options: ["-v", "--verbose"],
86
209
  flagOnly: true, // This flag does not expect a value
87
210
  description: "Enable verbose logging",
88
211
  },
89
212
  ]);
90
213
 
91
- // Parse command line arguments (excluding 'node' and script path)
92
- // If parsing fails (e.g., missing mandatory flag), ArgParser handles the error
93
- // by printing a message and exiting (process.exit(1)) by default.
94
- const args = parser.parse(process.argv.slice(2));
214
+ // Parse and execute
215
+ const result = parser.parse(process.argv.slice(2));
216
+ console.log("Result:", result);
217
+ ```
95
218
 
96
- // If parsing succeeds and no command handler was executed,
97
- // execution continues here with the parsed args.
98
- console.log("Parsing successful! Arguments:", args);
219
+ ### **MCP Server Usage (v1.1.0+)**
99
220
 
100
- // Example of using parsed arguments:
101
- if (args.phase === "chunking") {
102
- if (args.verbose) {
103
- console.debug("Starting the chunking phase...");
104
- }
105
- // Perform chunking logic...
106
- }
221
+ Transform your CLI into an MCP server with minimal changes:
222
+
223
+ ```typescript
224
+ import { ArgParser } from "@alcyone-labs/arg-parser";
225
+
226
+ const cli = ArgParser.withMcp({
227
+ appName: "Data Processor",
228
+ appCommandName: "data-proc",
229
+ description: "A tool for processing data phases (CLI + MCP server)",
230
+ handler: async (ctx) => {
231
+ console.log("Processing data with phase:", ctx.args.phase);
232
+ return { success: true, phase: ctx.args.phase, batch: ctx.args.batch };
233
+ },
234
+ })
235
+ .addFlags([
236
+ {
237
+ name: "phase",
238
+ options: ["--phase"],
239
+ type: "string",
240
+ mandatory: true,
241
+ enum: ["chunking", "pairing", "analysis"],
242
+ description: "Processing phase to execute",
243
+ },
244
+ {
245
+ name: "batch",
246
+ options: ["-b", "--batch-number"],
247
+ type: "number",
248
+ defaultValue: 0,
249
+ description: "Batch number for processing",
250
+ },
251
+ ])
252
+ .addMcpSubCommand("serve", {
253
+ name: "data-processor-mcp",
254
+ version: "1.1.0",
255
+ description: "Data Processor MCP Server",
256
+ });
257
+
258
+ // Use as CLI: data-proc --phase chunking --batch 5
259
+ // Use as MCP server: data-proc serve
260
+ // Use with custom transport: data-proc serve --transport sse --port 3001
107
261
  ```
108
262
 
263
+ ## MCP Integration (v1.1.0+)
264
+
265
+ ArgParser v1.1.0 introduces powerful Model Context Protocol (MCP) integration, allowing you to expose any CLI as an MCP server with minimal code changes.
266
+
267
+ ### **Quick MCP Setup**
268
+
269
+ 1. **Import the MCP-enabled class:**
270
+ ```typescript
271
+ import { ArgParser } from "@alcyone-labs/arg-parser";
272
+ ```
273
+
274
+ 2. **Create your CLI with MCP support:**
275
+ ```typescript
276
+ const cli = ArgParser.withMcp({
277
+ appName: "My Tool",
278
+ appCommandName: "my-tool",
279
+ handler: async (ctx) => ({ result: "success", args: ctx.args }),
280
+ })
281
+ .addFlags([/* your flags */])
282
+ .addMcpSubCommand("serve", {
283
+ name: "my-mcp-server",
284
+ version: "1.0.0",
285
+ });
286
+ ```
287
+
288
+ 3. **Use as CLI or MCP server:**
289
+ ```bash
290
+ # CLI usage
291
+ my-tool --input data.txt --verbose
292
+
293
+ # MCP server (stdio)
294
+ my-tool serve
295
+
296
+ # MCP server (HTTP)
297
+ my-tool serve --transport sse --port 3001
298
+
299
+ # Multiple transports
300
+ my-tool serve --transports '[{"type":"stdio"},{"type":"sse","port":3001}]'
301
+ ```
302
+
303
+ ### **MCP Transport Options**
304
+
305
+ - **`stdio`** (default): Standard input/output for CLI tools
306
+ - **`sse`**: Server-Sent Events over HTTP for web applications
307
+ - **`streamable-http`**: HTTP with streaming support for advanced integrations
308
+
309
+ ### **Multiple Transports Simultaneously**
310
+
311
+ Run multiple transport types at once for maximum flexibility:
312
+
313
+ ```bash
314
+ my-tool serve --transports '[
315
+ {"type":"stdio"},
316
+ {"type":"sse","port":3001,"path":"/sse"},
317
+ {"type":"streamable-http","port":3002,"path":"/mcp","host":"0.0.0.0"}
318
+ ]'
319
+ ```
320
+
321
+ ### **Automatic Tool Generation**
322
+
323
+ Your CLI flags are automatically converted to MCP tools with:
324
+ - **Type-safe schemas** using Zod validation
325
+ - **Automatic documentation** from flag descriptions
326
+ - **Enum validation** for restricted values
327
+ - **Error handling** with detailed messages
328
+
109
329
  ## Core Concepts
110
330
 
111
331
  ### Defining Flags
@@ -242,6 +462,8 @@ ArgParser excels at building CLIs with nested commands, like `git clone` or `doc
242
462
 
243
463
  Define sub-commands using the `subCommands` option in the `ArgParser` constructor or the `.addSubCommand(subCommand)` method. Each sub-command requires a `name`, `description`, and a dedicated `ArgParser` instance for its own flags and nested sub-commands.
244
464
 
465
+ Note that each flag name set is debounced to make sure there are no duplicates, but the flags are sandboxed within their respective sub-commands. So it's ok to use the same flag on different sub-commands.
466
+
245
467
  ```typescript
246
468
  import {
247
469
  ArgParser,
@@ -471,9 +693,242 @@ try {
471
693
  }
472
694
  ```
473
695
 
696
+ ## Environment Configuration Export
697
+
698
+ ArgParser includes a built-in system flag `--s-save-to-env` that allows you to export the current parser's configuration and parsed arguments to various file formats. This is useful for creating configuration templates, documenting CLI usage, or generating environment files for deployment.
699
+
700
+ ### Usage
701
+
702
+ ```bash
703
+ # Export to .env format (default for no extension)
704
+ your-cli --flag1 value1 --flag2 --s-save-to-env config.env
705
+
706
+ # Export to YAML format
707
+ your-cli --flag1 value1 --flag2 --s-save-to-env config.yaml
708
+
709
+ # Export to JSON format
710
+ your-cli --flag1 value1 --flag2 --s-save-to-env config.json
711
+
712
+ # Export to TOML format
713
+ your-cli --flag1 value1 --flag2 --s-save-to-env config.toml
714
+ ```
715
+
716
+ ### Supported Formats
717
+
718
+ The format is automatically detected based on the file extension:
719
+
720
+ - **`.env`** (or no extension): Bash environment variable format
721
+ - **`.yaml` / `.yml`**: YAML format
722
+ - **`.json` / `.jsonc`**: JSON format with metadata
723
+ - **`.toml` / `.tml`**: TOML format
724
+
725
+ ### Behavior
726
+
727
+ - **Works at any parser level**: Can be used with root commands or sub-commands
728
+ - **Includes inherited flags**: Shows flags from the current parser and all parent parsers in the chain
729
+ - **Comments optional flags**: Flags that are optional and not set are commented out but still documented
730
+ - **Preserves values**: Set flags show their actual values, unset flags show default values or are commented out
731
+ - **Rich documentation**: Each flag includes its description, options, type, and constraints
732
+
733
+ ### Example Output
734
+
735
+ For a CLI with flags `--verbose`, `--output file.txt`, and `--count 5`:
736
+
737
+ **`.env` format:**
738
+ ```bash
739
+ # Environment configuration generated by ArgParser
740
+ # Format: Bash .env style
741
+
742
+ # verbose: Enable verbose output
743
+ # Options: -v, --verbose
744
+ # Type: Boolean
745
+ # Default: false
746
+ VERBOSE="true"
747
+
748
+ # output: Output file path
749
+ # Options: -o, --output
750
+ # Type: String
751
+ OUTPUT="file.txt"
752
+
753
+ # count: Number of items to process
754
+ # Options: -c, --count
755
+ # Type: Number
756
+ # Default: 10
757
+ COUNT="5"
758
+ ```
759
+
760
+ **`.yaml` format:**
761
+ ```yaml
762
+ # Environment configuration generated by ArgParser
763
+ # Format: YAML
764
+
765
+ # verbose: Enable verbose output
766
+ # Options: -v, --verbose
767
+ # Type: Boolean
768
+ # Default: false
769
+
770
+ verbose: true
771
+ output: "file.txt"
772
+ count: 5
773
+ ```
774
+
775
+ ## System Flags (v1.1.0+)
776
+
777
+ ArgParser includes several built-in system flags that provide debugging, configuration management, and introspection capabilities. These flags are processed before normal argument parsing and will cause the program to exit after execution.
778
+
779
+ ### **Overview**
780
+
781
+ System flags use the `--s-*` pattern and provide powerful development and deployment tools:
782
+
783
+ - **`--s-debug`**: Runtime debugging with step-by-step parsing analysis
784
+ - **`--s-with-env <file>`**: Load configuration from files (`.env`, `.yaml`, `.json`, `.toml`)
785
+ - **`--s-save-to-env <file>`**: Export current configuration to various formats
786
+ - **`--s-debug-print`**: Export complete parser configuration for inspection
787
+ - **`--s-enable-fuzzy`**: Enable fuzzy testing mode (dry-run with no side effects)
788
+
789
+ ### `--s-save-to-env <file>`
790
+
791
+ Exports the current parser's configuration and parsed arguments to various file formats.
792
+
793
+ ```bash
794
+ # Export to .env format (default for no extension)
795
+ your-cli --flag1 value1 --flag2 --s-save-to-env config.env
796
+
797
+ # Export to YAML format
798
+ your-cli --flag1 value1 --flag2 --s-save-to-env config.yaml
799
+
800
+ # Export to JSON format
801
+ your-cli --flag1 value1 --flag2 --s-save-to-env config.json
802
+
803
+ # Export to TOML format
804
+ your-cli --flag1 value1 --flag2 --s-save-to-env config.toml
805
+ ```
806
+
807
+ **Features:**
808
+ - Works at any parser level (root command or sub-commands)
809
+ - Includes inherited flags from parent parsers in the chain
810
+ - Comments out optional flags that are not set
811
+ - Rich documentation for each flag (description, options, type, constraints)
812
+ - Automatic format detection based on file extension
813
+
814
+ ### `--s-with-env <file>`
815
+
816
+ Loads configuration from a file and merges it with command line arguments. CLI arguments take precedence over file configuration.
817
+
818
+ ```bash
819
+ # Load from .env format (default for no extension)
820
+ your-cli --s-with-env config.env
821
+
822
+ # Load from YAML format
823
+ your-cli --s-with-env config.yaml
824
+
825
+ # Load from JSON format
826
+ your-cli --s-with-env config.json
827
+
828
+ # Load from TOML format
829
+ your-cli --s-with-env config.toml
830
+
831
+ # Combine with CLI arguments (CLI args override file config)
832
+ your-cli --s-with-env config.yaml --verbose --output override.txt
833
+ ```
834
+
835
+ **Supported Formats:**
836
+
837
+ The format is automatically detected based on the file extension:
838
+
839
+ - **`.env`** (or no extension): Dotenv format with `KEY=value` pairs
840
+ - **`.yaml` / `.yml`**: YAML format
841
+ - **`.json` / `.jsonc`**: JSON format (metadata is ignored if present)
842
+ - **`.toml` / `.tml`**: TOML format
843
+
844
+ **Behavior:**
845
+
846
+ - **File validation**: Checks if the file exists and can be parsed
847
+ - **Type conversion**: Automatically converts values to match flag types (boolean, number, string, array)
848
+ - **Enum validation**: Validates values against allowed enum options
849
+ - **CLI precedence**: Command line arguments override file configuration
850
+ - **Error handling**: Exits with error code 1 if file cannot be loaded or parsed
851
+ - **Flag matching**: Only loads values for flags that exist in the current parser chain
852
+
853
+ **Example Configuration Files:**
854
+
855
+ **.env format:**
856
+ ```bash
857
+ VERBOSE=true
858
+ OUTPUT=file.txt
859
+ COUNT=5
860
+ TAGS=tag1,tag2,tag3
861
+ ```
862
+
863
+ **YAML format:**
864
+ ```yaml
865
+ verbose: true
866
+ output: file.txt
867
+ count: 5
868
+ tags:
869
+ - tag1
870
+ - tag2
871
+ - tag3
872
+ ```
873
+
874
+ **JSON format:**
875
+ ```json
876
+ {
877
+ "verbose": true,
878
+ "output": "file.txt",
879
+ "count": 5,
880
+ "tags": ["tag1", "tag2", "tag3"]
881
+ }
882
+ ```
883
+
884
+ ### `--s-debug-print`
885
+
886
+ Prints the complete parser configuration to a JSON file and console for debugging complex parser setups.
887
+
888
+ ```bash
889
+ your-cli --s-debug-print
890
+ ```
891
+
892
+ **Output:**
893
+ - Creates `ArgParser.full.json` with the complete parser structure
894
+ - Shows all flags, sub-commands, handlers, and configuration
895
+ - Useful for debugging complex parser hierarchies
896
+ - Human-readable console output with syntax highlighting
897
+
898
+ ### `--s-debug`
899
+
900
+ Provides detailed runtime debugging information showing how arguments are parsed step-by-step.
901
+
902
+ ```bash
903
+ your-cli --flag1 value1 sub-command --flag2 value2 --s-debug
904
+ ```
905
+
906
+ **Output:**
907
+ - Shows command chain identification process
908
+ - Step-by-step argument parsing simulation
909
+ - Final parser identification
910
+ - Accumulated arguments at each level
911
+ - Remaining arguments after parsing
912
+ - Complete static configuration of the final parser
913
+
914
+ **Useful for:**
915
+ - Understanding complex command chains
916
+ - Debugging argument parsing issues
917
+ - Seeing how flags are inherited between parsers
918
+ - Troubleshooting sub-command resolution
919
+
920
+ ### Usage Notes
921
+
922
+ - System flags are processed before normal argument parsing
923
+ - They cause the program to exit after execution (exit code 0 for success)
924
+ - Can be used with any combination of regular flags and sub-commands
925
+ - Particularly useful during development and debugging
926
+
474
927
  ## Debugging
475
928
 
476
- The `printAll(filePath?: string)` method is useful for debugging complex parser configurations. It recursively outputs the structure, options, flags, and handlers of a parser instance and its sub-commands.
929
+ ### Programmatic Debugging
930
+
931
+ The `printAll(filePath?: string)` method is useful for debugging complex parser configurations programmatically. It recursively outputs the structure, options, flags, and handlers of a parser instance and its sub-commands.
477
932
 
478
933
  - `parser.printAll()`: Prints a colored, human-readable output to the console.
479
934
  - `parser.printAll('./config.json')`: Writes the configuration as a pretty-printed JSON file.
@@ -491,13 +946,221 @@ const parser = new ArgParser({ appName: "Debug App" })
491
946
  parser.printAll(); // Output to console
492
947
  ```
493
948
 
949
+ ### Runtime Debugging
950
+
951
+ For runtime debugging, use the system flags documented above:
952
+
953
+ - `--s-debug-print`: Export complete parser configuration
954
+ - `--s-debug`: Show step-by-step argument parsing process
955
+ - `--s-save-to-env <file>`: Export current configuration to various formats
956
+ - `--s-with-env <file>`: Load configuration from file and merge with CLI arguments
957
+
958
+ ### `--s-enable-fuzzy`
959
+
960
+ Enables fuzzy testing mode, which acts as a dry-run mode for safe testing without side effects. **No boilerplate code required** - the system automatically prevents CLI execution during fuzzy testing.
961
+
962
+ ```bash
963
+ # Enable fuzzy mode for testing
964
+ your-cli --s-enable-fuzzy --input test.txt --format json
965
+ ```
966
+
967
+ **Features:**
968
+ - **Automatic execution prevention**: No need for complex conditional logic in your CLI code
969
+ - **Zero boilerplate**: Simply export your CLI with `export default cli` and call `cli.parse()`
970
+ - Disables error handling to allow error collection
971
+ - Skips mandatory flag validation for comprehensive testing
972
+ - **Prevents handler function execution** (no side effects)
973
+ - **Logs what each handler would receive** for testing visibility
974
+ - Recursively applies to all subcommand parsers
975
+ - Safe for testing production CLIs with database operations, file modifications, or API calls
976
+
977
+ **Example Output:**
978
+ ```
979
+ [--s-enable-fuzzy] handler() skipped for command chain: (root)
980
+ Input args: [--s-enable-fuzzy --input test.txt --format json]
981
+ Parsed args: {"input":"test.txt","format":"json"}
982
+ ```
983
+
984
+ **Use Cases:**
985
+ - Fuzzy testing CLI argument parsing
986
+ - Validating CLI configuration without executing business logic
987
+ - Testing complex command hierarchies safely
988
+ - Automated testing of CLI interfaces
989
+
990
+ These system flags are particularly useful when you need to debug a CLI application without modifying the source code.
991
+
992
+ ## Fuzzy Testing
993
+
994
+ ArgParser includes comprehensive fuzzy testing capabilities to automatically test CLI configurations and catch edge cases that manual testing might miss. The fuzzy testing utility systematically explores command paths and generates various flag combinations to ensure robustness.
995
+
996
+ ### **Quick Start**
997
+
998
+ Test any ArgParser configuration using the built-in fuzzy testing CLI:
999
+
1000
+ ```bash
1001
+ # Test an ArgParser file
1002
+ bun src/fuzzy-test-cli.ts --file examples/getting-started.ts
1003
+
1004
+ # Test with custom options and save results
1005
+ bun src/fuzzy-test-cli.ts \
1006
+ --file examples/getting-started.ts \
1007
+ --output test-results.json \
1008
+ --format json \
1009
+ --max-depth 3 \
1010
+ --random-tests 20 \
1011
+ --verbose
1012
+ ```
1013
+
1014
+ **Important Note**: Make sure that the `examples/getting-started.ts` file exports the parser instance using `export default` for the fuzzy testing CLI to work correctly.
1015
+
1016
+ ### **System Flag Integration**
1017
+
1018
+ The `--s-enable-fuzzy` system flag makes any CLI fuzzy-test compatible **without any code modifications or boilerplate**:
1019
+
1020
+ ```bash
1021
+ # Enable fuzzy mode for safe testing (dry-run with no side effects)
1022
+ your-cli --s-enable-fuzzy --input test.txt --format json
1023
+
1024
+ # The fuzzy testing CLI automatically uses this flag
1025
+ bun src/fuzzy-test-cli.ts --file your-cli.ts
1026
+ ```
1027
+
1028
+ **Fuzzy mode features:**
1029
+ - **Zero boilerplate**: No conditional logic needed - just `export default cli` and `cli.parse()`
1030
+ - **Automatic prevention**: System automatically prevents CLI execution during fuzzy testing
1031
+ - **Dry-run execution**: Prevents handler function execution (no side effects)
1032
+ - **Error collection**: Disables error handling to collect all parsing errors
1033
+ - **Argument logging**: Shows what each handler would receive for testing visibility
1034
+ - **Safe testing**: Test production CLIs with database operations, file modifications, or API calls
1035
+
1036
+ ### **Testing Capabilities**
1037
+
1038
+ The fuzzy tester automatically tests:
1039
+
1040
+ - **Valid combinations**: Proper flag usage with correct types and values
1041
+ - **Invalid combinations**: Wrong inputs to verify error handling
1042
+ - **Random combinations**: Pseudo-random flag combinations for edge cases
1043
+ - **Command paths**: All subcommand combinations up to configurable depth
1044
+ - **Performance**: Execution timing for different input complexities
1045
+
1046
+ ### **Programmatic Usage**
1047
+
1048
+ ```typescript
1049
+ import { ArgParserFuzzyTester } from "@alcyone-labs/arg-parser/fuzzy-tester";
1050
+ import { myArgParser } from "./my-cli";
1051
+
1052
+ const tester = new ArgParserFuzzyTester(myArgParser, {
1053
+ maxDepth: 5,
1054
+ randomTestCases: 10,
1055
+ includePerformance: true,
1056
+ testErrorCases: true,
1057
+ verbose: false,
1058
+ });
1059
+
1060
+ const report = await tester.runFuzzyTest();
1061
+ console.log(`Success rate: ${(report.successfulTests / report.totalTests * 100).toFixed(1)}%`);
1062
+ ```
1063
+
1064
+ ### **Output Formats**
1065
+
1066
+ Generate reports in multiple formats:
1067
+
1068
+ ```bash
1069
+ # Human-readable console output
1070
+ bun src/fuzzy-test-cli.ts --file my-cli.ts --format text
1071
+
1072
+ # Machine-readable JSON
1073
+ bun src/fuzzy-test-cli.ts --file my-cli.ts --format json --output results.json
1074
+
1075
+ # Documentation-friendly Markdown
1076
+ bun src/fuzzy-test-cli.ts --file my-cli.ts --format markdown --output report.md
1077
+ ```
1078
+
1079
+ For complete documentation, examples, and advanced usage patterns, see the [Fuzzy Testing Documentation](docs/fuzzy-testing.md).
1080
+
494
1081
  ## API Reference
495
1082
 
496
1083
  This section provides a quick overview of the main components. See the sections above for detailed explanations and examples.
497
1084
 
498
- ### `new ArgParser(options?, initialFlags?)`
1085
+ ### **Core Classes**
499
1086
 
500
- Constructor for creating a parser instance.
1087
+ #### `ArgParserBase`
1088
+
1089
+ Base class providing core CLI parsing functionality without MCP features. Use this for lightweight CLIs that don't need MCP server capabilities.
1090
+
1091
+ **Constructor:**
1092
+ - `new ArgParserBase(options?, initialFlags?)`: Create basic parser instance
1093
+
1094
+ #### `ArgParser` (v1.1.0+)
1095
+
1096
+ Main class with built-in MCP server capabilities. Extends `ArgParserBase` with MCP integration.
1097
+
1098
+ **Constructors:**
1099
+ - `new ArgParser(options?, initialFlags?)`: Create parser with MCP capabilities
1100
+ - `ArgParser.withMcp(options?, initialFlags?)`: Factory method for MCP-enabled parser (same as constructor)
1101
+ - `ArgParser.fromArgParser(parser)`: Convert existing ArgParserBase to MCP-enabled
1102
+
1103
+ **MCP Methods:**
1104
+ - `toMcpTools(options?)`: Generate MCP tool structures from CLI definition
1105
+ - `createMcpServer(serverInfo, toolOptions?)`: Create MCP server instance
1106
+ - `startMcpServer(serverInfo, toolOptions?)`: Start MCP server with stdio transport
1107
+ - `startMcpServerWithTransport(serverInfo, transportType, transportOptions?, toolOptions?)`: Start with specific transport
1108
+ - `startMcpServerWithMultipleTransports(serverInfo, transports, toolOptions?)`: Start with multiple transports (manual approach)
1109
+ - `addMcpSubCommand(name, serverInfo, options?)`: Add MCP server sub-command with optional preset transports (recommended approach)
1110
+ - `parse(args, options?)`: Async version supporting async handlers
1111
+
1112
+ **MCP Types:**
1113
+ - `McpTransportConfig`: Configuration for a single transport (`{ type, port?, host?, path?, sessionIdGenerator? }`)
1114
+ - `McpSubCommandOptions`: Options for MCP sub-command (`{ defaultTransport?, defaultTransports?, toolOptions? }`)
1115
+
1116
+ **Transport Types:**
1117
+ - `"stdio"`: Standard input/output
1118
+ - `"sse"`: Server-Sent Events over HTTP
1119
+ - `"streamable-http"`: HTTP with streaming support
1120
+
1121
+ **Example:**
1122
+ ```typescript
1123
+ const cli = ArgParser.withMcp({
1124
+ appName: "My CLI",
1125
+ handler: async (ctx) => ({ result: ctx.args }),
1126
+ })
1127
+ .addFlags([/* flags */])
1128
+ .addMcpSubCommand("serve", {
1129
+ name: "my-mcp-server",
1130
+ version: "1.0.0",
1131
+ });
1132
+
1133
+ // Elegant approach: Configure default transports in addMcpSubCommand
1134
+ const cli = ArgParser.withMcp({
1135
+ appName: "My Tool",
1136
+ handler: async (ctx) => ({ result: ctx.args }),
1137
+ })
1138
+ .addFlags([/* your flags */])
1139
+ .addMcpSubCommand("serve", {
1140
+ name: "my-server",
1141
+ version: "1.0.0",
1142
+ }, {
1143
+ // Default multiple transports - used when no CLI flags provided
1144
+ defaultTransports: [
1145
+ { type: "stdio" },
1146
+ { type: "sse", port: 3001 },
1147
+ { type: "streamable-http", port: 3002 }
1148
+ ]
1149
+ });
1150
+
1151
+ // Usage: my-tool serve (uses all default transports)
1152
+ // Usage: my-tool serve --transports '[{"type":"sse","port":4000}]' (overrides defaults)
1153
+ ```
1154
+
1155
+ ### Constructors
1156
+
1157
+ #### `new ArgParserBase(options?, initialFlags?)`
1158
+
1159
+ Constructor for creating a basic parser instance without MCP capabilities.
1160
+
1161
+ #### `new ArgParser(options?, initialFlags?)`
1162
+
1163
+ Constructor for creating a parser instance with MCP capabilities.
501
1164
 
502
1165
  - `options`: An object (`IArgParserParams`) configuring the parser.
503
1166
  - `appName?: string`: Display name.
@@ -582,3 +1245,139 @@ Recursively prints the parser configuration.
582
1245
  - `IParseOptions`: Options for the `parse()` method.
583
1246
  - `IArgParserParams`: Options for the `ArgParser` constructor.
584
1247
  - `ArgParserError`: Custom error class thrown on parsing failures when `handleErrors` is `false`.
1248
+
1249
+ ## Quick Reference
1250
+
1251
+ ### **Basic CLI Setup**
1252
+ ```typescript
1253
+ import { ArgParser } from "@alcyone-labs/arg-parser";
1254
+
1255
+ const cli = new ArgParser({
1256
+ appName: "My Tool",
1257
+ appCommandName: "my-tool",
1258
+ handler: async (ctx) => ({ result: ctx.args }),
1259
+ })
1260
+ .addFlags([
1261
+ { name: "input", options: ["--input", "-i"], type: "string", mandatory: true },
1262
+ { name: "verbose", options: ["--verbose", "-v"], type: "boolean", flagOnly: true },
1263
+ ])
1264
+ .addSubCommand({
1265
+ name: "process",
1266
+ description: "Process data",
1267
+ handler: async (ctx) => ({ processed: true }),
1268
+ parser: new ArgParser({}, [
1269
+ { name: "format", options: ["--format"], type: "string", enum: ["json", "xml"] },
1270
+ ]),
1271
+ });
1272
+ ```
1273
+
1274
+ ### **MCP Integration**
1275
+ ```typescript
1276
+ import { ArgParser } from "@alcyone-labs/arg-parser";
1277
+
1278
+ const mcpCli = ArgParser.withMcp({ /* same options */ })
1279
+ .addFlags([/* same flags */])
1280
+ .addMcpSubCommand("serve", {
1281
+ name: "my-mcp-server",
1282
+ version: "1.0.0",
1283
+ });
1284
+
1285
+ // CLI: my-tool --input data.txt process --format json
1286
+ // MCP: my-tool serve --transport sse --port 3001
1287
+ ```
1288
+
1289
+ ### **MCP Preset Transport Configuration**
1290
+ Configure default transports that will be used when no CLI transport flags are provided:
1291
+
1292
+ ```typescript
1293
+ import { ArgParser, McpTransportConfig } from "@alcyone-labs/arg-parser";
1294
+
1295
+ // Single preset transport
1296
+ const cliWithPreset = ArgParser.withMcp({
1297
+ appName: "My Tool",
1298
+ handler: async (ctx) => ({ result: ctx.args }),
1299
+ })
1300
+ .addMcpSubCommand("serve", {
1301
+ name: "my-server",
1302
+ version: "1.0.0",
1303
+ }, {
1304
+ defaultTransport: {
1305
+ type: "sse",
1306
+ port: 3001,
1307
+ host: "0.0.0.0"
1308
+ }
1309
+ });
1310
+
1311
+ // Multiple preset transports
1312
+ const cliWithMultiplePresets = ArgParser.withMcp({
1313
+ appName: "Multi-Transport Tool",
1314
+ handler: async (ctx) => ({ result: ctx.args }),
1315
+ })
1316
+ .addMcpSubCommand("serve", {
1317
+ name: "multi-server",
1318
+ version: "1.0.0",
1319
+ }, {
1320
+ defaultTransports: [
1321
+ { type: "stdio" },
1322
+ { type: "sse", port: 3001 },
1323
+ { type: "streamable-http", port: 3002, path: "/api/mcp" }
1324
+ ],
1325
+ toolOptions: {
1326
+ includeSubCommands: true
1327
+ }
1328
+ });
1329
+
1330
+ // CLI flags always take precedence over presets
1331
+ // my-tool serve -> Uses preset transports
1332
+ // my-tool serve --transport sse -> Overrides preset with CLI flags
1333
+ ```
1334
+
1335
+ ### **System Flags**
1336
+ ```bash
1337
+ # Debug parsing
1338
+ my-tool --s-debug --input data.txt process
1339
+
1340
+ # Load configuration
1341
+ my-tool --s-with-env config.yaml --input override.txt
1342
+
1343
+ # Save configuration
1344
+ my-tool --input data.txt --s-save-to-env template.yaml
1345
+ ```
1346
+
1347
+ ### **Multiple MCP Transports**
1348
+ ```bash
1349
+ # Single transport
1350
+ my-tool serve --transport sse --port 3001
1351
+
1352
+ # Multiple transports
1353
+ my-tool serve --transports '[
1354
+ {"type":"stdio"},
1355
+ {"type":"sse","port":3001},
1356
+ {"type":"streamable-http","port":3002}
1357
+ ]'
1358
+ ```
1359
+
1360
+ ---
1361
+
1362
+ **📖 For complete examples and tutorials, see the [`examples/`](./examples/) directory.**
1363
+
1364
+ ---
1365
+
1366
+ ## Backlog
1367
+
1368
+ - [x] Publish as an open-source library
1369
+ - [x] Make ArgParser compatible with MCP out-of-the-box
1370
+ - [x] Rename --LIB-* flags to --s-*
1371
+ - [x] Make it possible to pass a `--s-save-to-env /path/to/file` parameter that saves all the parameters to a file (works with Bash-style .env, JSON, YAML, TOML)
1372
+ - [x] Make it possible to pass a `--s-with-env /path/to/file` parameter that loads all the parameters from a file (works with Bash-style .env, JSON, YAML, TOML)
1373
+ - [ ] Add System flags to args.systemArgs
1374
+ - [ ] Improve flag options collision prevention
1375
+ - [ ] Add support for locales / translations
1376
+ - [ ] Add support for async type function to enable more flexibility
1377
+ - [ ] (potentially) add support for fully typed parsed output, this has proven very challenging
1378
+ - [ ] Upgrade to Zod/V4 (V4 does not support functions well, this will take more time, not a priority)
1379
+
1380
+ ### (known) Bugs / DX improvement points
1381
+
1382
+ - [ ] When a flag with `flagOnly: false` is going to consume a value that appears like a valid flag from the set, raise the appropriate warning
1383
+ - [ ] When a flag with `allowMultiple: false` and `flagOnly: true` is passed multiple times (regardless of the options, for example "-1" and later "--one", both being valid), raise the correct error