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
- Schema definition — Zod schema defines the shape
- Generic capture —
const generic preserves literal types
- Output extraction —
z.output<> gets runtime type
- Context typing — Type flows to
c.args, c.options, etc.
- 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.