The loop in five minutes
Fragments keeps agents on your design system while they write. It runs in the editor, on every save, with no network. Five steps.
Install
npx @usefragments/cli initinitwritesfragments.config.tsand the hooks for Claude Code, Cursor and Codex. When it finds your components it also writesfragments.manifest.json. Diff them; they are yours.Discover your Fragments
npx @usefragments/cli discoverdiscoverreads your component library and proposesfragments.manifest.json: every exported primitive with its members and props, your token prefix, and empty slots for intents, patterns and grammar. It infers nothing at check time. You curate the file once; it is the contract. Run it again after you add a primitive.Terminal$ npx @usefragments/cli discover Wrote fragments.manifest.json (2 primitives, FCID ddadca30512b).About one second on a small React app with
src/components/{Button,Card}and a@/*alias intsconfig.json. Discover reads the alias for the import path and your stylesheets for the token prefix. If it cannot tell how your app imports the components it stops and asks for--library <import path>instead of writing an empty file.Commit the manifest
The manifest's content hash is the FCID. Every check, every verdict, every receipt cites it. Change the manifest, get a new FCID.
Open your editor
The next Claude Code, Cursor or Codex session starts with a card: your Fragments, what each is for, the patterns you named, the grammar you wrote. Sixty lines at most.
cardFragments vocabulary card FCID: `69793552072061f8ea29849fbb350c2d772a5082ed6fad02ce8deec385a0274d` Import from `@usefragments/ui`. Canonical primitives (71 roots): Accordion, Alert, AppShell, Avatar, Badge, BentoGrid, Box, Breadcrumbs, Button ButtonGroup, Card, Chart, Checkbox, Chip, CodeBlock, Collapsible, ColorPicker, Combobox Command, ComponentDefaults, ConversationList, DataTable, DatePicker, Dialog, Drawer Editor, EmptyState, Field, Fieldset, Form, Grid, Header, Icon, IconButton, Image, Input Link, List, Listbox, Loading, Main, Markdown, Menu, Message, NavigationMenu, Pagination Popover, Progress, Prompt, RadioGroup, ScrollArea, Select, Separator, Sidebar, Skeleton Slider, Stack, Switch, Table, TableOfContents, Tabs, Text, Textarea, Theme, ThemeToggle ThinkingIndicator, Toast, Toggle, ToggleGroup, Tooltip, VisuallyHidden Use for: - Button: action, submit, cta, primary, secondary, destructive · not raw <button> - Table: ledger, repositories, findings, pull requests, merges · not clickable flex rows without semantics - Alert: inline status, warning, error callout, blocked state · not hand-styled callout - Badge: status, severity, count, verdict · not decorative colour - CodeBlock: command, digest, snippet, copyable code · not raw <pre> with hardcoded colours - EmptyState: no data, unsupported, first run, nothing to do · not blank card - Text: typography, body copy, mono digest, tabular numbers · not raw <p>/<span> with own styles - Accordion: expandable sections, faq, long evidence list · not nest inside Card - Combobox: typeahead, file picker, searchable select · not bespoke dropdown - Dialog: confirmation, decision modal, destructive action · not hand-rolled modal - Input: text input, search, filter · not raw <input> - Main: page masthead, page header, section head · not per-page heading row - Menu: overflow actions, third and later verbs, row actions · not custom dropdown - Progress: quota, usage, determinate progress · not decorative bars Patterns: - PageMasthead: top of a page: one status sentence and one primary action — Main.Header > Text(statement) + Button(primary) (apps/cloud/src/page/contract/components/contract-masthead.tsx:112) - SectionHead: section heading with at most one action — WorkspaceSectionHead(title, action?) (apps/cloud/src/components/workspace-section-head.tsx:30) - Ledger: paged rows of repositories, findings, pull requests or merges — Table.Root > Table.Head + Table.Body(rows with drill-through) ; Pagination (apps/cloud/src/page/findings/org-pull-request-detail-page.tsx:607) - EmptyStateWithAction: no data, unsupported, or nothing to do — EmptyState > Title + Description + Actions(one Button) (apps/cloud/src/page/findings/org-exceptions-tab.tsx:225) - WaitingRows: loading a ledger or a block — Skeleton rows matching the loaded shape (apps/cloud/src/page/findings/org-pull-requests-states.tsx:49) - DecisionDialog: confirm an authority or destructive action with its consequences — Dialog > Header + Body(digest, actor, consequence) + Footer(cancel + explicit verb) (apps/cloud/src/page/settings/components/sections/repository-row-detail.tsx:194) - SettingsForm: a form with labelled controls and right-aligned actions — Form > Field[] + Form.Actions(≤2 Buttons) (apps/cloud/src/page/settings/components/sections/invite-member-dialog.tsx:91) - FilterBar: filter a ledger by scope, status or text — Stack(row) > Select[] + Input(search) ; overflow in Menu (apps/cloud/src/page/findings/org-issues-chrome.tsx:144) - StatStrip: three or more figures in a row — Stack(row) > (Text(label) + Text(value, tabularNums))[] (apps/cloud/src/components/workspace-fact-strip.tsx:38) - VerdictCapsule: a pass / block / indeterminate verdict with its evidence beside it — Badge(tone by verdict) + Text(reason) + Popover(evidence) (apps/cloud/src/page/findings/org-pull-request-detail-page.tsx:635) Tokens: --fui-* · no-raw-values Grammar: - The top of a page carries one status sentence and one primary action; competing important cards are a defect. - Verb clusters are right-aligned and hold at most two Buttons; the third verb and later go in a Menu. - Never nest a Card inside a Card. - The page shell owns the gutter and measure; route children never add a full-page container or padding layer. - Parent owns spacing: Stack gap over child margins. - Colour is earned by semantic state only (verdict, severity); never decorative. A new user never sees red. - Status never relies on colour alone; every state has copy and an action. - Loading, queued, unsupported, indeterminate, stale, failed, bypassed and disconnected are distinct states with distinct copy. No generic green complete. - Evidence sits beside the claim (Popover, Collapsible); never behind a tooltip or an advanced drawer. - Authority actions (activate contract, exception, bypass, canonical addition) use a DecisionDialog, never an ordinary Save. - No raw colours, spacing, dimensions or typography; tokens only, and SCSS uses var(--fui-x, $fui-x). - Every CSS custom property used is defined by the token sources. - No Tailwind classes in Cloud. - Canonical primitives replace raw HTML: Button not <button>, Select not <select>, Link not <a>. - Compound components stay compound: Card.Header via the parent import, never split exports. - Named exports only; page UI lives in src/page/<feature>/, route files stay thin. - A page-title word appears once on the page; no eyebrow restating the h1; no repeated copy. - No gradients, glass panels, dot grids, oversized display type, or a new radius/shadow system. Search: local MCP `search("intent")` via `npx @usefragments/cli mcp --stdio`. Verify: `npx @usefragments/cli check --changed`.Sixty lines, recorded from the Fragments repository on 2026-09-02. Yours lists your primitives.
Watch the first correction
Ask the agent for a form. When it writes
<button>, the check runs on save and the agent reads:PostToolUseapps/cloud/src/prod-smoke/ProdSmokeGovernance.tsx:9 FUI1004 Bespoke <button> has a library equivalent. Swap to <Button> from @usefragments/ui. → Replace <button> with <Button>The agent repairs before you look. When the session stops, the loop checks the whole diff once more and holds the stop until introduced findings are zero.
What you have now
A manifest your team owns. A card every agent session starts from. A check on every save and a proof at every stop, all local.