Directory Structure
Why This Matters
When an LLM creates a new file, it needs to decide where to put it. Without structure rules, the model defaults to whatever looks common in its training data β which may not match your project at all. A new utility function might land in src/utils/, lib/helpers/, common/, or shared/ depending on the modelβs mood.
Wrong file placement breaks imports, violates module boundaries, and creates an inconsistent codebase. A clear directory structure guideline eliminates this entirely.
What to Include
- Top-level layout β what each root directory contains
- Module boundaries β what can import from what
- Where new files go β rules for adding features, modules, tests, configs, scripts
- Naming conventions for files and directories β kebab-case, PascalCase, etc.
- What doesnβt belong in the repo β generated files, build output, environment files
How to Write It
- Map your current structure. Run
tree -L 2or equivalent and document what you see. - Annotate each directory. A one-line description of what goes there.
- State the import rules. Which layers can depend on which? This prevents the model from creating circular dependencies or violating your architecture.
- Give placement rules for common file types. βNew feature modules go in
src/features/[name]/.β βNew shared helpers go insrc/shared/.β
Example
## Directory Structure
src/
features/ β Capability modules (each owns its local logic and boundaries)
core/ β Domain rules and shared business types
adapters/ β External integrations (DB, HTTP, queues, file I/O)
shared/ β Cross-cutting helpers (pure, framework-light)
config/ β App configuration (loaded from env vars)
tests/
unit/ β Fast isolated tests (no network or external I/O)
integration/ β Boundary tests (real adapters where needed)
e2e/ β Full workflow tests
generated/ β Generated artifacts (read-only)
Dependency rules:
- features may depend on core + adapters + shared
- core must not depend on adapters or framework code
- shared must not import from features
- generated code is never edited by hand
Adding modules:
- New capability? Add `src/features/[name]/`
- New integration? Add `src/adapters/[system]/`
- New reusable helper? Add to `src/shared/` only if reused across features
Common Mistakes
Just showing the tree without import rules. The directory tree tells the model where files go. Import rules tell it how they connect. Both matter.
Being too granular. You donβt need to document every subdirectory. Focus on the top 2 levels and the rules for creating new entries.
Not updating when structure changes. If you refactored from layer-based to feature-based folders (or vice versa), update the guideline. The model will follow whatever you wrote, even if the filesystem says otherwise.
Forgetting generated and ignored files. If dist/, node_modules/, or generated/ shouldnβt be touched, say so. The model might try to edit generated code.
Tool-Specific Notes
- Claude Code: Include in CLAUDE.md. Claude Code navigates your file system, so accurate structure is critical. Subdirectory CLAUDE.md files can add module-specific rules.
- Cursor: Can scope rules to directories with glob patterns. A rule scoped to
src/routes/**can have route-specific guidelines without cluttering the global rules. - Copilot: Include in instructions. Copilot generates code inline so file placement is mostly handled by the user, but import rules still help.
- AGENTS.md: Subdirectory AGENTS.md files can provide directory-specific context (closest file wins).