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.
Declare a vars schema on Cli.create() to enable typed variables. Middleware sets them with c.set(), and both middleware and command handlers read them via c.var.
Basic Usage
import { Cli, z } from 'incur'
type User = { id: string; name: string }
const cli = Cli.create('my-cli', {
description: 'My CLI',
vars: z.object({
user: z.custom<User>(),
requestId: z.string(),
debug: z.boolean().default(true),
}),
})
cli.use(async (c, next) => {
c.set('user', await authenticate())
c.set('requestId', crypto.randomUUID())
await next()
})
cli.command('whoami', {
run(c) {
return { user: c.var.user, requestId: c.var.requestId, debug: c.var.debug }
},
})
$ my-cli whoami
# → user:
# → id: u_123
# → name: Alice
# → requestId: 550e8400-e29b-41d4-a716-446655440000
# → debug: true
How It Works
- Declare the schema — pass
vars to Cli.create() with a Zod object schema
- Set values in middleware — call
c.set(key, value) to populate variables
- Read in handlers — access
c.var.key in middleware or command handlers
Variable Defaults
Use .default() for variables that don’t need middleware:
const cli = Cli.create('my-cli', {
description: 'My CLI',
vars: z.object({
debug: z.boolean().default(false),
timeout: z.number().default(30_000),
}),
})
cli.command('run', {
run(c) {
// debug and timeout are available without middleware
return { debug: c.var.debug, timeout: c.var.timeout }
},
})
Middleware Example
Authentication
import { Cli, middleware, z } from 'incur'
type User = { id: string; name: string; admin: boolean }
const cli = Cli.create('my-cli', {
description: 'My CLI',
vars: z.object({ user: z.custom<User>() }),
})
const requireAuth = middleware<typeof cli.vars>((c, next) => {
if (!c.var.user) return c.error({ code: 'AUTH', message: 'must be logged in' })
return next()
})
const requireAdmin = middleware<typeof cli.vars>((c, next) => {
if (!c.var.user?.admin) throw new Error('admin required')
return next()
})
cli.command('deploy', {
middleware: [requireAuth, requireAdmin],
run() {
return { deployed: true }
},
})
$ my-cli deploy
# Error (AUTH): must be logged in
Request Context
const cli = Cli.create('my-cli', {
description: 'My CLI',
vars: z.object({
requestId: z.string(),
startTime: z.number(),
}),
})
cli.use(async (c, next) => {
c.set('requestId', crypto.randomUUID())
c.set('startTime', Date.now())
await next()
})
cli.command('run', {
run(c) {
const duration = Date.now() - c.var.startTime
return { requestId: c.var.requestId, duration }
},
})
Type Inference
The vars schema flows through generics to middleware and command handlers:
const cli = Cli.create('my-cli', {
vars: z.object({
user: z.custom<User>(),
requestId: z.string(),
}),
})
cli.use((c, next) => {
c.var.user // Type: User | undefined
c.var.requestId // Type: string | undefined
c.set('user', { id: 'u_123', name: 'Alice' })
c.set('requestId', crypto.randomUUID())
return next()
})
cli.command('whoami', {
run(c) {
c.var.user // Type: User | undefined
c.var.requestId // Type: string | undefined
return { user: c.var.user }
},
})
Middleware Type Hints
For external middleware, use the middleware helper with type parameters:
import { middleware, z } from 'incur'
type User = { id: string; name: string }
const vars = z.object({ user: z.custom<User>() })
const auth = middleware<typeof vars>((c, next) => {
c.var.user // Type: User | undefined
c.set('user', await authenticate())
return next()
})
const cli = Cli.create('my-cli', { vars })
cli.use(auth)
Environment + Variables
Combine CLI-level env with vars for environment variables plus middleware state:
const cli = Cli.create('my-cli', {
description: 'My CLI',
env: z.object({
API_TOKEN: z.string(),
}),
vars: z.object({
user: z.custom<User>(),
}),
})
cli.use(async (c, next) => {
// CLI-level env is available in middleware
const token = c.env.API_TOKEN
const user = await fetchUser(token)
c.set('user', user)
await next()
})
cli.command('whoami', {
run(c) {
// Both env and var are available
return { user: c.var.user, hasToken: !!c.env.API_TOKEN }
},
})
Typing External Middleware
For middleware defined outside your CLI, pass both vars and env as type parameters:
import { middleware, z } from 'incur'
type User = { id: string; name: string }
const vars = z.object({ user: z.custom<User>() })
const env = z.object({ API_TOKEN: z.string() })
const auth = middleware<typeof vars, typeof env>((c, next) => {
c.var.user // Type: User | undefined
c.env.API_TOKEN // Type: string
return next()
})
Per-Command Middleware
Per-command middleware inherits the CLI’s vars schema:
const cli = Cli.create('my-cli', {
vars: z.object({ user: z.custom<User>() }),
})
const requireAdmin = middleware<typeof cli.vars>((c, next) => {
if (!c.var.user?.admin) throw new Error('admin required')
return next()
})
cli.command('deploy', {
middleware: [requireAdmin],
run() {
return { deployed: true }
},
})
Best Practices
- Use
vars for state set by middleware (user, session, etc.)
- Use
.default() for static configuration (timeouts, flags)
- Use
z.custom<T>() for complex types
- Type external middleware with
middleware<typeof cli.vars, typeof cli.env>()
Don’t
- Don’t use
vars for arguments or options — use args and options schemas
- Don’t use
vars for environment variables — use env schema
- Don’t mutate
c.var directly — always use c.set()