You open a fresh session and ask for a small change. The assistant runs the wrong test command, edits a generated file, and adds a dependency you banned months ago. None of this is its fault. Nobody told it.

That is what project instruction files are for. Claude Code reads CLAUDE.md. Codex and many other coding agents read AGENTS.md. Both are plain Markdown files at the root of your project, and both are read at the start of a session.

This guide shows you what to put in them, what to keep out, how to write rules an assistant can follow, and how to maintain one set of instructions for several tools. You will finish with a complete example you can adapt.

Which assistant reads which file

Keep this part simple and accurate:

FileRead byTypical location
CLAUDE.mdClaude CodeProject root
AGENTS.mdCodex and many other coding agentsProject root

Recent versions of Claude Code can also read AGENTS.md, but by default only when the project has no CLAUDE.md. Claude Code also supports a personal CLAUDE.md in your user-level configuration folder (~/.claude/CLAUDE.md), which applies to every project on your machine. That file is for your preferences. The project file is for the project. Keep them apart, and never copy the personal one into a repository.

Tools differ in the details, such as whether they also read files in subfolders. Check your tool's own documentation before relying on anything beyond "the file at the root is read". For Claude Code, Anthropic's own documentation on memory and CLAUDE.md is the reference.

One source of truth for several tools

If your team uses more than one assistant, do not maintain two diverging copies. A common setup, described in the Claude Code documentation: write the shared rules in AGENTS.md, and make CLAUDE.md import it with an @path import:

# CLAUDE.md
@AGENTS.md

## Claude Code only
- Use the project's test command, not a guessed one.

Now both tools read the same rules, and CLAUDE.md holds only what is specific to Claude Code. Prefer an import over a symbolic link: links break on some systems (Windows clones among them), and some tools and sync services refuse them.

What to put in

Good instruction files answer the questions a capable new contributor would ask in their first hour.

  1. Commands. How to install, build, test, lint and run. Exact commands, not descriptions.
  2. Layout. Which folders hold what, and which are generated or vendored and must not be edited.
  3. Conventions. The rules a linter does not enforce: naming, error handling, where new code goes.
  4. Boundaries. What the assistant must not do without asking: add dependencies, change the database schema, touch CI config.
  5. Definition of done. What must be true before a change is finished.
  6. Pointers. Where decisions and notes live, so the assistant reads them before proposing changes. The guide on project memory for AI coding explains how to set that up.

A complete example

Here is an AGENTS.md for a small web app. Adapt the specifics; keep the shape.

# AGENTS.md — invoice-tool

## Commands
- Install: `pnpm install`
- Dev server: `pnpm dev` (http://localhost:3000)
- Tests: `pnpm test` (unit), `pnpm test:e2e` (needs the dev server)
- Lint and types: `pnpm lint && pnpm typecheck`

## Layout
- `src/app/` — pages and routes
- `src/lib/` — shared logic; no UI imports here
- `src/generated/` — generated from the API schema. Never edit by hand.
  Regenerate with `pnpm gen:api`.
- `migrations/` — database migrations. Never edit an existing file.

## Conventions
- TypeScript strict mode. No `any` without a comment explaining why.
- Money is stored in integer cents. Never use floats for amounts.
- Dates are UTC ISO strings in the database and API.
- New modules get a test file next to them: `foo.ts` → `foo.test.ts`.

## Ask before you
- add or upgrade a dependency
- create a migration
- change anything in `.github/`

## Done means
- `pnpm lint && pnpm typecheck && pnpm test` pass
- New behaviour has a test
- No new TODO without an issue reference

## Project memory
- Read `.prjcontext/memory/decisions.md` before proposing design changes.
  Do not reintroduce anything marked as rejected.
- Read `.prjcontext/memory/current-state.md` at the start of a session.

It is short, specific and checkable. Every line either tells the assistant what to do or what not to do.

What to leave out

Instruction files get read by every session and often shared with everyone on the project. Keep them lean and safe.

  • Secrets. No keys, tokens, passwords or connection strings. Point to .env.example instead. More in keeping secrets out of your AI context.
  • Private paths. /Users/anna/work/... breaks on every other machine and reveals more than you think. Use paths relative to the project root.
  • Personal preferences. "Answer briefly" or "I prefer tabs in my editor" belong in your personal assistant settings, not the project.
  • History. The story of how you got here belongs in decision notes. The instruction file says what is true now.
  • Things tools already enforce. If the formatter fixes indentation, you do not need a rule about it.
  • Wishes. "Write clean, maintainable code" gives the assistant nothing to act on.

Write rules the assistant can follow

The test for every line: could someone check whether it was followed? Compare:

VagueFollowable
"Be careful with the database.""Never edit an existing file in migrations/. Create a new one."
"Use our API client.""Call the backend through src/lib/api.ts. Do not call fetch directly."
"Keep tests passing.""Run pnpm test before saying a task is done."
"Don't over-engineer.""Do not add a new abstraction for a single caller."

A few more habits help:

  • Say why, in a few words, for surprising rules. "Money in integer cents (floats caused rounding errors in totals)" makes the rule harder to argue away.
  • Use headings and short bullets. Assistants and humans both scan.
  • Put the most important rules first. If a rule prevents data loss, it goes near the top.
  • Use the same words as your code. If the code says workspace, do not write "team area" in the instructions.

Test it and keep it current

An instruction file is code for your assistant. Test it like code.

The fresh-session test. Start a new session and ask: "Before we begin, summarise the rules of this project and the commands you will use to test a change." If the answer is wrong or missing something, fix the file, not the session.

The task test. Give a small, real task that touches a boundary, such as "add a field to the invoice table". A good file makes the assistant ask before creating a migration.

Update in the same change. When you switch the test runner or rename a folder, update the instruction file in the same commit. Stale instructions are worse than none, because they are followed.

Review occasionally. Read the file top to bottom every few weeks. Delete rules nobody breaks anymore and add the ones you keep repeating in chat.

How PrjLab handles this

We built PrjLab so instructions travel with the project instead of being retyped on each machine.

  • CLAUDE.md and AGENTS.md at the project root are recognised as project instructions. Longer instruction files can live in .prjcontext/instructions/.
  • prj status shows what would be captured before prj push, and every push creates a version with a line diff, so you can see when a rule changed.
  • prj clone brings the same instructions to a new machine or a teammate. Global assistant folders, such as your personal settings, are never scanned.
  • Share a repository by handle as a reader or writer; it stays private until you choose otherwise. The getting-started guide walks through it.

Frequently asked questions

Do I need both CLAUDE.md and AGENTS.md? Only if your team uses tools that read different files. If so, keep the rules in AGENTS.md and import it from CLAUDE.md, so every tool reads the same text.

How long should an instruction file be? Long enough to cover commands, layout, conventions and boundaries, and short enough to read in a couple of minutes. Move history and reasoning to project memory.

Where do my personal preferences go? In your user-level assistant settings, not in the project. They apply to you, not to everyone who opens the repository.

Why does my assistant still ignore a rule? Usually the rule is vague, buried or contradicted elsewhere. Make it specific, move it up, and run the fresh-session test again.

To push a project with its instructions, follow the getting-started guide.