# AGENTS.md > The file for people and agents who work on the Pico Reforged repository itself. Page: https://pico.rusticstack.com/docs/ai/agents-md `AGENTS.md` at the root of the repository tells an agent how to work on Pico Reforged itself: where the source lives, which files are generated, the CSS rules and the commands. It is not the file to read when you build a page with Pico Reforged. For that, use the [skill](https://pico.rusticstack.com/docs/ai/skill). The file is shipped in the npm package too, so it is next to the code in `node_modules/@rusticstack/pico-reforged/AGENTS.md`. ## What it covers ### Layout and commands The CSS is plain CSS in `src/`, with the entries `pico.css`, `pico.classless.css`, `pico.colors.css` and `pico.extras.css`. `css/` is build output and is never edited by hand. The commands are run with pnpm: ```shell pnpm build # tokens, themes, AI files, then the whole file matrix into css/ pnpm test # Vitest pnpm test:api # the v2.1.1 public surface pnpm test:visual # pixel diff against the frozen current look pnpm test:extras # screenshots and axe-core for each extra pnpm check # format, lint and types ``` ### Generated files Some files are produced from data and must not be edited: the palette, scheme and theme CSS, `ai/tokens.json`, `ai/components.json` and the references in the skill. The file says which source to change and which generator to run. A test fails when a generated file is stale. ### CSS rules The rules an agent has to keep when it edits `src/`: - All rules sit in the `pico` layer, in the order `pico.tokens`, `pico.theme`, `pico.core`, `pico.extras`, `pico.utilities`. - Colors are OKLCH, and light and dark values are written once with `light-dark()`. - Specificity stays at the v2.1.1 level or lower, and logical properties are used so RTL needs no overrides. - Semantic HTML and ARIA come first. An extra uses at most one documented `data-*` hook and needs no class. - Every public selector and `--pico-*` variable of v2.1.1 stays, unless the [migration notes](https://pico.rusticstack.com/docs/migration/from-pico-css) list the removal. ### Adding an extra The file lists the steps: the CSS file with its tokens, the entry in the extras list, a fixture, an entry in `scripts/data/components.ts`, and then `pnpm generate:ai`, `pnpm check` and `pnpm test`. ### Writing style Plain and short, no emoji, no dashes used as punctuation, and no AI attribution or co-author trailers in commits or pull requests. Commit messages follow `type: short description`. ## Use it with your tool Many coding agents read `AGENTS.md` on their own. Claude Code reads `CLAUDE.md`, so a project can point to it from there. Cloning the repository is enough for contributions: the agent finds the file at the root. If you maintain your own project that uses Pico Reforged, do not copy this file. Write your own `AGENTS.md` and refer to the skill in it: ```md ## Styling This project uses Pico Reforged. Read .claude/skills/pico-reforged/SKILL.md before you write markup. Use semantic HTML, no utility classes, and change the look with --pico-* custom properties. ``` # components.json and tokens.json > The component manifest and the design tokens as data, with their formats. Page: https://pico.rusticstack.com/docs/ai/data-files Two JSON files in `ai/` describe Pico Reforged for tools. They are generated, so they match the CSS: a test fails when they are stale. Both are in the npm package and importable: ```js import tokens from "@rusticstack/pico-reforged/tokens.json" with { type: "json" }; import components from "@rusticstack/pico-reforged/components.json" with { type: "json" }; ``` ## components.json The top level has a `description`, the `package` name and a `components` array. There is one entry for every module of the core build and every opt-in extra: 35 modules and 11 extras. ```js const alert = components.components.find((c) => c.name === "alert"); console.log(alert.markup); console.log(alert.optIn.config); // "@pico { extras: alert; }" ``` Each entry has these fields: | Name | Type | Default | Description | | --- | --- | --- | --- | | `name` | `string` | | Short unique name, such as button, modal or tabs. | | `category` | `string` | | base, layout, content, forms, components, utilities or extras. | | `optIn` | `object` | | How it gets into a build. kind is core (always in pico.css), option (off by default, how says how to turn it on) or extra. | | `summary` | `string` | | The first comment of the module's CSS file. | | `use` | `string` | | One sentence on when to use it. | | `markup` | `string | null` | | The canonical example. null when there is no markup to write. | | `examples` | `array` | | Every example with a label and html. The first one is markup. | | `variants` | `array` | | Ways to switch the look. trigger is what to write, selector is the CSS it matches. | | `states` | `array` | | The same for states such as aria-current, aria-invalid and aria-busy. | | `aria` | `string[]` | | Accessibility notes. | | `notes` | `string[]` | | Extra remarks, when there are any. | | `tokens` | `object` | | reads lists the --pico-* tokens the module uses. defines lists the properties it declares itself. | | `js` | `object | null` | | The smallest script the component needs, with description, language and code. null when it needs none. | For an extra, `optIn` gives every way to load it: the source file, the CDN file, the all-extras file, the import path, the `@pico` config line and the CLI command. ```json { "kind": "extra", "css": "src/extras/alert.css", "cdn": "css/extras/alert.min.css", "allExtrasCdn": "css/pico.extras.min.css", "import": "@rusticstack/pico-reforged/extras/alert", "config": "@pico { extras: alert; }", "cli": "pico-reforged build --extras alert" } ``` The markup is cut from the pages in `test/fixtures`, so it is markup the tests render. Each `selector` is checked against the module's CSS when the file is generated, so a renamed hook fails the build instead of leaving a wrong entry. ## tokens.json The tokens are in the W3C Design Tokens format (Format Module 2025.10), and every token has an explicit `$type`. Colors are `oklch` color objects, with an sRGB `hex` as a fallback for tools that cannot read OKLCH. The groups: | Name | Type | Default | Description | | --- | --- | --- | --- | | `color` | `group` | | The semantic colors of the page: text, borders, buttons, forms, cards and so on. | | `dimension, number, font-family, font-weight, transition, shadow` | `groups` | | The rest of the root tokens, grouped by type. | | `palette` | `group` | | The OKLCH palette: one token per hue and step. | | `theme` | `group` | | One group per built-in theme (20), with the primary set it defines. | | `extras` | `group` | | Root tokens of the opt-in extras, one group per extra. | A token name is the CSS custom property without `--pico-`, so `--pico-primary-background` is `color.primary-background`. The exact property name is in `$extensions["com.rusticstack.pico-reforged"].cssVar`. ### Light and dark The format has no modes, so `$value` is the light value and the dark value sits in the vendor extension next to it: ```json "muted-color": { "$type": "color", "$value": { "colorSpace": "oklch", "components": [0.5268, 0.0236, 264.35], "hex": "#646b79" }, "$extensions": { "com.rusticstack.pico-reforged": { "cssVar": "--pico-muted-color", "dark": { "colorSpace": "oklch", "components": [0.6117, 0.0279, 263.25], "hex": "#7b8495" } } } } ``` A token without `dark` has the same value in both schemes. ### Themes and values the format cannot hold The primary tokens in `color` point to the default theme, azure. To read another theme use `theme..primary` and the other tokens in that group. A custom theme from one color is computed, so it is not listed. Build it with `pico-reforged build --theme "#e5484d"` or `@pico { theme: #e5484d; }`. See [Themes](https://pico.rusticstack.com/docs/customization/themes). The format has no type for percentages, `url()` icons, `calc()` or `color-mix()`. Those tokens are not guessed into a type. They are listed under `cssOnly` in the root extension with the CSS as written, the dark value when it differs, and `responsive` overrides from width media queries. Only tokens set on `:root`, `:host` and `[data-theme]` are in the file. Hooks that a component sets on its own elements, such as `--pico-alert-accent`, are in `tokens.defines` of that component in `components.json`. ## Uses - A design tool or Style Dictionary pipeline that reads `tokens.json`. - An editor plugin that suggests `--pico-*` names or the right markup for a component. - A linter that flags class names that `components.json` does not know. - An agent that looks up the exact markup of a component before it writes it. # llms.txt and llms-full.txt > A docs index and the full docs text for assistants, plus a Markdown copy of every page. Page: https://pico.rusticstack.com/docs/ai/llms-txt The docs are published in forms that language models and coding agents read without scraping HTML. ## The files | URL | What it is | | ---------------------------------- | --------------------------------------------------------------- | | [`/llms.txt`](https://pico.rusticstack.com/llms.txt) | a short header and an index of every docs page with its summary | | [`/llms-full.txt`](https://pico.rusticstack.com/llms-full.txt) | the text of every docs page in one file | | `/md/
/.md` | the Markdown of one page, for example `/md/ai/skill.md` | `llms.txt` starts with the project name, a one-line description, and links to `llms-full.txt` and to the [skill](https://pico.rusticstack.com/docs/ai/skill) at `/skill/SKILL.md`. Below that is one line per page, taken from each page's `title` and `description`. Every docs page also has a **Copy page as Markdown** button at the top. Paste the result into an assistant when you ask for help with that page. ## Use them Point a tool at the index and let it fetch the pages it needs: ```text https://pico.rusticstack.com/llms.txt ``` Or give it everything at once. The file is large, so it fits best in tools with a long context window: ```text https://pico.rusticstack.com/llms-full.txt ``` In a chat with web access, a prompt like this works: ```text Read https://pico.rusticstack.com/llms.txt, then build a pricing page with Pico Reforged. Use semantic HTML and no utility classes. ``` ## Notes The Markdown of a page keeps its live examples as `html` code blocks, so the model sees the exact markup. The files are generated from the same pages as the site, so they match it. For a project that already uses the package, the [skill](https://pico.rusticstack.com/docs/ai/skill) is a better fit than the docs: it is shorter, it is loaded only when needed, and it works offline. # Using Pico Reforged with AI agents > What Pico Reforged ships for coding agents, and which piece to use for which job. Page: https://pico.rusticstack.com/docs/ai/overview Pico Reforged styles semantic HTML, which suits language models: the right element is the right answer, and there are few class names to get wrong. Models still guess. They reach for `class="btn btn-primary"` or a `.card` wrapper out of habit. The pieces below give an agent the facts so it does not have to guess. ## What is available | Piece | Use it for | | ------------------------------------------------------ | --------------------------------------------------------- | | [llms.txt and llms-full.txt](https://pico.rusticstack.com/docs/ai/llms-txt) | handing an assistant these docs as plain text | | [The agent skill](https://pico.rusticstack.com/docs/ai/skill) | teaching an agent to write correct markup in your project | | [AGENTS.md](https://pico.rusticstack.com/docs/ai/agents-md) | working on the Pico Reforged repository itself | | [components.json and tokens.json](https://pico.rusticstack.com/docs/ai/data-files) | tools that need the components and tokens as data | | [Prompting tips](https://pico.rusticstack.com/docs/ai/prompting) | getting semantic HTML out of any model | ## Where to start If you build a site with Pico Reforged and use a coding agent, install the [skill](https://pico.rusticstack.com/docs/ai/skill). It carries the rules, the component cheat sheet and the common mistakes, and the agent loads it when a task involves Pico Reforged. If you chat with an assistant that has no skill support, paste the link to [`/llms-full.txt`](https://pico.rusticstack.com/llms-full.txt) or copy one page with the **Copy page as Markdown** button. If you contribute to the repository, read [AGENTS.md](https://pico.rusticstack.com/docs/ai/agents-md) first. ## One naming rule Pico Reforged is a fork of Pico CSS by Lucas Larroche (MIT), rewritten as plain modern CSS. It is not the official Pico CSS. The skill tells agents to say "Pico Reforged" and not to use the Pico logo, so generated text and code do not pass this project off as the original. # Prompting tips > How to ask an assistant for pages that use semantic HTML and Pico Reforged correctly. Page: https://pico.rusticstack.com/docs/ai/prompting Models write what they have seen most. For CSS frameworks that means Bootstrap and Tailwind names. A few lines in the prompt, or the [skill](https://pico.rusticstack.com/docs/ai/skill), move the output to semantic HTML. ## Tell it the rules Say what the framework is and what to avoid: ```text Use Pico Reforged (@rusticstack/pico-reforged). Write semantic HTML: button, label, article, details, dialog, table. Do not add utility classes or made-up component classes. Use a class only if the Pico Reforged docs list it. ``` Add the facts that decide the setup: class based or classless, the theme, and the extras you want. ```text Use the classless build. Load the tabs and badge extras after the core file. Theme: jade. ``` ## Ask for the element, not the look A prompt that names a look gets a div with classes. A prompt that names the job gets the element. | Instead of | Ask for | | --------------------------------- | ---------------------------------------------------- | | "a card with a header and footer" | an `article` with a `header` and a `footer` | | "a toggle switch" | a checkbox with `role="switch"` | | "a collapsible FAQ" | `details` and `summary` | | "a popup" | a `dialog` opened with `showModal()`, or a `popover` | | "a status banner" | an element with `role="status"` and `data-variant` | ## Give it the exact markup When the model gets a component wrong, paste the entry from [`components.json`](https://pico.rusticstack.com/docs/ai/data-files) or the matching docs page and ask it to follow that. The `markup` field is the canonical example and `aria` lists the accessibility notes. ```text Here is the alert markup from the Pico Reforged docs. Use the same structure for the three messages on this page. ``` Here is that markup: **Example: Alert extra** ```html
Tip. You can drag files onto the table to upload them.
Payment failed. Your card was declined. Try another payment method.
``` ## Check the output These problems show up often. Look for them in a review, or tell the model about them up front. - Classes such as `btn`, `btn-primary`, `card`, `row`, `col` or `mt-4`. Nothing styles them. - A `div` around every input. A label wraps its control: ``. - Classes in a classless page. The classless build has no class rules, so `.container`, `.grid` and `.secondary` do nothing there. - An extra used without its stylesheet. Extras are not in `pico.css`. - A `.dark` class for dark mode. Use `data-theme="dark"` on `html` or on any element. - State in classes such as `.active` or `.disabled`. Use `aria-current`, `aria-invalid`, `aria-busy`, `disabled` and `open`. - `!important` or inline colors. Override `--pico-*` properties in your own CSS, which sits outside the `pico` layer and wins without `!important`. - Sass variables such as `$primary`. There is no Sass. - Essential text in `data-tooltip`. It is not an accessible name or description. ## Ask for accessible forms Name the states in the prompt so the model uses the right attributes: "show the email error with `aria-invalid="true"` and link the message with `aria-describedby`". Without it, models often add an error class. **Example: Invalid field with a message** ```html ``` ## Keep the setup in the prompt If the project uses Vite or PostCSS, say so, and include the purge note: the integrations remove unused rules in production, and markup that only exists at run time needs `@source inline("name")` or a safelist. See [Integrations](https://pico.rusticstack.com/docs/integrations/overview) for the setup. # The agent skill > A skill that teaches coding agents the Pico Reforged rules, and how to install it in Claude Code or another agent. Page: https://pico.rusticstack.com/docs/ai/skill The package includes an agent skill in `skills/pico-reforged/`. It is the compact version of these docs, written for a model: the core rules, a cheat sheet of every component, the opt-in extras, setup for the CDN, Vite and PostCSS, and a list of mistakes that models make often. ## What is in it ```text skills/pico-reforged/ SKILL.md references/ setup.md theming.md components.md extras.md ``` `SKILL.md` has a name and a description in its frontmatter. An agent reads the description to decide when the skill applies, for example when a project links `pico.min.css` or imports `@rusticstack/pico-reforged`, and loads the rest only then. The files in `references/` hold the detail, and `SKILL.md` links to them. ## Install in Claude Code Claude Code reads skills from `.claude/skills//` in a project, or from `~/.claude/skills//` for all projects. Copy the whole `pico-reforged` folder, because `SKILL.md` links to the files in `references/`. If the package is installed, copy it from `node_modules`: ```shell npm install @rusticstack/pico-reforged mkdir -p .claude/skills cp -r node_modules/@rusticstack/pico-reforged/skills/pico-reforged .claude/skills/ ``` Without the package, clone the repository and copy the folder from there: ```shell git clone https://github.com/rusticstack/pico-reforged cp -r pico-reforged/skills/pico-reforged .claude/skills/ ``` Commit the folder so your team gets the same rules. After an upgrade of the package, copy it again to refresh the skill. ## Install in other agents The skill is a Markdown file with frontmatter, which is the common skill format, so agents that support skills can use the same folder in their own skills directory. For agents without skill support, put the rules in the file the tool does read, such as `AGENTS.md`, `CLAUDE.md` or a rules file. Copy the body of `SKILL.md` into it, or link to the file. The site serves `SKILL.md` alone at [`/skill/SKILL.md`](https://pico.rusticstack.com/skill/SKILL.md), which is enough for a single paste into a chat. Its links to `references/` then point to files you do not have, so for the full set use the folder from the package. ## What it asks the agent to do - Use the semantic element first and a class only when the cheat sheet lists one. - Never invent utility classes or component classes such as `.btn`, `.card`, `.row` or `.mt-4`. - Show state with attributes (`aria-invalid`, `aria-current`, `aria-busy`, `disabled`, `open`) and not with classes. - Change the look with `--pico-*` custom properties, outside any layer, and not with `!important`. - Force a color scheme with `data-theme`, and not a `.dark` class. - Load extras with their own stylesheet, after the core file. - Say "Pico Reforged" and credit Pico CSS by Lucas Larroche as the origin. ## Check that it works Ask the agent for a small page and look at the markup it returns: ```text Make a sign-up form with name, email, a password and a submit button using Pico Reforged. ``` A correct answer wraps each input in a `label`, uses a plain `button` or `input type="submit"`, and has no `btn`, `form-group` or `col` classes. If it does not, check that the skill folder is in the right place and that the agent lists it. ## Related The skill points to [`components.json`](https://pico.rusticstack.com/docs/ai/data-files) for exact markup per component. See [Prompting tips](https://pico.rusticstack.com/docs/ai/prompting) for how to ask. # Accordion > Collapsible sections from the native details and summary elements, with an animated height where supported. Page: https://pico.rusticstack.com/docs/components/accordion An accordion is a `
` element. No script, no class. The summary gets a chevron that turns when the section opens. Browsers that support `::details-content` and `interpolate-size` also animate the height, and the rest open and close instantly. **Example: Accordion** ```html
What is Pico Reforged?

A rewrite of Pico CSS v2.1.1 in plain modern CSS.

Does it need JavaScript?

No. Details and summary work in the browser on their own.

``` ## One at a time Give several `
` the same `name` and the browser keeps only one open. This is a native feature, so there is nothing to add on the CSS side. In a browser that ignores `name`, every section simply opens on its own. **Example: Exclusive accordion** ```html
First

Opening another one closes this one.

Second

Only one is open at a time.

Third

The same goes for this one.

``` ## Animated open and close The animation is on by default and needs no markup. It is wrapped in `@supports (interpolate-size: allow-keywords) and selector(::details-content)` and in `prefers-reduced-motion: no-preference`, so it is skipped where the browser cannot do it and for people who ask for less motion. The duration comes from `--pico-transition`. The dropdown (`details.dropdown`) is left out, because its menu is a floating list and not content that pushes the page down. ## Button style summary Add `role="button"` to the `` and it looks like a button. Add a class such as `secondary`, `contrast` or `outline` to change the style. **Example: Summary as a button** ```html
Show more

Hidden until you ask for it.

Outline button

The same, as an outline.

``` ## Accessibility `
` and `` are keyboard accessible by default: Tab to the summary, Enter or Space toggles it. The summary shows a focus ring on `:focus-visible`. The chevron is a background image, so it is not read out. Keep the summary text short and put the detail in the body. ## Customization | Variable | Default | Description | | --- | --- | --- | | `--pico-accordion-border-color` | | Border color token, kept from Pico CSS v2.1.1. | | `--pico-accordion-close-summary-color` | `var(--pico-color)` | Summary text while the section is closed. | | `--pico-accordion-open-summary-color` | `var(--pico-muted-color)` | Summary text while the section is open. | | `--pico-accordion-active-summary-color` | `var(--pico-primary-hover)` | Summary text while it has focus. | | `--pico-icon-chevron` | | The chevron image, an SVG data URI. | | `--pico-transition` | `0.2s ease-in-out` | Duration and easing of the chevron and the height animation. | See also the [Dropdown](https://pico.rusticstack.com/docs/components/dropdown), which is a `
` with a floating menu. # Card > A boxed surface from the article element, with an optional header and footer. Page: https://pico.rusticstack.com/docs/components/card An `
` is a card. A `
` or `