Agents & automation
Which surfaces of this site are a contract a machine can rely on, which are not, and what an agent is expected to do when the answer is "that does not exist".
Overview
A large share of the code written against a design system is now written by a model, and models fail against design systems in a very specific way: asked for a component that does not exist, they invent a plausible one. The invented component has a plausible API, plausible props, and no relationship to anything real. In a to-do app that is an annoying hour. In an app that shows somebody their blood-pressure reading it is a defect with a clinical shape.
opsinjs is built on the assumption that this will happen, and tries to make the failure impossible rather than unlikely. The strategy has three parts:
- Every guessable URL answers. A component that is only specified still resolves, and the answer says "planned, not implemented" in a form a machine can read. A 404 is what an agent fills with an invention; a definite negative is not.
- Every page has a machine twin. Add
.mdto any docs URL and you get the processed markdown of that page. There is no chrome and no scraping, and the documentation components are left as self-describing tags whose attributes are the content. - Everything measurable is generated. Prop tables, token tables, contrast figures and the catalogue come from source, so what a machine reads is the same thing CI checks.
This page is the map. If you are configuring a tool, jump to MCP server. If you are writing a prompt, jump to Rules for agents.
What is a contract and what is not
The distinction matters more than the list. A contract is something that will not change shape without a version and a changelog entry. Everything else is free to move.
| Surface | Status | What it is |
|---|---|---|
/**.md | Contract | Processed markdown twin of any docs page |
/llms.txt | Contract | Curated index with absolute URLs and section headers |
/llms-full.txt | Contract | The whole corpus, size-capped |
/llms-components.txt, /llms-health.txt, /llms-foundations.txt, /llms-reference.txt | Contract | Shards, for context windows that cannot take the whole thing. Each carries its sections whole |
/r/registry.json | Contract | The shadcn-spec catalog. Required by the MCP server |
/r/index.json | Contract | Name, type, status, category, links and aliases per item |
/r/<name>.json | Contract | One registry item at the default base and style |
/r/docs.json | Contract | The offline bundle, versioned |
| The HTML of any page | Not a contract | Chrome, markup and class names change freely |
| Anchor ids | Not a contract | Headings are edited; link to a page, not to a fragment |
/view/** | Not a contract | Chrome-less preview host, and robots.txt disallows it |
If you are scraping the HTML, stop; the markdown twin exists precisely so that you do not have to, and it is stable in a way the HTML is not.
Pick a surface
For a coding agent inside an editor
Install the agent skill, or configure the MCP server, or both. The skill carries the rules; the MCP server carries the inventory. They solve different halves of the same problem and are meant to be used together.
For a retrieval pipeline
Start at /llms.txt for the index and fetch the .md twins of the
pages it names. See llms.txt and the shards and
Raw markdown API.
For a build script or a validator
Use the machine-readable schemas: the catalogue, the token set, the status vocabulary and the glossary, each as JSON at a stable path.
For an agent with no network
Fetch the offline bundle once and carry it.
The one rule that matters most
Every catalogue row is implemented and installable, and every one has been audited against WCAG 2.2 AA by the authors who built it, in a static source pass and a rendered pass, with the findings fixed in the same change. None has had an independent accessibility review, and none has had a clinical review, so nothing here is for a production health surface until a clinician signs it. That is why an agent's first job is to read the status a surface reports before it writes anything. The surface is arranged so that it can, without guessing: every id resolves, and the answer carries the distinction in a field.
For a shipped id the correct behaviour is to install it from the registry and
to say that the API may change in any release, that it has been audited against
WCAG 2.2 AA by the authors but has had no independent accessibility review and no
clinical review, and that it is therefore not for a production health surface
until a clinician signs it. The record is
ADR 0025. Installing copies the source into the
project, because there is no published opsinjs package to import. For a
planned id the correct behaviour is to describe the specification, refuse to
emit an import, and stop. No id sits there today, so that
rule currently guards the mechanism rather than a live entry. Inventing a name
that does not exist, or refusing one that ships, are the two failures this whole
surface exists to prevent. Both are stated in full, as testable rules, in
Rules for agents, and they are what the
evals measure.
The discriminator is implemented on /r/index.json, meta.opsinjs.implemented
on a registry item, and the x-opsinjs-implemented-count response header on
every machine surface. Three redundant channels, because an agent that misses
one will usually catch another.
Verify it worked
The twin returns markdown
curl -s https://opsinjs.pensievelabs.org/components/range-bar.md | head -20You should get frontmatter and prose, not HTML. Documentation components arrive
as <PascalCase … /> tags and that is the format working; an import statement
at the top means you have raw MDX from somewhere else.
The index is reachable and absolute
/llms.txt should contain fully qualified URLs. A relative URL in an index is
useless to a client that fetched it from somewhere else.
Troubleshooting
The .md twin returns HTML. You requested a path that is not a docs page.
The rewrite applies to /:path*.md and to /index.md; other routes have no
twin.
The MCP server sees no components. That is a real fault. All sixty built
items list source files, and the per-item payloads at /r/<name>.json carry
that source inline, so every id the server lists resolves to real files and
there is no metadata-only entry to mistake for a fault. An inventory that is
empty across the board means something
is broken: check that components.json carries the @opsinjs entry in the
{name} template form and that the fetch is not being blocked.
An agent invented a prop. Report it as an eval failure rather than as a documentation bug. An implemented component's API reference is generated from the source the registry serves, so an invented prop is a generation failure and not a gap in the page. See Evals.
/llms-full.txt is truncated. It is size-capped on purpose, and "use the
shards" is only half an answer, because the four shards cover eight of the
sixteen sections and no more: Components, Screens, Health, Accessibility,
Content & language, Foundations, Theming & tokens and Reference. Start here,
Recipes, Patterns, Handbook, Agents, Registry & distribution and Project have no
shard, nor do the package pages, which sit outside the sixteen groups. That is
roughly a third of the corpus, and a shard is not its recovery route and never
was. Two things are. Any capped file that drops a page ends in a ## Truncated
block naming every page it dropped, with the .md URL to fetch each one, so
what is missing is enumerated rather than implied. And /llms.txt is not
capped. It lists every page in the corpus, names the sections that have no
shard, and every URL in it answers to a .md suffix. Fetching one twin is a
single request and is usually cheaper than a shard you then have to search.
Next
- Rules for agents has the hard rules, written to be pasted into a system prompt.
- MCP server is five minutes to a working setup.
- Writing docs for agents is the page to read if you are contributing pages rather than consuming them.
@opsinjs/tailwind.css
The opsinjs stylesheet as a versioned import, carrying token values, preference degradations, the base layer and the dark variant, in the one order that works.
llms.txt and the shards
The curated index a model should read first, the four topic shards that exist because context windows are finite, and the size budget that governs them.