@gunshi/docs 0.27.0-beta.4

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.
@@ -0,0 +1,281 @@
1
+ # Auto Usage Generation
2
+
3
+ Gunshi automatically generates comprehensive usage information for your commands, ensuring your CLI is self-documenting and user-friendly without additional effort.
4
+
5
+ ## How Auto Usage Works
6
+
7
+ When you define a command with Gunshi, the library automatically:
8
+
9
+ - Adds `--help` and `-h` flags to every command
10
+ - Adds `--version` and `-v` flags when you provide a version in the CLI options
11
+ - Generates formatted usage text based on your command configuration
12
+ - Displays usage information when users request help or provide invalid arguments
13
+ - Includes descriptions, examples, and type information you provide
14
+
15
+ The generated usage follows standard CLI conventions, making your application immediately familiar to users.
16
+
17
+ ## Understanding Bracket Notation
18
+
19
+ Gunshi uses consistent bracket notation throughout the generated usage to indicate whether elements are required or optional:
20
+
21
+ ### Angle Brackets `<>` - Required Elements
22
+
23
+ Angle brackets indicate required elements or parameters without default values:
24
+
25
+ - `<OPTIONS>` - The command has required options (at least one option without a default value)
26
+ - `<name>` - An option parameter that must be provided (no default value)
27
+ - `<positional>` - A required positional argument
28
+
29
+ Example:
30
+
31
+ ```sh
32
+ USAGE:
33
+ app <OPTIONS>
34
+
35
+ OPTIONS:
36
+ -n, --name <name> Name to use (required)
37
+ ```
38
+
39
+ ### Square Brackets `[]` - Optional Elements
40
+
41
+ Square brackets indicate optional elements or parameters with default values:
42
+
43
+ - `[name]` - An option parameter with a default value
44
+ - `[COMMANDS]` - Sub-command selection (when multiple commands exist)
45
+ - `[commandName]` - A default command that runs when no sub-command is specified
46
+
47
+ Example:
48
+
49
+ ```sh
50
+ USAGE:
51
+ app [COMMANDS]
52
+
53
+ COMMANDS:
54
+ [manage] Default command for managing resources
55
+
56
+ OPTIONS:
57
+ -t, --type [type] Resource type (default: standard)
58
+ ```
59
+
60
+ This notation provides immediate visual feedback about what users must provide versus what they can omit, making your CLI more intuitive to use.
61
+
62
+ <!-- eslint-disable markdown/no-missing-label-refs -->
63
+
64
+ > [!TIP]
65
+ > Auto-usage generation is powered by the `@gunshi/plugin-renderer` plugin, which is automatically included when you use the standard `cli()` function. This plugin handles all help text rendering and formatting.
66
+
67
+ <!-- eslint-enable markdown/no-missing-label-refs -->
68
+
69
+ ## Generated Help Output
70
+
71
+ Gunshi transforms your command definitions into professional help documentation.
72
+
73
+ Here's what users see when they request help.
74
+
75
+ ### Basic Command Help
76
+
77
+ For a simple command with basic configuration (see [Getting Started](./getting-started.md) for implementation details), running with `--help` displays:
78
+
79
+ ```sh
80
+ A greeting CLI (greet-cli v1.0.0)
81
+
82
+ USAGE:
83
+ greet-cli <OPTIONS>
84
+
85
+ OPTIONS:
86
+ -h, --help Display this help message
87
+ -v, --version Display this version
88
+ -n, --name <name> Name to greet
89
+ -u, --uppercase Convert greeting to uppercase
90
+ ```
91
+
92
+ <!-- eslint-disable markdown/no-missing-label-refs -->
93
+
94
+ > [!NOTE]
95
+ > The `--help` flag is automatically added - you never need to define it manually.
96
+
97
+ <!-- eslint-enable markdown/no-missing-label-refs -->
98
+
99
+ ### Help with Arguments and Examples
100
+
101
+ When your command includes argument definitions and examples (see [Declarative Configuration](./declarative.md) for how to define these), the generated help becomes more comprehensive:
102
+
103
+ ```sh
104
+ app (app v1.0.0)
105
+
106
+ USAGE:
107
+ app <OPTIONS>
108
+
109
+ OPTIONS:
110
+ -p, --path <path> File or directory path to operate on
111
+ -r, --recursive Operate recursively on directories
112
+ --no-recursive Negatable of -r, --recursive
113
+ -o, --operation <operation> Operation to perform: list, copy, move, or delete
114
+ -h, --help Display this help message
115
+ -v, --version Display this version
116
+
117
+ EXAMPLES:
118
+ # List files in current directory
119
+ $ app --operation list
120
+
121
+ # Copy files recursively
122
+ $ app --operation copy --path ./source --recursive
123
+
124
+ # Delete files
125
+ $ app --operation delete --path ./temp
126
+ ```
127
+
128
+ <!-- eslint-disable markdown/no-missing-label-refs -->
129
+
130
+ > [!IMPORTANT]
131
+ > Boolean options automatically receive a negatable version with the `--no-` prefix. This allows users to explicitly disable boolean flags.
132
+
133
+ <!-- eslint-enable markdown/no-missing-label-refs -->
134
+
135
+ ## Customizing Help Output
136
+
137
+ ### Displaying Option Types
138
+
139
+ Enable type display in the usage output to help users understand what value each option expects:
140
+
141
+ ```js
142
+ await cli(process.argv.slice(2), command, {
143
+ name: 'app',
144
+ version: '1.0.0',
145
+ usageOptionType: true // Enable type display
146
+ })
147
+ ```
148
+
149
+ This adds type information to each option:
150
+
151
+ ```sh
152
+ OPTIONS:
153
+ -p, --path <path> [string] File or directory path to operate on
154
+ -r, --recursive [boolean] Operate recursively on directories
155
+ --no-recursive [boolean] Negatable of -r, --recursive
156
+ -o, --operation <operation> [string] Operation to perform: list, copy, move, or delete
157
+ -h, --help [boolean] Display this help message
158
+ -v, --version [boolean] Display this version
159
+ ```
160
+
161
+ ## Sub-command Help Generation
162
+
163
+ For CLIs with sub-commands (see [Composable Sub-commands](./composable.md) for implementation), Gunshi generates hierarchical help documentation.
164
+
165
+ ### Main Command Help
166
+
167
+ When users run the main command with `--help`:
168
+
169
+ ```sh
170
+ resource-manager (resource-manager v1.0.0)
171
+
172
+ USAGE:
173
+ resource-manager [COMMANDS] <OPTIONS>
174
+
175
+ COMMANDS:
176
+ [manage] <OPTIONS> Manage resources
177
+ create <OPTIONS> Create a new resource
178
+ list <OPTIONS> List all resources
179
+
180
+ For more info, run any command with the `--help` flag:
181
+ resource-manager --help
182
+ resource-manager create --help
183
+ resource-manager list --help
184
+
185
+ OPTIONS:
186
+ -h, --help Display this help message
187
+ -v, --version Display this version
188
+ ```
189
+
190
+ <!-- eslint-disable markdown/no-missing-label-refs -->
191
+
192
+ > [!NOTE]
193
+ > The brackets in `[manage]` indicate it's the default command that runs when no sub-command is specified.
194
+
195
+ <!-- eslint-enable markdown/no-missing-label-refs -->
196
+
197
+ ### Sub-command Specific Help
198
+
199
+ Each sub-command has its own help, accessible via `command --help`. The below `create --help`:
200
+
201
+ ```sh
202
+ resource-manager (resource-manager v1.0.0)
203
+
204
+ Create a new resource
205
+
206
+ USAGE:
207
+ resource-manager create <OPTIONS>
208
+
209
+ OPTIONS:
210
+ -h, --help Display this help message
211
+ -v, --version Display this version
212
+ -n, --name <name> Name of the resource
213
+ -t, --type [type] Type of resource (default: default)
214
+ ```
215
+
216
+ ### Positional Arguments Display
217
+
218
+ When commands accept positional arguments (arguments without flags), they appear in the `ARGUMENTS` line:
219
+
220
+ ```sh
221
+ resource-manager (resource-manager v1.0.0)
222
+
223
+ Manage resources
224
+
225
+ USAGE:
226
+ resource-manager manage <OPTIONS> <resource>
227
+
228
+ ARGUMENTS:
229
+ resource Type of resource to manage (e.g., user, project)
230
+
231
+ OPTIONS:
232
+ -h, --help Display this help message
233
+ -v, --version Display this version
234
+ ```
235
+
236
+ Positional arguments are displayed with clear, descriptive names that indicate their purpose. Currently, all positional arguments are shown as required using angle brackets (e.g., `<resource>`).
237
+
238
+ ## Automatic Features
239
+
240
+ Gunshi provides several automatic features without requiring any configuration:
241
+
242
+ ### Help Flag (`--help`, `-h`)
243
+
244
+ - Automatically added to all commands
245
+ - Displays usage information and exits
246
+ - Works at every command level (main and sub-commands)
247
+
248
+ ### Version Flag (`--version`, `-v`)
249
+
250
+ - Automatically added when you provide a `version` in CLI options
251
+ - Displays the version and exits
252
+ - Available at all command levels
253
+
254
+ ### Negatable Boolean Options
255
+
256
+ - Boolean options automatically get `--no-` prefixed versions
257
+ - Allows explicit disabling of boolean flags
258
+ - Example: `--recursive` automatically creates `--no-recursive`
259
+
260
+ ### Invalid Argument Handling
261
+
262
+ - Usage is automatically displayed when users provide invalid arguments
263
+ - Helps users understand what went wrong
264
+ - Provides immediate guidance for correct usage
265
+
266
+ ## Key Points
267
+
268
+ When working with auto-generated usage:
269
+
270
+ - The `--help` flag is automatically added to all commands - you don't need to define it
271
+ - Usage is displayed when users provide invalid arguments or explicitly request help
272
+ - Descriptions in your `args` configuration become the help text for each option
273
+ - The `examples` field accepts both single strings and multi-line strings for multiple examples
274
+ - Sub-command help is accessible both from the main help and individually via `command --help`
275
+ - Required options are shown with angle brackets `<option>` in the USAGE line
276
+ - Boolean options automatically get negatable versions (`--no-` prefix) when not required
277
+ - The `usageOptionType` CLI option adds type annotations to help output
278
+
279
+ ## Next Steps
280
+
281
+ Learn about the [Plugin System](./plugin-system.md) to extend functionality.
@@ -0,0 +1,332 @@
1
+ # Composable Sub-commands
2
+
3
+ In [the previous chapter](./type-safe.md), you learned how to create type-safe commands using the `define` function.
4
+
5
+ Now, let's extend that knowledge to build CLIs with multiple sub-commands while maintaining the same type safety benefits.
6
+
7
+ Gunshi's composable sub-command system allows you to create modular, organized CLIs similar to tools like Git (with commands like `git commit` and `git push`).
8
+
9
+ ## Why Use Sub-commands?
10
+
11
+ Sub-commands are useful when your CLI needs to perform different operations that warrant separate commands.
12
+
13
+ Benefits include:
14
+
15
+ - **Organization**: Group related functionality logically
16
+ - **Scalability**: Add new commands without modifying existing ones
17
+ - **User experience**: Provide a consistent interface for different operations
18
+ - **Help system**: Each sub-command can have its own help documentation
19
+ - **Plugin integration**: Plugins are shared across all sub-commands for consistent functionality
20
+
21
+ ## Basic Structure
22
+
23
+ A CLI with sub-commands typically has this structure:
24
+
25
+ ```sh
26
+ cli <command> [command options]
27
+ ```
28
+
29
+ For example:
30
+
31
+ ```sh
32
+ your-cli create --name my-resource
33
+ ```
34
+
35
+ ## Creating Type-Safe Sub-commands
36
+
37
+ Building on the `define` function from the previous chapter, let's create a CLI with multiple sub-commands:
38
+
39
+ ```ts [cli.ts]
40
+ import { cli, define } from 'gunshi'
41
+
42
+ // Define type-safe sub-commands
43
+ const createCommand = define({
44
+ name: 'create',
45
+ description: 'Create a new resource',
46
+ args: {
47
+ name: { type: 'string', short: 'n', required: true }
48
+ },
49
+ run: ctx => {
50
+ // ctx.values is fully typed
51
+ console.log(`Creating resource: ${ctx.values.name}`)
52
+ }
53
+ })
54
+
55
+ const listCommand = define({
56
+ name: 'list',
57
+ description: 'List all resources',
58
+ run: () => {
59
+ console.log('Listing all resources...')
60
+ }
61
+ })
62
+
63
+ // Define the main command
64
+ const mainCommand = define({
65
+ name: 'manage',
66
+ description: 'Manage resources',
67
+ run: ctx => {
68
+ // This runs when no sub-command is provided
69
+ console.log('Available commands: create, list')
70
+ console.log('Run "manage --help" for more information')
71
+ }
72
+ })
73
+
74
+ // Run the CLI with composable sub-commands
75
+ await cli(process.argv.slice(2), mainCommand, {
76
+ name: 'my-app',
77
+ version: '1.0.0',
78
+ subCommands: {
79
+ create: createCommand,
80
+ list: listCommand
81
+ }
82
+ })
83
+ ```
84
+
85
+ <!-- eslint-disable markdown/no-missing-label-refs -->
86
+
87
+ > [!TIP]
88
+ > The example fully code is [here](https://github.com/kazupon/gunshi/tree/main/playground/essentials/composable/basic).
89
+
90
+ <!-- eslint-enable markdown/no-missing-label-refs -->
91
+
92
+ This structure provides:
93
+
94
+ - Full type safety for all commands and sub-commands
95
+ - Automatic help generation for each command level
96
+ - Shared configuration across the command hierarchy
97
+
98
+ ## Automatic Help for Sub-commands
99
+
100
+ Gunshi automatically generates help documentation for your sub-commands.
101
+
102
+ Using the code from the previous section, you can see the help for each command level:
103
+
104
+ ```sh
105
+ # Show main command help
106
+ $ npx tsx cli.ts --help
107
+
108
+ # Show sub-command help
109
+ $ npx tsx cli.ts create --help
110
+ ```
111
+
112
+ <!-- eslint-disable markdown/no-missing-label-refs -->
113
+
114
+ > [!TIP]
115
+ > [`tsx`](https://github.com/privatenumber/tsx) is a TypeScript execution tool that allows you to run TypeScript files directly without compilation. Use it directly with `npx tsx`.
116
+
117
+ <!-- eslint-enable markdown/no-missing-label-refs -->
118
+
119
+ <!-- eslint-disable markdown/no-missing-label-refs -->
120
+
121
+ > [!NOTE]
122
+ > On Node.js v22.6.0, you can run TypeScript with `--experimental-strip-types`:
123
+ >
124
+ > ```sh
125
+ > node --experimental-strip-types cli.ts --help
126
+ > ```
127
+ >
128
+ > From Node.js v23.6.0 and newer, type stripping is enabled by default (no flag needed for erasable TS). Features requiring transformation (e.g., `enum`) still need `--experimental-transform-types`.
129
+
130
+ <!-- eslint-enable markdown/no-missing-label-refs -->
131
+
132
+ Each sub-command's help includes its description, available options, and usage examples.
133
+
134
+ ## Organizing Your Commands
135
+
136
+ As your CLI grows, organizing commands in separate files improves maintainability.
137
+
138
+ Here's a recommended project structure:
139
+
140
+ ```sh
141
+ my-cli/
142
+ ├── src/
143
+ │ ├── commands/
144
+ │ │ ├── create.ts # Create command implementation
145
+ │ │ └── list.ts # List command implementation
146
+ │ ├── main.ts # Main command definition
147
+ │ └── cli.ts # CLI entry point
148
+ ├── package.json
149
+ └── tsconfig.json
150
+ ```
151
+
152
+ <!-- eslint-disable markdown/no-missing-label-refs -->
153
+
154
+ > [!TIP]
155
+ > The example fully code is [here](https://github.com/kazupon/gunshi/tree/main/playground/essentials/composable/organizing).
156
+
157
+ <!-- eslint-enable markdown/no-missing-label-refs -->
158
+
159
+ This structure provides:
160
+
161
+ - Clear separation of concerns
162
+ - Shared utilities across commands
163
+ - Centralized type definitions
164
+ - Easy testing of individual components
165
+
166
+ ### Individual Command Files
167
+
168
+ ```ts [commands/create.ts]
169
+ import { define } from 'gunshi'
170
+
171
+ export default define({
172
+ name: 'create',
173
+ description: 'Create a new resource',
174
+ args: {
175
+ name: {
176
+ type: 'string',
177
+ short: 'n',
178
+ required: true,
179
+ description: 'Name of the resource'
180
+ },
181
+ type: {
182
+ type: 'string',
183
+ short: 't',
184
+ default: 'default',
185
+ description: 'Type of resource'
186
+ }
187
+ },
188
+ run: ctx => {
189
+ console.log(`Creating ${ctx.values.type} resource: ${ctx.values.name}`)
190
+ }
191
+ })
192
+ ```
193
+
194
+ ```ts [commands/list.ts]
195
+ import { define } from 'gunshi'
196
+
197
+ export default define({
198
+ name: 'list',
199
+ description: 'List all resources',
200
+ args: {
201
+ filter: {
202
+ type: 'string',
203
+ short: 'f',
204
+ description: 'Filter resources'
205
+ }
206
+ },
207
+ run: ctx => {
208
+ const filter = ctx.values.filter || 'all'
209
+ console.log(`Listing resources with filter: ${filter}`)
210
+ }
211
+ })
212
+ ```
213
+
214
+ ### Main Command File
215
+
216
+ ```ts [main.ts]
217
+ import { define } from 'gunshi'
218
+
219
+ export default define({
220
+ name: 'manage',
221
+ description: 'Manage resources',
222
+ run: () => {
223
+ console.log('Use a sub-command')
224
+ console.log('Run "resource-manager --help" for available commands')
225
+ }
226
+ })
227
+ ```
228
+
229
+ ### Entry Point
230
+
231
+ <!-- eslint-disable markdown/no-missing-label-refs -->
232
+
233
+ > [!NOTE]
234
+ > Some code examples in this guide include TypeScript file extensions (`.ts`) in import/export statements. If you use this pattern in your application, you'll need to enable `allowImportingTsExtensions` in your `tsconfig.json`.
235
+
236
+ <!-- eslint-enable markdown/no-missing-label-refs -->
237
+
238
+ ```ts [cli.ts]
239
+ import { cli } from 'gunshi'
240
+ import main from './main.ts'
241
+ import create from './commands/create.ts'
242
+ import list from './commands/list.ts'
243
+
244
+ await cli(process.argv.slice(2), main, {
245
+ name: 'resource-manager',
246
+ version: '1.0.0',
247
+ subCommands: {
248
+ create,
249
+ list
250
+ }
251
+ })
252
+ ```
253
+
254
+ ## Handling Unknown Sub-commands
255
+
256
+ By default, Gunshi shows an error when users provide an unknown sub-command.
257
+
258
+ You can customize this behavior using the `fallbackToEntry` option:
259
+
260
+ ```ts [cli.ts]
261
+ await cli(process.argv.slice(2), main, {
262
+ name: 'resource-manager',
263
+ version: '1.0.0',
264
+ fallbackToEntry: true,
265
+ subCommands: {
266
+ create,
267
+ list
268
+ }
269
+ })
270
+ ```
271
+
272
+ This option enables flexible command handling:
273
+
274
+ ```sh
275
+ # Runs the create sub-command
276
+ npx tsx src/cli.ts create --name resource
277
+ resource-manager (resource-manager v1.0.0)
278
+
279
+ Creating default resource: resource
280
+
281
+ # Runs the list sub-command
282
+ npx tsx src/cli.ts list --filter active
283
+ resource-manager (resource-manager v1.0.0)
284
+
285
+ Listing resources with filter: active
286
+
287
+ # Falls back to main command when "unknown" sub-command is not found
288
+ npx tsx src/cli.ts unknown --flag value
289
+ resource-manager (resource-manager v1.0.0)
290
+
291
+ Use a sub-command
292
+ Run "resource-manager --help" for available commands
293
+
294
+ # Runs the main command directly
295
+ npx tsx src/cli.ts --help
296
+ resource-manager (resource-manager v1.0.0)
297
+
298
+ USAGE:
299
+ resource-manager [COMMANDS] <OPTIONS>
300
+
301
+ COMMANDS:
302
+ [manage] <OPTIONS> Manage resources
303
+ create <OPTIONS> Create a new resource
304
+ list <OPTIONS> List all resources
305
+
306
+ For more info, run any command with the `--help` flag:
307
+ resource-manager --help
308
+ resource-manager create --help
309
+ resource-manager list --help
310
+
311
+ OPTIONS:
312
+ -h, --help Display this help message
313
+ -v, --version Display this version
314
+ ```
315
+
316
+ This approach is particularly useful for CLIs that:
317
+
318
+ - Need to handle file paths or patterns as direct arguments
319
+ - Want to provide a default action when no sub-command matches
320
+ - Implement dynamic command resolution based on context
321
+
322
+ ## Next Steps
323
+
324
+ Throughout this guide, you've learned how to build composable sub-commands that scale from simple to complex CLI applications.
325
+
326
+ You've seen how Gunshi maintains type safety across nested command structures, enables powerful routing patterns with default commands, and supports both synchronous and asynchronous command execution.
327
+
328
+ Now that you understand how to compose commands into well-organized hierarchies, you're ready to explore how to optimize their performance.
329
+
330
+ The next section on [Lazy & Async Command Loading](./lazy-async.md) will show you how to significantly improve your CLI's startup time by loading commands only when they're actually needed.
331
+
332
+ With composable sub-commands as your foundation, adding lazy loading will make your CLI applications both powerful and performant, especially as they grow to include many commands with varying resource requirements.