Skip to main content
Type safety isn’t just for humans—agents building CLIs with incur get immediate feedback when they pass the wrong argument type or return the wrong shape. Schemas flow through generics so run callbacks, output, and cta commands are all fully inferred with zero manual annotations.

Inferred Arguments and Options

Types flow from Zod schemas to the run callback:
No type annotations needed—TypeScript infers everything from the schemas.

Inferred Output Schema

The output schema validates return values:

Inferred CTA Commands

Command names in CTAs are type-checked:

Inferred CTA Arguments

Arguments in CTA command objects are type-checked:

Inferred Environment Variables

Environment variable types flow to the context:

Inferred Middleware Variables

Variables set by middleware are type-checked:

Const Generics

incur uses const generic parameters to preserve literal types:
This enables precise type-checking in CTAs:

Output Type Inference

Use z.output<> to get the type after transforms and defaults:

Chained Type Inference

Types flow through .command() chains:

Mounted CLI Type Inference

Types flow through mounted sub-CLIs:

Generic Type Flow

How types flow through incur:

Type Inference Path

  1. Schema definition — Zod schema defines the shape
  2. Generic captureconst generic preserves literal types
  3. Output extractionz.output<> gets runtime type
  4. Context typing — Type flows to c.args, c.options, etc.
  5. Validation — Return value is checked against output schema

Type Tests

incur includes type tests to ensure inference works correctly. From src/Cli.test-d.ts:

Zero Annotations

Notice how the examples above have zero type annotations in the run callbacks. Everything is inferred:
This is critical for agents building CLIs—they can focus on logic without wrestling with TypeScript annotations.

Type-Driven Development

Define schemas first, then implementation:
Schemas are the source of truth. Types flow from schemas to callbacks automatically—no manual annotations needed.