VeanUI CLI

vean is the command-line tool for VeanUI. It helps you initialize projects, add components, manage your UI configuration, and migrate a project to VeanUI.

Installation

pnpm add -D @vean/cli

Or run directly:

npx @vean/cli@latest init

Commands

vean init

Initialize a new VeanUI project or add configuration to an existing one.

vean init [options]
OptionDescriptionDefault
-m, --monorepoUse monorepo (pnpm workspaces) structurefalse
--ui-dir <path>Component output directorysrc/ui (single) / packages/ui (monorepo)
--size <size>Component size: xs / sm / md / lg / xl / 2xlmd
--style <style>Style preset: soybean / clean / densesoybean
-b, --base <base>Base color: zinc / neutral / stone / slate / grayzinc
--primary <primary>Primary color: indigo / blue / green / …indigo
--radius <radius>Border radius: none / xs / sm / md / lg / xl / 2xlmd
-p, --preset <code>Preset code (base62 encoded config)—
--icon-library <lib>Icon library: lucide / material-symbols / ph / tabler / solar / radix-iconslucide
--font-sans <font>Sans-serif font: inter / roboto / geist / …—
--font-heading <font>Heading font or inherit—
-y, --yesSkip confirmation promptfalse
-d, --defaultsUse default configurationfalse
-f, --forceOverwrite existing configurationfalse

Interactive prompts will guide you through the configuration when no options are provided.

vean add

Add components to your project.

vean add <component...> [options]
OptionDescription
-y, --yesSkip confirmation prompt
-o, --overwriteOverwrite existing files
-p, --path <path>Target path (default: uiDir from config)
--dry-runPreview changes without writing
--diffShow diff between local and registry
--viewView component source without adding
-a, --allAdd all available components
-s, --silentMute output

vean build

Build registry JSON files from a registry.json manifest.

vean build [registry] [options]
OptionDescriptionDefault
-o, --output <path>Output directory./public/r

vean search

Search for available components.

vean search [query] [options]
OptionDescription
-a, --allShow all components
-t, --type <type>Filter by type: component / hook / style / lib / theme
-l, --limit <limit>Max results (default: 50)
-o, --offset <offset>Pagination offset

vean list

List registry items, optionally filtered by package.

vean list [options]
OptionDescription
--package <name>Filter by package namespace (currently: ui; future peripheral packages are added under their own namespace)
--jsonOutput as JSON

Items are namespaced by package (currently ui/button, ui/accordion, …; future peripheral packages follow <package>/<component>).

vean view

View a component’s source code.

vean view <component>

vean info

Show project configuration and available preset values.

vean info [options]
OptionDescription
--jsonOutput as JSON

vean template

Scaffold a new project from a template.

vean template [name] [options]
OptionDescription
-l, --listList available templates
-o, --output <dir>Output directory

Available templates: vue-vite, nuxt.

vean preset

Manage configuration presets.

vean preset <preset>

vean migrate

Migrate a SoybeanUI-era project — one depending on @soybeanjs/* or using the sbean CLI — to VeanUI (@vean/*).

vean migrate [migration] [options]
OptionDescriptionDefault
-c, --cwd <cwd>Working directoryCurrent dir
-w, --writeApply the changes (without it the run is a dry run)false
--runtime-contractAlso rewrite data-soybean-* attributes and --soybean-* CSS variablesfalse
--cliAlso rewrite sbean CLI references and rename sbean.json to vean.jsonfalse
--new-domain <host>Also rewrite ui.soybeanjs.cn to <host> (CDN target becomes assets.<host>)—
--new-cdn <host>Rewrite only the r2.soybeanjs.tech / img.soybeanjs.dev CDN host—
--repo-slug <owner/repo>Rewrite only github.com/soybeanjs/soybean-ui—
-f, --forceRun even when the project shows no SoybeanUI-era tracefalse
-q, --quietPrint the summary only, without per-file previewsfalse

Available migrations: rebrand (SoybeanUI → Vean). Package specifier rewrites always apply; the runtime-contract, CLI and hostname tiers are opt-in, and --new-domain, --new-cdn and --repo-slug are independent of each other.

vean migrate rebrand                       # preview
vean migrate rebrand --write               # apply
vean migrate rebrand -w --runtime-contract --cli --new-domain veanui.com

Preflight. After scanning, the command looks for SoybeanUI-era traces: @soybeanjs/* dependencies in package.json, a sbean.json, @soybeanjs/* specifiers in source, data-soybean-* / --soybean-* contracts and sbean invocations. When none are found — the directory is wrong, or the project is already migrated — it refuses to run, exits 1 and writes nothing. A project with only old hostname links is refused too, unless you asked for a hostname rewrite explicitly. Use --force to run regardless.

Every run ends with two project-specific blocks: Worth adding (opt-in flags that still match something in the project, e.g. “12 data-soybean-* references → add --runtime-contract”) and Still manual (only the steps that apply, such as a dependency swap built from the actual package.json). Lock files, node_modules, build output and CHANGELOG.md are never rewritten, and the run is idempotent. See the brand migration guide for the complete walkthrough.

Configuration

The vean.json file stores your project configuration:

{
  "iconLibrary": "lucide",
  "uno": {
    "base": "zinc",
    "primary": "indigo",
    "size": "md",
    "radius": "md"
  },
  "font": {
    "sans": "inter",
    "heading": "inherit"
  },
  "aliases": {
    "ui": "#ui"
  },
  "registries": {}
}
FieldTypeDescription
iconLibrarystringIcon library prefix
uno.basestringBase (neutral) color
uno.primarystringPrimary (brand) color
uno.sizestringBase component size
uno.radiusstringBorder radius
font.sansstringSans-serif font name
font.headingstringHeading font or "inherit"
aliasesobjectImport aliases per package (e.g. ui; future peripheral packages likewise) — each maps to an output dir via tsconfig paths (default src/<package>)
registriesobjectAdditional registry namespace → URL mappings

Project Structure

Single Package

project/
├── src/
│   └── ui/           ← component output (uiDir)
│       ├── components/
│       ├── styles/
│       ├── theme/
│       ├── constants/
│       ├── resolver/
│       └── nuxt/
├── vean.json
├── tsconfig.json
└── uno.config.ts

Monorepo (pnpm workspaces)

project/
├── packages/
│   └── ui/           ← component output (uiDir)
│       ├── components/
│       ├── styles/
│       ├── theme/
│       ├── constants/
│       ├── resolver/
│       └── nuxt/
├── vean.json
├── tsconfig.json
├── uno.config.ts
└── pnpm-workspace.yaml

Alias System

VeanUI uses the #ui TypeScript path alias for all component imports:

// tsconfig.json
{
  "compilerOptions": {
    "paths": {
      "#ui/*": ["./src/ui/*"]
    }
  }
}

All component imports use this namespace:

import { SButton } from '#ui/components/button';
import { buttonVariants } from '#ui/styles/button';

Registry

Vean fetches component source from the VeanUI registry at https://veanui.com/r/<package>/<component>.json — the core ui package from r/ui/{name}.json (e.g. r/ui/button.json) and the catalog index from r/registry.json. Registry items are namespaced by package, so {name} in a registry URL template is the qualified item name (ui/button), not the bare component name. Core ui components can be referenced without a prefix (vean add button); components from any future peripheral package will require the namespace prefix (vean add <package>/<component>). A local cache (~/.vean/cache) is maintained with 24-hour TTL and ETag support for efficient updates.