Skip to main content
Sub-commands let you group related commands under a namespace. This creates nested hierarchies like my-cli pr list or docker container ls.

When to Use Sub-Commands

Use sub-commands when you need:
  • Logical grouping - Group related operations (e.g., all PR commands under pr)
  • Namespace separation - Keep command names short without conflicts
  • Modular organization - Split large CLIs into separate modules
  • Deep hierarchies - Create multi-level command trees
Examples: git remote add, docker container stop, gh pr create

Creating Command Groups

1
Create the root CLI
2
Start with a router CLI:
3
import { Cli, z } from 'incur'

const cli = Cli.create('my-cli', {
  description: 'My CLI',
})
4
Create a separate group CLI
5
Create another Cli instance for the group:
6
const pr = Cli.create('pr', {
  description: 'Pull request commands',
})
7
Add commands to the group
8
pr.command('list', {
  description: 'List pull requests',
  options: z.object({
    state: z.enum(['open', 'closed', 'all']).default('open'),
  }),
  run(c) {
    return { prs: [], state: c.options.state }
  },
})
9
Mount the group
10
Mount the group on the root CLI:
11
cli
  .command(pr)  // Mount the entire pr group
  .serve()

Complete Example from README

Here’s the complete PR group example from the incur README:

Usage

Help Text

Multiple Commands in a Group

Add multiple commands to create a rich command group:

Multiple Groups

Mount multiple command groups on the root CLI:

Nested Command Hierarchies

You can nest groups multiple levels deep:

Output Policy Inheritance

Groups can set output policies that inherit to all child commands:
When users run my-cli internal sync in a terminal, they won’t see the output data (but agents will receive it via --json or --format).

Override per Command

Middleware Inheritance

Groups can register middleware that runs for all child commands:
Middleware runs in order: root CLI → groups (in traversal order) → per-command. Each level’s middleware wraps the next.

Best Practices

Group by Domain

Organize groups around logical domains:

Keep Groups Focused

Each group should have a clear purpose:

Use Consistent Naming

Use consistent verb patterns within groups:
Sub-command names must be unique within their parent. Don’t create two commands with the same name in the same group.