Repository Boundaries
Sets clear limits on files and directories an agent may inspect or modify.
Scenario
You have a TypeScript application divided into three important areas:
features
shared
generated
Developers understand that generated files should not be edited manually and that feature modules should not reach directly into another feature's internal files.
A coding agent may not know those boundaries.
You want AGENTS.md to make the repository's ownership rules explicit.
Repository Structure
application/
├── src/
│ ├── features/
│ │ ├── users/
│ │ │ ├── index.ts
│ │ │ └── internal/
│ │ └── billing/
│ │ ├── index.ts
│ │ └── internal/
│ ├── shared/
│ │ ├── logger.ts
│ │ └── validation.ts
│ └── generated/
│ └── api-types.ts
├── scripts/
│ └── generate-api.ts
└── AGENTS.md
AGENTS.md
# Project Instructions
## Feature Boundaries
- Keep feature-specific code inside its owning directory under `src/features`.
- Do not import another feature's `internal/` modules directly.
- Use the feature's public exports when functionality must be consumed by another feature.
## Shared Code
- Put code in `src/shared` only when it is genuinely used across multiple features.
- Do not move feature-specific business logic into `src/shared` simply to make it accessible elsewhere.
## Generated Code
- Do not manually edit files under `src/generated`.
- When generated API types need to change, update the source schema or generator and run `pnpm generate:api`.
## Validation
- Run tests for affected features.
- Run `pnpm lint` and `pnpm typecheck` before completing the task.
What This Does
This tells the agent which parts of the repository it can modify directly and how modules are expected to interact.
For example:
src/features/users/internal/user-repository.ts
is an implementation detail of the users feature.
Another feature should not bypass the users module's public interface with:
import { findUser } from "../users/internal/user-repository";
Instead, it should consume functionality intentionally exposed by the users feature.
The instructions also establish that:
src/generated/
has a different modification workflow from ordinary source code.
What This Does NOT Do
The file does not prevent all cross-feature communication.
This would be too restrictive:
- Features must never use functionality from another feature.
Real applications often require collaboration between domains.
The important distinction is how that functionality is accessed.
Likewise, the instruction:
- Do not manually edit files under `src/generated`.
does not mean generated code can never change.
It means the agent should change the source or generation workflow rather than editing the output directly.
Why These Instructions Matter
Repository boundaries are easy to violate when solving a task locally.
Suppose the billing feature needs user information.
The fastest change might appear to be:
import { userRepository } from "../users/internal/user-repository";
That solves the immediate problem but couples billing to an internal implementation detail of users.
Later, changing the users feature becomes harder because other features depend on its internals.
A boundary instruction helps the agent recognize that the repository has an intended dependency structure.
Generated code presents a similar problem.
An agent may see:
src/generated/api-types.ts
and fix a type directly.
The immediate error disappears, but the next generation run overwrites the fix.
The instruction:
- When generated API types need to change, update the source schema or generator and run `pnpm generate:api`.
provides the correct workflow.
Key Decisions
State boundaries explicitly
A directory name such as:
internal/
suggests intent to a human, but an explicit instruction removes ambiguity.
Explain the allowed path
A weak boundary says:
- Do not edit generated files.
A stronger instruction says:
- Do not manually edit files under `src/generated`.
- Update the source schema or generator and run `pnpm generate:api`.
The second version tells the agent what to do instead.
Protect ownership without creating silos
The goal is not to stop modules from interacting.
The goal is to preserve deliberate interfaces between them.
Keep shared code genuinely shared
shared directories can easily become dumping grounds.
This instruction:
- Put code in `src/shared` only when it is genuinely used across multiple features.
helps preserve ownership.
When to Use This Pattern
Use this pattern when a repository contains areas with different ownership or modification rules, such as:
- feature modules;
- internal APIs;
- shared libraries;
- generated code;
- vendored code;
- migrations;
- infrastructure;
- public package interfaces.
Repository boundaries become increasingly important as a codebase grows, but even a small project can benefit from documenting a few critical ones.