Jesse A. Green / notebook

shadcn/ui — User Guide

Generated May 2026 from shadcn-ui/ui at b9f78c8

AI-generated documentation. The library is checked by sampling (three repositories so far); this guide was not individually reviewed. Verify against the project before relying on it.

shadcn/ui is a CLI-driven component registry that copies beautifully designed, accessible React UI components directly into your project. Unlike traditional component libraries installed as npm dependencies, shadcn/ui gives you full ownership of every component — the source code lives in your repo, you control it, and you can customize it however you want. Components are built on Radix UI or Base UI primitives and styled with Tailwind CSS.

This guide covers the shadcn CLI (version 4.3.0), every command and option, project setup across all supported frameworks, and real-world recipes for common tasks.


1. Quick Start

What is shadcn/ui?

shadcn/ui is not a component library you npm install. It is a CLI tool (shadcn) that fetches component source code from a registry and copies it into your project. You get the actual .tsx files in your codebase — no black-box dependency, no version lock-in. When you need to change how a button looks or a dialog behaves, you edit the file directly.

Key Features

  • Copy-paste architecture — components live in your repo, not node_modules
  • 12 CLI commands — init, add, apply, search, build, migrate, diff, docs, view, info, mcp, registry
  • 6 framework templates — Next.js, Vite, React Router, TanStack Start, Astro, Laravel
  • 2 component bases — Radix UI (default) or Base UI (MUI)
  • Tailwind CSS styling — CSS variables, dark mode, RTL support out of the box
  • Custom registries — host and share your own component sets
  • MCP server — integrate with AI coding tools (Claude Code, Cursor, VS Code, Codex, OpenCode)
  • Monorepo support — automatic workspace detection and file distribution

Prerequisites

Requirement Minimum Version
Node.js 20+
Package manager npm, pnpm, yarn, or bun
React 18+ (19 recommended)
Tailwind CSS v3 or v4

Fastest Way to Start

Create a new Next.js project with shadcn/ui in one command:

npx shadcn@latest init

This scaffolds a new project, installs dependencies, configures Tailwind CSS, sets up path aliases, and creates a components.json configuration file.

Then add your first component:

npx shadcn@latest add button

Expected output:

✔ Done. Installed 1 component.

  - button (components/ui/button.tsx)

Use it in your code:

import { Button } from "@/components/ui/button"

export default function Home() {
  return <Button variant="outline">Click me</Button>
}

What to Try Next


2. Installation

System Requirements

Component Requirement Notes
Node.js v20 or later Required for the CLI
npm / pnpm / yarn / bun Any recent version CLI auto-detects your package manager
Git Any recent version Required for project scaffolding
Operating System macOS, Linux, Windows All platforms supported
Disk Space ~50 MB For CLI + dependencies

Install Methods

Note

You do not install shadcn as a global package. Instead, use your package manager's exec command to run it directly. This ensures you always use the latest version.

npm

npx shadcn@latest init

pnpm

pnpm dlx shadcn@latest init

yarn

yarn dlx shadcn@latest init

bun

bunx shadcn@latest init

All subsequent examples in this guide use npx shadcn@latest. Substitute your preferred package manager's exec command as shown above.

Post-Install Verification

After running init, verify your setup:

  1. Check that components.json exists at your project root:
cat components.json

You should see a JSON file with $schema, style, aliases, and tailwind fields.

  1. Check that the utils file was created:
ls src/lib/utils.ts
  1. Run the info command to confirm the CLI can read your project:
npx shadcn@latest info

This prints your framework, component base, style, and alias configuration.

Install Troubleshooting

npm error Invalid Version

This occurs when your Node.js version is below 20. Upgrade Node.js:

node --version  # Must be v20+

EACCES: permission denied

On Linux/macOS, avoid running with sudo. Instead, fix npm permissions:

mkdir -p ~/.npm-global
npm config set prefix '~/.npm-global'
export PATH=~/.npm-global/bin:$PATH

Cannot find module errors after init

Run your package manager's install command to ensure all dependencies are resolved:

npm install

3. Configuration

The components.json File

Every shadcn/ui project has a components.json file at the project root. This file tells the CLI where to put components, what style to use, and how to resolve imports.

{
  "$schema": "https://ui.shadcn.com/schema.json",
  "style": "new-york-v4",
  "rsc": true,
  "tsx": true,
  "tailwind": {
    "config": "tailwind.config.js",
    "css": "app/globals.css",
    "baseColor": "zinc",
    "cssVariables": true,
    "prefix": ""
  },
  "aliases": {
    "components": "@/components",
    "utils": "@/lib/utils",
    "ui": "@/components/ui",
    "lib": "@/lib",
    "hooks": "@/hooks"
  },
  "iconLibrary": "lucide",
  "rtl": false,
  "registries": {}
}

Configuration Fields Reference

Field Type Description
$schema string JSON schema URL for validation. Always "https://ui.shadcn.com/schema.json"
style string Component style preset (e.g., "new-york-v4", "base-nova")
rsc boolean Enable React Server Components support
tsx boolean Use TypeScript (.tsx). Set false for JavaScript (.jsx)
tailwind.config string Path to your Tailwind config file
tailwind.css string Path to your global CSS file
tailwind.baseColor string Base color palette: "neutral", "zinc", "stone", or "mauve"
tailwind.cssVariables boolean Use CSS variables for theming (recommended: true)
tailwind.prefix string Tailwind class prefix (e.g., "tw-" to avoid conflicts)
aliases.components string Import alias for the components directory
aliases.utils string Import alias for the utils module
aliases.ui string Import alias for the UI components directory
aliases.lib string Import alias for the lib directory
aliases.hooks string Import alias for the hooks directory
iconLibrary string Icon library name (e.g., "lucide")
rtl boolean Enable right-to-left layout support
menuColor string Menu color mode: "default", "inverted", "default-translucent", "inverted-translucent"
menuAccent string Menu accent style: "subtle" or "bold"
registries object Custom registry definitions (see Custom Registries)

Common Configuration Combinations

Next.js with App Router (TypeScript, Radix, CSS variables)

{
  "style": "new-york-v4",
  "rsc": true,
  "tsx": true,
  "tailwind": {
    "css": "app/globals.css",
    "baseColor": "zinc",
    "cssVariables": true
  },
  "aliases": {
    "components": "@/components",
    "utils": "@/lib/utils",
    "ui": "@/components/ui"
  }
}

Vite + React (no RSC, Base UI)

{
  "style": "base-nova",
  "rsc": false,
  "tsx": true,
  "tailwind": {
    "css": "src/index.css",
    "baseColor": "neutral",
    "cssVariables": true
  },
  "aliases": {
    "components": "@/components",
    "utils": "@/lib/utils",
    "ui": "@/components/ui"
  }
}

JavaScript Project (no TypeScript)

{
  "tsx": false,
  "style": "new-york-v4"
}

Components will be output as .jsx files instead of .tsx.

RTL-Enabled Project

{
  "style": "new-york-v4",
  "rtl": true
}

Custom Tailwind Prefix (avoiding class collisions)

{
  "tailwind": {
    "prefix": "tw-",
    "cssVariables": true,
    "baseColor": "zinc"
  }
}

Environment Variables

Variable Purpose Default
REGISTRY_URL Override the component registry URL https://ui.shadcn.com/r
https_proxy HTTP/HTTPS proxy for registry fetches None

Set REGISTRY_URL to point at a self-hosted or custom registry:

REGISTRY_URL=https://my-company.com/r npx shadcn@latest add button

Tip

For detailed configuration of custom registries, Tailwind CSS integration, advanced theming, and deployment considerations, see the Admin Guide — Section: Configuration Mastery.


4. Core Usage

This section covers every CLI command organized by user intent — what you want to accomplish and how to do it.

Adding Components

The add command is the most frequently used command. It fetches component source code from a registry and writes it into your project.

Add a Single Component

npx shadcn@latest add button

The CLI resolves the component from the configured registry, downloads its source, resolves any dependencies (other components it needs), installs required npm packages, and writes the files to your configured aliases.ui directory.

Add Multiple Components at Once

npx shadcn@latest add button card dialog input textarea

Each component and its dependencies are resolved and installed together.

Add All Available Components

npx shadcn@latest add -a

or:

npx shadcn@latest add --all

Warning

Adding all components installs 50+ component files and their dependencies into your project. This is useful for exploration but may add significant files to your codebase. Use --dry-run first to preview what will be added.

Add from a URL

You can add components by providing a direct URL to a registry item:

npx shadcn@latest add https://ui.shadcn.com/r/styles/new-york-v4/button.json

This is useful for adding components from third-party registries or specific versions.

Add from a Custom Registry

If you have custom registries configured in components.json, prefix the component name with the registry key:

npx shadcn@latest add my-registry/custom-button

Add from a Local Path

npx shadcn@latest add ./path/to/component.json

Add to a Specific Directory

Override the default output path:

npx shadcn@latest add button -p src/components/custom

Preview Changes Without Writing (Dry Run)

npx shadcn@latest add button --dry-run

This shows what files would be created or modified without actually writing anything to disk. Always a good idea before adding unfamiliar components or using --all.

Overwrite Existing Components

If a component already exists and you want to replace it with the latest version:

npx shadcn@latest add button -o

or:

npx shadcn@latest add button --overwrite

Check What Changed Before Overwriting

View the diff between your local version and the registry version:

npx shadcn@latest add button --diff

View the full registry file contents:

npx shadcn@latest add button --view

Target a specific file path within the component:

npx shadcn@latest add button --diff src/components/ui/button.tsx
npx shadcn@latest add button --view src/components/ui/button.tsx

Skip Confirmation Prompts

npx shadcn@latest add button -y

Silent Mode

Suppress all output:

npx shadcn@latest add button -s

Complete add Options Reference

Option Short Description
[components...] Component names, URLs, or local paths
--yes -y Skip confirmation prompt
--overwrite -o Overwrite existing files
--cwd <cwd> -c Set working directory
--all -a Add all available components
--path <path> -p Custom output path
--silent -s Suppress output
--dry-run Preview without writing files
--diff [path] Show diff for a component file
--view [path] Show component file contents

Initializing a New Project

The init command (alias: create) scaffolds a new project or configures shadcn/ui in an existing project.

Basic Initialization

npx shadcn@latest init

This launches an interactive setup that asks you to choose a framework, component base, style, base color, and alias configuration.

Initialize with Defaults

Skip all prompts and use default settings (Next.js template, base-nova preset):

npx shadcn@latest init -d

or:

npx shadcn@latest init --defaults

Initialize with a Specific Template

npx shadcn@latest init -t vite

Available templates:

Template Value Description
Next.js next Next.js with App Router
Vite vite Vite + React
React Router react-router React Router framework mode
TanStack Start start TanStack Start with file-based routing
Astro astro Astro with React islands
Laravel laravel Laravel (requires existing Laravel app)

Important

The Laravel template does not scaffold a new Laravel project. It configures shadcn/ui within an existing Laravel application. You must have a Laravel app already created.

Initialize with a Component Base

Choose between Radix UI and Base UI primitives:

# Radix UI (default)
npx shadcn@latest init -b radix

# Base UI (MUI)
npx shadcn@latest init -b base

Initialize with a Preset

npx shadcn@latest init -p base-nova

Presets bundle a style, theme, and configuration together for a specific look and feel.

Initialize a Monorepo

npx shadcn@latest init --monorepo

This scaffolds the project as a monorepo with separate workspace packages for UI components, hooks, and library utilities.

To explicitly disable monorepo detection:

npx shadcn@latest init --no-monorepo

Name Your Project

npx shadcn@latest init -n my-app

Force Overwrite Existing Configuration

npx shadcn@latest init -f

Caution

The --force flag overwrites your existing components.json and related configuration files without warning. Back up your configuration before using this flag.

Enable RTL Support

npx shadcn@latest init --rtl

Disable CSS Variables

npx shadcn@latest init --no-css-variables

Re-install Existing UI Components

After reconfiguring, reinstall all previously added components:

npx shadcn@latest init --reinstall

This re-downloads and regenerates all tracked components using your current configuration.

Complete init Options Reference

Option Short Description
--template <template> -t Framework template: next, vite, react-router, start, astro, laravel
--base <base> -b Component library: radix, base
--monorepo / --no-monorepo Enable/disable monorepo scaffolding
--preset [name] -p Use a preset configuration
--yes -y Skip confirmation (default: true)
--defaults -d Use defaults: --template=next --preset=base-nova
--force -f Force overwrite existing config
--cwd <cwd> -c Set working directory
--name <name> -n Project name
--silent -s Suppress output
--css-variables / --no-css-variables Enable/disable CSS variables for theming (default: true)
--rtl / --no-rtl Enable/disable RTL support
--reinstall / --no-reinstall Re-install existing UI components

Applying Presets

The apply command applies a preset configuration to an existing project. Presets can change style, theme, component variants, and more — all at once.

npx shadcn@latest apply base-nova

or using the --preset flag:

npx shadcn@latest apply --preset base-nova

Apply Options Reference

Option Short Description
[preset] Preset name (positional argument)
--preset <preset> Preset to apply (flag form)
--yes -y Skip confirmation
--cwd <cwd> -c Set working directory
--silent -s Suppress output

Note

The apply command modifies your components.json and may update existing component files to match the new preset's style. Use version control so you can review and revert changes if needed.


Searching and Browsing Registries

The search command (alias: list) lets you discover available components across registries.

Search All Items in a Registry

npx shadcn@latest search @shadcn

The @shadcn registry is the built-in default pointing to https://ui.shadcn.com/r.

Search with a Query

npx shadcn@latest search @shadcn -q button

Limit and Paginate Results

npx shadcn@latest search @shadcn -q dialog -l 5 -o 0

Search Options Reference

Option Short Description
<registries...> One or more registry names to search
--query -q Search query string
--limit -l Maximum results to return
--offset -o Skip first N results

Viewing Registry Items

The view command outputs raw JSON data for a registry item. Useful for scripting or inspecting component metadata.

npx shadcn@latest view button

Output is structured JSON containing the component's files, dependencies, and registry metadata.


Getting Component Documentation

The docs command retrieves documentation, API references, and usage examples for a component directly in the terminal.

npx shadcn@latest docs button

This is especially helpful when you want to see all available props, variants, and usage patterns without leaving the terminal or opening a browser.

npx shadcn@latest docs dialog
npx shadcn@latest docs form
npx shadcn@latest docs table

Checking Diffs and Updates

Important

The standalone diff command is deprecated. Use add [component] --diff instead.

To see what has changed in a component since you last added it:

npx shadcn@latest add button --diff

To view the current contents of a component from the registry:

npx shadcn@latest add button --view

You can also target a specific file path within the component:

npx shadcn@latest add button --diff src/components/ui/button.tsx
npx shadcn@latest add button --view src/components/ui/button.tsx

This is the recommended workflow for updating components:

  1. Check the diff: npx shadcn@latest add button --diff
  2. Review changes
  3. If acceptable, overwrite: npx shadcn@latest add button --overwrite

Running Migrations

The migrate command performs automated codebase transformations for common upgrade paths.

Available Migrations

Migration Description
icons Migrate to a different icon library
radix Migrate to the radix-ui mono package (replaces individual @radix-ui/* packages)
rtl Add RTL (right-to-left) support to existing components

Run a Migration

npx shadcn@latest migrate icons
npx shadcn@latest migrate radix
npx shadcn@latest migrate rtl

List Available Migrations

npx shadcn@latest migrate -l

or:

npx shadcn@latest migrate --list

Migration Options Reference

Option Short Description
--list -l List available migrations
--yes -y Skip confirmation
--cwd <cwd> -c Set working directory

Working with the MCP Server

shadcn/ui includes a Model Context Protocol (MCP) server that integrates with AI coding tools. This lets AI assistants add components, search the registry, and read documentation directly through your editor.

Start the MCP Server

npx shadcn@latest mcp

This starts the server using stdio transport. It is designed to be invoked by an MCP client, not run standalone in a terminal.

Initialize MCP Configuration for a Client

npx shadcn@latest mcp init --client cursor

Supported clients:

Client Value
Claude Code claude-code
Cursor cursor
VS Code vscode
Codex codex
OpenCode opencode

This writes the necessary MCP configuration file for your chosen client so it can discover and connect to the shadcn MCP server automatically.

Example: Setting Up MCP for Claude Code

npx shadcn@latest mcp init --client claude-code

After initialization, Claude Code can:

  • Add components to your project
  • Search the component registry
  • Retrieve component documentation and usage examples
  • All through natural language commands

Getting Project Information

The info command prints a summary of your shadcn/ui project configuration:

npx shadcn@latest info

Output includes your detected framework, component base, style, Tailwind configuration, aliases, and installed components. Useful for debugging configuration issues or verifying setup.


Building a Custom Registry

The build command compiles your component registry for distribution.

npx shadcn@latest build

By default, this reads ./registry.json and outputs to ./public/r.

Specify a Registry File

npx shadcn@latest build ./my-registry.json

Specify Output Directory

npx shadcn@latest build -o ./dist/r

Build Options Reference

Option Short Description
[registry] Path to registry JSON file (default: ./registry.json)
--output <path> -o Output directory (default: ./public/r)

Registry Commands

The registry command provides additional registry-related utilities:

npx shadcn@latest registry

5. Common Tasks

Setting Up a Next.js Project from Scratch

# Create and initialize in one step
npx shadcn@latest init -t next -n my-next-app

# Navigate into the project
cd my-next-app

# Add components you need
npx shadcn@latest add button card dialog input label

# Start the dev server
npm run dev

Setting Up a Vite + React Project

npx shadcn@latest init -t vite -n my-vite-app
cd my-vite-app
npx shadcn@latest add button
npm run dev

Setting Up a React Router Project

npx shadcn@latest init -t react-router -n my-rr-app
cd my-rr-app
npx shadcn@latest add button navigation-menu
npm run dev

Setting Up a TanStack Start Project

npx shadcn@latest init -t start -n my-start-app
cd my-start-app
npx shadcn@latest add button
npm run dev

Setting Up an Astro Project

npx shadcn@latest init -t astro -n my-astro-app
cd my-astro-app
npx shadcn@latest add button
npm run dev

Adding shadcn/ui to an Existing Laravel Project

cd existing-laravel-app
npx shadcn@latest init -t laravel
npx shadcn@latest add button card

Adding a Dialog Component and Using It

npx shadcn@latest add dialog

Then in your React code:

import {
  Dialog,
  DialogContent,
  DialogDescription,
  DialogHeader,
  DialogTitle,
  DialogTrigger,
} from "@/components/ui/dialog"

export function ConfirmDialog() {
  return (
    <Dialog>
      <DialogTrigger>Open</DialogTrigger>
      <DialogContent>
        <DialogHeader>
          <DialogTitle>Are you sure?</DialogTitle>
          <DialogDescription>
            This action cannot be undone.
          </DialogDescription>
        </DialogHeader>
      </DialogContent>
    </Dialog>
  )
}

Adding a Form with Validation

npx shadcn@latest add form input label button

The form component integrates with react-hook-form and zod for validation:

import { useForm } from "react-hook-form"
import { zodResolver } from "@hookform/resolvers/zod"
import * as z from "zod"
import { Button } from "@/components/ui/button"
import {
  Form,
  FormControl,
  FormField,
  FormItem,
  FormLabel,
  FormMessage,
} from "@/components/ui/form"
import { Input } from "@/components/ui/input"

const formSchema = z.object({
  username: z.string().min(2).max(50),
})

export function ProfileForm() {
  const form = useForm({
    resolver: zodResolver(formSchema),
    defaultValues: { username: "" },
  })

  function onSubmit(values: z.infer<typeof formSchema>) {
    console.log(values)
  }

  return (
    <Form {...form}>
      <form onSubmit={form.handleSubmit(onSubmit)}>
        <FormField
          control={form.control}
          name="username"
          render={({ field }) => (
            <FormItem>
              <FormLabel>Username</FormLabel>
              <FormControl>
                <Input placeholder="shadcn" {...field} />
              </FormControl>
              <FormMessage />
            </FormItem>
          )}
        />
        <Button type="submit">Submit</Button>
      </form>
    </Form>
  )
}

Building a Data Table

npx shadcn@latest add table

The table component provides the structural primitives. Pair with @tanstack/react-table for full data table functionality:

import {
  Table,
  TableBody,
  TableCell,
  TableHead,
  TableHeader,
  TableRow,
} from "@/components/ui/table"

export function InvoiceTable() {
  return (
    <Table>
      <TableHeader>
        <TableRow>
          <TableHead>Invoice</TableHead>
          <TableHead>Status</TableHead>
          <TableHead className="text-right">Amount</TableHead>
        </TableRow>
      </TableHeader>
      <TableBody>
        <TableRow>
          <TableCell>INV001</TableCell>
          <TableCell>Paid</TableCell>
          <TableCell className="text-right">$250.00</TableCell>
        </TableRow>
      </TableBody>
    </Table>
  )
}

Switching from Radix to Base UI

If you started with Radix and want to switch to Base UI:

npx shadcn@latest init -b base -f

Then reinstall your components:

npx shadcn@latest init --reinstall

Tip

The --reinstall flag re-downloads all previously added components using the new component base. Your customizations will be overwritten — commit your changes first if you want to preserve them.

Setting Up a Monorepo with Shared UI Package

npx shadcn@latest init --monorepo -n my-monorepo

The CLI creates a workspace structure where:

  • UI components go to the UI package
  • Hooks go to the hooks package
  • Library utilities go to the lib package

Each workspace gets its own package.json, and the root components.json maps aliases to the correct workspace paths.

Configuring Dark Mode

shadcn/ui components support dark mode via Tailwind CSS's dark: variant. With CSS variables enabled (the default), theming is controlled through CSS custom properties.

  1. Ensure cssVariables: true in your components.json:
{
  "tailwind": {
    "cssVariables": true
  }
}
  1. Your global CSS file contains light and dark theme variables:
:root {
  --background: 0 0% 100%;
  --foreground: 240 10% 3.9%;
  /* ... */
}

.dark {
  --background: 240 10% 3.9%;
  --foreground: 0 0% 98%;
  /* ... */
}
  1. Toggle dark mode using your framework's theme provider or by adding/removing the dark class on <html>.

For Next.js, the popular approach is next-themes:

import { ThemeProvider } from "next-themes"

export default function RootLayout({ children }) {
  return (
    <html lang="en" suppressHydrationWarning>
      <body>
        <ThemeProvider attribute="class" defaultTheme="system" enableSystem>
          {children}
        </ThemeProvider>
      </body>
    </html>
  )
}

Setting Up RTL (Right-to-Left) Support

For RTL layouts (Arabic, Hebrew, Farsi, etc.):

During initialization:

npx shadcn@latest init --rtl

For an existing project — run the RTL migration:

npx shadcn@latest migrate rtl

This transforms component source files to use logical CSS properties and RTL-aware layouts.

Using a Custom Registry

Custom registries let you share components across teams or organizations.

  1. Define the registry in components.json:
{
  "registries": {
    "my-company": {
      "url": "https://components.my-company.com/r/{style}/{name}.json"
    }
  }
}

The {name} and {style} placeholders are replaced at fetch time with the component name and your configured style.

  1. Add components from your custom registry:
npx shadcn@latest add my-company/custom-button
  1. Search your custom registry:
npx shadcn@latest search my-company -q button

Building Your Own Registry

  1. Create a registry.json at your project root:
{
  "name": "my-registry",
  "items": [
    {
      "name": "fancy-button",
      "type": "registry:ui",
      "files": [
        {
          "path": "registry/fancy-button.tsx",
          "type": "registry:ui"
        }
      ]
    }
  ]
}

Registry item types:

Type Description
registry:ui UI component
registry:hook React hook
registry:lib Library utility
registry:theme Theme configuration
registry:style Style preset
registry:base Base configuration
registry:font Font configuration
  1. Build the registry:
npx shadcn@latest build

This outputs JSON files to ./public/r by default.

  1. Host the output on any static file server or CDN. Users can then add your registry to their components.json and install your components.

Previewing Changes with --dry-run

Before adding or overwriting components, preview exactly what will change:

npx shadcn@latest add dialog --dry-run

Output shows which files would be created, modified, or have dependencies installed — without writing anything. Combine with --all to see everything:

npx shadcn@latest add --all --dry-run

Migrating Icon Libraries

Switch from one icon library to another:

npx shadcn@latest migrate icons

The migration scans your component files, identifies icon imports, and rewrites them to use the new library. Run with -y to skip confirmation:

npx shadcn@latest migrate icons -y

Migrating to the Radix UI Mono Package

Radix UI consolidated individual packages (e.g., @radix-ui/react-dialog, @radix-ui/react-popover) into a single radix-ui package. Migrate automatically:

npx shadcn@latest migrate radix

This updates all @radix-ui/react-* imports to use the mono package and cleans up your package.json.

Setting Up MCP for AI Coding Tools

Claude Code

npx shadcn@latest mcp init --client claude-code

Cursor

npx shadcn@latest mcp init --client cursor

VS Code

npx shadcn@latest mcp init --client vscode

Codex

npx shadcn@latest mcp init --client codex

OpenCode

npx shadcn@latest mcp init --client opencode

After initialization, your AI tool can use the MCP server to:

  • Add components to your project via natural language
  • Search the component registry
  • Retrieve component documentation and usage examples
  • Understand your project's shadcn/ui configuration

Viewing Component Docs from the Terminal

npx shadcn@latest docs dialog

This retrieves the full documentation for the component, including props, variants, and usage examples.

Updating a Component to the Latest Version

There is no dedicated update command. To update a component:

  1. Check what changed:
    npx shadcn@latest add button --diff
    
  2. If the changes look good, overwrite:
    npx shadcn@latest add button --overwrite
    

Working in a Different Directory

All commands accept -c or --cwd to operate on a project in another directory:

npx shadcn@latest add button -c /path/to/other/project
npx shadcn@latest info -c /path/to/other/project
npx shadcn@latest init -c /path/to/new/project

Adding Components Through a Proxy

If your network requires a proxy for HTTPS connections:

https_proxy=http://proxy.company.com:8080 npx shadcn@latest add button

Using a Self-Hosted Registry

Point all CLI operations at your internal registry:

REGISTRY_URL=https://internal.company.com/r npx shadcn@latest add button

Or set it permanently in your shell profile:

export REGISTRY_URL=https://internal.company.com/r

Changing Base Colors

The four available base color palettes are:

Color Description
neutral Clean, balanced grays
zinc Cool-toned grays (default)
stone Warm-toned grays
mauve Purple-tinted grays

Set during initialization when prompted, or edit components.json directly:

{
  "tailwind": {
    "baseColor": "stone"
  }
}

Then reinstall components to apply the new color:

npx shadcn@latest init --reinstall

Using JavaScript Instead of TypeScript

During init, set TypeScript off. Or edit components.json:

{
  "tsx": false
}

Components will be generated as .jsx files without type annotations.

Customizing Menu Appearance

Set menu styling in components.json:

{
  "menuColor": "inverted",
  "menuAccent": "bold"
}
menuColor Value Description
default Standard menu colors
inverted Inverted color scheme
default-translucent Standard with transparency
inverted-translucent Inverted with transparency
menuAccent Value Description
subtle Understated accent colors
bold Prominent accent colors

Batch Adding Components for a Dashboard

A typical dashboard needs several components. Add them all at once:

npx shadcn@latest add card table chart badge button input select tabs dialog dropdown-menu avatar separator -y

Setting Up a Component with Custom Alias Path

If your project uses a non-standard directory structure:

# Add to a custom path
npx shadcn@latest add button -p src/shared/ui

# Or update components.json to change the default
{
  "aliases": {
    "ui": "@/shared/ui"
  }
}

Creating a Landing Page Component Set

For a marketing/landing page, a common component set:

npx shadcn@latest add button card badge separator accordion tabs -y

Creating an Admin Panel Component Set

For an admin panel or back-office:

npx shadcn@latest add table card button input label select checkbox dialog dropdown-menu sidebar navigation-menu badge avatar separator tabs command -y

6. Troubleshooting

Error: npm error Invalid Version

Cause: Node.js version is below the minimum requirement (v20).

Solution:

  1. Check your Node.js version: node --version
  2. Upgrade to Node.js v20 or later
  3. If using nvm: nvm install 20 && nvm use 20

Prevention: Use a .nvmrc file in your project root with 20 to ensure the correct version.

(Related: GitHub issue #10377)


Error: Cannot find module '@/components/ui/button'

Cause: Path aliases are not configured in your bundler/TypeScript config, or the alias in components.json does not match your tsconfig.json paths.

Solution:

  1. Check components.json aliases match your tsconfig.json paths:
    {
      "compilerOptions": {
        "baseUrl": ".",
        "paths": {
          "@/*": ["./src/*"]
        }
      }
    }
    
  2. Restart your dev server after modifying tsconfig.json
  3. Run npx shadcn@latest info to verify alias resolution

Prevention: Let shadcn init configure aliases automatically rather than editing them manually.


Error: Installation failure when adding components

Cause: Network issues, registry unavailability, or incompatible Node.js version.

Solution:

  1. Check network connectivity: curl https://ui.shadcn.com/r
  2. Verify Node.js version: node --version (must be v20+)
  3. Clear npm cache: npm cache clean --force
  4. Try with a different package manager: pnpm dlx shadcn@latest add button

Prevention: Ensure stable internet and correct Node.js version before running CLI commands.

(Related: GitHub issue #7129)


Error: Unable to download accordion with npx shadcn@latest add accordion

Cause: Registry fetch failure, often due to network restrictions, proxy requirements, or stale npm cache.

Solution:

  1. Clear npx cache: npx clear-npx-cache or delete ~/.npm/_npx
  2. Try specifying the registry URL explicitly: REGISTRY_URL=https://ui.shadcn.com/r npx shadcn@latest add accordion
  3. Check if a proxy is needed: https_proxy=http://your-proxy:port npx shadcn@latest add accordion

Prevention: Configure https_proxy environment variable if behind a corporate firewall.

(Related: GitHub issue #5263)


Error: components.json not found

Cause: Running a command outside of an initialized shadcn/ui project, or the --cwd flag points to the wrong directory.

Solution:

  1. Run npx shadcn@latest init to create the configuration file
  2. If using --cwd, verify the path: ls /path/to/project/components.json
  3. Check you are in the correct directory: pwd

Prevention: Always run commands from the project root, or use --cwd to specify the correct directory.


Error: Separator component renders incorrectly

Cause: Known issue with the separator component's default rendering.

Solution:

  1. After adding the separator component, inspect components/ui/separator.tsx
  2. Ensure Tailwind CSS classes are applied correctly
  3. Verify no CSS conflicts with other libraries in your project
  4. Check the component's orientation prop is set correctly ("horizontal" or "vertical")

Prevention: Test components immediately after adding them.

(Related: GitHub issue #10415)


Error: Combobox loses selected value on parent re-render

Cause: The Combobox component's internal state resets when the parent component re-renders due to uncontrolled state management.

Solution:

  1. Lift the selected value state to the parent component
  2. Pass the value and onChange handler as controlled props
  3. Use React.memo or useMemo to prevent unnecessary re-renders of the parent

(Related: GitHub issue #10414)


Error: CommandInput of Combobox inside Dialog not working

Cause: Focus management conflict between the Dialog and Command components. The Dialog traps focus, preventing the CommandInput from receiving keyboard events properly.

Solution:

  1. Use the cmdk library's built-in Dialog variant: CommandDialog
  2. Alternatively, set shouldFilter={false} on the Command component and handle filtering manually
  3. Add onOpenAutoFocus={(e) => e.preventDefault()} to DialogContent if focus management is the issue

Prevention: When combining multiple compound components (Dialog + Command), test interaction behavior early.

(Related: GitHub issue #4516)


Error: CLI apply command does not work in monorepo

Cause: The apply command may not correctly resolve workspace roots in monorepo setups.

Solution:

  1. Run the command from the workspace root that contains components.json
  2. Use --cwd to explicitly point to the correct workspace:
    npx shadcn@latest apply base-nova --cwd packages/ui
    
  3. Ensure components.json exists in the target workspace

(Related: GitHub issue #10411)


Error: @container/field-group not allowing div to grow

Cause: CSS container query scoping conflict where @container/field-group prevents child elements from expanding.

Solution:

  1. Check that your Tailwind CSS version supports container queries
  2. Verify the container name is correctly applied to the parent element
  3. Override the container styling in your component:
    .field-group > div {
      flex-grow: 1;
    }
    

(Related: GitHub issue #9301)


Error: Animations not working with Tailwind v4

Cause: Tailwind CSS v4 changed how animations are configured. The tailwind.config.js animation definitions from v3 do not carry over.

Solution:

  1. For Tailwind v4, animations are defined in CSS rather than tailwind.config.js
  2. Check that your global CSS file includes the animation keyframes
  3. If migrating from Tailwind v3 to v4, move animation definitions from the config file to your global CSS

Prevention: When starting a new project with Tailwind v4, let shadcn init configure animations automatically.

(Related: GitHub issue #6536)


Error: React 19 hydration warning with dark mode script

Cause: React 19 emits a hydration warning when a <script> tag is used in the document body for dark mode initialization.

Solution:

  1. Move the dark mode script to <head> using your framework's head management (e.g., Next.js <Script strategy="beforeInteractive">)
  2. Use a theme provider library (e.g., next-themes) that handles script placement correctly
  3. Add suppressHydrationWarning to the <html> tag

(Related: GitHub issue #10104)


Components render unstyled or without Tailwind classes

Cause: Tailwind CSS is not scanning the component directory for classes, or the global CSS file is not imported.

Solution:

  1. For Tailwind v3, verify your config includes the component paths:
    // tailwind.config.js
    content: [
      "./src/components/**/*.{ts,tsx}",
      "./components/**/*.{ts,tsx}",
    ]
    
  2. For Tailwind v4, ensure your CSS @source directive covers the component paths
  3. Confirm your global CSS file is imported in your app entry point (e.g., layout.tsx, main.tsx)

Prevention: Run npx shadcn@latest info after init to confirm Tailwind configuration paths are correct.


init fails with ENOENT: no such file or directory

Cause: The CLI cannot find or create the target directory structure.

Solution:

  1. Create the target directory manually: mkdir -p my-project
  2. Ensure you have write permissions to the parent directory
  3. On Windows, check for path length limitations and try a shorter path

Components have TypeScript errors after adding

Cause: Missing dependencies or incompatible TypeScript configuration.

Solution:

  1. Install all dependencies: npm install
  2. Check that tsconfig.json includes "jsx": "react-jsx" (or "preserve" for Next.js)
  3. Ensure path aliases in tsconfig.json match components.json
  4. Restart your TypeScript language server (in VS Code: Ctrl+Shift+P then "TypeScript: Restart TS Server")

Styles look different from the shadcn/ui website previews

Cause: Different base color, missing CSS variables, or Tailwind configuration mismatch.

Solution:

  1. Compare your components.json style and baseColor with the website defaults
  2. Ensure cssVariables: true is set in your Tailwind configuration
  3. Check that your global CSS file contains the full set of CSS custom properties generated during init
  4. Verify you are using the same style preset shown in the website preview

add --all takes very long or appears to hang

Cause: Downloading and installing 50+ components and their npm dependencies takes time.

Solution:

  1. Use --dry-run first to verify the component list: npx shadcn@latest add --all --dry-run
  2. Ensure stable internet connection
  3. Add components in batches instead:
    npx shadcn@latest add button card dialog input label -y
    npx shadcn@latest add table tabs select textarea badge -y
    

Monorepo: components installed in wrong workspace

Cause: components.json aliases point to the wrong workspace package.

Solution:

  1. Check components.json in your workspace root
  2. Ensure the aliases.ui path points to the correct workspace:
    {
      "aliases": {
        "ui": "@repo/ui/components"
      }
    }
    
  3. Run npx shadcn@latest info to verify workspace detection

Proxy/firewall blocks registry fetches

Cause: Corporate network requires HTTP proxy for external HTTPS connections.

Solution:

  1. Set the proxy environment variable:
    export https_proxy=http://proxy.company.com:8080
    npx shadcn@latest add button
    
  2. For npm-specific proxy:
    npm config set https-proxy http://proxy.company.com:8080
    

npx shadcn@latest runs an old cached version

Cause: npx caches previous versions of packages.

Solution:

  1. Clear the npx cache:
    npx clear-npx-cache
    
  2. The @latest tag forces npm to check for the newest version, but the cache can still interfere. Clearing it resolves the issue.

Error: Could not resolve path aliases

Cause: The alias configuration in components.json does not match your project's path resolution setup.

Solution:

  1. For Next.js/TypeScript projects, ensure tsconfig.json has matching paths:
    {
      "compilerOptions": {
        "baseUrl": ".",
        "paths": {
          "@/*": ["./src/*"]
        }
      }
    }
    
  2. For Vite, check vite.config.ts has the resolve alias:
    import path from "path"
    
    export default defineConfig({
      resolve: {
        alias: {
          "@": path.resolve(__dirname, "./src"),
        },
      },
    })
    
  3. Run npx shadcn@latest init to reconfigure aliases from scratch

Components missing after init --reinstall

Cause: Reinstall only re-downloads components that are tracked internally. Manually added or renamed components may not be tracked.

Solution:

  1. Re-add specific components explicitly: npx shadcn@latest add button dialog -o
  2. Check which components the CLI tracks: npx shadcn@latest info

Error: EPERM: operation not permitted on Windows

Cause: File locked by another process (IDE, dev server, antivirus).

Solution:

  1. Close your IDE and dev server
  2. Run the command again
  3. If using Windows Defender, add your project directory to the exclusion list
  4. Check for any file locks with Process Explorer or equivalent

CSS variables not applying in dark mode

Cause: The .dark class is not being toggled on the <html> element, or the dark mode CSS variables are missing from your stylesheet.

Solution:

  1. Verify your theme provider adds the dark class to <html> (not <body>)
  2. Check your global CSS includes the .dark selector with variable overrides
  3. For Next.js with next-themes, ensure attribute="class" is set on the ThemeProvider

Diff shows no changes but component behaves differently

Cause: Component behavior changes may come from updated dependencies (Radix UI, Tailwind CSS) rather than component source code changes.

Solution:

  1. Check your package.json for dependency version changes
  2. Compare current Radix UI / Base UI versions with what the component was built against
  3. Update dependencies: npm update
  4. Check the registry for any changelogs or migration notes

Error: ECONNREFUSED or ETIMEDOUT when fetching components

Cause: Cannot connect to the registry server. Network issue, DNS resolution failure, or the registry is temporarily down.

Solution:

  1. Check if the registry is accessible: curl -I https://ui.shadcn.com/r
  2. Try a different DNS resolver (e.g., 8.8.8.8)
  3. If behind a VPN, try disconnecting and reconnecting
  4. Wait a few minutes and retry — the registry may be experiencing temporary issues

Components have peer dependency warnings

Cause: Your project's React or Tailwind version does not match the expected range for a component's dependencies.

Solution:

  1. Check the warnings for specific version requirements
  2. Update your React version: npm install react@latest react-dom@latest
  3. Use --legacy-peer-deps if you need to force installation (npm only):
    npm install --legacy-peer-deps
    

7. FAQ

Q: Is shadcn/ui a component library?

No. shadcn/ui is a CLI tool and component registry. Instead of installing a library as a dependency, the CLI copies component source code directly into your project. You own the code and can modify it freely. There is no shadcn-ui package in your node_modules.


Q: Do I need to install shadcn/ui as a dependency?

No. You run the CLI using npx shadcn@latest (or your package manager's equivalent). The CLI itself is not added to your project's package.json. Only the components' runtime dependencies (like Radix UI primitives, class-variance-authority, clsx) are installed as project dependencies.


Q: What is the difference between Radix UI and Base UI?

Radix UI (from WorkOS) and Base UI (from MUI) are both unstyled, accessible component primitive libraries. shadcn/ui supports both as the underlying foundation for its components. Radix is the default and has broader community adoption. Choose Base UI if you prefer MUI's approach or already use MUI in your project. Select your base with --base radix or --base base during init.


Q: Can I use shadcn/ui with JavaScript (not TypeScript)?

Yes. Set "tsx": false in your components.json or choose JavaScript during init. Components will be generated as .jsx files without type annotations.


Q: How do I update a component to the latest version?

Run npx shadcn@latest add <component> --overwrite. There is no dedicated update command. Use --diff first to review what changed before overwriting.


Q: Will updating a component overwrite my customizations?

Yes. The --overwrite flag replaces the entire component file with the latest version from the registry. Commit your customizations before updating, then use --diff to see what changed so you can re-apply your modifications afterward.


Q: Can I use shadcn/ui with Tailwind CSS v3?

Yes. The CLI supports both Tailwind CSS v3 and v4. The init command detects your Tailwind version and configures accordingly. Be aware that animation configuration differs between v3 (config file) and v4 (CSS).


Q: What frameworks does shadcn/ui support?

Six frameworks have built-in templates: Next.js, Vite (React), React Router, TanStack Start, Astro, and Laravel. Other React-based frameworks may work with manual configuration of components.json.


Q: Can I use shadcn/ui in a monorepo?

Yes. Use npx shadcn@latest init --monorepo to scaffold a monorepo setup. The CLI distributes components, hooks, and utilities to the correct workspace packages. For existing monorepos, ensure components.json is in the workspace root with correct alias paths.


Q: How do I add dark mode support?

Dark mode works through Tailwind CSS's dark: variant and CSS custom properties. Ensure cssVariables: true in components.json, and use a theme provider (like next-themes for Next.js) to toggle the dark class on the <html> element. The CSS variables for dark mode are generated automatically during init.


Q: What is components.json?

It is the configuration file for shadcn/ui, created at your project root during init. It tells the CLI your style preferences, file paths, import aliases, icon library, RTL settings, and registry configuration. The CLI reads this file for every operation.


Q: Can I use a custom component registry?

Yes. Define custom registries in the registries field of components.json using a URL template with {name} and {style} placeholders. Then add components with npx shadcn@latest add <registry-name>/<component>.


Q: How do I build and host my own registry?

Create a registry.json file defining your components (with types like registry:ui, registry:hook, registry:lib, registry:theme, registry:style, registry:base, registry:font), run npx shadcn@latest build to compile it, and host the output directory on any static file server.


Q: What is the MCP server for?

The MCP (Model Context Protocol) server allows AI coding tools like Claude Code, Cursor, VS Code, Codex, and OpenCode to interact with shadcn/ui programmatically. The AI can add components, search the registry, and read documentation through the MCP interface. Initialize with npx shadcn@latest mcp init --client <client-name>.


Q: What does shadcn init --defaults do?

It initializes a project with --template=next and --preset=base-nova, skipping all interactive prompts. This is the fastest way to start a new project with sensible defaults.


Q: What is the apply command for?

The apply command applies a preset configuration to an existing project. Presets bundle a style, theme, and component configuration. Use it to change the visual identity of your project without re-initializing from scratch.


Q: How do I set up RTL (right-to-left) layouts?

Either initialize with --rtl or run the migration on an existing project: npx shadcn@latest migrate rtl. The migration transforms component files to use logical CSS properties (e.g., margin-inline-start instead of margin-left).


Q: What does migrate radix do?

It migrates your imports from individual @radix-ui/react-* packages to the consolidated radix-ui mono package. This simplifies your dependency tree and aligns with Radix UI's current distribution model.


Q: Can I use shadcn/ui without React Server Components?

Yes. Set "rsc": false in components.json. This is the default for non-Next.js frameworks (Vite, React Router, etc.) that do not support RSC. Components will include "use client" directives where needed.


Q: Where are components installed by default?

Components go to the path defined by aliases.ui in components.json (typically @/components/ui, which resolves to src/components/ui/). You can override this per-command with the --path flag.


Q: Can I add components from a URL?

Yes. Pass a full URL to a registry JSON file: npx shadcn@latest add https://example.com/r/styles/new-york-v4/button.json. This works with any URL that serves a valid component registry JSON.


Q: How do I preview what add will do without making changes?

Use --dry-run: npx shadcn@latest add dialog --dry-run. This shows what files would be created and what dependencies would be installed, without writing anything to disk.


Q: What is the REGISTRY_URL environment variable?

It overrides the default registry URL (https://ui.shadcn.com/r). Set it to point at a self-hosted or custom registry for all CLI operations. Useful for air-gapped environments or internal component libraries.


Q: How do I check which components are installed?

Run npx shadcn@latest info to see your project configuration. You can also inspect the files in your UI directory (typically src/components/ui/) directly.


Q: What happens if I run add for a component that already exists?

The CLI prompts you for confirmation before overwriting. To overwrite without prompting, use --overwrite (-o). Without that flag, existing files are preserved and the command exits without changes.


Q: Can I use shadcn/ui with a Tailwind prefix?

Yes. Set "prefix" in components.json under the tailwind field (e.g., "prefix": "tw-"). All generated Tailwind classes will include the prefix, avoiding collisions with other CSS frameworks.


Q: Which icon library does shadcn/ui use by default?

Lucide, configured via "iconLibrary": "lucide" in components.json. You can migrate to a different icon library using npx shadcn@latest migrate icons.


Q: What is the diff command?

The standalone diff command is deprecated. Use npx shadcn@latest add <component> --diff instead to see what has changed between your local version and the registry version of a component.


Q: What base colors are available?

Four base color palettes: neutral (balanced grays), zinc (cool grays, the default), stone (warm grays), and mauve (purple-tinted grays). Set via tailwind.baseColor in components.json.


Q: How does the search command work?

npx shadcn@latest search <registry> -q <query> searches a registry for components matching your query. The list alias works identically. Use -l to limit results and -o to paginate.


Q: Can I use shadcn/ui with Astro?

Yes. Use npx shadcn@latest init -t astro to scaffold an Astro project with React islands. Components are added the same way as any other framework — npx shadcn@latest add button.