CLI
The brutx-vue CLI helps you initialize BrutxUI in your project and add components with a single command.
Overview
npx brutx-vue@latest <command>The CLI automatically handles dependency installation, file creation, and configuration updates.
brutx-vue init
Initialize BrutxUI in your project. It sets up the base configuration:
npx brutx-vue@latest initThe init command will:
- Detect your project framework (Vite, Nuxt, etc.)
- Install required dependencies (
reka-ui,class-variance-authority,clsx,tailwind-merge,@lucide/vue) - Create the
cn()utility function insrc/lib/utils.ts - Inject
--brutal-*CSS custom properties into your stylesheet - Add BrutxUI styles (including Tailwind utility class layers) to your CSS
- Set up the component directory structure
Init also supports monorepo workspace detection. If a pnpm-workspace.yaml, lerna.json, or turbo.json file is found, the CLI will detect the workspace root and offer to install shared dependencies there while keeping component-specific dependencies in the current package. Use --workspace-root to explicitly specify the workspace root.
Options
| Flag | Description | Default |
|---|---|---|
--yes / -y | Skip prompts and use defaults | false |
--defaults / -d | Use default configuration | false |
--cwd <path> | Set working directory | Current directory |
--force / -f | Force overwrite existing configuration | false |
--silent / -s | Silent output | false |
--vscode | Generate VS Code snippets | Auto-detected |
--workspace-root <path> | Specify monorepo workspace root directory | Auto-detected |
brutx-vue add
Add individual components to your project:
npx brutx-vue@latest add <component...>Examples
Add a single component:
npx brutx-vue@latest add buttonAdd multiple components:
npx brutx-vue@latest add button card dialog inputAdd all available components:
npx brutx-vue@latest add --allVersion Pinning
Use the @ syntax to pin a component to a specific version. The string after @ is injected as a git ref (branch, tag, commit) into the registry source URL, so all component files are fetched from that ref:
npx brutx-vue@latest add button@1.2.0Interaction with --registry
@version only works with GitHub raw URL registries (matching https://raw.githubusercontent.com/{owner}/{repo}/{ref}/...). The CLI replaces the {ref} segment of the current --registry URL with the @version, leaving the rest of the path intact. This means it composes cleanly with custom forks:
# Pull button from the v1.2.0 tag of your personal fork
npx brutx-vue@latest add button@1.2.0 \
--registry https://raw.githubusercontent.com/<you>/<fork>/main/registryIf --registry is not a GitHub raw URL (e.g. a local path or self-hosted HTTP registry), using @version throws a REGISTRY_VERSION_UNSUPPORTED error. Remove @version or switch --registry to a GitHub raw URL.
Version mismatch warning
When the installed component version differs from the requested version, the CLI prints a warning (non-blocking):
⚠ Version mismatch: "button" is already installed at version 1.0.0, but you requested 1.2.0.Version constraints in update
update skips version-pinned components by default (it should not silently change a ref the user explicitly locked). To update across versions, pass --across-versions:
# Skips button@1.0.0 by default
npx brutx-vue@latest update
# Explicitly update across the locked version
npx brutx-vue@latest update --across-versionsOptions
| Flag | Description | Default |
|---|---|---|
--all | Add all available components | false |
--yes / -y | Skip confirmation prompts | false |
--cwd <path> | Set working directory | Current directory |
--overwrite | Overwrite existing component files | false |
--path <path> / -p | Specify the path to add components to | — |
--silent / -s | Silent output | false |
--dry-run | Simulate adding without writing files | false |
--registry <registry> / -r | Specify registry path or URL | — |
--no-cache | Skip registry cache | false |
--vscode | Update VS Code snippets with new components | false |
brutx-vue doctor
Check project configuration health and diagnose common issues:
npx brutx-vue@latest doctorThe doctor command will check:
- Whether
components.jsonexists and is valid - Whether the
$schemafield is present - Whether the
$versionconfig version is up to date - Whether the
stylefield is present - Tailwind CSS file contains BrutxUI design tokens
- Whether configured alias paths point to real files/directories
- Whether required dependencies are installed (
reka-ui,class-variance-authority,clsx,tailwind-merge) - Whether the
cn()utility function exists - File integrity of installed components
Examples
Basic diagnostics:
npx brutx-vue@latest doctorAuto-fix fixable issues:
npx brutx-vue@latest doctor --fix --yesApply only a specific fix:
npx brutx-vue@latest doctor --fix-only add-schemaOutput JSON format report:
npx brutx-vue@latest doctor --jsonOptions
| Flag | Description | Default |
|---|---|---|
--cwd <path> | Set working directory | Current directory |
--fix | Auto-fix fixable issues | false |
--fix-only <fixId> | Apply only the specified fix | — |
--json | Output JSON format report | false |
--yes / -y | Skip confirmation prompts | false |
--silent / -s | Silent output | false |
--sbom | Generate a CycloneDX 1.5 SBOM and exit (skips doctor checks) | false |
--sbom-output <path> | SBOM output file path | ./brutx-sbom.json |
Output Example
Brutx-Vue Doctor
[PASS] components.json exists — components.json found.
[PASS] $schema field present — $schema field is present.
[PASS] config version — Configuration version is 1.
[PASS] style field present — style is "brutalism".
[PASS] tailwind.css contains BrutxUI tokens — CSS file contains BrutxUI tokens.
[PASS] aliases.components → @/components — Directory exists.
[PASS] aliases.utils → @/lib/utils — File exists.
[PASS] tailwindcss installed — ^4.3.0 installed.
[PASS] reka-ui installed — ^2.9.9 installed.
[PASS] cn() function exists — cn() function found.
Summary: 10 passed, 0 warnings, 0 errorsAuto-Fixable Issues
| Issue | Fix Action |
|---|---|
Missing $schema | Write schema URL |
Missing or outdated $version | Update to current version |
Missing style | Set to brutalism |
| CSS missing BrutxUI tokens | Inject CSS styles |
| Component directory missing | Create directory |
| Utils file missing | Create utils file |
cn() function missing | Add cn() function |
brutx-vue diff
Compare locally installed components against the latest registry versions:
npx brutx-vue@latest diff [components...]Examples
Compare a single component:
npx brutx-vue@latest diff buttonCompare multiple components:
npx brutx-vue@latest diff button card dialogCompare all installed components:
npx brutx-vue@latest diff --allOutput JSON format:
npx brutx-vue@latest diff --all --jsonOptions
| Flag | Description | Default |
|---|---|---|
--all | Compare all installed components | false |
--cwd <path> | Set working directory | Current directory |
--registry <path> / -r | Specify local registry path | — |
--json | Output JSON format | false |
--silent / -s | Silent output | false |
--no-cache | Skip registry cache | false |
Output Example
Compare a single component:
Component Diff: button
Status: MODIFIED (1 file changed)
src/components/ui/button/Button.vue
--- registry/src/components/ui/button/Button.vue
+++ local/src/components/ui/button/Button.vue
- variant?: 'default' | 'destructive' | 'outline' | 'ghost';
+ variant?: 'default' | 'destructive' | 'outline' | 'ghost' | 'link';
+ loading?: boolean;
Summary: 1 file modified, 0 files unchangedCompare all components:
Component Diff Report
MODIFIED (2)
— button (1 file changed)
— card (2 files changed)
UP-TO-DATE (5)
— badge
— dialog
— input
— select
— toast
Summary: 2 modified, 5 up-to-date, 0 local-onlybrutx-vue update
Check for and apply component updates from the registry. Components with local modifications will be flagged before overwriting:
npx brutx-vue@latest update [components...]Examples
Update a specific component:
npx brutx-vue@latest update buttonUpdate all outdated components without prompts:
npx brutx-vue@latest update --all --yesPreview which components have updates available:
npx brutx-vue@latest update --dry-runOptions
| Flag | Description | Default |
|---|---|---|
--all / -a | Update all outdated components | false |
--yes / -y | Skip confirmation prompts | false |
--cwd <path> | Set working directory | Current directory |
--dry-run | Show which components would be updated without writing | false |
--registry <registry> / -r | Specify registry URL | — |
--no-cache | Skip registry cache | false |
--silent / -s | Silent output | false |
--across-versions | Allow updating version-pinned components across their locked version (see Version Pinning) | false |
brutx-vue list
List all installed components in your project, including file counts and dependencies:
npx brutx-vue@latest listExamples
List installed components:
npx brutx-vue@latest listOutput as JSON:
npx brutx-vue@latest list --jsonOptions
| Flag | Description | Default |
|---|---|---|
--cwd <path> | Set working directory | Current directory |
--json | Output JSON format | false |
--silent / -s | Silent output | false |
Output Example
Installed Components
Name Files Dependencies
────────── ────── ────────────────────────
badge 2 reka-ui
button 3 reka-ui, @lucide/vue
card 2 none
dialog 2 reka-ui, @lucide/vue
4 component(s) installedbrutx-vue info
Show detailed information about a component, including registry metadata, local files, dependencies, and installation status:
npx brutx-vue@latest info <component>Examples
Show info for a component:
npx brutx-vue@latest info buttonOutput as JSON:
npx brutx-vue@latest info button --jsonOptions
| Flag | Description | Default |
|---|---|---|
--cwd <path> | Set working directory | Current directory |
--json | Output JSON format | false |
--registry <registry> / -r | Specify registry path or URL | — |
--silent / -s | Silent output | false |
brutx-vue remove
Remove installed components from your project. Also detects and cleans up orphaned files (composables, utilities, locales) that are no longer referenced by any remaining component:
npx brutx-vue@latest remove <components...>Examples
Remove a single component:
npx brutx-vue@latest remove buttonRemove multiple components:
npx brutx-vue@latest remove button card dialogPreview removal without deleting files:
npx brutx-vue@latest remove button --dry-runOptions
| Flag | Description | Default |
|---|---|---|
--yes / -y | Skip confirmation prompts | false |
--cwd <path> | Set working directory | Current directory |
--dry-run | Show which files would be removed without deleting | false |
--silent / -s | Silent output | false |
brutx-vue create
Scaffold a new Vue 3 project with BrutxUI pre-configured. Creates the project, installs dependencies, and runs init automatically:
npx brutx-vue@latest create <project-name>Examples
Create a project with the default Vite + Vue 3 + TypeScript template:
npx brutx-vue@latest create my-appCreate a Nuxt 3 project:
npx brutx-vue@latest create my-app --template nuxtCreate a project using npm as the package manager:
npx brutx-vue@latest create my-app --package-manager npmOptions
| Flag | Description | Default |
|---|---|---|
--template <template> / -t | Project template (default, nuxt) | default |
--package-manager <pm> | Package manager to use (pnpm, npm, yarn, bun) | pnpm |
--cwd <path> | The directory to create the project in | Current directory |
--yes / -y | Skip confirmation prompts | false |
components.json Configuration File
The components.json file is created by brutx-vue init and stores your project configuration. All CLI commands read this file to locate components, utilities, and styles.
{
"$schema": "https://brutx-vue.dev/schema.json",
"$version": 1,
"style": "brutalism",
"tailwind": {
"config": "tailwind.config.js",
"css": "src/assets/index.css"
},
"aliases": {
"components": "@/components",
"utils": "@/lib/utils",
"composables": "@/composables"
}
}| Field | Description |
|---|---|
$schema | JSON schema URL for IDE validation and autocompletion. |
$version | Configuration format version. Used by doctor to detect outdated configs that may need migration. |
style | The design style variant. Currently only brutalism is supported. |
tailwind.config | Path to your Tailwind CSS config file. Empty string for Tailwind v4 (no config file needed). |
tailwind.css | Path to your main CSS file where BrutxUI design tokens are injected. |
aliases.components | Import alias for the components directory (e.g. @/components). |
aliases.utils | Import alias for the utility file containing cn() (e.g. @/lib/utils). |
aliases.composables | Import alias for the composables directory (e.g. @/composables). |
Global Options
The following options apply to all commands and must be placed before the subcommand:
npx brutx-vue@latest [global-options] <command> [command-options]| Flag | Description | Default |
|---|---|---|
--verbose | Show detailed error output (equivalent to -v) | false |
--dry-run | Global dry-run: simulate all write operations without touching disk (stacks with command-level --dry-run) | false |
--require-signature | Strict signature mode: fail when manifest signature is invalid (default is warn, see Supply Chain Security) | false |
--verbose-level <level> | Verbose output level (1=steps, 2=cache/network details, 3=stack traces) | 0 |
-v | Equivalent to --verbose-level 1 | — |
-vv | Equivalent to --verbose-level 2 | — |
-vvv | Equivalent to --verbose-level 3 | — |
Global dry-run
The --dry-run global flag activates dry-run semantics for all commands without needing to add --dry-run after each subcommand. Can also be activated via the BRUTX_DRY_RUN=1 environment variable:
# These two are equivalent
BRUTX_DRY_RUN=1 npx brutx-vue@latest add button
npx brutx-vue@latest --dry-run add buttonWhen activated, add/update/remove only print paths that would be written; no files are modified.
Verbose levels
Control output verbosity via -v/-vv/-vvv or the BRUTX_VERBOSE=<n> environment variable:
| Level | Label | Meaning |
|---|---|---|
1 | [STEP] | Step-level, e.g. "resolving dependencies" |
2 | [DETAIL] | Cache/network details, e.g. "cache hit button@v1" |
3 | [TRACE] | Stack/debug details |
Audit Log
After add/remove/update/diff commands execute, a JSONL record is appended to .brutx/audit.log containing:
timestamp: ISO timestampcommand: command type (add/remove/update/diff)components: list of components operated onregistrySource: registry sourcesuccess: whether the operation succeededdryRun: whether it was a dry-runerror: error message on failure
doctor reads the last 5 failure records from the audit log as diagnostic clues:
npx brutx-vue@latest doctorExample output:
⚠ audit log health — 1 recent failure(s) in audit log: update(button).
Latest: update failed at 2026-07-16T02:30:00Z — Network unreachableSupply Chain Security: Signature & SBOM
P1-6 introduces manifest Ed25519 signature verification and CycloneDX 1.5 SBOM generation to detect supply chain tampering.
Manifest Signature
At registry build time, registry-manifest.json carries signature + keyId fields holding an Ed25519 signature over the integrity field. The CLI automatically verifies the signature when fetching the manifest.
Trusted Public Keys
Trusted public keys are injected via the BRUTX_REGISTRY_PUBLIC_KEYS environment variable (JSON array):
BRUTX_REGISTRY_PUBLIC_KEYS='[{"keyId":"v1","publicKey":"<base64-SPKI-DER>"}]' \
npx brutx-vue@latest add buttonpublicKey is a base64-encoded SPKI DER (single-line, easy to embed in JSON). When the env var is unset, verification degrades to skip (backward compatible).
Default warn vs strict mode
On signature failure, the default behavior is warn (print a warning and continue) so that projects without configured keys are not blocked during migration:
[Signature] Manifest signed with unknown keyId "v1". No matching trusted public key found.
(use --require-signature to enforce)To fail hard on signature errors, activate strict mode:
# Via flag
npx brutx-vue@latest --require-signature add button
# Or via environment variable
BRUTX_REQUIRE_SIGNATURE=1 npx brutx-vue@latest add buttonIn strict mode, a signature failure throws REGISTRY_SIGNATURE_INVALID (exit 1). The integrity field still backstops tampering: even when signature verification is skipped, tampered content will fail because integrity no longer matches.
Key Rotation
Public keys are indexed by keyId. When rotating keys:
- New key signs the manifest: add the new public key to
BRUTX_REGISTRY_PUBLIC_KEYS - Transition period: the old key remains in the list, old manifests stay trusted
- Revoke the old key: remove it from the env var
SBOM Generation
Registry SBOM (build time)
pnpm --filter brutx-registry-vue build automatically generates packages/registry/registry/registry-sbom.json containing:
- All registry components (
type: application,bom-ref: brutx:<name>) - All npm dependencies (
type: library,bom-ref: npm:<dep>) dependenciesarrays referencing other bom-refs to form the dependency graphintegrityfield (sha256 overbomFormat/specVersion/components)manifestIntegrityfield binding the SBOM to the correspondingregistry-manifest.jsonintegrity
serialNumber is a random UUID regenerated each build, excluded from integrity computation, and added to the build:verify diff exclusion set.
Project SBOM (doctor --sbom)
doctor --sbom generates an SBOM for installed components, written to ./brutx-sbom.json (customize with --sbom-output):
npx brutx-vue@latest doctor --sbom
npx brutx-vue@latest doctor --sbom --sbom-output ./reports/sbom.jsonIt reads installed component versions, dependencies, registryDependencies, and integrity from the .brutx/components.json manifest and emits a CycloneDX 1.5 SBOM. Errors out if no components are installed.
Available Components
accordion, activity-log-page, alert, alert-dialog, auth-card, avatar, badge, before-after, blog-card, blog-list-page, breadcrumb, brutalist-hero, button, calendar, card, card-3d, carousel, chat-bubble, checkbox, code-block, combobox, command, cookie-consent, copy-to-clipboard, counter, dashboard-shell, dashboard-stats, data-table, dialog, dropdown-menu, empty-state, faq-section, feedback-form, file-card, footer-section, form, gallery-section, glitch-text, hardcore-input, header-section, input, kbd, kanban, loading, marquee, not-found-page, number-input, overview-page, pagination, popover, pricing-section, profile-page, progress, quick-actions, radio-group, result, scratch-card, scroll-area, search-widget, select, separator, settings-page, sheet, skeleton, sketchy-chart, slider, spinner, stepper, switch, table, tabs, tags-input, testimonial-card, textarea, timeline, toast, toggle, toggle-group, tooltip, tree-view, upload, waitlist-page