Running copilot inside a NestJS project gives you an agent that can read your existing modules, DTOs, and test files from the terminal. The practical workflow is to codify NestJS conventions in an instructions file, then use the agent in small, tested chunks. This guide covers setup, prompts, pitfalls, and verification for NestJS teams.
Why NestJS’s predictable structure helps Copilot CLI
NestJS has a strongly standardized structure: modules declare controllers and providers, decorators define routes and dependency injection, and class-validator handles DTO validation. This consistency helps the agent generate code that matches the existing codebase. Because NestJS is TypeScript-first, the CLI can use tsconfig, package.json, Jest configuration, and Prisma or TypeORM schema files to work with the actual types instead of guessing. For example, when you ask it to add a PaymentsModule, it can inspect src/modules/orders or src/modules/users and mirror the same controller-service-DTO pattern. This reduces the number of boilerplate errors that normally come from copy-pasting module files. It is most useful for repetitive but detail-heavy tasks like adding a new feature slice, writing validation DTOs, updating module metadata, and generating Jest specs. The agent is especially effective when the project already has a clean module structure; if modules are messy, spend a sprint cleaning boundaries before relying on it. However, NestJS runtime behavior depends on metadata that TypeScript alone does not verify, so the agent needs clear guardrails.
Writing project instructions for GitHub Copilot CLI in NestJS
Add either .github/copilot-instructions.md or AGENTS.md at the repository root. Keep it short and prescriptive; the agent reads it at the start, so list only commands and rules that matter for NestJS. A useful file includes build, test, and lint commands, folder structure, module-boundary rules, DTO validation conventions, and the data-access layer choice. If you use TypeORM instead of Prisma, change the data-access bullet to use repositories and entities. Either way, name the exact service class the agent should inject. Keep the file versioned and review it when directory conventions change; stale instructions cause more harm than no instructions. The general setup flow is covered in How to use GitHub Copilot CLI: a step-by-step guide.
Example instructions file:
# NestJS instructions
## Commands
- Install: npm ci
- Build: npm run build
- Lint: npm run lint
- Test: npm run test
- e2e: npm run test:e2e
## Structure
- Keep one feature per module under src/modules/<feature>/
- Controllers only parse HTTP input and return responses
- Providers contain business logic and data access
- DTOs live in src/modules/<feature>/dto/ and use class-validator decorators
- Use PrismaService from src/prisma/prisma.service.ts for database access
## Rules
- Do not change global config, tsconfig.json, or package.json without asking
- Always register controllers and providers in the module metadata
- Preserve existing dependency injection and naming patterns
- Add or update Jest tests for new services, controllers, and DTO validation
- Run npm run lint and npm run test before reporting a task as done
A NestJS change loop: plan small, test often, review diff
Work in small deltas: describe the change, let the agent propose a plan, then execute. Before writing code, ask the agent to list which files it will touch and any new dependencies it wants to add. This is where you catch module-boundary mistakes early. After each task, run lint, tests, and a build; review the git diff before moving on. After the agent finishes, run git diff --stat and open the changed .module.ts files first; this is the fastest way to spot missing providers or controllers. If a task spans several modules, split it into one prompt per module and run the test suite between them. For larger features, write a short spec first and paste it into the agent. More structured execution is covered in Spec-driven development with AI agents: a practical guide.
Example prompts for common NestJS tasks:
- “Create a UsersModule with UsersController, UsersService, and a CreateUserDto using class-validator. Register it in AppModule and add a Jest unit test for UsersService.”
- “Add GET /users/:id to UsersController. Use Prisma to fetch the user and throw NotFoundException with a useful message when no user exists.”
- “Refactor AuthService into AuthModule with a separate TokenService provider. Update module imports and existing tests.”
- “Add an e2e test for POST /auth/login using supertest; mock the database and assert the JWT response shape.”
- “Find potential circular dependencies in src/modules/orders before we add a new export.”
Good fits and pitfalls in NestJS code generation
The agent performs well on simple modules, DTOs with validation decorators, CRUD controllers, service unit tests, and Prisma or TypeORM queries. It also handles “explain this module” or “where is the validation for this DTO” questions well because it can search across the codebase. It is also useful for explaining existing NestJS wiring and suggesting refactors.
Watch these NestJS-specific pitfalls after every generated change:
- Missing or incorrect module metadata: a generated service may not be added to the providers array, or a controller may be missing from controllers.
- Wrong injection tokens: custom providers may use strings or symbols; the agent can mix them up.
- DTO validation gaps: class-validator decorators may be incomplete, especially for nested objects and arrays.
- Over-eager relations: TypeORM or Prisma queries can load too much data or create circular JSON in responses.
- Test over-mocking: generated Jest tests may mock internals so heavily that they no longer test real NestJS dependency injection behavior.
A common failure is generating a module file where the controller or provider is imported but not registered. Always open the generated .module.ts first. For Prisma, ask it to use the generated client types; for TypeORM, prefer the repository pattern and avoid raw query builder unless there is no alternative.
Verifying generated code: build, lint, and Jest for NestJS
NestJS makes testing natural with Jest and TestingModule. After any agent change, have it run the full verification set and then fix only the failures caused by its change.
| Check | Why it matters for NestJS |
|---|---|
npm run build | Catches TypeScript errors such as missing decorators, wrong DI types, and broken imports |
npm run test | Runs Jest unit tests; verifies providers, controllers, and DTO validation logic |
npm run test:e2e | Executes HTTP-level tests through the real module graph, including pipes and guards |
npm run lint | Enforces import order, unused providers, and formatting rules |
The agent can write a test that creates a TestingModule with the provider under test and a mock repository; review that the test asserts behavior and not internal method calls. For e2e, use the app from AppModule with a supertest agent, and ensure any global pipes, filters, or guards are applied the same way as in main.ts. When a generated test fails due to missing module imports, the fix is usually in the test’s testing module, not the source code. Ask the agent to update or add tests for any new code before you accept the diff. When a test fails, have the agent read the failure output and change only the relevant module or spec file.
Coordinating multiple agents on a NestJS codebase with AgentVera
When a NestJS project splits into several feature modules, multiple agents can work in parallel through AgentVera, each in its own terminal and git worktree, so independent changes do not overwrite each other. Automatic code review after each turn is especially useful for catching NestJS module metadata and dependency injection mistakes, with findings linked to file and line. Checkpoints let you undo a bad refactor, and token budgets stop a long-running agent from consuming the whole day. This fits the modular, test-driven way NestJS teams usually work.
Final thoughts on using Copilot CLI for NestJS
GitHub Copilot CLI is not a replacement for understanding NestJS, but it becomes a reliable workhorse when you feed it the right project instructions and keep changes small. Focus on DTOs, module wiring, providers, and Jest verification, and review the diff for NestJS-specific mistakes. With that loop, it can speed up routine feature work without sacrificing the structure that makes NestJS maintainable.