Coding agents read a repository instruction file before they touch anything, which makes it the highest-leverage documentation in the codebase — it is the only document guaranteed to be read before every change. Most of the ones I see are either three lines of nothing or two thousand words of generic advice, and both produce roughly the same result.
The useful content is specific, surprising, and unavailable from the code itself. An agent can read your imports; it cannot know that the payments module looks abandoned but is load-bearing, or that a particular test suite must run against a real database because the mock is a known lie.
What belongs in it
- How to run things — the exact commands for tests, a subset of tests, lint, and a local server. This is the most-used section by a wide margin.
- Conventions a reader would violate innocently: where new modules go, how errors are handled, which patterns were deliberately abandoned and must not come back.
- Traps. The generated files that must not be edited, the service that looks dead and is not, the test that fails locally for a known reason.
- Boundaries: what the agent should never do without asking — touch migrations, change public API contracts, modify infrastructure code.
- Pointers rather than copies. Name the file where the pattern lives instead of pasting the pattern; the file stays current and the instruction file does not rot.
# Working in this repo
## Commands
- Tests: `uv run pytest` (whole suite ~4 min). One file: `uv run pytest path::test`
- Integration tests need Docker: `make services` first, or they fail confusingly.
- Lint and types must both pass before a PR: `make check`
## Conventions
- New domain logic goes in `src/<module>/Internal/`. Only `Public/` may be
imported across modules — `make check` fails the build otherwise.
- Errors: raise a domain exception, never return None to signal failure.
- We do not use the repository pattern here. See `src/billing/queries.py`
for the approach we do use.
## Traps
- `src/legacy/pricing.py` looks unused. It serves two enterprise contracts.
Do not delete or refactor it without asking.
- `tests/fixtures/tenants.json` is generated. Edit `tools/gen_fixtures.py`.
## Ask before
- Any change under `migrations/` or `infra/`
- Changing a public API response shapeNotice what is absent: no description of what the product does, no list of the directory structure, no general software engineering advice. The agent can see the directories, and telling it to write clean code accomplishes nothing while consuming the attention that the trap about the legacy pricing module needs.
Keep it short enough to be followed
Instruction files degrade as they grow, in a way that is easy to observe: once past a certain length, specific rules start being missed because they are competing with a great deal of text that carries no information. Ruthless editing is the maintenance task. If a line would not change what an agent does, delete it.
Write it for a competent engineer joining tomorrow who will not ask you any questions. That is exactly the reader you have.
The unexpected benefit is that it is genuinely good onboarding documentation for people, for the same reason — it is the short list of things that are true about this codebase and not inferable from reading it. Several teams I have worked with started writing these for the tooling and kept them because new engineers found them more useful than the wiki nobody had updated since 2023.