# shadcn/ui — Administrator & Developer Guide

This guide covers the complete internals of **shadcn/ui** (v4.3.0) — a CLI-driven component registry system that copies React UI component source code directly into your project. Unlike traditional component libraries installed as npm dependencies, shadcn/ui fetches component files from a remote registry, applies a chain of AST-based transforms to match your project's configuration, and writes the results into your source tree. You own the code from the moment it lands.

The system is organized as a pnpm monorepo managed by Turborepo. The primary deliverable is the `shadcn` npm package (a CLI tool), accompanied by a Next.js documentation website, integration test suites, and project scaffolding templates for ten framework configurations. Components are built on either **Radix UI** (v1.4.3) or **Base UI** (`@base-ui/react` v1.3.0) primitives and styled with **Tailwind CSS 4.x**.

This document is written for administrators deploying custom registries, developers contributing to the codebase, and architects evaluating the system's design. Written from source code.

---

## 1. Architecture Overview

### 1.1 What the System Does

shadcn/ui solves a specific problem in the React ecosystem: developers want pre-built, accessible UI components but also want full control over the source code. Traditional npm-installed libraries create a dependency you cannot easily customize. shadcn/ui flips this model — the `shadcn` CLI fetches component source from a registry, rewrites imports and styles to match your project's aliases and configuration, then writes the files directly into your codebase. After that, the CLI is no longer involved; the components are yours to modify.

The registry system supports multiple "bases" (Radix UI and Base UI), multiple style variants, icon library swapping, RTL transforms, CSS variable theming, Tailwind prefix handling, and monorepo-aware file routing. A preset system allows encoding an entire design configuration into a compact string or named preset, enabling one-command project setup.

The CLI also implements the **Model Context Protocol (MCP)**, allowing AI coding tools (Claude Code, Cursor, VS Code Copilot, Codex, OpenCode) to programmatically add components to projects.

### 1.2 Component Inventory

| Component | Path | Role |
|-----------|------|------|
| CLI Package | `packages/shadcn/` | Published npm package; all user-facing commands |
| Documentation Website | `apps/v4/` | Next.js 16 site with MDX docs and live examples |
| Component Registry Source | `apps/v4/registry/` | Source files for all registry components |
| Integration Tests | `packages/tests/` | End-to-end tests that build registry + run CLI |
| Project Templates | `templates/` | Scaffolding templates for 10 framework configurations |
| AI Agent Skills | `skills/shadcn/` | Rules and instructions for AI agents |

### 1.3 Technology Stack

| Layer | Technology | Version |
|-------|-----------|---------|
| Language | TypeScript (ESM) | — |
| CLI Framework | Commander.js | — |
| Build (CLI) | tsup | — |
| Build (Monorepo) | Turborepo | — |
| Package Manager | pnpm | 9.0.6 |
| UI Primitives | Radix UI | 1.4.3 |
| UI Primitives (alt) | Base UI (`@base-ui/react`) | 1.3.0 |
| Styling | Tailwind CSS | 4.x |
| Validation | Zod | — |
| Config Loading | cosmiconfig | — |
| Website Framework | Next.js | 16.1.6 (Turbopack) |
| Documentation Engine | Fumadocs (MDX) | — |
| Testing | Vitest | — |
| Code Transform | Babel, ts-morph 26.0, recast | — |
| HTTP Client | node-fetch + https-proxy-agent | — |
| MCP Server | @modelcontextprotocol/sdk | — |
| Charts | Recharts | 3.8.0 |
| State Management | Jotai, nuqs | — |
| Package Publishing | Changesets | — |

### 1.4 Data Flow

The core operation — adding a component — follows this pipeline:

```
User runs: npx shadcn add button
        │
        ▼
┌─────────────────────┐
│  1. Config Loading   │  cosmiconfig reads components.json
│     (get-config)     │  Validates against Zod schema
└─────────┬───────────┘
          ▼
┌─────────────────────┐
│  2. Pre-flight       │  Check framework, TypeScript, Tailwind,
│     Checks           │  package manager, RSC support
└─────────┬───────────┘
          ▼
┌─────────────────────┐
│  3. Registry         │  Fetch item from https://ui.shadcn.com/r
│     Resolution       │  Recursively resolve all dependencies
└─────────┬───────────┘
          ▼
┌─────────────────────┐
│  4. Transform        │  9-stage pipeline rewrites each file:
│     Pipeline         │  imports → RSC → CSS vars → TW prefix →
│                      │  icons → menu → RTL → font → cleanup
└─────────┬───────────┘
          ▼
┌─────────────────────┐
│  5. Write Phase      │  Validate targets (isSafeTarget)
│                      │  Update dependencies (npm/pnpm/yarn/bun)
│                      │  Update tailwind config
│                      │  Update env vars
│                      │  Update fonts
│                      │  Write transformed files
│                      │  Update CSS (last — triggers rebuild)
└─────────────────────┘
```

---

## 2. System Requirements

### 2.1 Runtime Requirements

| Requirement | Minimum | Notes |
|-------------|---------|-------|
| Node.js | >= 20 | Required for ESM support and native fetch |
| Package Manager | pnpm 9.0.6, npm, yarn, or bun | pnpm required for monorepo development; users may use any supported manager |
| Git | Any recent version | Required for `shadcn init` post-init step |
| Operating System | macOS, Linux, Windows | Node.js cross-platform |

### 2.2 Supported Frameworks

The CLI detects and supports these frameworks via the project detection system in `packages/shadcn/src/utils/get-project-info.ts`:

| Framework | Template Variants |
|-----------|-------------------|
| Next.js | Single app, Monorepo |
| Vite (React) | Single app, Monorepo |
| React Router | Single app, Monorepo |
| TanStack Start | Single app, Monorepo |
| Astro | Single app, Monorepo |

> [!NOTE]
> Framework detection examines `package.json` dependencies, configuration files (e.g., `next.config.js`, `vite.config.ts`, `astro.config.mjs`), and directory structure to determine the active framework. The detection is automatic during `shadcn init`.

### 2.3 Development Requirements

For contributing to the shadcn/ui monorepo itself:

| Requirement | Detail |
|-------------|--------|
| pnpm | 9.0.6 (enforced via `packageManager` field) |
| Node.js | >= 20 |
| Turbo | Installed via pnpm (devDependency) |
| Disk Space | ~2 GB (node_modules across all workspaces) |

---

## 3. Configuration Reference

### 3.1 components.json — Complete Schema

The `components.json` file is the project-level configuration for shadcn/ui. It is created by `shadcn init` and read by every subsequent command via cosmiconfig. The schema is validated by Zod in `packages/shadcn/src/schema/`.

| Field | Type | Default | Description |
|-------|------|---------|-------------|
| `$schema` | `string` | `"https://ui.shadcn.com/schema.json"` | JSON Schema URL for editor autocompletion |
| `style` | `string` | — | Active style variant name (e.g., `"new-york-v4"`) |
| `rsc` | `boolean` | — | Whether the project uses React Server Components |
| `tsx` | `boolean` | — | Whether to output `.tsx` files (false = `.jsx`) |
| `tailwind.config` | `string` | — | Path to Tailwind config file |
| `tailwind.css` | `string` | — | Path to the global CSS file |
| `tailwind.baseColor` | `string` | — | Base color for theming (e.g., `"zinc"`, `"slate"`) |
| `tailwind.cssVariables` | `boolean` | — | Whether to use CSS custom properties for theming |
| `tailwind.prefix` | `string` | `""` | Tailwind class prefix (e.g., `"tw-"`) |
| `aliases.components` | `string` | — | Import alias for components (e.g., `"@/components"`) |
| `aliases.utils` | `string` | — | Import alias for utility functions |
| `aliases.ui` | `string` | — | Import alias for UI components (defaults to `{components}/ui`) |
| `aliases.lib` | `string` | — | Import alias for lib directory |
| `aliases.hooks` | `string` | — | Import alias for hooks directory |
| `iconLibrary` | `string` | — | Icon library identifier (e.g., `"lucide"`, `"icons"`) |
| `rtl` | `boolean` | `false` | Enable right-to-left layout transforms |
| `menuColor` | `string` | `"default"` | Menu color variant: `"default"`, `"inverted"`, `"default-translucent"`, `"inverted-translucent"` |
| `menuAccent` | `string` | `"subtle"` | Menu accent style: `"subtle"`, `"bold"` |
| `registries` | `Record<string, string \| { url: string, headers?: Record<string, string> }>` | — | Custom registry definitions |

> [!IMPORTANT]
> The `registries` field supports two forms. A simple string is treated as the registry URL. An object form allows specifying `url` and optional `headers` (useful for private registries requiring authentication). URLs support `{name}` and `{style}` template placeholders.

#### Example components.json

```json
{
  "$schema": "https://ui.shadcn.com/schema.json",
  "style": "new-york-v4",
  "rsc": true,
  "tsx": true,
  "tailwind": {
    "config": "tailwind.config.ts",
    "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": {
    "acme": "https://components.acme.com/r"
  }
}
```

### 3.2 Environment Variables

| Variable | Purpose | Where Used |
|----------|---------|------------|
| `REGISTRY_URL` | Override the default registry base URL (`https://ui.shadcn.com/r`) | `packages/shadcn/src/registry/constants.ts` |
| `https_proxy` | Route all registry HTTP fetches through a proxy | `packages/shadcn/src/registry/fetcher.ts` |
| `SHADCN_TEMPLATE_DIR` | Override the template directory for project scaffolding | `packages/shadcn/src/utils/scaffold.test.ts` |
| `SHADCN_GITHUB_URL` | Override the GitHub URL used during scaffolding | `packages/shadcn/src/utils/scaffold.test.ts` |
| `npm_config_user_agent` | Read by the CLI to detect which package manager invoked it | `packages/shadcn/src/utils/get-package-manager.ts` |

> [!NOTE]
> The `SHADCN_TEMPLATE_DIR` and `SHADCN_GITHUB_URL` variables are primarily used in test environments. The `REGISTRY_URL` variable is the recommended way to point the CLI at a custom or self-hosted registry during development or in air-gapped environments.

### 3.3 Registry URL Configuration in components.json

Registry URLs in the `registries` field support environment variable expansion using `${VAR}` syntax. This allows storing tokens or dynamic segments in environment variables rather than hardcoding them:

```json
{
  "registries": {
    "private": {
      "url": "https://registry.internal.com/r",
      "headers": {
        "Authorization": "Bearer ${REGISTRY_TOKEN}"
      }
    }
  }
}
```

The builder resolves `${REGISTRY_TOKEN}` from `process.env` at fetch time. If the variable is not set, the CLI raises `RegistryMissingEnvironmentVariablesError`.

### 3.4 CLI Commands and Options — Complete Reference

The CLI registers 12 commands in `packages/shadcn/src/index.ts`. Below is every command with every option, written from the Commander.js definitions in source.

#### 3.4.1 `shadcn init`

Initialize a new shadcn/ui project or reconfigure an existing one.

| Option | Alias | Type | Default | Description |
|--------|-------|------|---------|-------------|
| `--template` | `-t` | `string` | — | Project template to use |
| `--base` | `-b` | `string` | — | Base UI library (radix or base) |
| `--monorepo` / `--no-monorepo` | — | `boolean` | — | Enable/disable monorepo mode |
| `--preset` | `-p` | `string` | — | Named preset or preset code |
| `--yes` | `-y` | `boolean` | `false` | Skip confirmation prompts |
| `--defaults` | `-d` | `boolean` | `false` | Use default configuration |
| `--force` | `-f` | `boolean` | `false` | Overwrite existing configuration |
| `--cwd` | `-c` | `string` | `.` | Working directory |
| `--name` | `-n` | `string` | — | Project name (for new projects) |
| `--silent` | `-s` | `boolean` | `false` | Suppress output |
| `--css-variables` / `--no-css-variables` | — | `boolean` | — | Enable/disable CSS variables |
| `--rtl` / `--no-rtl` | — | `boolean` | — | Enable/disable RTL mode |
| `--reinstall` / `--no-reinstall` | — | `boolean` | — | Reinstall dependencies |

#### 3.4.2 `shadcn add`

Add components to a project from the registry.

| Option | Alias | Type | Default | Description |
|--------|-------|------|---------|-------------|
| `--yes` | `-y` | `boolean` | `false` | Skip confirmation prompts |
| `--overwrite` | `-o` | `boolean` | `false` | Overwrite existing files |
| `--all` | `-a` | `boolean` | `false` | Add all available components |
| `--path` | `-p` | `string` | — | Custom path for component files |
| `--silent` | `-s` | `boolean` | `false` | Suppress output |
| `--dry-run` | — | `boolean` | `false` | Show what would be added without writing |
| `--diff` | — | `boolean` | `false` | Show diff of changes |
| `--view` | — | `boolean` | `false` | View component source without adding |
| `--cwd` | `-c` | `string` | `.` | Working directory |

#### 3.4.3 `shadcn apply`

Apply a preset to an existing project.

| Option | Alias | Type | Default | Description |
|--------|-------|------|---------|-------------|
| `--preset` | — | `string` | — | Preset name or code to apply |
| `--yes` | `-y` | `boolean` | `false` | Skip confirmation prompts |
| `--silent` | `-s` | `boolean` | `false` | Suppress output |
| `--cwd` | `-c` | `string` | `.` | Working directory |

#### 3.4.4 `shadcn build`

Build a custom component registry from local source.

| Option | Alias | Type | Default | Description |
|--------|-------|------|---------|-------------|
| `--output` | `-o` | `string` | `./public/r` | Output directory for the built registry |
| `--cwd` | `-c` | `string` | `.` | Working directory |

#### 3.4.5 `shadcn diff`

Show differences between local components and registry versions.

| Option | Alias | Type | Default | Description |
|--------|-------|------|---------|-------------|
| `--yes` | `-y` | `boolean` | `false` | Skip confirmation prompts |
| `--cwd` | `-c` | `string` | `.` | Working directory |

> [!WARNING]
> The `diff` command is **deprecated**. It remains functional but may be removed in a future release.

#### 3.4.6 `shadcn docs`

Display documentation for components.

| Option | Alias | Type | Default | Description |
|--------|-------|------|---------|-------------|
| `--json` | — | `boolean` | `false` | Output as JSON |
| `--cwd` | `-c` | `string` | `.` | Working directory |
| `--base` | `-b` | `string` | — | Base library filter |

#### 3.4.7 `shadcn info`

Display project configuration information.

| Option | Alias | Type | Default | Description |
|--------|-------|------|---------|-------------|
| `--json` | — | `boolean` | `false` | Output as JSON |
| `--cwd` | `-c` | `string` | `.` | Working directory |

#### 3.4.8 `shadcn search`

Search the component registry.

| Option | Alias | Type | Default | Description |
|--------|-------|------|---------|-------------|
| `--query` | `-q` | `string` | — | Search query |
| `--limit` | `-l` | `number` | — | Maximum results to return |
| `--offset` | `-o` | `number` | — | Offset for pagination |
| `--cwd` | `-c` | `string` | `.` | Working directory |

#### 3.4.9 `shadcn migrate`

Run migrations (icon library, radix-to-base, RTL, etc.).

| Option | Alias | Type | Default | Description |
|--------|-------|------|---------|-------------|
| `--list` | `-l` | `boolean` | `false` | List available migrations |
| `--yes` | `-y` | `boolean` | `false` | Skip confirmation prompts |
| `--cwd` | `-c` | `string` | `.` | Working directory |

#### 3.4.10 `shadcn mcp`

Start the MCP (Model Context Protocol) server.

| Option | Alias | Type | Default | Description |
|--------|-------|------|---------|-------------|
| `--cwd` | `-c` | `string` | `.` | Working directory |

**Subcommand: `shadcn mcp init`**

| Option | Alias | Type | Default | Description |
|--------|-------|------|---------|-------------|
| `--client` | — | `string` | — | Target MCP client (claude, cursor, vscode, codex, opencode) |

#### 3.4.11 `shadcn view`

View component source code from the registry.

| Option | Alias | Type | Default | Description |
|--------|-------|------|---------|-------------|
| `--cwd` | `-c` | `string` | `.` | Working directory |

#### 3.4.12 `shadcn registry`

Registry management commands.

| Option | Alias | Type | Default | Description |
|--------|-------|------|---------|-------------|
| `--cwd` | `-c` | `string` | `.` | Working directory |

### 3.5 Workspace Configuration (Monorepo)

In monorepo mode, the CLI detects workspace roots by examining the package manager's workspace configuration (`pnpm-workspace.yaml`, `package.json#workspaces`). It then:

1. Creates a root-level `components.json` with shared settings.
2. Routes component files to the correct workspace package based on type:
   - `registry:ui` items route to the UI package
   - `registry:hook` items route to the hooks package
   - Other items route to the consuming application
3. Propagates design settings (`menuColor`, `menuAccent`, `rtl`, `iconLibrary`) to workspace-level `components.json` files.

---

## 4. Deployment & Scaling

### 4.1 Building the CLI Package

The CLI is built with **tsup** (a TypeScript bundler based on esbuild). The build configuration lives in the `packages/shadcn/` workspace.

```bash
# From monorepo root
pnpm --filter shadcn build
```

This produces a single ESM bundle at `packages/shadcn/dist/index.js` with the `#!/usr/bin/env node` shebang, ready for npm publishing.

### 4.2 Publishing to npm

The project uses **Changesets** for version management and publishing:

```bash
# Create a changeset
pnpm changeset

# Version packages based on changesets
pnpm changeset version

# Publish to npm
pnpm pub:release    # stable release
pnpm pub:beta       # beta release
```

> [!IMPORTANT]
> The `release` script in the root `package.json` orchestrates the full release pipeline via Turbo. Always run `pnpm release` for production releases rather than publishing individual packages manually.

### 4.3 Building the Documentation Website

The docs site is a Next.js 16 application at `apps/v4/`:

```bash
# Development (with Turbopack)
pnpm v4:dev

# Production build
pnpm v4:build
```

The dev server runs on port 4000. The site uses Next.js App Router with MDX content powered by Fumadocs.

### 4.4 Building a Custom Component Registry

Organizations can host their own component registries. The `shadcn build` command compiles a registry from local source:

```bash
# Build registry to default output (./public/r)
npx shadcn build

# Build registry to custom output
npx shadcn build -o ./dist/registry
```

The built registry is a set of static JSON files that can be served from any HTTP server or CDN. The output structure follows the same format as the official registry at `https://ui.shadcn.com/r`.

#### Registry Item Structure

Each registry item is a JSON file containing:

```json
{
  "name": "button",
  "type": "registry:ui",
  "files": [
    {
      "path": "ui/button.tsx",
      "content": "...",
      "type": "registry:ui",
      "target": "components/ui/button.tsx"
    }
  ],
  "dependencies": ["@radix-ui/react-slot"],
  "devDependencies": [],
  "cssVars": {},
  "css": "",
  "tailwind": {},
  "fonts": [],
  "envVars": [],
  "docs": ""
}
```

#### Registry Item Types

| Type | Description |
|------|-------------|
| `registry:ui` | UI component |
| `registry:theme` | Theme definition |
| `registry:style` | Style variant |
| `registry:base` | Base configuration |
| `registry:font` | Font definition |
| `registry:hook` | React hook |
| `registry:lib` | Library utility |

### 4.5 Deploying the Documentation Site

The Next.js docs site can be deployed to any platform that supports Next.js:

```bash
# Build for production
cd apps/v4
pnpm build

# The output is in .next/ — deploy per your hosting platform
```

> [!NOTE]
> The official site at `ui.shadcn.com` serves both documentation and the component registry. The registry is built by `scripts/build-registry.ts` and output to `public/r/` within the website.

---

## 5. Operations

### 5.1 Development Environment Setup

```bash
# Clone and install
git clone https://github.com/shadcn-ui/ui.git
cd ui
pnpm install

# Start all dev servers in parallel
pnpm dev

# Or start specific workspaces
pnpm v4:dev           # Docs website on port 4000
pnpm shadcn:dev       # CLI in dev mode
```

### 5.2 Building the Component Registry

The registry build is a critical step that compiles all component source files from `apps/v4/registry/` into static JSON served by the docs site:

```bash
pnpm registry:build
```

This runs `apps/v4/scripts/build-registry.ts`, which:

1. Reads all component definitions from `apps/v4/registry/`.
2. Resolves dependencies between components.
3. Compiles each component into a registry JSON file.
4. Writes output to `apps/v4/public/r/`.

The registry source is organized into bases:

```
apps/v4/registry/bases/
├── base/          # Base UI primitives
│   ├── ui/        # Components
│   ├── blocks/    # Page-level compositions
│   └── examples/  # Usage examples
└── radix/         # Radix UI primitives
    ├── ui/        # Components
    ├── blocks/    # Page-level compositions
    └── examples/  # Usage examples
```

### 5.3 Running Tests

```bash
# Full test suite (builds registry, starts server, runs vitest)
pnpm test

# Run CLI unit tests only
pnpm --filter shadcn test

# Run integration tests only
pnpm --filter tests test
```

> [!WARNING]
> The full `pnpm test` command first builds the registry and starts a local server, then runs all Vitest suites. This can take several minutes. For iterative development, use the filtered commands above.

### 5.4 Template Syncing

Templates in `templates/` serve as scaffolding for `shadcn init`. They must stay synchronized with the latest component conventions:

```bash
pnpm sync:templates
```

This copies shared configuration and boilerplate across all 10 template variants.

### 5.5 Registry Capture (Screenshots)

For documentation, the registry capture script generates screenshots of all components:

```bash
pnpm registry:capture
```

### 5.6 Linting

```bash
pnpm lint           # Check for linting issues
pnpm lint:fix       # Auto-fix where possible
```

### 5.7 Monorepo Task Graph

Turborepo manages the task dependency graph. Key tasks defined in `turbo.json`:

| Task | Dependencies | Outputs |
|------|--------------|---------|
| `build` | `^build` (dependent builds first) | `dist/**` |
| `dev` | — (runs in parallel) | — |
| `lint` | — | — |
| `test` | `build` | — |

---

## 6. Performance

### 6.1 Turbopack for Development

The documentation site (`apps/v4/`) uses **Turbopack** as its development bundler via Next.js 16. Turbopack provides near-instant hot module replacement (HMR) for the 8,550+ files in the monorepo, significantly faster than webpack for large codebases.

### 6.2 Registry Fetch Optimization

The registry fetcher (`packages/shadcn/src/registry/fetcher.ts`) optimizes network requests through:

- **Dependency deduplication**: When resolving a component tree, the resolver tracks already-fetched items to avoid duplicate requests.
- **Parallel fetching**: Independent dependencies are fetched concurrently.
- **Proxy support**: The `https_proxy` environment variable routes traffic through a corporate or caching proxy, reducing latency in enterprise environments.

### 6.3 Component Resolution

The resolver (`packages/shadcn/src/registry/resolver.ts`) builds a dependency tree for each requested component:

1. Fetch the requested item from the registry.
2. Extract its `dependencies` (npm packages) and `registryDependencies` (other registry items).
3. Recursively resolve all registry dependencies, deduplicating along the way.
4. Return a flat list of all items to install, in dependency order.

This ensures that adding a complex component like `data-table` automatically pulls in all required sub-components (e.g., `table`, `button`, `dropdown-menu`) without duplicating any.

### 6.4 Build Performance

Turborepo provides:

- **Task caching**: Build outputs are cached based on file hashes; unchanged packages are not rebuilt.
- **Parallel execution**: Independent tasks run concurrently across all available CPU cores.
- **Incremental builds**: Only modified packages and their dependents are rebuilt.

---

## 7. Security

### 7.1 Registry Fetch Security

All registry fetches use HTTPS by default. The default registry URL is `https://ui.shadcn.com/r`. The fetcher in `packages/shadcn/src/registry/fetcher.ts` enforces:

- **HTTPS transport**: The registry URL scheme is not validated at the code level, but the default and all official registries use HTTPS.
- **Proxy support**: When `https_proxy` is set, requests are routed through an `https-proxy-agent`, enabling corporate proxy inspection and logging.
- **Error classification**: The fetcher maps HTTP status codes to specific error classes (`RegistryNotFoundError` for 404, `RegistryUnauthorizedError` for 401, `RegistryForbiddenError` for 403, `RegistryGoneError` for 410), providing clear diagnostics.

> [!CAUTION]
> Custom registries specified in `components.json` can point to any URL. In shared or CI environments, audit the `registries` field to ensure it references trusted sources only. A compromised registry could inject malicious code into components that the CLI writes directly to your source tree.

### 7.2 Environment Variable Handling

Registry URLs and headers support `${VAR}` expansion from `process.env`. The CLI raises `RegistryMissingEnvironmentVariablesError` if a referenced variable is not set, preventing accidental requests with empty authentication tokens.

> [!CAUTION]
> Environment variables referenced in `headers` (e.g., `Authorization: Bearer ${TOKEN}`) are expanded at runtime and sent in HTTP requests. Store sensitive tokens in environment variables rather than hardcoding them in `components.json`, which may be committed to version control.

### 7.3 Registry Validation

The registry system validates incoming data at multiple levels:

- **Schema validation**: All registry responses are validated against Zod schemas (`packages/shadcn/src/schema/`). Malformed responses are rejected with `RegistryParseError`.
- **Namespace validation**: Registry namespaces (e.g., `@shadcn`, `@v0`) are validated against the configured registries. Unknown namespaces raise `RegistryInvalidNamespaceError`.
- **Config validation**: The `components.json` file is validated on load. Missing or malformed configuration raises `ConfigMissingError` or `ConfigParseError`.

### 7.4 Safe Target Path Validation

When the CLI writes component files to disk, it validates target paths using the `isSafeTarget` function. This prevents path traversal attacks where a malicious registry item could specify a target like `../../../etc/passwd`. The validator ensures:

- Target paths are within the project directory.
- Target paths do not traverse above the project root.
- Target paths do not overwrite critical project files (e.g., `package.json`, config files).

> [!IMPORTANT]
> The `isSafeTarget` check is a critical security boundary. It runs before any file write operation during `shadcn add`. If a registry item specifies a target path that fails validation, the entire operation is aborted.

### 7.5 Credential Hygiene

- Registry authentication tokens belong in environment variables, not in `components.json`.
- The CLI does not log or display registry headers (which may contain tokens).
- The `--dry-run` flag on `shadcn add` allows previewing what will be written without executing any file operations or network requests beyond the initial fetch.

---

## 8. Developer Internals

### 8.1 Repository Structure

```
shadcn-ui/ui/
├── apps/
│   └── v4/                           # Next.js 16 documentation website
│       ├── app/                      # App Router pages and layouts
│       ├── registry/                 # Component registry source
│       │   ├── bases/
│       │   │   ├── base/             # Base UI components, blocks, examples
│       │   │   └── radix/            # Radix UI components, blocks, examples
│       │   ├── new-york-v4/          # New York v4 style variant
│       │   ├── icons/                # Icon library definitions
│       │   └── styles/               # Style definitions
│       ├── styles/                   # Pre-built CSS style variants
│       ├── content/docs/             # MDX documentation pages
│       ├── examples/                 # Live example components
│       ├── lib/                      # Shared website utilities (21 files)
│       ├── hooks/                    # Website React hooks
│       ├── components/               # Website-specific components
│       └── scripts/                  # Build scripts
│           ├── build-registry.ts     # Compiles registry JSON
│           ├── build-icons.ts        # Compiles icon definitions
│           └── ...
├── packages/
│   ├── shadcn/                       # CLI package (npm: "shadcn")
│   │   ├── src/
│   │   │   ├── index.ts              # CLI entry point (Commander setup)
│   │   │   ├── commands/             # 12 command implementations
│   │   │   ├── registry/             # Registry system (fetch, resolve, build)
│   │   │   ├── utils/                # Utilities (transforms, updaters, config)
│   │   │   ├── schema/               # Zod validation schemas
│   │   │   ├── preflights/           # Pre-flight check system
│   │   │   ├── preset/               # Preset system
│   │   │   ├── templates/            # Framework template handlers
│   │   │   ├── migrations/           # Migration system
│   │   │   ├── mcp/                  # MCP server implementation
│   │   │   ├── icons/                # Icon library definitions
│   │   │   └── styles/               # Style definitions
│   │   └── test/                     # CLI unit tests with fixtures
│   └── tests/                        # Integration tests
├── templates/                        # 10 project scaffolding templates
│   ├── next-app/
│   ├── next-monorepo/
│   ├── vite-app/
│   ├── vite-monorepo/
│   ├── react-router-app/
│   ├── react-router-monorepo/
│   ├── start-app/
│   ├── start-monorepo/
│   ├── astro-app/
│   └── astro-monorepo/
└── skills/
    └── shadcn/                       # AI agent skill definitions
```

### 8.2 CLI Entry Point — `packages/shadcn/src/index.ts`

The entry point configures Commander.js with all 12 commands. Each command is imported from `packages/shadcn/src/commands/` and registered with its options. The file includes the shebang `#!/usr/bin/env node` for direct execution.

### 8.3 Command Modules — `packages/shadcn/src/commands/`

This directory contains 12 files (approximately 90K characters of TypeScript total), one per CLI command.

| File | Command | Description |
|------|---------|-------------|
| `init.ts` | `shadcn init` | Project initialization. Detects framework, runs preflights, applies template, creates `components.json`, installs base dependencies. Supports preset-based initialization. |
| `add.ts` | `shadcn add` | Component addition. Resolves registry tree, runs transforms, writes files. The most complex command — orchestrates the entire fetch-transform-write pipeline. |
| `apply.ts` | `shadcn apply` | Preset application. Decodes a preset (named or encoded) and applies it to an existing project's `components.json` and CSS. |
| `diff.ts` | `shadcn diff` | Component diffing. Fetches the latest registry version of installed components and shows a unified diff against local versions. Deprecated. |
| `docs.ts` | `shadcn docs` | Documentation display. Fetches and renders component documentation from the registry. |
| `view.ts` | `shadcn view` | Component viewing. Displays component source code from the registry without writing any files. |
| `search.ts` | `shadcn search` | Registry search. Queries the registry API for components matching a search term. |
| `migrate.ts` | `shadcn migrate` | Migration runner. Executes available migrations (icon library swap, radix-to-base, RTL enablement). |
| `info.ts` | `shadcn info` | Project info. Displays the current `components.json` configuration and detected project settings. |
| `build.ts` | `shadcn build` | Registry builder. Compiles a custom registry from local source into static JSON. |
| `mcp.ts` | `shadcn mcp` | MCP server. Starts a Model Context Protocol server for AI tool integration. Has `init` subcommand for client configuration. |
| `registry.ts` | `shadcn registry` | Registry management commands. |

### 8.4 Registry System — `packages/shadcn/src/registry/`

The registry system (28 files, approximately 61K characters) handles all interaction with component registries — fetching, resolving dependencies, building custom registries, and validating data.

| File | Role |
|------|------|
| `api.ts` | High-level registry API functions used by commands |
| `builder.ts` | Builds custom registries from local source files; supports env var expansion in URLs (`${VAR}` syntax) and headers |
| `config.ts` | Registry configuration management, URL resolution, namespace mapping |
| `constants.ts` | Default registry URL (`https://ui.shadcn.com/r`), built-in registry definitions (`@shadcn`, `@v0`) |
| `context.ts` | Registry context object carrying config + state through operations |
| `errors.ts` | 15 error classes for granular error handling (see hierarchy below) |
| `fetcher.ts` | HTTP fetch with `https-proxy-agent` proxy support, status-to-error mapping, response parsing |
| `resolver.ts` | Recursive dependency tree resolution with deduplication; produces flat install order |
| `search.ts` | Registry search implementation for `shadcn search` command |
| `validator.ts` | Zod-based validation of registry responses against schema definitions |
| `utils.ts` | Shared registry utilities (URL construction, name parsing, namespace extraction) |

#### 8.4.1 Error Hierarchy

The registry defines 15 error classes in `errors.ts`, all extending `RegistryError`:

```
RegistryError (base)
├── RegistryNotFoundError          (HTTP 404)
├── RegistryGoneError              (HTTP 410)
├── RegistryUnauthorizedError      (HTTP 401)
├── RegistryForbiddenError         (HTTP 403)
├── RegistryFetchError             (other HTTP errors)
├── RegistryNotConfiguredError     (registry not in components.json)
├── RegistryLocalFileError         (local file access issues)
├── RegistryParseError             (malformed JSON response)
├── RegistryMissingEnvironmentVariablesError
├── RegistryInvalidNamespaceError
├── ConfigMissingError             (no components.json found)
├── ConfigParseError               (invalid components.json)
├── RegistriesIndexParseError      (invalid registries index response)
└── InvalidConfigIconLibraryError  (unknown icon library in config)
```

#### 8.4.2 Built-in Registries

Two registries are built in and do not need explicit configuration:

| Namespace | URL | Purpose |
|-----------|-----|---------|
| `@shadcn` | `https://ui.shadcn.com/r` | Official shadcn/ui component registry |
| `@v0` | v0.dev integration URL | Integration with Vercel's v0.dev AI design tool |

Components are referenced by `namespace/name` syntax. Bare names (no namespace) default to `@shadcn`.

#### 8.4.3 Registry Resolution Algorithm

When `shadcn add button dropdown-menu` is invoked, the resolver executes:

1. **Parse names**: Split each argument into namespace + component name. Bare names default to `@shadcn`.
2. **Resolve registry URL**: Map namespace to URL via `constants.ts` (built-in) or `components.json#registries` (custom).
3. **Fetch root items**: HTTP GET each component JSON from `{registryUrl}/styles/{style}/{name}.json`.
4. **Extract registry dependencies**: Each item may declare `registryDependencies` — other registry items it depends on.
5. **Recursive resolution**: For each dependency not already seen, repeat steps 2-4. A `Set` of visited names prevents cycles and duplicates.
6. **Flatten**: Return a deduplicated, topologically-ordered list of all items to install.
7. **Merge**: Aggregate all npm `dependencies` and `devDependencies` across all resolved items.

### 8.5 Utilities — `packages/shadcn/src/utils/`

The utilities directory (35 files, approximately 161K characters) contains the heaviest logic in the CLI. Key modules:

| File | Role |
|------|------|
| `add-components.ts` | Orchestrates the full component-addition pipeline (resolve, validate, deps, config, files, CSS) |
| `create-project.ts` | Project scaffolding (clone template, configure, install) |
| `get-config.ts` | Configuration loading via cosmiconfig with Zod validation |
| `get-project-info.ts` | Framework detection (Next.js, Vite, Astro, React Router, TanStack Start) |
| `get-package-manager.ts` | Package manager detection (npm, pnpm, yarn, bun) via `npm_config_user_agent` and lockfile heuristics |
| `scaffold.ts` | Template-based project scaffolding |
| `transformers.ts` | Entry point for the 9-stage transform pipeline |

#### 8.5.1 Transform Pipeline Modules

Located within `packages/shadcn/src/utils/`, these modules implement the AST-based transforms applied to every component file during `shadcn add`:

| Transform | Order | Module | Description |
|-----------|-------|--------|-------------|
| `transformImport` | 1 | `transform-import.ts` | Rewrites import paths to match project aliases (e.g., `@/components/ui` to the user's configured alias). Uses ts-morph for AST manipulation. |
| `transformRsc` | 2 | `transform-rsc.ts` | Adds or removes `"use client"` directives based on the `rsc` config flag. Components that use hooks or browser APIs get the directive; server-safe components do not. |
| `transformCssVars` | 3 | `transform-css-vars.ts` | Converts between inline Tailwind utility classes and CSS custom property usage based on `tailwind.cssVariables`. |
| `transformTwPrefixes` | 4 | `transform-tw-prefixes.ts` | Applies Tailwind class prefixes (e.g., `bg-primary` becomes `tw-bg-primary`) when `tailwind.prefix` is set. |
| `transformIcons` | 5 | `transform-icons.ts` | Swaps icon imports between icon libraries (e.g., Lucide to custom icon set) based on `iconLibrary` configuration. |
| `transformMenu` | 6 | `transform-menu.ts` | Applies menu color and accent transforms based on `menuColor` and `menuAccent` settings. |
| `transformRtl` | 7 | `transform-rtl.ts` | Applies right-to-left layout transforms: swaps `left`/`right` classes, adjusts margin and padding directional utilities, mirrors layout-related properties. |
| `transformFont` | 8 | `transform-font.ts` | Processes font marker comments in component source, replacing them with the configured font family. |
| `transformCleanup` | 9 | `transform-cleanup.ts` | Final cleanup pass: removes internal markers, normalizes whitespace, ensures consistent formatting of the output file. |

> [!NOTE]
> Transforms use a combination of **Babel** (for JSX/TSX parsing), **ts-morph** (for TypeScript AST manipulation), and **recast** (for code printing that preserves formatting). This three-tool approach handles the full spectrum of code transformations while maintaining readable output.

#### 8.5.2 Updater Modules

These modules handle the "write phase" after transforms complete:

| File | Role |
|------|------|
| `updaters/update-dependencies.ts` | Runs `npm install` / `pnpm add` / `yarn add` / `bun add` for newly required npm dependencies |
| `updaters/update-tailwind-config.ts` | Patches the Tailwind configuration file with new content paths or plugins required by added components |
| `updaters/update-files.ts` | Writes transformed component files to disk with `isSafeTarget` validation |
| `updaters/update-css.ts` | Updates the global CSS file with new CSS variable definitions or component styles (run last to trigger rebuild) |
| `updaters/update-env-vars.ts` | Adds required environment variables to `.env` files when components declare `envVars` |
| `updaters/update-fonts.ts` | Registers font imports required by components |

#### 8.5.3 Component Addition Orchestration

The `add-components.ts` module orchestrates the full write phase in a specific order designed for correctness:

1. **Resolve registry tree** — fetch the component and all transitive dependencies.
2. **Validate file targets** — ensure all target paths pass `isSafeTarget`.
3. **Update dependencies** — install npm packages first so TypeScript/bundler can resolve imports.
4. **Update Tailwind config** — add content paths or plugins.
5. **Update env vars** — write `.env` entries.
6. **Update fonts** — register font imports.
7. **Write files** — write all transformed component files.
8. **Update CSS** — write CSS changes **last** to trigger a hot reload that picks up all preceding changes.

> [!TIP]
> The CSS-last ordering is intentional. In development with HMR, a CSS change triggers a rebuild. By making it the final step, the rebuild sees all new files and dependencies already in place, avoiding transient errors.

### 8.6 Pre-flight Checks — `packages/shadcn/src/preflights/`

Pre-flight checks run before command execution to validate the project environment:

| Check | Purpose |
|-------|---------|
| Framework detection | Verify the project uses a supported framework |
| TypeScript detection | Determine `.ts`/`.tsx` vs `.js`/`.jsx` output |
| Tailwind CSS detection | Verify Tailwind is configured and locate its CSS entry point |
| Package manager detection | Determine which package manager to use for dependency installation |
| RSC detection | Determine if the project supports React Server Components |
| Config validation | Validate `components.json` exists and is well-formed |

### 8.7 Preset System — `packages/shadcn/src/preset/`

Presets encode a complete design configuration — style, base, font, icon library, colors, menu settings — into either a named preset or a compact encoded string.

**Named presets** include: `lyra`, `nova`, `sera`, and others. Each preset maps to a specific combination of configuration values that produce a cohesive visual design.

**Preset codes** are compact strings generated by the preset builder at `ui.shadcn.com/create`. They encode all configuration as a URL-safe string that the CLI can decode and apply. The encoding captures:

- Style variant
- Base UI library (Radix or Base)
- Font family
- Icon library
- Color palette
- Menu color and accent
- RTL setting

The preset system is used by both `shadcn init --preset` and `shadcn apply --preset`.

### 8.8 Template System — `packages/shadcn/src/templates/`

Each of the 10 supported framework configurations has a template handler:

| Template | Framework | Layout |
|----------|-----------|--------|
| `next` | Next.js | Single application |
| `next-monorepo` | Next.js | pnpm workspace monorepo |
| `vite` | Vite (React) | Single application |
| `vite-monorepo` | Vite (React) | pnpm workspace monorepo |
| `react-router` | React Router | Single application |
| `react-router-monorepo` | React Router | pnpm workspace monorepo |
| `start` | TanStack Start | Single application |
| `start-monorepo` | TanStack Start | pnpm workspace monorepo |
| `astro` | Astro | Single application |
| `astro-monorepo` | Astro | pnpm workspace monorepo |

Each template handler implements:
- **`init()`** — framework-specific initialization logic (copy boilerplate, configure package.json, set up routing)
- **`postInit()`** — post-initialization steps (e.g., `git init`, install dependencies)

Template source files live in the top-level `templates/` directory. Each template directory contains a complete, minimal project scaffold for its framework. The `pnpm sync:templates` command synchronizes shared files across all templates.

### 8.9 Migration System — `packages/shadcn/src/migrations/`

Migrations handle breaking changes between versions and enable bulk transformations across installed components. Available migrations:

| Migration | Purpose |
|-----------|---------|
| Icons migration | Swap between icon libraries across all installed components (e.g., migrating from Lucide to a custom icon set) |
| Radix migration | Migrate components from Radix UI to Base UI primitives (or vice versa), rewriting imports and adapting API usage |
| RTL migration | Enable or disable RTL support across all installed components, applying directional transforms |

Migrations are run via `shadcn migrate`. The `--list` flag shows available migrations without executing them. The `--yes` flag skips confirmation prompts for CI usage.

### 8.10 MCP Server — `packages/shadcn/src/mcp/`

The MCP (Model Context Protocol) server exposes shadcn/ui's component-addition capabilities to AI coding tools. It implements the `@modelcontextprotocol/sdk` server interface, allowing AI agents to programmatically:

- Search the component registry
- Add components to the project
- View component documentation
- Inspect project configuration

**Supported clients** (configured via `shadcn mcp init --client`):

| Client | Config File | Format |
|--------|-------------|--------|
| Claude Code | `.mcp.json` | JSON (project root) |
| Cursor | `.cursor/mcp.json` | JSON |
| VS Code | `.vscode/mcp.json` | JSON |
| Codex | `~/.codex/config.toml` | TOML |
| OpenCode | `opencode.json` | JSON |

The `shadcn mcp init` command generates the appropriate configuration file for the chosen client, pointing it at the `shadcn mcp` server command. After initialization, the AI tool can invoke shadcn operations as MCP tool calls.

### 8.11 Schema Definitions — `packages/shadcn/src/schema/`

Zod schemas define and validate all data structures at system boundaries:

| Schema | Validates |
|--------|-----------|
| Config schema | `components.json` structure (all fields, types, constraints) |
| Registry item schema | Individual registry entries (files, dependencies, metadata) |
| Registry index schema | Registry listing responses (array of available items) |
| Preset schema | Preset definitions and encoded preset codes |

Every external input — config files loaded from disk, JSON fetched from registries, user-provided options — passes through Zod validation before use. Parse failures produce structured `ZodError` instances with path information for debugging.

### 8.12 Icon Libraries — `packages/shadcn/src/icons/`

Icon library definitions map icon names to their import sources. The system supports multiple icon libraries, and the `iconLibrary` config key determines which one is active. The CLI uses these definitions when:

- Initializing a project with a specific icon library via `shadcn init`
- Migrating between icon libraries via `shadcn migrate`
- Transforming icon imports during `shadcn add` (the `transformIcons` stage)

Each icon library definition maps logical icon names (e.g., `"chevron-right"`, `"search"`, `"close"`) to their actual import paths and component names in the target library.

### 8.13 Style Definitions — `packages/shadcn/src/styles/`

Style definitions describe the available component style variants. These are referenced by the `style` field in `components.json`. The `apps/v4/styles/` directory contains pre-built CSS for each style variant:

- `base-*` variants — styles built for Base UI components
- `radix-*` variants — styles built for Radix UI components

Each style variant determines the default appearance of components: colors, spacing, border radius, typography, and other visual properties.

### 8.14 Code Patterns and Conventions

**ESM throughout**: The entire codebase uses ECMAScript modules. The CLI bundle is ESM with a Node.js shebang. All imports use the `import` statement; there are no CommonJS `require()` calls.

**Zod for validation**: Every external data boundary (config files, registry responses, CLI arguments) is validated with Zod schemas. Parsing failures produce structured errors with clear messages and paths.

**Commander.js for CLI**: All command definitions, option parsing, and help text generation are handled by Commander.js. Each command module exports a function that receives the Commander program instance and registers its options.

**cosmiconfig for config loading**: The `components.json` file is loaded via cosmiconfig, which searches for configuration in multiple formats and locations. The search resolves the nearest config file up the directory tree.

**Atomic write ordering**: File writes during `shadcn add` follow a strict order (dependencies first, CSS last) to ensure consistent project state at every intermediate step.

**Error-first design**: The registry system uses a rich error hierarchy (15 classes) to provide specific, actionable error messages. HTTP errors are mapped to domain-specific error types that carry context about what went wrong and how to fix it.

**ts-morph for AST transforms**: TypeScript source files are manipulated programmatically using ts-morph (v26.0), which wraps the TypeScript compiler API in a developer-friendly interface. Babel handles JSX parsing, and recast preserves original formatting when printing modified ASTs.

### 8.15 Testing Strategy

#### Unit Tests — `packages/shadcn/test/`

The CLI unit tests use **Vitest** with an extensive fixture system:

| Fixture Category | Configurations Tested |
|------------------|-----------------------|
| Next.js | App Router, Pages Router, `/src` layout, monorepo |
| Vite | Standard, monorepo |
| Remix | Standard layout |
| T3 Stack | Standard layout |
| Custom aliases | Various alias configurations |

Tests cover:
- Config loading and validation
- Project detection across all supported frameworks
- Package manager detection from multiple signals
- Transform pipeline correctness (import rewriting, RSC directive handling, CSS variable conversion, Tailwind prefix application, icon swapping, menu transforms, RTL transforms, font processing, cleanup)
- Registry fetching and parsing (mocked with MSW)
- Preset encoding and decoding
- Scaffold and template system

#### Integration Tests — `packages/tests/`

Integration tests exercise the full pipeline end-to-end:

1. Build the component registry from source (`pnpm registry:build`).
2. Start a local HTTP server to serve the built registry.
3. Run CLI commands against the local registry.
4. Verify output files match expectations (correct imports, correct file locations, correct dependencies).

#### Mock Service Worker (MSW)

Registry API calls in unit tests are intercepted by MSW handlers that return fixture data. This avoids network dependency in tests while exercising the full fetch-parse-validate pipeline. MSW handlers are configured to return realistic registry responses matching the production schema.

### 8.16 Potential Improvements

Based on source analysis, these areas present opportunities for enhancement:

| Area | Observation |
|------|-------------|
| **Transactional writes** | When a multi-component `add` fails partway through, already-written files are not rolled back. A transactional write approach (write to temp, then atomically move) would improve reliability. |
| **Local registry cache** | The CLI fetches registry data on every invocation. A local cache with TTL-based invalidation would reduce network calls, improve offline support, and speed up repeated operations. |
| **Single-pass transforms** | The 9-stage transform pipeline parses and re-prints the AST multiple times. A single-pass approach with composed visitors would reduce parse overhead for large component files. |
| **Broader workspace detection** | Monorepo detection relies on pnpm, npm, yarn, and bun workspace patterns. Nx and Lerna workspaces are not currently detected. |
| **Config migration** | When the `components.json` schema changes between CLI versions, users must manually update their configuration. An automatic config migration system (similar to the component migration system) would smooth upgrades. |
| **Offline mode** | No explicit offline mode exists. The CLI could fall back to a local cache or bundled registry subset when network is unavailable. |

### 8.17 Contributing

#### Development Workflow

1. Fork and clone the repository.
2. Install dependencies: `pnpm install`
3. Create a feature branch.
4. Make changes.
5. Run tests: `pnpm test`
6. Run linting: `pnpm lint`
7. Create a changeset: `pnpm changeset` (for changes that affect published packages).
8. Submit a pull request.

#### Key Development Commands

| Command | Purpose |
|---------|---------|
| `pnpm dev` | Start all dev servers in parallel |
| `pnpm shadcn:dev` | Run CLI in dev mode (watches for changes) |
| `pnpm shadcn:prod` | Run CLI against production registry |
| `pnpm registry:build` | Rebuild component registry from source |
| `pnpm registry:capture` | Capture component screenshots for docs |
| `pnpm test` | Full test suite (build + serve + vitest) |
| `pnpm lint` | ESLint checks across all packages |
| `pnpm lint:fix` | Auto-fix lint issues |
| `pnpm sync:templates` | Synchronize template scaffolds |
| `pnpm v4:dev` | Run docs website in dev mode (port 4000) |
| `pnpm v4:build` | Production build of docs website |

#### Adding a New Component to the Registry

1. Create the component source in `apps/v4/registry/bases/{base}/ui/` (choose `radix` or `base` directory).
2. Define the component's registry metadata (name, type, dependencies, registryDependencies).
3. Create usage examples in `apps/v4/registry/bases/{base}/examples/`.
4. Add MDX documentation in `apps/v4/content/docs/`.
5. Run `pnpm registry:build` to compile the registry.
6. Test locally with `pnpm shadcn:dev add {component-name}`.
7. Add unit tests in `packages/shadcn/test/` if the component introduces new patterns.

#### Adding a New CLI Command

1. Create a new file in `packages/shadcn/src/commands/` following the existing command pattern.
2. Export the command registration function.
3. Import and register the command in `packages/shadcn/src/index.ts`.
4. Add tests in `packages/shadcn/test/`.
5. Update the `shadcn --help` text if needed (Commander generates it automatically from option definitions).

---

## 9. Integration Points

### 9.1 MCP Protocol Integration

The MCP server (`packages/shadcn/src/mcp/`) implements the Model Context Protocol, enabling AI coding assistants to interact with shadcn/ui programmatically. The integration is bidirectional:

- **AI to shadcn**: AI agents invoke CLI operations (add, search, docs) through MCP tool calls.
- **shadcn to AI**: The `shadcn mcp init` command configures the appropriate MCP config file for each supported client.

Configuration files written by `shadcn mcp init`:

| Client | File | Format |
|--------|------|--------|
| Claude Code | `.mcp.json` | JSON (project root) |
| Cursor | `.cursor/mcp.json` | JSON |
| VS Code | `.vscode/mcp.json` | JSON |
| Codex | `~/.codex/config.toml` | TOML |
| OpenCode | `opencode.json` | JSON |

> [!TIP]
> When using Claude Code with shadcn/ui, run `npx shadcn mcp init --client claude` in your project root. This creates `.mcp.json` so Claude can add components directly during conversation.

### 9.2 Custom Registry API Contract

To host a custom component registry, serve static JSON files at a URL that matches this contract:

**Base URL**: `https://your-registry.com/r`

**Endpoints** (static JSON files):

| Path | Returns |
|------|---------|
| `/r/index.json` | Array of all available registry items with name, type, and description |
| `/r/styles/{style}/{name}.json` | Individual component definition with files, dependencies, and metadata |

Each component JSON follows the registry item schema:

```json
{
  "name": "string",
  "type": "registry:ui | registry:hook | registry:lib | ...",
  "files": [
    {
      "path": "string (source path within registry)",
      "content": "string (full file content)",
      "type": "string (registry item type)",
      "target": "string (target path in user's project)"
    }
  ],
  "dependencies": ["string (npm package names)"],
  "devDependencies": ["string (npm dev package names)"],
  "registryDependencies": ["string (other registry item names)"],
  "cssVars": {
    "light": { "variable-name": "value" },
    "dark": { "variable-name": "value" }
  },
  "css": "string (additional CSS to inject)",
  "tailwind": {
    "config": {}
  },
  "fonts": ["string (font definitions)"],
  "envVars": ["string (required environment variables)"],
  "docs": "string (component documentation markdown)"
}
```

> [!TIP]
> Use `shadcn build` to generate a compatible registry from your component source. This ensures the output matches the expected schema without manual JSON authoring.

### 9.3 v0.dev Integration

The `@v0` built-in registry namespace connects to Vercel's v0.dev AI design tool. Components generated by v0 can be added to a shadcn/ui project using:

```bash
npx shadcn add @v0/component-id
```

This fetches the v0-generated component through the `@v0` registry, applies the same transform pipeline as standard components (import rewriting, RSC handling, CSS variables, etc.), and writes the result to the project. The integration allows designers to generate components with v0's AI and immediately integrate them into a shadcn/ui project.

### 9.4 Framework Detection System

The framework detection system (`packages/shadcn/src/utils/get-project-info.ts`) examines multiple signals to identify the active framework:

| Signal | Frameworks Detected |
|--------|-------------------|
| `package.json` dependencies | Next.js (`next`), Vite (`vite`), Astro (`astro`), React Router (`react-router`), TanStack Start (`@tanstack/start`) |
| Config files | `next.config.*`, `vite.config.*`, `astro.config.*`, router config files |
| Directory structure | `app/` (App Router), `pages/` (Pages Router), `src/` layout variants |
| TypeScript config | `tsconfig.json` paths, compiler options, JSX settings |

The detection result drives:
- **Template selection** during `shadcn init` (which scaffolding to use)
- **RSC support detection** (Next.js App Router = RSC enabled; Vite = no RSC)
- **File target resolution** (where components are written relative to project root)
- **Import alias detection** (read from `tsconfig.json` paths)

### 9.5 Package Manager Detection

The package manager detection system (`packages/shadcn/src/utils/get-package-manager.ts`) uses a multi-signal approach:

| Signal | Priority | Detection |
|--------|----------|-----------|
| `npm_config_user_agent` | Highest | Set automatically by npm/pnpm/yarn/bun when running scripts |
| Lock files | High | `pnpm-lock.yaml`, `package-lock.json`, `yarn.lock`, `bun.lockb` |
| `packageManager` field | Medium | `package.json#packageManager` (Corepack) |

The detected package manager determines:
- Which install command to run (`npm install`, `pnpm add`, `yarn add`, `bun add`)
- Which workspace configuration format to read
- How to detect monorepo workspace roots

> [!NOTE]
> If the CLI detects the wrong package manager, ensure the correct lock file exists in your project root, or invoke the CLI through the correct package manager (e.g., `pnpm dlx shadcn` instead of `npx shadcn`).

### 9.6 Known Open Issues

The following issues are tracked in the shadcn-ui/ui GitHub repository:

**Bugs**: #10415, #10414, #4516, #5263, #10411, #9301, #7129, #10377, #6536, #10104, #7202, #7206

**Feature Requests**: #7187, #7199, #9407

> [!NOTE]
> Issue numbers reference the `shadcn-ui/ui` GitHub repository. Check the repository's issue tracker for current status, as issues may have been resolved since this document was generated.

---

_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. Unofficial; not affiliated with or reviewed by the project._
