CLI & Copy-Paste
Use the Unified UI CLI to copy components directly into your project — like shadcn/ui, with automatic dependency resolution.
Overview
The Unified UI CLI lets you copy components directly into your project as local source files. Instead of importing from node_modules, you own the code — edit variants, change animations, add custom logic, or restyle anything.
This is the same workflow popularized by shadcn/ui, adapted for the Unified UI design system. The CLI handles:
- Dependency resolution — Automatically pulls in other components, utilities, and styles that a component depends on.
- npm dependency installation — Detects and installs required npm packages (Radix UI, Framer Motion, etc.).
- Import rewriting — Rewrites internal
@unified-ui/*imports to local project paths (e.g.,@/components/ui/*,@/lib/*). - Client directive detection — Marks files that need
"use client"for Next.js App Router.
You can use the CLI alongside the npm package. For example, install the full package for most components but copy specific ones you need to customize heavily.
Quick Start
Initialize your project
npx @work-rjkashyap/unified-ui initThis creates a unified-ui.json config file and sets up the directory structure for copied components.
Add components
npx @work-rjkashyap/unified-ui add button card badgeThe CLI fetches each component from the registry, resolves its full dependency tree, copies source files into your project, and installs any required npm packages.
Import and use
import { Button } from "@/components/ui/button";
import { Card, CardBody } from "@/components/ui/card";
import { Badge } from "@/components/ui/badge";
export default function Page() {
return (
<Card>
<CardBody className="space-y-3">
<Badge variant="success">New</Badge>
<Button variant="primary">Get Started</Button>
</CardBody>
</Card>
);
}Customize
The files are yours. Open them up and change anything:
// Add a new variant, change the default size,
// swap out the loading spinner, adjust colors —
// it's all local source code now.Commands
init
Initialize an existing project for Unified UI copy-paste mode.
npx @work-rjkashyap/unified-ui initWhat it does:
- Creates a
unified-ui.jsonconfig file in the project root. - Sets up alias paths for components, utilities, and styles.
- Detects your package manager (npm, pnpm, yarn, bun).
- Optionally installs base dependencies (
tailwind-merge,clsx,class-variance-authority).
Flags:
| Flag | Description |
|---|---|
--template, -t | Scaffold a new project with a framework (see below) |
--yes | Skip interactive prompts and use defaults |
--src | Use src/ directory structure (default: true) |
--cwd <dir> | Set the working directory |
init --template (Starter Kits)
Scaffold a brand-new project with a framework of your choice, fully configured with Unified UI.
# Interactive — prompts you to pick a framework
npx @work-rjkashyap/unified-ui init -t
# Specify framework and project name directly
npx @work-rjkashyap/unified-ui init -t nextjs my-app
npx @work-rjkashyap/unified-ui init --template vite-react my-appAvailable templates:
| Template | Framework | Repo | What's included |
|---|---|---|---|
nextjs | Next.js 16, App Router | unified-ui-template-nextjs | Full component library, next-themes, SSR-ready |
vite-react | Vite + React 19 | unified-ui-template-react | Full component library, DSThemeProvider, Tailwind CSS v4 |
tanstack-router | React 19, Vite, TanStack Router | unified-ui-template-tanstack-router | Full component library, file-based routing, Tailwind CSS v4 |
vuejs | Vue 3 + Vite | — | 10 Vue SFC components, design tokens, Tailwind CSS v4 |
laravel-blade | Laravel 12 + Blade | unified-ui-template-laravel | 10 Blade anonymous components, design tokens, Tailwind |
You can also clone templates directly from their GitHub repos — see the Starter Kits page for full instructions.
How it works:
- Runs the official scaffolding tool for the chosen framework (
create-vite,create-next-app,create-vue, orcomposer create-project). - Installs
@work-rjkashyap/unified-uiand any framework-specific dependencies. - Overlays Unified UI files — CSS imports, theme providers, demo pages, and config updates.
- Initializes git with a clean commit.
React starters (nextjs, vite-react, tanstack-router) include the full 75+ component library. Vue & Laravel starters include 10 framework-native UI components (Button, Badge, Card, Input, Alert, Heading, Text, etc.) plus all design tokens.
add
Add one or more components, utilities, or styles to your project.
npx @work-rjkashyap/unified-ui add <name...>Examples:
# Add a single component
npx @work-rjkashyap/unified-ui add button
# Add multiple components
npx @work-rjkashyap/unified-ui add button card badge tabs dialog
# Add everything
npx @work-rjkashyap/unified-ui add --all
# Overwrite existing files
npx @work-rjkashyap/unified-ui add button --overwriteWhat it does:
- Fetches the component's registry entry (source, dependencies, metadata).
- Resolves the full dependency tree — other registry items + internal utilities.
- Rewrites imports from
@unified-ui/*to your project's local paths. - Writes files to the correct directories based on your
unified-ui.jsonconfig. - Detects and reports npm packages that need to be installed.
- Optionally runs your package manager to install npm dependencies.
Flags:
| Flag | Description |
|---|---|
--all | Add all available registry items |
--overwrite | Overwrite existing files without prompting |
--no-deps | Skip npm dependency installation |
--cwd <dir> | Set the working directory |
By default, the CLI will not overwrite files that already exist. Use
--overwrite to force replacement, or use diff to review changes first.
list
List all available components, utilities, and styles in the registry.
npx @work-rjkashyap/unified-ui listOutput:
Components (75):
accordion, alert, alert-dialog, avatar, badge, banner, breadcrumb,
button, calendar, card, carousel, chart, checkbox, code, collapsible,
color-picker, combobox, command, confirm-dialog, context-menu, ...
Utilities (4):
cn, focus-ring, contrast, merge-slots
Motion (2):
presets, hooks
Styles (1):
unified-ui.cssdiff
Compare a local component against the latest registry version.
npx @work-rjkashyap/unified-ui diff buttonThis shows a unified diff of your local button.tsx against the registry's version, so you can see what's changed upstream and decide whether to merge the updates.
Flags:
| Flag | Description |
|---|---|
--cwd <dir> | Set the working directory |
Configuration
The unified-ui.json file controls where the CLI writes files and how imports are resolved.
{
"aliases": {
"components": "@/components/ui",
"utils": "@/lib",
"styles": "@/styles"
},
"src": true,
"registryUrl": "https://www.unified-ui.space/r"
}Options
| Key | Type | Default | Description |
|---|---|---|---|
aliases.components | string | "@/components/ui" | Where component files are written |
aliases.utils | string | "@/lib" | Where utility files (cn.ts, focus-ring.ts) go |
aliases.styles | string | "@/styles" | Where CSS files go |
src | boolean | true | Whether your project uses a src/ directory |
registryUrl | string | "https://www.unified-ui.space/r" | Base URL for the component registry |
Directory Mapping
With the default config and src: true, files are written to:
| Registry Type | Alias Path | Filesystem Path |
|---|---|---|
| Components | @/components/ui/ | src/components/ui/button.tsx |
| Utilities | @/lib/ | src/lib/cn.ts |
| Styles | @/styles/ | src/styles/unified-ui.css |
| Motion | @/lib/motion/ | src/lib/motion/presets.ts |
Dependency Resolution
When you add a component, the CLI automatically resolves its full dependency tree. There are three types of dependencies:
1. Registry Dependencies
Other Unified UI components that the added component imports. For example, dialog depends on button, so adding dialog will also add button if it's not already in your project.
dialog
├── button (registry dependency)
├── visually-hidden (registry dependency)
└── cn (internal utility)2. Internal Dependencies
Shared utilities that components rely on:
| Utility | What it provides |
|---|---|
cn | clsx + tailwind-merge class merging |
focus-ring | Focus ring CSS class utilities |
contrast | WCAG color contrast checking |
merge-slots | Slot merging for compound component APIs |
3. npm Dependencies
External packages that need to be installed from npm:
| Package | Used by |
|---|---|
@radix-ui/react-dialog | Dialog, AlertDialog, Sheet |
@radix-ui/react-popover | Popover, Combobox, DatePicker |
@radix-ui/react-tabs | Tabs |
framer-motion | All animated components |
class-variance-authority | All components with variants |
tailwind-merge | cn() utility |
clsx | cn() utility |
The CLI detects your package manager and generates the correct install command:
# npm
npm install @radix-ui/react-dialog framer-motion
# pnpm
pnpm add @radix-ui/react-dialog framer-motion
# yarn
yarn add @radix-ui/react-dialog framer-motion
# bun
bun add @radix-ui/react-dialog framer-motionRegistry
The component registry is a collection of JSON files served from the documentation site. Each item contains:
{
"name": "button",
"type": "component",
"description": "Primary action button with variants, sizes, loading state, and icon support.",
"client": true,
"files": [
{
"path": "components/ui/button.tsx",
"content": "\"use client\";\n\nimport { cn } from \"@/lib/cn\";\n..."
}
],
"dependencies": ["class-variance-authority", "tailwind-merge", "clsx"],
"registryDependencies": ["cn", "focus-ring"],
"internalDependencies": [],
"exports": ["Button", "buttonVariants"]
}Registry Endpoints
| URL | Description |
|---|---|
/r/index.json | Full manifest of all available items |
/r/<name>.json | Individual item metadata + source |
/r/schema/ | Registry schema definitions |
Building the Registry
If you're contributing to Unified UI or self-hosting, build the registry locally:
npm run build:registryThis scans packages/unified-ui/src/ and generates JSON files in public/r/.
Import Rewriting
When a component is copied into your project, internal imports are automatically rewritten to match your path aliases.
Before (registry source)
import { cn } from "@unified-ui/utils/cn";
import { focusRingClasses } from "@unified-ui/utils/focus-ring";
import type { FontFamilyKey } from "@unified-ui/tokens/typography";After (your project)
import { cn } from "@/lib/cn";
import { focusRingClasses } from "@/lib/focus-ring";
import type { FontFamilyKey } from "@/lib/tokens/typography";The rewriting is based on your unified-ui.json aliases configuration.
Using with Next.js App Router
Components that use React hooks, event handlers, or browser APIs are marked with "use client" automatically. The CLI detects this from the registry metadata and ensures the directive is present in the copied file.
"use client";
import { cn } from "@/lib/cn";
import { cva, type VariantProps } from "class-variance-authority";
import { forwardRef } from "react";
// ... component implementationToken and utility files are pure JavaScript/TypeScript with no React dependency, so they work in both Server and Client Components.
Updating Components
To update a component to the latest registry version:
Check what changed
npx @work-rjkashyap/unified-ui diff buttonReview the diff to see what's new in the upstream version.
Re-apply your customizations
If you had local changes, re-apply them after the update. Using git, you can review and cherry-pick changes:
git diff src/components/ui/button.tsxFor projects that need automatic updates without manual merging, consider
using the npm package workflow instead. Semver releases mean you
can upgrade with npm update and review breaking changes in the changelog.
Comparison: npm Package vs CLI
| Feature | npm Package | Copy & Paste CLI |
|---|---|---|
| Installation | npm i @work-rjkashyap/unified-ui | npx @work-rjkashyap/unified-ui add |
| Code location | node_modules/ | Your project (src/components/ui/) |
| Updates | npm update | diff + add --overwrite |
| Customization | Override via className/variants | Edit source directly |
| Bundle size | Tree-shaken by bundler | Only what you add |
| Type safety | Full .d.ts declarations | Full source with types |
| Version tracking | package.json semver | Manual via diff |
| Cross-project consistency | Guaranteed (same version) | Manual (divergence possible) |
| Token system | Included via CSS import | CSS file copied locally |
| Theme provider | Included | Copied as local file |
Frequently Asked Questions
Can I use both the npm package and the CLI?
Yes. A common pattern is to install the npm package for the base system (tokens, theme, primitives) and copy specific components you need to customize heavily.
Do I need to copy the CSS file?
Yes. When using the CLI, run npx @work-rjkashyap/unified-ui add styles to copy the design system CSS file. This provides all the CSS custom properties and Tailwind @theme integration.
What happens if I add a component that depends on another?
The CLI resolves the full dependency tree automatically. If dialog needs button, both are added. If button already exists in your project, it's skipped (unless you pass --overwrite).
Can I use a custom registry URL?
Yes. Set the registryUrl field in unified-ui.json to point to your own hosted registry:
{
"registryUrl": "https://your-internal-registry.com/r"
}How do I contribute a component back?
If you've built a component on top of the Unified UI token system and want to contribute it:
- Add the source file to
packages/unified-ui/src/components/. - Export it from
packages/unified-ui/src/components/index.ts. - Re-export from
packages/unified-ui/src/index.ts. - Run
npm run build:registryto generate the registry entry. - Write documentation in
content/components/<name>.mdx. - Submit a pull request.