The problem I kept hitting
Every project I hand to a coding agent gets a context file: CLAUDE.md in
most of mine, AGENTS.md where I’ve kept things vendor-neutral. This one
started small — a few build gotchas, a domain-specific guardrail, a pointer
to where the real content lives. It stayed small for a while, the same way
every one of them does.
Then it doesn’t. A database schema excerpt shows up because the agent kept guessing wrong about a column name. A paragraph about voice and tone gets added because a derived document read wrong once. A hard-won CI scar gets appended so nobody re-learns it the expensive way. None of these additions are wrong in isolation — each one earned its place the day it was written. The failure mode is cumulative: eventually the agent is reading a database schema while it edits CSS, a standing behavioral rule sits three paragraphs above a one-off project decision from eight months ago, and the file has grown past the point where anyone, human or model, reads it end to end before acting.
I’d already been doing a version of this without naming it. A few of my own
projects split documentation three ways — a README for what’s built, a
design doc for what it’s for, a CLAUDE.md for operational/agent guidance
— specifically so the agent isn’t handed all three audiences’ worth of
content in one read. That’s the same instinct, applied inconsistently,
project by project. What was missing was a name for the general pattern and
a way to make an agent apply it on its own.
What dotagents is
dotagents (github.com/bgreenwell/dotagents) is Brandon Greenwell’s proposal for exactly this: split a project’s agent context into a router and a library.
AGENTS.mdat the repo root is the router. It’s slim, it’s always read, and its job is to tell the agent where to look for deeper context, conditionally, rather than contain that context itself..agents/is a hidden directory holding the heavy material, organized by kind:rules/(standing behavioral constraints),context/(static reference, like schemas or API types),memory/(durable decisions that evolve),personas/(specialized roles: QA, architect),skills/(reusable multi-step procedures),specs/(the current task’s requirements),logs/(session records).
The mechanism is progressive disclosure: the agent loads a screenful of routing rules up front, then pulls in only the specific files the current task matches. It’s the same principle behind why a debug-only diagnostics endpoint stays out of production builds, or why a good API surfaces one endpoint per concern instead of one endpoint that returns everything. Load what’s needed, when it’s needed, not before.
The broader .agents Protocol is a
superset worth knowing about separately: it keeps the same .agents/ idea
but adds a global ~/.agents/ layer that merges with the project layer,
machine-readable config (mcp.json, models.json), structured sub-agents /
tasks / memories with their own frontmatter schemas, and a public Hub for
sharing bundles. Core dotagents is for hand-authored project context; reach
for the Protocol extensions when you need a global layer or MCP wiring. The
two are easy to conflate because they share a directory name. Worth being
explicit about which one you mean.
The hard part: the taxonomy
Reading the dotagents README is a five-minute exercise. Applying it
correctly to an existing, messy CLAUDE.md is not: the standard tells you
that context should be split by kind, not which kind a given paragraph
is. That classification step is where the skill earns its keep:
| If the context is… | it’s a… | goes in |
|---|---|---|
| An invariant rule (“always run tests before commit”) | rule | rules/ |
| Static reference the agent occasionally needs (schema, API types) | context | context/ |
| Durable knowledge that evolves (“we chose Postgres for JSONB”) | memory | memory/ |
| A specialized role adopted temporarily (QA, security auditor) | persona | personas/ |
| A reusable, multi-step procedure (migration, release) | skill | skills/{id}/ |
| The requirements of this task | spec | specs/ |
| A session record / audit trail | log | logs/ |
The two pairs that get confused most, worth internalizing on their own:
- rule vs. memory. A rule is a standing instruction you always obey. A memory is a fact or decision that explains history and may change. Mixing them is the original sin the whole standard exists to prevent: you end up unable to tell “you must” from “we once decided.”
- context vs. specs.
context/is durable and read-only, true across many tasks.specs/is “what we’re building right now” and gets superseded the moment the task ships.
What the skill packages, concretely
dotagents-standard
is an Agent Skill: the SKILL.md format an agent
loads by name and description, then reads in full once a task matches. It
triggers on three situations: setting up a fresh .agents/ layout,
migrating a bloated AGENTS.md/CLAUDE.md/.cursorrules into one, or
working inside a repo that already has one and needing to navigate it
without over-reading.
It applies progressive disclosure to itself, which is the detail I’m
proudest of. SKILL.md stays a screenful: the mental model, the taxonomy
table, the two workflows (Utilize an existing setup, Implement a new
one), the router pattern. Deep material lives in references/:
directory-reference.md goes subdirectory-by-subdirectory in depth,
protocol-extensions.md covers the Protocol superset, and both only get
read when the task needs that depth. assets/templates/ holds copy-paste
starters (AGENTS.md, a rules file, a decisions memory file, a persona, a
skill template), and examples/sample-project/ is a fully filled-in
.agents/ layout for a hypothetical billing API — the concrete counterpart
to the blank templates.
A good router rule, per the skill’s own guidance, names a trigger and carries an action verb:
## Context routing
- **If working on the database:** READ `.agents/context/schema.sql`.
- **If writing new features:** CHECK `.agents/specs/` for the active PRD.
- **If facing an architectural choice:** CONSULT `.agents/memory/decisions.md`.
- **If reviewing or testing:** ADOPT the persona in `.agents/personas/qa.md`.
READ / CHECK / CONSULT / ADOPT / RUN each tell the agent what to
do with the pointer, not just that the file exists. Every line names a
when. That’s the whole savings mechanism: skip it, and an unconditional
“always read everything” router just recreates the monolith one directory
deeper.
memory/ is explicitly read/write. When an agent using the skill makes a
durable decision or learns a lasting preference mid-task, the instruction is
to write it back: an ADR appended to memory/decisions.md, a preference
noted in memory/user.md, so the next session inherits it instead of
re-deriving it. If a task needs context the router doesn’t point to yet,
that’s treated as a bug in the router, not a dead end: read the file anyway,
finish the task, then add the missing routing rule.
Why I think this is worth other people’s five minutes
The context-bloat problem gets worse as agents take on more, not better. More autonomy means more sessions, more accumulated decisions, and more temptation to just append one more paragraph to a file that’s already too long. A single well-factored router pays for itself on the first session where the agent doesn’t read a schema file to fix a stylesheet. And because the skill is installed once and then applies itself, the discipline compounds without needing to be re-explained project to project. That was the whole gap I was trying to close.
Trying it
npx skills add zaventh/dotagents-standard-skill
installs it for any agentskills.io-compatible
agent, kept current via npx skills check / npx skills update. For Claude
Code specifically, a symlink into ~/.claude/skills/ works just as well.
MIT-licensed, with CI validating the skill’s own frontmatter and
link-checking every reference on push. The artifact holds itself to the
same bar it’s asking other repos to meet.