AI agents
A coding agent that has never heard of Dowel does the worst possible thing: it writes its own Button. A second button, with a different focus ring, different disabled semantics and hardcoded colours — and now the design system has a hole in it that nobody notices until someone tabs into it.
The fix is not a better prompt. It is giving the agent the catalogue, generated from the registry so it cannot go stale.
In your project
One command writes documentation for every agent that works in this repository. It reads the registry you install from and your components.json, so the catalogue is accurate and marks what you already have.
pnpm dlx @dowel-ui/cli agents| Target | Writes | What it is for |
|---|---|---|
| dowel | .dowel/conventions.md, components.md, ai.md, themes.md | The reference set. Read by any agent that reads the repository. |
| agents | AGENTS.md | A marked block appended to the file, replaced in place on regeneration. The rest of the file is yours. |
| claude | .claude/skills/dowel-ui/SKILL.md | A Claude Code skill, loaded when the work is React UI. |
| cursor | .cursor/rules/dowel-ui.mdc | A Cursor project rule, scoped to .tsx and .jsx files. |
Name targets to narrow it: dowel agents claude cursor. With none, it writes them all.
It is generated output, so regenerate it after an upgrade rather than editing it. --check writes nothing, reports what is stale and exits non-zero, which is what you want in CI — a catalogue that has fallen a release behind is worse than none, because the agent trusts it.
MCP server
The files above are a snapshot. The MCP server is the live version: the agent queries the registry directly, gets a component’s real source rather than a description of it, and is told when it has typed a name that does not exist.
{
"mcpServers": {
"dowel": {
"command": "npx",
"args": ["-y", "@dowel-ui/mcp"],
"env": {
"DOWEL_IMPORT_FROM": "@/components/ui"
}
}
}
}Set DOWEL_IMPORT_FROM to the alias your components live under — the server has no way to see your components.json, and an agent told the wrong import path writes code that does not resolve. Point DOWEL_REGISTRY at a fork or an internal mirror if you have one.
| Tool | What it answers |
|---|---|
| search_components | Find what already exists, by name, description or category. |
| get_component | One component in full — accessibility notes, what it installs alongside, and optionally its source. |
| get_guide | Conventions, theming, the AI components, or the whole catalogue. |
| install_command | The exact command, and everything it will write. |
llms.txt
For an agent that can fetch a URL but cannot run a server, this site serves the whole catalogue as plain text — generated from the same registry, at build time, so it is never a release behind.
- /llms.txt — the index: every one of the 184 components and 51 blocks, with a link to its page.
- /llms-full.txt — everything in one request: conventions, accessibility rules, theming, the AI components, and per-component detail.
What the agent is told
Not a general lecture on accessibility, which gets ignored. A short list of the places this library differs from the ones a model has already read a million lines of:
- A loading
Buttonusesaria-disabled, neverdisabled— disabling a control mid-action strands keyboard focus. Alertis not a live region by default. One that exists on first paint announces for no reason.Separator,SkeletonandSpinnerare decorative. Do not add ARIA to them by reflex.- Semantic tokens only. Never raw hex, never Tailwind’s own palette.
- Check for a block before assembling a page out of primitives.