AGENTS.md is the single most effective thing I do for coding agent quality. Without it, the agent guesses and decides for you. With it, the agent knows how to run tests, what patterns to follow, and what to avoid. I’ve been maintaining these files across all my projects for over a year now.

The agent reads AGENTS.md (or CLAUDE.md for Claude Code) automatically at the start of every session. It’s always in context. Any @ references in the file — like @some-other-file.md — get pulled in too, so you usually never want to do that in AGENTS.md. The agent starts every conversation already knowing the project.

Starting From Scratch

For a new project, I tell the agent to study the repo and write an AGENTS.md. It looks at the directory structure, the package manager, the scripts in package.json, the framework, the test setup — and produces a reasonable first draft. Then I edit it. Remove what’s wrong, add what’s missing, tighten the wording.

It won’t get everything right — it doesn’t know my conventions or preferences yet. But it gets the development commands and architecture close enough that I’m editing instead of writing from scratch.

Then I add instructions as problems come up.

What Goes In

Every AGENTS.md I write has the same core sections.

Development commands — how to run the dev server, run tests, lint, build, deploy. The agent needs these constantly and will guess wrong without them. Exact commands, not descriptions.

## Tools & Commands

### Package Manager & Runtime

- Use `pnpm` (not npm) for installs and package scripts
- Use `bun` for ad-hoc scripts (not node/npm)
- Use `fetch` (not axios)

### Required After Edits

1. `pnpm run type-check` in frontend and backend
2. `pnpm run lint` in frontend and backend
3. `pnpm prettier --write <file_path>` in each package
4. After `package.json` changes: `pnpm install`

### Deployment

scripts/push-and-deploy.sh     # Auto-detect changed roles
kamal deploy --roles=<role>    # Single role deploy

“Use pnpm (not npm)” saves me from correcting the agent every other session.

Architecture — what the project is, what tech it uses, how the codebase is organized. I keep this brief — just enough that the agent knows where things live.

## Project Structure

frontend/           # Vue app
backend/            # Node/Fastify API
api/                # API service (OG images, screenshots, R2)
shared/             # Shared code - keep flat, no subdirectories

### Path Aliases

- `@` resolves to `src/` in both frontend and backend
- Use `import { env } from "@/env"` not relative imports

### Database

- Drizzle ORM; edit `shared/src/schemas/` not `.sql` files directly

Coding conventions — patterns the agent should follow. “Use function declarations for top-level functions, not arrow functions.” “Always use curly braces for if/else/for/while, even for one-liners.” Without these, the agent will write correct but inconsistent code.

## Code Style

- Use TypeScript for all code files
- Use function declarations for top-level functions (not arrow functions)
- Use object parameters to avoid argument ordering mistakes
- Prefer `const` over `let`; use ternary expressions instead of reassignment
- Write few or no comments; code should be self-explanatory

Critical rules — things the agent must never do. I put these at the top of the file so the agent sees them first.

## Critical Rules (Never Violate)

- Never generate Drizzle migrations unless explicitly told
- Never commit unless explicitly instructed
- Never commit without running prettier on changed files first
- Never modify files under the `reference/` or `screenshots/` directories

These came from real mistakes. The agent ran a migration once without asking, and that was the last time — because I added it here.

Git commit style — how I want commit messages written. Atomic commits, single-line messages, describe “why” not “what.” I also tell it to append “with Claude Code” so I can tell which commits were agent-assisted.

Hints for common tasks — anything the agent repeatedly gets wrong or needs to know. “The API server runs in tmux window 3, pane 0.” “When I say ‘commit’, use the commit-succinct skill.” “Development servers live reload — don’t restart them.”

What I Don’t Put In

I keep AGENTS.md focused on what the agent needs to do its job. I don’t put in:

  • Long explanations of why the architecture is what it is
  • Every possible command — just the ones the agent actually uses
  • Documentation for humans — this file is for the agent

If a section isn’t changing agent behavior, it doesn’t belong.

One File, Three Agents

I use Droid, Claude Code, and Codex. I wrote about my shared configuration setup — the short version is that CLAUDE.md is just a single line (@AGENTS.md) so I only maintain one file. All three agents read the same instructions.

This works because all three agents understand markdown, and the instructions are about the project, not the agent. “Use pnpm not npm” is the same regardless of which agent reads it.

It’s Not Just About Code

I also tell the agent about my tmux setup — which windows run what, that I always use one tmux session, and what “tmux 3.0” means (session “main”, window 3, pane 0). Without this, the agent can’t check server output or run commands in the right place.

Same for skill triggers. The agent doesn’t always pick up the right skill on its own — especially for common words like “commit.” So I add a line: “If I said ‘commit’, use the commit-succinct skill.” Without the hint, the agent ignores the skill half the time. More on this below.

When AGENTS.md Becomes a Skill

If the agent doesn’t know something or does something I don’t like — I write it in AGENTS.md. That’s often enough. But sometimes the instructions for a task get long enough that they deserve their own file. That’s when I extract them into a skill.

A skill is often just an extraction of what I’d otherwise write in AGENTS.md about that task. Most of the time I only need the skill file. But I keep a short reference in AGENTS.md — something like “commit (check skill) changes” instead of just “commit changes” — to nudge the agent to look for the skill, especially when the trigger word is something common.

This keeps AGENTS.md lean and the detailed instructions reusable across projects.

How I Maintain It

The file evolves constantly. When the agent does something wrong — uses the wrong test command, creates a file in the wrong directory, ignores a convention — I add a line to prevent it next time. It’s reactive. The best instructions come from actual mistakes.

I also have a reflect skill. At the end of a session, I tell the agent to reflect on what it learned and update AGENTS.md. It adds things like “API routes follow the pattern routes/{resource}/index.ts” or “always run just check before committing.” Over time, the file gets better without me having to remember every detail.

I treat it like code — I review what the agent adds, cut what’s unnecessary, and keep it tight. A bloated AGENTS.md is almost as bad as none at all, because the agent has a context window and every unnecessary line competes with the lines that matter.

I also watch the agent’s behavior when something changes — a new project, a new model, a major version bump. When I moved from Opus 4.1 to Opus 4.5, the newer model reacted more strongly to instructions and I had to tame some of them down. A nudge that worked for 4.1 became over-correction for 4.5. I give it a session or two after switching, then adjust.

Project-Level vs. Global

I have two levels of instructions:

  • Global AGENTS.md — lives in ~/.config/coding-agents/ and applies to all projects. This has things like notification commands, tmux conventions, tool preferences (use rg over grep), and workflow habits (always check git status before committing).
  • Project AGENTS.md — lives in the repo root. Architecture, dev commands, coding conventions, project-specific hints.

The global file handles how I work. The project file handles how this project works. The agent reads both.