> ## Documentation 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.

# Commands

> Register and define commands with arguments, options, and handlers

## Overview

Commands are registered with `.command()`, which accepts a name and a definition object containing schemas, metadata, and a `run` handler.

## Registering Commands

Chain `.command()` calls to register multiple commands:

```typescript theme={null}
import { Cli, z } from 'incur'

Cli.create('my-cli', { description: 'My CLI' })
  .command('status', {
    description: 'Show repo status',
    run() {
      return { clean: true }
    },
  })
  .command('install', {
    description: 'Install a package',
    args: z.object({
      package: z.string().describe('Package name'),
    }),
    run(c) {
      return { installed: c.args.package }
    },
  })
  .serve()
```

```bash theme={null}
$ my-cli status
clean: true

$ my-cli install express
installed: express
```

## Command Definition Structure

A command definition includes schemas for inputs, output, and the handler function.

### Required Fields

<ParamField path="run" type="function" required>
  The command handler. Receives a context object with parsed `args`, `options`, `env`, and helper functions. Can return a value, a Promise, or an AsyncGenerator for streaming.
</ParamField>

### Input Schemas

<ParamField path="args" type="z.ZodObject<any>">
  Zod schema for positional arguments. Keys define the order arguments are parsed.

  ```typescript theme={null}
  args: z.object({
    source: z.string().describe('Source file'),
    dest: z.string().describe('Destination file'),
  })
  ```
</ParamField>

<ParamField path="options" type="z.ZodObject<any>">
  Zod schema for named options/flags.

  ```typescript theme={null}
  options: z.object({
    force: z.boolean().optional().describe('Overwrite existing files'),
    verbose: z.boolean().default(false).describe('Show detailed output'),
  })
  ```
</ParamField>

<ParamField path="env" type="z.ZodObject<any>">
  Zod schema for environment variables. Keys are the variable names.

  ```typescript theme={null}
  env: z.object({
    DEPLOY_TOKEN: z.string(),
    API_BASE: z.string().default('https://api.example.com'),
  })
  ```
</ParamField>

<ParamField path="output" type="z.ZodType">
  Zod schema for the return value. Validates the data returned from `run()`.

  ```typescript theme={null}
  output: z.object({
    url: z.string(),
    duration: z.number(),
  })
  ```
</ParamField>

### Metadata

<ParamField path="description" type="string">
  A short description of what the command does. Shown in help output.
</ParamField>

<ParamField path="alias" type="Record<string, string>">
  Map of option names to single-character aliases.

  ```typescript theme={null}
  alias: { saveDev: 'D', force: 'f' }
  ```

  Enables `-D` as shorthand for `--saveDev`.
</ParamField>

<ParamField path="examples" type="Example[]">
  Usage examples shown in help output.

  ```typescript theme={null}
  examples: [
    { args: { env: 'staging' }, description: 'Deploy to staging' },
    { args: { env: 'production' }, options: { force: true }, description: 'Force deploy to production' },
  ]
  ```
</ParamField>

<ParamField path="hint" type="string">
  Plain text hint displayed in help after examples and before global options.
</ParamField>

### Behavior

<ParamField path="format" type="'toon' | 'json' | 'yaml' | 'md' | 'jsonl'">
  Default output format for this command. Overrides CLI-level format.
</ParamField>

<ParamField path="outputPolicy" type="'all' | 'agent-only'">
  Controls when output data is displayed. Overrides CLI-level or group-level policy.
</ParamField>

<ParamField path="middleware" type="MiddlewareHandler[]">
  Middleware that runs only for this command, after root and group middleware.
</ParamField>

## Mounting Sub-CLIs

Mount another CLI instance as a command group by passing it directly to `.command()`:

```typescript theme={null}
import { Cli, z } from 'incur'

const cli = Cli.create('my-cli', { description: 'My CLI' })

// Create a sub-group for database commands
const db = Cli.create('db', { description: 'Database commands' })
  .command('migrate', {
    description: 'Run migrations',
    run() {
      return { migrated: true }
    },
  })
  .command('seed', {
    description: 'Seed the database',
    run() {
      return { seeded: true }
    },
  })

cli
  .command('run', {
    description: 'Run a task',
    run() {
      return { ok: true }
    },
  })
  .command(db)  // Mount the db group
  .serve()
```

```bash theme={null}
$ my-cli db migrate
migrated: true

$ my-cli db seed
seeded: true
```

## Run Handler Context

The `run` function receives a context object with parsed inputs and helpers:

```typescript theme={null}
run(c) {
  c.agent      // boolean: true if stdout is not a TTY (consumed by an agent)
  c.args       // Parsed positional arguments
  c.options    // Parsed named options
  c.env        // Parsed environment variables
  c.var        // Variables set by middleware
  c.name       // CLI name
  c.version    // CLI version string
  
  // Helpers
  c.ok(data, { cta })    // Return success with optional CTAs
  c.error({ code, message, cta })  // Return error with optional CTAs
}
```

### Returning Success

Return a value directly or use `c.ok()` to attach CTAs:

```typescript theme={null}
run(c) {
  return { deployed: true }
}

// With CTAs
run(c) {
  return c.ok(
    { deployed: true },
    {
      cta: {
        commands: [
          { command: 'logs', description: 'View logs' },
          { command: 'status', description: 'Check status' },
        ],
      },
    }
  )
}
```

### Returning Errors

Throw an error or use `c.error()` for structured errors:

```typescript theme={null}
run(c) {
  throw new Error('Something went wrong')
}

// Structured error with code
run(c) {
  return c.error({
    code: 'NOT_AUTHENTICATED',
    message: 'Token not found',
    retryable: false,
  })
}
```

## Async Handlers

Handlers can be async:

```typescript theme={null}
run(async c) {
  const response = await fetch('https://api.example.com/data')
  const data = await response.json()
  return data
}
```

## Streaming Handlers

Use `async *run` to stream chunks incrementally:

```typescript theme={null}
cli.command('logs', {
  description: 'Tail logs',
  async *run() {
    yield 'connecting...'
    yield 'streaming logs'
    yield 'done'
  },
})
```

```bash theme={null}
$ my-cli logs
connecting...
streaming logs
done
```

With `--format jsonl`, each chunk becomes `{"type":"chunk","data":"..."}`. You can also yield objects:

```typescript theme={null}
async *run() {
  yield { progress: 50 }
  yield { progress: 100 }
}
```

Return `c.ok()` or `c.error()` from a streaming handler to attach CTAs:

```typescript theme={null}
async *run(c) {
  yield { step: 1 }
  yield { step: 2 }
  return c.ok(undefined, {
    cta: {
      commands: [{ command: 'status', description: 'Check status' }],
    },
  })
}
```

## Command Aliases

Use the `alias` field to define single-character shortcuts for options:

```typescript theme={null}
cli.command('deploy', {
  options: z.object({
    force: z.boolean().optional(),
    dryRun: z.boolean().optional(),
  }),
  alias: { force: 'f', dryRun: 'n' },
  run(c) {
    return { deployed: !c.options.dryRun }
  },
})
```

```bash theme={null}
$ my-cli deploy -f
deployed: true

$ my-cli deploy -fn
deployed: false
```

Short aliases can be stacked (e.g. `-fn`) when all but the last are boolean flags.

## Agent Detection

The `c.agent` boolean is `true` when stdout is not a TTY (piped or consumed by an agent). Use it to tailor behavior:

```typescript theme={null}
cli.command('deploy', {
  args: z.object({
    env: z.enum(['staging', 'production']),
  }),
  run(c) {
    if (!c.agent) {
      console.log(`Deploying to ${c.args.env}...`)
    }
    return { url: `https://${c.args.env}.example.com` }
  },
})
```

## Next Steps

<CardGroup cols={2}>
  <Card title="Schemas" icon="shield-check" href="/core-concepts/schemas">
    Explore Zod schema validation and type inference
  </Card>

  <Card title="Output" icon="terminal" href="/core-concepts/output">
    Learn about output formats and CTAs
  </Card>
</CardGroup>
