@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.
- package/LICENSE +20 -0
- package/package.json +52 -0
- package/src/guide/advanced/advanced-lazy-loading.md +312 -0
- package/src/guide/advanced/command-hooks.md +469 -0
- package/src/guide/advanced/context-extensions.md +545 -0
- package/src/guide/advanced/custom-rendering.md +945 -0
- package/src/guide/advanced/docs-gen.md +594 -0
- package/src/guide/advanced/internationalization.md +677 -0
- package/src/guide/advanced/type-system.md +561 -0
- package/src/guide/essentials/auto-usage.md +281 -0
- package/src/guide/essentials/composable.md +332 -0
- package/src/guide/essentials/declarative.md +724 -0
- package/src/guide/essentials/getting-started.md +252 -0
- package/src/guide/essentials/lazy-async.md +408 -0
- package/src/guide/essentials/plugin-system.md +472 -0
- package/src/guide/essentials/type-safe.md +154 -0
- package/src/guide/introduction/setup.md +68 -0
- package/src/guide/introduction/what-is-gunshi.md +68 -0
- package/src/guide/plugin/decorators.md +545 -0
- package/src/guide/plugin/dependencies.md +519 -0
- package/src/guide/plugin/extensions.md +317 -0
- package/src/guide/plugin/getting-started.md +298 -0
- package/src/guide/plugin/guidelines.md +940 -0
- package/src/guide/plugin/introduction.md +294 -0
- package/src/guide/plugin/lifecycle.md +432 -0
- package/src/guide/plugin/list.md +37 -0
- package/src/guide/plugin/testing.md +843 -0
- package/src/guide/plugin/type-system.md +529 -0
- package/src/index.md +44 -0
- package/src/release/v0.27.md +722 -0
- package/src/showcase.md +11 -0
|
@@ -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.
|