# Ouro HX > Designed down to the last tap and the last prop. Interactions that feel right to the humans using them. Code that's obvious to the agents building with them. Copy-in source distributed as a shadcn/ui registry on GitHub (ourostack/ouro-ui). It is not an npm package: the shadcn CLI copies the components you add into your app. Ouro HX is the component library within Ouro UI. Ouro AX, its counterpart for the interfaces agents use, is the other half (see "Ouro AX" below). The repository, @ouro namespace and install addresses are unchanged. Check what you build first: build your app, run node lib/ouro/check/check.ts (from the ouro-check item: npx shadcn@latest add ourostack/ouro-ui/ouro-check#v1.3.10) and fix what it reports. It opens your pages at screen sizes from a phone to a wide desktop, light and dark, and finds overlap, sideways scroll, clipped text, blurry pictures and serious axe-core violations, and long lines only where you declare a measure.[^check] Long lines are opt-in, because a fixed text measure is a design choice.[^long-lines] Declare one in ouro-check.json only where your design or the request sets it, and don't cap text width just to quiet the check. Guide: https://ui.ouroboros.bot/docs/guardrails.md ## Install In an existing Vite or Next.js app with Tailwind CSS v4[^tailwind-4] and an "@/*" path alias, run shadcn init once, with the Base UI base and without -t/--template, then add items: ```sh npx shadcn@latest init --base base --preset nova --yes --no-monorepo npx shadcn@latest search 'ourostack/ouro-ui#v1.3.10' # list the items npx shadcn@latest view 'ourostack/ouro-ui/dialog#v1.3.10' # read one item # Once per app, before the first component: the tokens every component needs. npx shadcn@latest add ourostack/ouro-ui/ouro-base#v1.3.10 npx shadcn@latest add ourostack/ouro-ui/dialog#v1.3.10 # install a component ``` - Add ouro-base once, before the first component. No component installs it, so no later add changes the app's stylesheet (in v0.7.0 every component still installs it, and an add can rewrite the stylesheet).[^ouro-base-only][^v0.7.0] Without it, overlays have no backdrop or motion and fields no border, and in development the first component to mount logs the command to run.[^theme-check] - A new Vite app needs @tailwindcss/vite, @import "tailwindcss";, a Vite @ alias, and "paths": { "@/*": ["./src/*"] } in both tsconfig.json and tsconfig.app.json (no baseUrl on TypeScript 6) before init: shadcn reads the root file, and tsc -b builds the app one.[^vite-app] - --preset nova lets init run without prompts. It sets shadcn's starting theme, font and icons, which Ouro components read like any shadcn theme. The install test runs nova and vega; other presets are untested. - A GitHub source is owner/repo#ref; an item is owner/repo/item#ref. @v1.3.10, github: and /tree/ URLs do not work. - A release tag (#v1.3.10) installs the item and every Ouro dependency at that tag.[^release-pins] Every install needs a release tag or @ouro: main has no registry.json, so an address without a ref fails with "did not return a root registry.json file".[^main-no-registry] - Components land in components/ouro// and the helpers they import in lib/ouro/, one file each.[^lands] Ouro UI never writes to components/ui/, so do not pass --overwrite on a first install.[^not-ui] - Tests are optional: add -tests beside the item (npx shadcn@latest add ourostack/ouro-ui/dialog#v1.3.10 ourostack/ouro-ui/dialog-tests#v1.3.10), or ouro-tests for all of them.[^ouro-tests] They need Vitest 4.1.11 or later in browser mode, Playwright 1.58.1 or later, axe-core 4.13.0 or later and Storybook 10.2.10 or later, and never change a version the app already has (v0.7.0's items still carry versions: after add, restore the versions you had pinned).[^minimums][^v0.7.0] Ouro UI's own CI runs them on Vitest 5 only; Vitest 4 is the stated minimum, not a tested one.[^vitest-5][^minimums] The ouro-testing install message lists the config files to add. - The @ouro namespace serves the newest release (the same code as #v1.3.10)[^namespace]: add "registries": { "@ouro": "https://ui.ouroboros.bot/r/{name}.json" } to components.json, then npx shadcn@latest add @ouro/ouro-base @ouro/dialog (ouro-base once per app). ## Ouro AX Ouro AX is Ouro UI's half for agents: it is for the interfaces an agent uses, such as a CLI, an HTTP API or an MCP server, as Ouro HX is for the screens a person uses. Its parts: - A standard with an X-ray: `ax-claims` holds the standard as checkable claims about agent-facing surfaces. `ax-xray` calls an interface from outside, the way an agent would, and reports which claims hold on which command, route and tool, with the fix where one does not. - A kit: with `ax-command`, one definition of a command gives its parser, its help and `help --json`, `--json` output, exit codes, one-line errors that name the fix, and the same command as an MCP tool. An action returns a typed outcome (`ax-outcome`), a wait returns a typed wait with a cursor (`ax-wait`), and `ax-work-event` records who acted for whom. - The evaluation gate: a claim is `must` only when an agent evaluation shows agents failing without it, or when it guards against a stated safety, compatibility or integrity hazard. ```sh npx shadcn@latest add ourostack/ouro-ui/ouro-ax#v1.3.10 # the kit and the X-ray, in lib/ouro/ax/ npx shadcn@latest add ourostack/ouro-ui/ouro-ax-tests#v1.3.10 # with their node:test tests ``` The guide: https://ui.ouroboros.bot/docs/ax.md. A morning with an agent, with the kit's example tool running in your browser: https://ui.ouroboros.bot/ax/ ## Ouro UI for Apple Ouro HX and Ouro AX in Swift, for iPhone, iPad and Mac (ourostack/ouro-ui-apple): https://ui.ouroboros.bot/apple/. The section's checks ask the same app different questions: - The App Intents X-ray (claims held): reads a built app's App Intents from outside and checks them against Ouro AX for Apple's claims. https://ui.ouroboros.bot/apple/ax/ - Ouro Reins (behaviour): an agent reads the app's screens as state and actions and drives it with `ls` and `do`, headless, from fixtures, with the network blocked. Spoonjoy's Kitchen-to-cook-mode journey ran in a median 18.7 ms this way against 16.7 s through XCUITest.[^reins-timing] The idea is Shopify's Reflex (https://shopify.engineering/reflex). Its wire contract is a spec of its own, docs/ouro-reins/PROTOCOL.md in ouro-ui-apple, and a second driver speaks it for any app on a Mac, from the app's tree of controls or a screenshot's text.[^reins-protocol] https://ui.ouroboros.bot/apple/reins/ - Ouro Feel (how it feels): checks jank genre by genre from a UI test: the way back, overlay dismissal, inside the window, tap landing (with an absolute bar for rapid double taps), double-draw, jump after landing, late or lingering chrome, snap with no transition, settle time and place stability.[^feel-genres] https://ui.ouroboros.bot/apple/feel/ ```swift .package(url: "https://github.com/ourostack/ouro-ui-apple.git", from: "0.2.1") // the foundations and the X-ray ``` Ouro Feel and Ouro Reins are on ouro-ui-apple's main branch and are not in a release yet; their guides are docs/ouro-feel/README.md and docs/ouro-reins/README.md in that repository. ## Items - `ouro-base`: Add it once per app, before your first component; no component installs it, so later adds never touch your stylesheet. What every Ouro UI component needs in the app's CSS: success and warning colors, a destructive foreground, the field border color (--input) and --radius when your theme has none, the motion tokens, the press utility, the keyframes for spinners, progress bars and skeletons, and --ouro-layer, the z-index of sheets and dialogs (50; raise it in a :root rule of your own if your app has fixed bars above z-50). - `ouro-theme`: Ouro UI's own look, as a shadcn theme for :root and .dark. Skip it to keep your app's theme. - `ouro-lib`: Every helper in lib/ouro in one item. You don't need to add it: each component installs only the helpers it imports (the lib- items). - `ouro-testing`: Installed with every -tests item; you don't need to add it. The test kit Ouro UI's tests use: Vitest browser projects with the drag, flick, tap, doubleTap, touchDrag, touchStep, pointerPress, emulateMedia, pageZoom, resetPageZoom, setPageZoom and restoreTouch commands, the rotate helper (which turns the phone viewport and resets Chromium's zoom; the ouro-touch project fails a test that leaves the page zoomed), the act helper, the holdFrames helper (which holds animation frames and the clock still so a test steps a spring itself), the motion helpers (expectMotion, expectNoMotion, expectGestureSettle, expectTransition and parseDuration, which prove exactly which CSS properties a state change runs on each part), watchAnnouncements (which records what live regions announce, so a test proves a message is heard once per change), axeExclude, and the end-to-end story helper. - `button`: A button, or a link styled as one. Docs: https://ui.ouroboros.bot/docs/button.md - `text`: Body text in the theme's type scale and colors. Docs: https://ui.ouroboros.bot/docs/text.md - `heading`: A section title, `

` to `

`, in the theme's foreground color. Docs: https://ui.ouroboros.bot/docs/heading.md - `sheet`: A panel that slides in from an edge and is dragged back to dismiss: the mobile form of a dialog. Docs: https://ui.ouroboros.bot/docs/sheet.md - `dialog`: A dialog that presents itself for the screen: a centered dialog on wider screens and a bottom sheet you can drag away on phones (below 640px). Docs: https://ui.ouroboros.bot/docs/dialog.md - `confirm-dialog`: Asks the user to confirm an action, with Cancel focused first. Docs: https://ui.ouroboros.bot/docs/confirm-dialog.md - `field`: A labeled form control: the label, an optional description, the control and its error, wired together with ids that match between the server and the browser. Docs: https://ui.ouroboros.bot/docs/field.md - `fieldset`: A titled group of related fields, such as an address, rendered as a `
` named by its legend. Docs: https://ui.ouroboros.bot/docs/fieldset.md - `link`: A text link that navigates through your router. Docs: https://ui.ouroboros.bot/docs/link.md - `text-field`: A labeled one-line text input on the Field contract: pass `label`, and `error` from your server action or client check. Docs: https://ui.ouroboros.bot/docs/text-field.md - `text-area`: A labeled multi-line text field on the Field contract, a native `