How to Structure a NestJS Backend for AI-Assisted Development A developer outlined a NestJS backend structure designed for AI coding agents, arguing that repository conventions—not better prompts—keep agents from scattering queries into controllers, leaking entities, or running migrations unprompted. The approach centralizes rules in a single AGENTS.md (imported by CLAUDE.md and referenced by Gemini CLI settings), enforces a Controller → Service → Repository dependency rule, standardizes errors through a single AppException hierarchy and global filter with stable UPPER_SNAKE codes, and keeps default test suites infrastructure-free so agents actually run them. AI coding agents are good at writing NestJS code and bad at guessing your NestJS conventions. Left alone, they put queries in controllers, return entities straight from the database, add a fourth way of throwing errors, and cheerfully offer to run migration:run against whatever database your .env points at. The fix is not a cleverer prompt. It's a repository that states its rules where agents read them, makes correct changes cheap to verify, and enforces the few rules that must never be broken. Here's the structure I use. None of it needs a particular agent. Every major agent now reads a project instruction file. Codex, Cursor, GitHub Copilot and Gemini CLI with one setting read AGENTS.md . Claude Code reads CLAUDE.md , which can import another file. So: php < -- CLAUDE.md -- @AGENTS.md Claude Code specifics skills, subagents, permission rules: only what is genuinely Claude-specific // .gemini/settings.json { "context": { "fileName": "AGENTS.md" } } Rules live in AGENTS.md only. The day you have the same rule in two files, they start to drift, and some tools Copilot CLI, for one merge every instruction file they find without a precedence order. Keep AGENTS.md short a project map, commands, conventions, safety rules, report format and link to docs/ for detail. "Write clean code" changes nothing. What changes behaviour is a short list of things the agent must not do, written as rules with the exact words you want back: Stop rules 1. Do not generate, run or revert migrations until the user tells you to in this conversation. An entity change is not permission. Make the code change and report: "Schema change detected. Migration required. Not generated or run: no explicit approval." 2. Do not run or edit seeds until the user tells you to. 3. Do not format code. The pre-commit hook formats staged files; CI checks formatting. Rule 3 is a cost rule: formatting runs burn agent time and produce noisy diffs, and Husky + lint-staged already do it on every commit. Agents copy what they see. If the codebase has one pattern, they copy that one. Pick an explicit structure and write it down: src/