CLI
Scaffold noddde projects, domains, aggregates, projections, and sagas from the command line
The @noddde/cli package provides generators that scaffold noddde modules with the correct folder structure, type definitions, and wiring code.
Installation
npm install -g @noddde/cliOr use it without installing via npx:
npx @noddde/cli new project my-appCommands
All generators are under noddde new (alias noddde n).
noddde new project <name>
Scaffolds a complete runnable project with package.json, TypeScript config, a sample test, and the full domain structure inside src/.
noddde new project hotel-bookingThe command prompts you to choose a persistence adapter:
? Which persistence adapter?
❯ In-memory (no external dependencies)
Prisma (SQLite via @noddde/prisma)
Drizzle (SQLite via @noddde/drizzle)
TypeORM (@noddde/typeorm)Your choice determines which dependencies are added to package.json. You can always change this later.
After scaffolding:
cd hotel-booking
npm install
npm test # runs the sample test
npm start # runs src/main.tsSee Project Structure for a full breakdown of the generated layout.
noddde new domain <name>
Scaffolds the domain layer only — no package.json or config files. Use this when adding a domain to an existing project.
cd src
noddde new domain hotel-bookingGenerates event-model/, write-model/, read-model/, domain.ts, infrastructure/, and main.ts in the current directory.
noddde new aggregate <name>
Scaffolds a single aggregate with extracted command handlers. Run from the project root — the CLI automatically places files at src/domain/write-model/aggregates/<name>/.
noddde new aggregate BankAccountGenerates:
bank-account/
├── index.ts # barrel exports
├── state.ts # BankAccountState interface + initial state
├── bank-account.ts # defineAggregate + DefineEvents/DefineCommands
├── commands/
│ ├── index.ts
│ └── create-bank-account.ts # command payload interface
└── command-handlers/
├── index.ts
└── handle-create-bank-account.ts # standalone handler functionCommand handlers are standalone exported functions imported into the defineAggregate commands map. This keeps handlers testable in isolation and aggregates readable.
noddde new projection <name>
Scaffolds a single projection with extracted query handlers and view reducers. Run from the project root — the CLI automatically places files at src/domain/read-model/projections/<name>/.
noddde new projection OrderSummaryGenerates:
order-summary/
├── index.ts # barrel exports
├── order-summary.ts # defineProjection with on map
├── queries/
│ ├── index.ts # View interface + DefineQueries
│ └── get-order-summary.ts # query payload interface
├── query-handlers/
│ ├── index.ts
│ └── handle-get-order-summary.ts # standalone query handler
└── view-reducers/
├── index.ts
└── on-order-summary-created.ts # standalone reduce functionView reducers and query handlers are standalone functions imported into the defineProjection on and queryHandlers maps respectively.
noddde new saga <name>
Scaffolds a saga with extracted transition handlers. Run from the project root — the CLI automatically places files at src/domain/process-model/<name>/.
noddde new saga PaymentProcessingGenerates:
payment-processing/
├── index.ts # barrel exports
├── state.ts # PaymentProcessingSagaState + initial state
├── saga.ts # defineSaga with on map, imports handlers
└── transition-handlers/
├── index.ts
└── on-start-event.ts # standalone transition handler functionTransition handlers are standalone exported functions imported into the defineSaga on map. Each handler receives an event and the current saga state, and returns the new state plus optional commands to dispatch.
Name Handling
Names can be provided in any casing — the CLI normalizes them:
noddde new aggregate BankAccount # PascalCase
noddde new aggregate bank-account # kebab-case
noddde new aggregate bank_account # snake_caseAll three produce the same output: a bank-account/ directory with BankAccount as the PascalCase identifier in code.
Names must produce a valid TypeScript identifier (start with a letter). The CLI rejects invalid names with a clear error.