Yugen UI

@yugen-ui/cli

A command-line tool to create an app from a template, set up Yugen UI in an existing project, copy component source and check the setup.

Commands

CommandWhat it does
create [dir]New app from a template: starter, saas, blog, dashboard, ai-chat, glass, landing, admin, next-starter, docs, store. --ref <branch|tag> takes the templates from the repo.
initSet up an existing React project with the npm package or with copied source. Writes yugen.json and wraps the app in YugenProvider.
add <names…>Copy components and the components they depend on, install missing npm packages.
diff [names…]Compare copied source with the registry and print the diff. Changes nothing.
update [names…]Apply the registry version to copied source: shows the diff, asks, then writes.
remove <names…>Delete a component's files that nothing else imports.
cssWrite yugen-ui.css: only the CSS of the components your code imports (package mode).
theme --brand <hex>Generate a 16-step brand ramp into yugen-brand.css, with the Theme Designer's algorithm.
list [query]Components in the registry.
doctorCheck React, Tailwind CSS v4, the theme import, yugen-ui.css, the yugen-ui version and YugenProvider.

Nothing to install first: run it with npx @yugen-ui/cli@latest (or pnpm dlx, yarn dlx, bunx). Requires Node.js 24 or later.

Create an app

Asks for a directory and a template, copies the files, installs dependencies and runs git init.

npx @yugen-ui/cli@latest create my-app

Options: -t, --template, --lang en|vi (language of the app's text, for templates that have both; English by default), --pm npm|pnpm|yarn|bun, --no-install, --no-git, --force (write into a non-empty directory). npx create-yugen-ui@latest is a shorter way to run the same command. Templates ship inside the package, so this works offline. Preview them on Templates.

Set up an existing project

Detects Vite, Next.js, React Router or TanStack Start, the package manager and the main CSS file, then asks how you want to use Yugen UI.

npx @yugen-ui/cli@latest init
ModeWhat the CLI does
packageInstalls yugen-ui, writes yugen-ui.css with yugen css and adds @import "./yugen-ui.css"; right after @import "tailwindcss";. A CSS file that already imports yugen-ui/theme.css is left as it is. Without Tailwind CSS v4 it adds import "yugen-ui/styles.css"; to your entry file (main.tsx, app/layout.tsx).
sourceNeeds Tailwind CSS v4. Writes the theme as yugen.css next to your main CSS file and imports it, then copies cn() and YugenProvider into the project.
npx @yugen-ui/cli@latest init --mode source

Result in source mode for a Vite project with an @/ alias:

yugen.json
src/
  index.css                           # gains @import "./yugen.css"; after @import "tailwindcss";
  yugen.css                           # theme
  lib/cn.ts
  lib/cvx.ts                          # with yugen add button (variant classes)
  components/ui/YugenProvider/…       # plus the Toast and Tooltip it uses
  components/ui/Button/Button.tsx     # from yugen add

Imports in the copied code use your tsconfig alias (@/*, ~/*) when there is one and relative paths otherwise, so vite.config needs no changes. "use client" is kept for Next.js only. At the end the CLI prints the <YugenProvider applyToDocument> with <Toaster /> and the wrapper file to put it in.

Add components

Source mode. Names can be written either way: data-grid, DataGrid.

npx @yugen-ui/cli@latest add button dialog data-grid
npx @yugen-ui/cli add select --dry-run    # list the files it would write, write nothing
npx @yugen-ui/cli add --all               # every component
npx @yugen-ui/cli add button --overwrite  # also replace files you have edited
npx @yugen-ui/cli list grid               # search the registry, ✓ means already in the project

Existing files that differ from the registry (usually because you edited them) are left alone. The CLI lists them so you can re-run with --overwrite when you want the update. Commit first and use git's diff to keep your changes.

In package modeThe components are already in the yugen-ui package. add prints the matching import and adds the component to yugen-ui.css when the app has one.

Update and remove components

Source mode. Without names, the CLI looks at every Yugen component in the project.

npx @yugen-ui/cli diff                   # every copied component: print the diff against the registry
npx @yugen-ui/cli update button --dry-run # show the diff, write nothing
npx @yugen-ui/cli update                  # apply the registry version (asks before writing)
npx @yugen-ui/cli remove data-grid        # delete the files nothing else imports

update prints the diff of every file it would change, lists new files (for example a dependency the registry added), then asks before writing. Your edits in those files are replaced, so commit first. remove scans the project's imports (relative paths and aliases) and keeps files that are still used, for example Spinner while Button imports it. npm packages are not uninstalled.

Only the CSS you use

Package mode. theme.css makes Tailwind scan every component in the package; yugen-ui.css lists only the components your code imports.

npx @yugen-ui/cli css                       # write src/yugen-ui.css, import it in src/index.css
npx @yugen-ui/cli css --check               # CI: exit with 1 when the file is out of date, write nothing
npx @yugen-ui/cli css --src app --src lib   # read only these folders (default: the whole project)
npx @yugen-ui/cli css --precompile          # apps without Tailwind: compiled CSS that replaces styles.css
npx @yugen-ui/cli css --watch               # regenerate when component imports change

// vite.config.ts
import { yugenCss } from "@yugen-ui/cli/vite";
plugins: [yugenCss()]
/* src/yugen-ui.css */
@import "yugen-ui/theme-core.css";
@import "yugen-ui/sources/Button.css";
@import "yugen-ui/sources/Dialog.css";
@import "yugen-ui/sources/YugenProvider.css";

The command reads the imports from yugen-ui in your code, subpaths such as yugen-ui/Dialog included. Type imports and examples written inside strings or comments don't count. Each name is looked up in yugen-ui/sources/index.json and each component folder becomes one line. The first run replaces @import "yugen-ui/theme.css" in your main CSS file with @import "./yugen-ui.css". On the templates, the gzipped CSS goes from about 26 kB to 12–20 kB (table on Styling).

Run it again after you import another component; in package mode yugen add <name> does it for you. To keep it in sync, install the CLI as a dev dependency and add "predev": "yugen css" and "prebuild": "yugen css" to package.json. The file starts with the command that wrote it (--src and --out included), so the next run is just yugen css.

import * as Yugen from "yugen-ui", export * from "yugen-ui" and import("yugen-ui") can reach any component, so the file falls back to theme.css and names the file that caused it. Components imported in another package of a monorepo are not seen: add that folder with --src.

--precompile is for apps without Tailwind: the same list is compiled into plain CSS with your project's own tailwindcss, @tailwindcss/node and @tailwindcss/oxide (install them as dev dependencies; the CLI does not bundle Tailwind), and replaces import "yugen-ui/styles.css" in your entry file. On the templates: 26.8 kB down to 12.8–21.1 kB gzipped.

Brand color

Works in package and source mode, with the same algorithm as the Theme Designer.

npx @yugen-ui/cli theme --brand #0f6cbd --name acme
# → src/yugen-brand.css: [data-brand="acme"] { --brand-10 … --brand-160 }, imported from src/index.css
# <YugenProvider applyToDocument brand="acme"><Toaster />…</YugenProvider>

--vibrancy (50–150) and --torsion (−30…30) match the Theme Designer's two sliders. When white text on the primary button is under 4.5:1, the CLI warns and suggests a darker key that passes. For radius, density, fonts and the rest, use the Theme Designer.

Check the setup

Read-only. Exits with code 1 when something is wrong, so it can run in CI.

npx @yugen-ui/cli@latest doctor
◆  yugen.json: source mode
◆  React 19.3.1
◆  Tailwind CSS 4.3.3
◆  Theme imported: src/index.css → ./yugen.css
◆  15 component folders in src/components/ui
▲  YugenProvider not found
│  Wrap your app once: <YugenProvider applyToDocument><Toaster />…</YugenProvider>
└  Looks good, 1 warning

It checks for React 19 or later, Tailwind CSS v4 when the theme is used, a single theme import placed after @import "tailwindcss", a yugen-ui.css that is imported and matches your code (a warning when it is out of date), components imported without their sources file when you write the theme-core.css lines by hand, the installed yugen-ui against the latest on npm, the component folder and cn.ts in source mode, and a YugenProvider.

yugen.json and the registry

init writes this file at the project root; add, list and doctor read it. You can edit it, for example to change paths.ui and keep components somewhere else. Without it, a project that has yugen-ui installed (an app made by create, for example) is treated as package mode.

{
  "mode": "source",
  "framework": "vite",
  "rsc": false,
  "css": "src/index.css",
  "paths": { "ui": "src/components/ui", "lib": "src/lib" },
  "aliases": { "ui": "@/components/ui", "lib": "@/lib" }
}

Components come from the registry at https://trandat1114.github.io/Yugen-UI/r, the same source as the shadcn CLI. Projects that ran shadcn init with the Yugen registry can use yugen add straight away because the CLI reads components.json. Point --registry, or registry in yugen.json, at another URL or a local folder (public/r after npm run registry when working on Yugen).

Common options

OptionMeaning
-y, --yesNever prompt, use the defaults. On automatically in CI or without a terminal.
--cwd <dir>Run in another directory.
--no-installPrint the install command instead of running it (init, add, create).
--registry <url|dir>Use another registry (init, add, list).
-h, --helpHelp for each command.
npx @yugen-ui/cli@latest create app -t starter -y --no-git
npx @yugen-ui/cli@latest add button dialog -y --no-install