Multi-command CLIs act as routers, directing execution to different handlers based on the subcommand. This is the pattern used by tools likeDocumentation Index
Fetch the complete documentation index at: https://mintlify.com/wevm/incur/llms.txt
Use this file to discover all available pages before exploring further.
git, docker, and npm.
When to Use Multi-Command Pattern
Use this pattern when your CLI:- Provides multiple related operations
- Needs a clean namespace for different actions
- Benefits from command-specific help
git commit, docker build, npm install
Creating a Router CLI
cli
.command('status', {
description: 'Show repo status',
run() {
return { clean: true }
},
})
.command('install', {
description: 'Install a package',
args: z.object({
package: z.string().optional().describe('Package name'),
}),
options: z.object({
saveDev: z.boolean().optional().describe('Save as dev dependency'),
}),
alias: { saveDev: 'D' },
run(c) {
return { added: 1, packages: 451 }
},
})
.serve()
Command Organization
Each command is self-contained with its own args, options, and handler:Help Text Generation
Help is automatically generated for the router and each command.Router Help
Command-Specific Help
Multiple Arguments Per Command
Each command can have its own argument schema:Complete Multi-Command Example
Here’s a complete package manager CLI:Usage Examples
Type Safety
All arguments and options are fully typed:The
.command() method returns the same CLI instance, so you can chain as many commands as you need. The type system tracks all registered commands for features like CTAs.Router vs Single-Command
| Feature | Router (no run) | Single-Command (with run) |
|---|---|---|
| Subcommands | ✓ Yes | ✗ No |
| Root handler | ✗ No | ✓ Yes |
| Use case | Multi-purpose tool | Single-purpose utility |
| Help format | Lists commands | Shows usage |
| Example | git, docker | grep, curl |

