Skip to content

shadcn.io is an independent project built on shadcn/ui

Get started

Why AI coding tools love shadcn/ui

Coding agents edit what they can read. How copy-in components, a registry and an MCP server make Cursor, Claude Code and Copilot accurate with UI.

A coding agent works the way you do on an unfamiliar codebase: it reads the files, then changes them. How good its UI work is depends on what it can read. With a component package, the important part sits compiled in node_modules and the agent guesses. With shadcn/ui, the component is a file in your project, written in conventions models have met in many codebases. That difference is most of why agents do well with it, and the rest of this page is how to make the most of it with shadcn.io.

The component is a file you own

Install a component and you get its source, not a dependency:

shadcn CLILocked
Sign in to get your install command
Free with an account. It carries your token, so the CLI installs everything in one go.

The CLI writes components/ui/button.tsx into your project. When you ask for "a quieter button for the cancel action", the agent opens that file and finds the answer in plain sight:

components/ui/button.tsx
export const buttonVariants = tv({
  // …
  variants: {
    variant: {
      default: "bg-primary text-primary-foreground hover:bg-primary/80",
      ghost:
        "hover:bg-muted hover:text-foreground dark:hover:bg-muted/50 aria-expanded:bg-muted aria-expanded:text-foreground",
      link: "text-primary underline-offset-4 hover:underline",
      // destructive, outline, secondary…
    },
  },
});

It uses variant="ghost" because the file says it exists, not because a doc page it half remembers says so. Ask for a new variant and it adds one to the same object, in the same style, and your app has it. There's no theme API to learn and no upstream package to fight: the edit is a diff in your repository, reviewed like any other.

With a packaged library, the agent sees an import and a type definition. The markup, the styles and the states live in compiled code it can't usefully change, so it falls back on what it remembers of that library's API, which is where invented props come from.

The same conventions in every file

Every component is built the same way, so an agent that has read one has read them all:

  • Tailwind classes and theme tokens. Colors are bg-primary, text-muted-foreground, border-input: tokens from your theme, not hex values. Changes stay on-theme and follow dark mode for free.
  • Parts you compose. A Card is Card, CardHeader, CardTitle, CardContent, each a thin element with className. There's nothing hidden to configure, so "move the action into the header" is an edit to markup the agent can see.
  • data-slot on every part. data-slot="card-title", data-slot="button": stable hooks for styles and tests, the same in each file.
  • cn() for class names. Every component merges your className through cn from lib/utils.ts, so an override wins without !important.
  • Variants in one object. Sizes and variants live in one tv() call at the top of the file.

These are shadcn/ui's conventions, and shadcn/ui is widely used, so they're familiar to models before your project teaches them anything. Our components keep them, on Base UI, Radix UI, React Aria and Ark UI, so what the model knows transfers.

A registry the CLI and your agent can both read

Each component is published as a registry item: JSON with its files, the packages it needs, the other components it uses and any CSS it adds, in shadcn's registry format. One add installs all of it. That's what makes the install step safe to hand to an agent: it runs the same command you would, and the CLI asks before it overwrites a file you've changed.

To keep your token out of commands (and out of an agent's transcript), register our registry by name in components.json and keep the token in .env.local. Your agent then installs @shadcnio/date-picker like any shadcn/ui component. Installation has the setup.

Docs written for models too

Every docs page has a Markdown version at the same URL plus .md, such as /ui/button.md, with the prose, the usage and the API reference, and the site has an index for models at /llms.txt. Signed in, Copy page on any docs page copies the Markdown with every demo's code, ready to paste into a chat. That's the quickest way to give an agent one component's real API when it isn't connected to anything.

The MCP server: the catalog as tools

The shadcn.io MCP server (with Pro) connects your agent to the catalog itself, in any of 38 clients: Claude Code, Cursor, VS Code, Windsurf, Zed and more. Instead of remembering an API, the agent asks for it, for your stack. It reads your package.json for the framework and the primitives, and every answer is for that target.

ToolWhat the agent gets
search_componentsComponents by what they do ("date range", "modal"), best first
get_componentOne component in one call: its parts, demos, packages and install command
get_component_apiThe props of one part, with types and defaults, when it isn't sure
get_demoA working demo, its imports pointed at your components.json aliases
get_project_setupThe init for your framework, or the port's setup for Vue, Svelte and Solid
search_blocks, plan_pageWhole page sections, and a stack of them for a page
get_designA brand's DESIGN.md: tokens and rules to style the app with

A prompt like this is enough:

Prompt
use shadcnio to add a date picker to the booking form

The agent searches, gets the component for your stack, runs its install command (your editor asks before it does), and adapts the demo to your form. The quickstart connects it in about a minute; all 22 tools have a page each.

Where agents still go wrong

The files and the MCP remove most guessing, not all of it. Common mistakes, and the fix for each:

MistakeFix
A prop from another library: asChild on a Base UI trigger, render on Radix UIPoint it at the file in components/ui, or let it call get_component_api
Importing a component that isn't installedAdd it first, or tell the agent to install what it uses
Hex colors and arbitrary valuesAsk for theme tokens: "use the theme's colors, no hex"
Dropping a DialogTitle or a label to tidy the markupKeep accessible names: a visually hidden title is className="sr-only"
Mixing two libraries' files of the same nameKeep one library per app for the shared components

Two habits help most: install the component before you ask for the feature, and name the file you want changed ("in components/ui/sidebar.tsx…"). The agent then edits what's there instead of recreating it.

FAQ

Why do AI coding tools work better with shadcn/ui than with a component package?

Because the component is source code in your repository. The agent reads the real markup, classes and variants before it changes anything, and its change is an ordinary edit you review. With a package, the implementation is compiled in node_modules, so the agent works from memory of the API and guesses.

Which AI coding tools does this work with?

Any tool that can read and edit files in your project: Claude Code, Cursor, GitHub Copilot, Windsurf, Zed, Codex and the rest. The MCP server is optional on top, and has a setup guide for each of 38 clients.

Do I need the MCP server for an agent to use the components?

No. Once a component is in components/ui, the agent reads it like any file. The MCP adds what isn't in your project yet: finding the right component, its API for your stack, working demos, the install command and the project's setup.

Should I let the agent write components from scratch instead?

For one-off layout, sure. For controls people interact with (menus, dialogs, comboboxes, date pickers), install ours: focus management, keyboard support and screen reader behavior come from Base UI, Radix UI or React Aria, which are hard to get right from scratch and easy to get subtly wrong.

How do I stop an agent from inventing props?

Give it the source of truth: the file in components/ui, the page's Markdown (its URL plus .md), or the MCP's get_component_api. Invented props almost always come from another library's API, like asChild where Base UI uses render.

Does shadcn.io have an llms.txt?

Yes, at /llms.txt: every section of the site as links, each docs page linking its Markdown. Point an agent at it to find a page, then at the page's .md for the details.

If I let the agent change components, how do I get updates later?

Run the component's add again: the CLI shows that your file differs and asks before it overwrites it. Commit first, take the update, and reapply your changes from the diff, or ask the agent to merge them.

Does this work for Vue, Svelte and Solid too?

Yes. The ports are files in your project as well, installed with shadcn-vue, shadcn-svelte or the shadcn CLI, and the MCP answers for those frameworks when it sees them in package.json.

Is it safe to let an agent run install commands with my token?

Use the @shadcnio registry in components.json with SHADCNIO_TOKEN in .env.local, and the token never appears in a command or a transcript. Agents also ask before running commands in most editors; keep that on.