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.

  1. Install

    npx @usefragments/cli init

    init writes fragments.config.ts and the hooks for Claude Code, Cursor and Codex. When it finds your components it also writes fragments.manifest.json. Diff them; they are yours.

  2. Discover your Fragments

    npx @usefragments/cli discover

    discover reads your component library and proposes fragments.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 in tsconfig.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.

  3. 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.

  4. 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.

    card
    Fragments 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.

  5. Watch the first correction

    Ask the agent for a form. When it writes <button>, the check runs on save and the agent reads:

    PostToolUse
    apps/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.

Next steps