nest-commander
nest-commander lets NestJS developers build command-line apps using the same decorators, DI, and modules as their web services.
Repository Health
Technical Analysis
nest-commander brings NestJS’s dependency-injection and module architecture to command-line applications, letting developers structure CLIs the same way they structure NestJS HTTP or RPC services. Commands are defined as injectable classes decorated with @Command(), with @Option() decorators marking methods that parse individual CLI flags, and the library wires everything into a Commander.js instance under the hood via CommandFactory.run().
Beyond basic argument parsing, the package supports subcommands, root/default commands, shell-completion generation, a plugin system for extending third-party CLIs, and Inquirer.js integration for interactive prompts through @QuestionSet() and @Question() decorators. A companion nest-commander-testing package and a code-generation schematic round out the toolkit for teams building production CLI tools inside an existing NestJS codebase.
What You Get
@Command()and@Option()decorators for defining CLI commands and flags as injectable NestJS providers- A
CommandFactorythat bootstraps a Nest application context and drives Commander.js parsing/execution - Inquirer.js integration via
@QuestionSet()/@Question()for interactive prompts with validation, defaults, and conditional questions - Built-in support for subcommands, root/default commands, and shell tab-completion generation
- A companion
nest-commander-testingpackage for writing unit tests against command classes
Common Use Cases
- Internal developer tooling CLIs (scaffolding, codegen, deployment scripts) built inside an existing NestJS monorepo
- Database migration/seed scripts that need the same providers and services already registered in a Nest app
- Interactive setup wizards using Inquirer question sets alongside strict Commander argument parsing
- Publishing an npm-distributed CLI tool (like a custom
create-x-app) using Nest’s DI for testability
Under The Hood
Architecture
The library layers cleanly: command.decorators.ts only attaches reflect-metadata onto classes and methods (@Command, @Option, @QuestionSet, etc.); command-runner.service.ts, a Nest OnModuleInit provider, uses @golevelup/nestjs-discovery to scan the live DI container for providers carrying that metadata and assembles a real Commander.js Command tree from them (including recursive subcommand construction and an option-name remapping step); and command.factory.ts is the single public entrypoint, mirroring NestFactory’s own create/run contract by spinning up a full NestFactory.createApplicationContext before handing control to the runner service. Because command classes are constructed by the live Nest container before buildCommand runs, the whole system depends on commands resolving cleanly as standard injectable providers, and a change to the core CommandRunner.run(passedParams, options) contract would ripple through every decorator, the discovery pass, and the argument/option mapping logic together.
Tech Stack
Written in TypeScript and built through an Nx-managed pnpm monorepo (nx.json, pnpm-workspace.yaml), compiled with SWC (@swc/core, .swcrc). Runtime dependencies are commander (pinned to 11.1.0), inquirer (the legacy 8.x CJS API), cosmiconfig for rc-file-based plugin discovery, @golevelup/nestjs-discovery for provider/metadata scanning, and @fig/complete-commander for shell-completion generation; @nestjs/common/@nestjs/core are peer dependencies so the module tracks whatever Nest version the host app uses. A separate Astro + Preact/MDX docs site with Algolia DocSearch lives alongside the library packages, and releases are automated with Changesets and conventional-commit tooling (commitlint, husky, lint-staged).
Code Quality
Tests are extensive rather than minimal: 19 integration spec files under integration/ exercise basic commands, subcommands, root commands, plugins, option choices, output configuration, version flags, help text, and edge cases around this-binding, all run through a dedicated jest.integration.config.js against ts-jest. ESLint (typescript-eslint + Prettier integration) and Prettier are enforced via husky pre-commit hooks and lint-staged, with a GitHub Actions CI workflow running lint/build/test on every change. Error handling is explicit rather than swallowed — CommandRunnerService wraps command execution in try/catch, rethrows, and adds a targeted log message for a documented request-scoped-provider pitfall. Typing is strict TypeScript throughout, with looser Record<string, any> shapes appearing only where reflect-metadata-based option passing inherently requires it.
API Design
The public API is deliberately isomorphic to NestJS itself: CommandFactory.run(AppModule) mirrors NestFactory.create(AppModule), and @Command()/@Option() read like @Controller()/@Get() for CLI classes, so an existing Nest developer needs almost no new mental model to get a first command running. The main friction point is that option flags and the resulting options object are not type-linked automatically — consumers must hand-write an options interface to get compile-time safety on @Option() return values — and the cosmiconfig-based plugin mechanism is only lightly documented beyond a couple of README paragraphs.
Used by 3 apps in this directory
Bigcapital
Invoicing Finance
Self-hostable double-entry accounting platform with invoicing, inventory, multi-currency, and real-time financial reporting for small and medium businesses.
Hexabot
AI Development · Automation
Build and run agentic workflows across channels with YAML, tools, and RAG
twenty
CRM
The open-source CRM you build, ship, and version like the rest of your stack — with customizable objects, AI agents, and a TypeScript SDK.