Skip to main content
Register composable before/after hooks with cli.use(). Middleware executes in registration order, onion-style—each calls await next() to proceed to the next middleware or the command handler.

Basic Middleware

Use middleware for cross-cutting concerns like timing, logging, or auth:
Output

Middleware Context

Middleware receives a context object with metadata:
Output

Context Properties

PropertyTypeDescription
c.namestringThe CLI name
c.commandstringThe resolved command path
c.versionstring | undefinedCLI version
c.agentbooleanWhether stdout is not a TTY
c.envobjectParsed environment variables
c.varobjectVariables set by upstream middleware
c.set(key, value)functionSet a typed variable
c.error(opts)functionReturn an error result

Authentication Middleware

Short-circuit the chain by returning early:
Output

Dependency Injection with Variables

Declare a vars schema to enable typed variables. Middleware sets them with c.set(), and both middleware and command handlers read them via c.var:
Output

Default Values

Use .default() for variables that don’t need middleware:

Per-Command Middleware

Run middleware only for specific commands:
Output
Per-command middleware runs after root and group middleware.

Error Handling

Middleware can handle errors from downstream middleware or commands:

Structured Errors

Return structured errors with error codes:
Output
Structured errors show up in the output envelope with code and retryable flag.

Throwing Errors

Throwing also works and produces an UNKNOWN error code:

Typed Middleware

Use the middleware() helper for full type safety:

Environment Variables

Access parsed environment variables in middleware:
Environment variables are validated once at startup before any middleware runs.

Middleware Order

Middleware executes in an onion pattern:
Output

Execution Order

  1. Root CLI middleware (in registration order)
  2. Group CLI middleware (if mounted)
  3. Per-command middleware (if defined)
  4. Command run handler

Source Code

The middleware implementation is in src/middleware.ts:
Use middleware for cross-cutting concerns like auth, logging, and timing. Use variables (c.var and c.set()) for type-safe dependency injection.