Skip to main content
WireKit
Copy for LLM

CLI Reference

WireKit ships a family of Artisan commands covering install, diagnostics, scaffolding, asset publishing, extension installers, AI-tooling integration, and machine-readable manifests. All commands live under the wirekit: namespace and are registered automatically by the package's service provider — no manual registration required.

Discoverability features

Every WireKit CLI surface follows the same contract so AI tools and human users can rely on consistent behavior across commands.

"Did you mean?" semantics

Every command that reports Unknown X: <value> (unknown component, unknown preset, unknown category, unknown font key, unknown icon preset, unknown --as / --format value) follows the suggestion up with a Levenshtein-ranked hint when the typo is within distance 3 of a real value. The suggestion list is ranked closest-first with ties broken by shorter name first.

Concrete examples:

php artisan wirekit:show buttn
# → "Unknown component: buttn" + "Did you mean: button?"

php artisan wirekit:theme cuprtino
# → "Unknown preset: cuprtino" + "Did you mean: cupertino?"

php artisan wirekit:list --category=Markting
# → "Unknown category: Markting" + "Markting: Did you mean: Marketing?"

php artisan wirekit:publish-icons heroicns
# → "Unknown preset 'heroicns'" + "Did you mean: heroicons?"

The contract: distance ≤ 3, top-3 ranked suggestions, fires uniformly on every Unknown X error message. Runtime prop validation (WireKit::validateProp()) uses the same helper, so an invalid intent="primry" produces the same hint shape.

Command aliases

Canonical name Alias
wirekit:verify wirekit:doctor

Aliases resolve to the SAME command — running either name walks the identical check pipeline. php artisan list wirekit shows the canonical name with the alias listed underneath, NOT as a separate command row.

Exit codes

All commands follow Symfony's three-value exit-code convention:

Code Meaning
0 (SUCCESS) Command completed cleanly. Continue your pipeline.
1 (FAILURE) Runtime failure mid-command — investigate the output.
2 (INVALID) Input rejected (unknown value, mutually-exclusive flags, malformed argument). No side-effects ran.

See wirekit:install exit codes for the canonical CI / deploy wiring of these codes.

Interactive vs non-interactive mode

Commands that may prompt the user (e.g. wirekit:install's guided setup, wirekit:component's --base chooser) detect TTY status automatically. The behavior:

  • TTY present → prompts fire normally.
  • Non-TTY (CI, piped, redirected) → prompts are skipped; commands run with defaults or fail-fast on missing required input.
  • --no-interaction → forces non-TTY semantics even in a TTY.
  • --interactive → forces prompt mode even when TTY detection misfires (Herd / Docker / WSL setups).

ThemePresetRegistry

Pushery\WireKit\Theming\ThemePresetRegistry is the single source of truth for every WireKit theme preset. wirekit:theme, wirekit:install --preset=, and wirekit:export-api-map themesGroup() all read from this class — drift between their lists is impossible.

Key Label Shape
default Default No-op preset; applying it removes any existing wirekit:theme start/end block from app.css
minimal Minimal Clean, borderless aesthetic
soft Soft Rounded, gentle shadows
material Material Google Material Design 3 inspired
brutalist Brutalist Bold borders, no shadows
retro-terminal Retro Terminal Green-on-black hacker aesthetic
cupertino Cupertino Apple HIG inspired

Downstream packages can register custom presets at runtime via ThemePresetRegistry::register() from a service-provider boot hook:

use Pushery\WireKit\Theming\ThemePresetRegistry;

public function boot(): void
{
    ThemePresetRegistry::register('fintech', [
        'label' => 'FintechKit',
        'vars' => "    --color-wk-accent: oklch(0.65 0.22 220);",
        'dark_vars' => null,
    ]);
}

After registration the preset appears in wirekit:theme fintech, wirekit:install --preset=fintech, and the AI-tooling export.

Quick Reference

Command Purpose
wirekit:install One-command initial setup: publish config, publish assets, hint layout directives
wirekit:verify Diagnose integration health (assets, directives, Tailwind @source, optional deps)
wirekit:doctor Alias for wirekit:verify
wirekit:doctor:a11y Static-analysis a11y linter — scan your app's Blade templates for missing aria-labels, dialog-without-label, role="img" without label
wirekit:list List every component grouped by category
wirekit:fonts List every font preset grouped by category — pick a key for wirekit:install --font=…
wirekit:icons List every icon alias grouped by preset — discover which presets ship which aliases
wirekit:show {name} Show props, slots, and docs URL for a single component
wirekit:theme {preset} Inject a theme preset's CSS block into app.css
wirekit:make {name} Scaffold a Livewire page pre-wired with WireKit components
wirekit:component {name} Scaffold a custom component derived from a WireKit base
wirekit:publish-icons {preset} Publish a specific icon-set's SVG directory
wirekit:publish-fonts Publish the font families your config names
wirekit:glass install Publish the Liquid Glass extension CSS to your layout
wirekit:editor-preset {preset} Scaffold the window.wirekitEditor() factory snippet for the editor
wirekit:export-json Emit a machine-readable JSON manifest of every component
wirekit:export-api-map Emit an AI-friendly hierarchical sitemap of every WireKit surface
wirekit:cursor-rules Publish the WireKit Cursor rules file to .cursor/rules/wirekit.mdc
wirekit:mcp-serve Run the local MCP server (JSON-RPC over stdio) for AI coding assistants
wirekit:boost-skills Publish a Laravel Boost skill manifest (.boost/wirekit.json) for AI-editor autocomplete

wirekit:install

php artisan wirekit:install
php artisan wirekit:install --preset=cupertino
php artisan wirekit:install --font=inter
php artisan wirekit:install --font=inter --font-serif=lora --font-mono=jetbrains-mono
php artisan wirekit:install --interactive       # Force interactive prompts even when TTY detection misfires (Herd / Docker / WSL)
php artisan wirekit:install --no-gitignore      # Skip auto-adding /public/vendor/wirekit to .gitignore (commit assets to repo)
php artisan wirekit:install --apex-license=community  # Opt into the optional ApexCharts adapter + record license tier

Flags:

  • --preset=... — apply a theme preset during install (default: default)
  • --font=... / --font-serif=... / --font-mono=... — inject font-family overrides
  • --interactive — force the guided prompt mode even when Symfony's TTY detection returns false (common in Herd / Docker / WSL setups where stdin goes through a wrapper)
  • --no-gitignore — skip the automatic /public/vendor/wirekit entry in your .gitignore. Use this when your deploy pipeline does NOT run vendor:publish --tag=wirekit-assets --force and you prefer to commit the published assets to your repo instead
  • --apex-license=community|commercial|oem — opt into the optional ApexCharts adapter and record your license tier in config/wirekit.php charts.apex_license. Always prints the License Notice once (Community License covers organizations under $2M USD revenue; Commercial License required above; OEM only for redistributed-product embeddings). Suppresses the wirekit:doctor reminder when the tier is commercial or oem. ApexCharts is non-MIT — see the License section on the Chart overview and apexcharts.com/license for the full terms.
  • --no-strict — opt OUT of strict-by-default mode. Pre-flight warnings print but do not abort. Recommended only for legacy CI scripts that depended on the v2.0.0 "warnings as success" behavior.
  • --force — bypass pre-flight warnings (token clobber, hand-edited marker blocks). Errors still abort. Mutually exclusive with --no-strict.
  • --ignore-failed-flags — per-flag failures report but do NOT abort install. Other flags still apply. Exit code reflects partial failure (non-zero so CI still detects it). Requires --no-strict (since strict-default would abort first).
  • --diff — dry-run mode. Reports what WOULD change in app.css / layout / config without writing any files. Exits 0 after rendering the would-be-state. Use to preview an install before committing.
  • --rollback — reverse the most-recent install session by replaying .wirekit-install.log before-snapshots. Per-file restore. Returns 0 on full success, 1 on partial restore. Mutually exclusive with every install flag.

Exit codes

Code Meaning
0 SUCCESS — install completed cleanly (or dry-run / rollback completed cleanly).
1 FAILURE — runtime error mid-install (verify failed, theme call failed, partial rollback).
2 INVALID — pre-flight validation found errors, OR mutually-exclusive flags were combined. No filesystem mutations happened.

Decision matrix

Pre-flight state default (strict) --no-strict --force
Clean proceed proceed proceed
Warnings only abort (exit 2) proceed proceed
Errors abort (exit 2) abort (exit 2) abort (exit 2)

Pre-flight collects EVERY error in one pass — the user sees the full picture before deciding how to fix.

Runs the one-command bootstrap:

  1. Publishes config/wirekit.php (overridable defaults for every component)
  2. Publishes dist/wirekit.css and dist/wirekit.js to public/vendor/wirekit/
  3. Adds public/vendor/wirekit/ to your .gitignore
  4. Prints the layout snippet to paste into your Blade master view
  5. When --font=<key> is passed: publishes the bundled font CSS to public/vendor/wirekit/fonts/ and injects an idempotent override block into resources/css/app.css setting BOTH --font-sans (drives Tailwind utilities) AND --font-wk-sans (drives WireKit chrome) to the resolved font family — so the two stay aligned automatically.
Flag Purpose
--preset=<name> Theme preset: default, minimal, soft, material, brutalist, retro-terminal, cupertino
--font=<key> Inject sans font-family override (e.g. inter, roboto, open-sans). Must be a sans-category key from FontRegistry; lists available keys on error. Local font CSS only — WireKit ships GDPR-compliant local font files; nothing is fetched from a CDN.
--font-serif=<key> Inject serif font-family override (e.g. lora, playfair-display, merriweather). Must be a serif-category key from FontRegistry.
--font-mono=<key> Inject mono font-family override (e.g. jetbrains-mono, fira-code). Must be a mono-category key from FontRegistry.

All three font flags are combinable and produce independent marker-pair blocks in app.css — each idempotent, each swappable on re-run. Wrong-category passes throw with a list of valid keys for the correct category.

Tailwind config support

WireKit detects which Tailwind config shape your project uses and writes the font override to the right file:

Shape Detected by Where the override is written
CSS-first (Tailwind v4 default) resources/css/app.css contains @theme {…} @theme { --font-sans: … } block in app.css
JS-config (legacy) tailwind.config.js exists, no @theme in app.css theme.extend.fontFamily.{sans,serif,mono} array in tailwind.config.js
Both both files exist CSS-first wins; info-log shows the choice (Tailwind v4 deprecates JS config)
Neither none of the above logs warning + skips font injection

If your tailwind.config.js has a custom shape WireKit can't auto-edit (heavy comments, non-standard module.exports layout), the install command logs an actionable skip message with the exact line to add manually.

Interactive mode

When you run wirekit:install without any flags AND in an interactive TTY (i.e. you're at the terminal, not in CI), the command opens a guided setup:

$ php artisan wirekit:install
Installing WireKit...

  i Interactive setup — press Enter at any prompt to skip.

  Theme preset [default]:
    default, minimal, soft, material, brutalist, retro-terminal, cupertino
  > cupertino

  Sans-serif font (skip = use bundled defaults) [skip]:
    skip, inter, roboto, open-sans, lato, montserrat
  > inter

  Serif font (optional) [skip]:
    skip, lora, playfair-display, merriweather
  >

  Monospace font (optional) [skip]:
    skip, jetbrains-mono, fira-code, source-code-pro
  > jetbrains-mono

  ✓ Published config/wirekit.php
  ...

Selected values route into the same code path as if you'd passed --preset=cupertino --font=inter --font-mono=jetbrains-mono on the command line.

CI-friendly: the prompts are skipped automatically when:

  • Any flag is passed (e.g. --preset=cupertino alone disables prompts)
  • --no-interaction is set
  • The command is running in a non-interactive context (piped scripts, GitHub Actions, etc.)

So php artisan wirekit:install --no-interaction in a CI workflow runs exactly as in v1.5.0 — zero new behavior.

Idempotent: safe to re-run after a composer update to refresh published assets. Re-running with the same --font=<key> produces byte-identical app.css; re-running with a different key swaps the bracketed override block in place.

wirekit:verify and wirekit:doctor

php artisan wirekit:verify
php artisan wirekit:doctor                       # alias — same checks, more conventional name
php artisan wirekit:verify --tier=package        # Run only package-tier checks (1-14)
php artisan wirekit:verify --tier=environment    # Run only environment-tier checks (15)
php artisan wirekit:verify --fix                 # Self-heal missing public/vendor/wirekit/* assets

Flags:

  • --tier=package|environment — filter to a single check tier. package covers the WireKit install itself (asset publishing / config / directives / Tailwind source / token alignment / Alpine cleanup — checks 1–14 below). environment covers Laravel host state that bites in interactive dev even when the package install is clean (currently just the compiled-views-freshness check — check 15 below). Default (flag omitted) runs every tier. Unknown tier values exit with INVALID (exit code 2).
  • --fix — proactively self-heal missing public/vendor/wirekit/*.{css,js} assets by running vendor:publish --tag=wirekit-assets --force and re-checking. Useful right after a fresh clone (where public/vendor/wirekit/ is .gitignored and starts empty) to avoid a red doctor on first run. Without --fix, the missing-assets check still emits the actionable "Run: php artisan vendor:publish --tag=wirekit-assets" hint and the --fix alternative is offered alongside.

Diagnostic checks grouped into named sections — see the dedicated wirekit:doctor reference for per-check explanations, mismatch examples, and CI / hook wiring.

Package-tier checks (run with default or --tier=package)

  1. Assets published (wirekit.css / wirekit.js in public/vendor/wirekit/)
  2. Asset freshness (md5 hash matches package source)
  3. Tailwind @source directive scanning the package views
  4. Config file published (config/wirekit.php)
  5. Blade directives present (@wirekitStyles + @wirekitScripts)
  6. Alpine.js available (skipped on Livewire v4+ which bundles Alpine)
  7. Bundle config valid (scripts.bundle is full or core)
  8. Published views not stale (warns if views/vendor/wirekit/ exists with file count)
  9. Font assets published when a custom font preset is configured
  10. CSS @import anti-pattern detection (warn if wirekit.css is @import-ed in app.css)
  11. Optional dependencies (Chart.js adapter, bacon-qr-code)
  12. Token alignment — token-pair checks across font, color, radius, shadow. Reports drift between Tailwind tokens (--font-sans, --color-accent, --radius, …) and the matching WireKit tokens (--font-wk-sans, --color-wk-accent, --radius-wk, …). Skips var(...) references.
  13. Light/dark color-token symmetry — every --color-wk-* declared in your :root {} block is also declared in your .dark {} block (and vice versa). Asymmetric tokens are reported with the missing-side name so you can add the matching declaration. Scoped to color tokens only; font / radius / shadow tokens are theme-agnostic and excluded.
  14. Alpine plugin cleanup hygiene — static analysis of your resources/js/ tree for custom Alpine plugins. Flags two anti-patterns: an observer (IntersectionObserver / MutationObserver / ResizeObserver) instantiated without a destroy() lifecycle method, AND a disconnect() call inside an observer callback without a preceding null-guard. Both produce silent TypeError console errors after Livewire morph / conditional render / SPA navigation. Respects a // wirekit-doctor: cleanup-ok opt-out comment marker for intentional patterns the heuristic doesn't recognize.

Environment-tier checks (run with default or --tier=environment)

  1. Compiled-views freshness — detects when resources/views/ mtimes exceed storage/framework/views/ by ≥ 60 seconds. The canonical "I edited the Blade source an hour ago, the test still asserts the old output" failure mode caused by Laravel's compiled-view cache lag. Emits a WARN with the actionable php artisan view:clear fix. 60-second buffer avoids false-positives on fast file-edit cycles; slow filesystems (NFS / Docker on macOS) may need a higher threshold (see the check's docblock).

Exit code 1 on any failure — add to your CI pipeline, or register as a post-task verification step in your AI coding agent (Claude Code's hooks system, ChatGPT Codex, Cursor rules, Aider, etc.) so drift between WireKit and your app surfaces automatically after every change.

wirekit:doctor:a11y

Static-analysis accessibility linter for your application's Blade templates. Scans every .blade.php file under a given path (defaults to resources/views) for the high-value bug classes that axe-core catches at runtime, but with zero browser cost:

  • <x-wirekit::button> whose only child is an icon (no text label) and which doesn't carry aria-labelERROR (WCAG 2.1 "Buttons must have discernible text").
  • Any element with role="dialog" or role="alertdialog" that doesn't carry aria-label or aria-labelledbyERROR (WCAG 4.1.2 + ARIA APG dialog pattern).
  • Any element with role="img" that doesn't carry aria-label or aria-labelledbyERROR (WCAG 1.1.1 non-text content).
php artisan wirekit:doctor:a11y                 # Scan resources/views (default)
php artisan wirekit:doctor:a11y app/Livewire    # Scan a specific path
php artisan wirekit:doctor:a11y --fail-on=warning   # Gate CI on warnings too
php artisan wirekit:doctor:a11y --theme-contrast    # + WCAG contrast audit on theme tokens

Flags:

  • --fail-on={error|warning|none} — Severity threshold that triggers a non-zero exit. error (default) — only ERROR findings fail the build. warning — both ERROR and WARNING fail (strict CI gate). none — never fail; print findings only.
  • --theme-contrast — Opt-in second stage. After the Blade scan, parses resources/css/app.css for --color-wk-* token overrides under :root and .dark blocks (accepting both the bare and :where(...) wrapped selector forms), then computes WCAG 2.1 contrast ratios for the canonical token pairings (accent as text on bg, accent-fg on accent — the primary-button label pairing — text-muted on bg, danger-fg on danger, etc.). Reports PASS / WARN / FAIL / EXEMPT per pairing × mode. Catches the bug class where a developer customizes --color-wk-accent without verifying the new value still clears 4.5:1 against --color-wk-accent-fg. Border handling follows WCAG 1.4.11: the communicating borders (the focus ring, plus the stateful border-error / border-success on bg) are hard-checked at 3:1, while the resting decorative borders (border, border-strong on bg) are reported as advisory INFO (decorative, WCAG 1.4.11 exempt) — printed with their ratio but never counted toward the verdict or the exit code, because pure dividers are exempt and WireKit's default palette intentionally sits in that ~1.3–2.5:1 band (see the theming guide's Intentional trade-offs section). Also enabled by setting WIREKIT_DOCTOR_THEME_CONTRAST=1 in the environment.

Exit code 1 when any finding at or above the --fail-on threshold is present. Pair with wirekit:verify in CI to gate on integration health AND a11y in one pass.

Scope. This linter audits two surfaces: the accessibility patterns above in your Blade templates, and — with --theme-contrast — the --color-wk-* token overrides in your app.css. It stops there: contrast inside your own CSS custom classes (e.g. a hand-written .promo-badge { background: …; color: #fff }) is outside its reach, so verify those colors yourself. A green run means the scanned surfaces are clean — not that every color on the page clears AA.

wirekit:list

php artisan wirekit:list
php artisan wirekit:list --category=Form               # Filter to a single category
php artisan wirekit:list --category=Marketing,Display  # Multi-category union (comma-separated)
php artisan wirekit:list --as=count                    # Just the integer count (script-API)
php artisan wirekit:list --as=slugs                    # Newline-separated component names
php artisan wirekit:list --as=categories               # JSON: per-category count map
php artisan wirekit:list --as=json                     # Full JSON manifest (name + tag + category + description)
php artisan wirekit:list --format=json                 # Alias for --as

Prints every component in ComponentRegistry, grouped by category, with a one-line description per component.

Flags:

  • --category=... — narrow the listing to one category. Accepts a comma-separated list (e.g. --category=Marketing,Display) for a multi-category union. Canonical category enum: Form, Layout, Typography, Navigation, Overlay, Display, Marketing, System. Useful when you remember "I need a form input" but not the exact component name.
  • --as=count|slugs|categories|json — emit a machine-readable format instead of the human-readable table. Stable for scripting:
    • count → single integer, no decoration, no trailing newline. WK_COUNT=$(php artisan wirekit:list --as=count).
    • slugs → newline-separated component names, one per line.
    • categories → JSON object mapping each category to its component count.
    • json → array of {name, tag, category, description} objects. Use this when you need the full per-component metadata in a single pipe.
  • --format=... — alias for --as. Matches the --format=json convention used by other Laravel commands; the two flags accept the same value set and must not be passed with different values simultaneously.

Programmatic discovery — PHP

For Laravel apps that need the component catalog at runtime (not via shell):

use Pushery\WireKit\ComponentRegistry;

$count = count(ComponentRegistry::all());
$names = array_keys(ComponentRegistry::all());
$formComponents = ComponentRegistry::category('Form');
$categories = ComponentRegistry::categories();

ComponentRegistry::all() is the canonical PHP-side discovery surface. The CLI --as=... flags above are thin wrappers over the same registry, optimized for shell-script consumption.

wirekit:fonts

php artisan wirekit:fonts
php artisan wirekit:fonts --category=sans     # Filter to a single category
php artisan wirekit:fonts --as=count          # Just the integer count
php artisan wirekit:fonts --as=slugs          # Newline-separated keys
php artisan wirekit:fonts --as=categories     # Newline-separated category names
php artisan wirekit:fonts --as=json           # Full JSON manifest
php artisan wirekit:fonts --format=json       # Alias for --as

Lists every font preset shipped with WireKit, grouped by category (sans / serif / mono). Each row shows the preset key, label, and font-family. The shipped preset keys map 1:1 to the values accepted by wirekit:install --font={key} — copy any key from the listing into the install command.

Flags:

  • --category=... — narrow the listing to one of sans, serif, mono. Unknown categories fail-fast with a Levenshtein-ranked Did-you-mean hint.
  • --as=count|slugs|categories|json — emit a machine-readable format. count for shell-script consumption, slugs for pipe-into-grep, categories for the list of available categories, json for the full per-preset metadata (each entry carries key / label / family / category / install fields).
  • --format=... — alias for --as. Matches the --format=json convention used by other Laravel commands.

Programmatic discovery — PHP

use Pushery\WireKit\Fonts\FontRegistry;

$allFonts = FontRegistry::all();
$sansFonts = FontRegistry::category('sans');
$inter = FontRegistry::get('inter');

FontRegistry is the canonical PHP-side discovery surface; the CLI's --as=... flags are thin wrappers over the same registry.

wirekit:icons

php artisan wirekit:icons
php artisan wirekit:icons --preset=heroicons-marketing   # Filter to one preset
php artisan wirekit:icons --as=count                     # Total alias count
php artisan wirekit:icons --as=presets                   # Newline-separated preset keys
php artisan wirekit:icons --as=aliases                   # Newline-separated unique alias list
php artisan wirekit:icons --as=json                      # Full JSON manifest
php artisan wirekit:icons --format=json                  # Alias for --as

Lists every icon alias shipped with WireKit, grouped by preset (heroicons / heroicons-app / heroicons-marketing / lucide / phosphor / tabler). Each section shows the alias-count summary, the [active] / [opt-in] indicator against your current wirekit.icons.preset / wirekit.icons.presets config, and every alias → Blade-Icon identifier mapping.

Active vs opt-in. Out of the box, heroicons is the only active preset. heroicons-app and heroicons-marketing are extension presets — opt in via wirekit.icons.presets => ['heroicons', 'heroicons-app'] in config/wirekit.php to stack additional alias sets. lucide / phosphor / tabler are alternative base presets — set wirekit.icons.preset => 'lucide' to swap out the heroicons default.

Flags:

  • --preset=... — narrow the listing to one preset. Unknown values fail with a Levenshtein Did-you-mean.
  • --as=count|presets|aliases|json — machine-readable formats:
    • count → total alias count across the (optionally filtered) preset set.
    • presets → newline-separated preset keys.
    • aliases → newline-separated UNIQUE alias list across every selected preset (sorted; useful for "do any presets define bolt?" lookups).
    • json → array of {key, count, active, requires, aliases} entries. The aliases field is the full mapping; requires carries the Composer-package dependency.
  • --format=... — alias for --as.

Programmatic discovery — PHP

use Pushery\WireKit\Icons\Presets\HeroiconsMarketingPreset;
use Pushery\WireKit\Icons\IconResolver;

$marketingAliases = (new HeroiconsMarketingPreset)->icons();
$builtIn = IconResolver::availablePresets();

wirekit:show {name}

php artisan wirekit:show button
php artisan wirekit:show card.body                              # Dotted sub-component
php artisan wirekit:show button --as=json                       # Structured schema as JSON
php artisan wirekit:show button --validate-against=app.blade.php # Lint a developer Blade file

Prints the component's props (with types and defaults), slots, and docs URL. Anti-drift tested — every prop in the Blade @props([...]) block has a registry entry.

Dotted sub-component names (card.body, modal.header, dropdown.item, etc.) resolve directly. The command walks resources/views/components/{parent}/{child}.blade.php, extracts props with the same parser used for top-level components, and emits the same human-readable output (or JSON via --as=json). Useful for IDE tooling that needs the schema for any sub-component without first running wirekit:show <parent> to discover the sub-tree.

Flags:

  • --as=json — emit the component's structured schema as JSON to stdout (no decoration). Includes name, tag, category, description, docs_url, props[] (full prop records with default, default_normalized, comment), and sub_components[]. Use this when your tooling needs the per-component schema without parsing the human-readable output.
  • --validate-against=<path> — read a developer Blade file, find every <x-wirekit::{name} ...> usage in it, and warn when a passed attribute does NOT match a known prop name. The warning includes the closest matching prop (Levenshtein-ranked) so typos like intnetintent surface immediately. Exits 1 on any unknown attribute — wire into pre-commit hooks for a pre-runtime "did I typo a prop?" catch. Skips standard Blade / Alpine / Livewire attributes (class, style, wire:*, x-*, @*, data-*, aria-*).

wirekit:theme {preset}

php artisan wirekit:theme cupertino
php artisan wirekit:theme retro-terminal
php artisan wirekit:theme default      # Remove any existing preset block — return to bundled values

Injects the preset's CSS block from docs/theming.md into your resources/css/app.css. Idempotent — re-running with the same preset is a no-op.

Available presets: default, minimal, soft, material, brutalist, retro-terminal, cupertino. The full list is read from Pushery\WireKit\Theming\ThemePresetRegistry — the single source of truth shared across wirekit:theme, wirekit:install --preset=, and wirekit:export-api-map.

The default preset is a special "stay on the bundled values" entry:

  • If a wirekit:theme start/end block already exists in app.css, it is removed and the bundled defaults take effect again.
  • If no preset block is present, the command succeeds without changes.

Use it as the undo path for an earlier wirekit:theme cupertino (etc.) when you want to clear the preset without manually editing app.css.

Unknown presets exit 1 with a Did-you-mean hint — e.g. wirekit:theme cuprtino suggests cupertino. See Discoverability features for the suggestion semantics.

wirekit:make {name}

php artisan wirekit:make page:dashboard
php artisan wirekit:make page:settings
php artisan wirekit:make page:login

# Recipe scaffolds — each maps to a docs.wirekit.app/blueprints/recipes/<name> page
php artisan wirekit:make recipe:marketing-landing-page
php artisan wirekit:make recipe:documentation-reader
php artisan wirekit:make recipe:live-kpi-strip
php artisan wirekit:make recipe:feature-numbered-marker
php artisan wirekit:make recipe:hero-with-code-aside
php artisan wirekit:make recipe:long-form-article
php artisan wirekit:make recipe:marketing-landing-toc
php artisan wirekit:make recipe:stat-with-sparkline
php artisan wirekit:make recipe:toolbar-filter-bar

Scaffolds a Livewire component class + Blade view pre-wired with WireKit's components.

Page templates (3): page:dashboard, page:settings, page:login produce skeletal Livewire pages with stat-grid, form-stack, and centerd-card patterns respectively.

Recipe templates (9): each recipe:<name> mirrors the corresponding docs/blueprints/recipes/<name>.md page — the scaffold ships a representative skeleton of the recipe's structural composition (e.g. recipe:marketing-landing-page lays out brand-bar + hero + feature-grid + cta + footer). Treat the scaffold as a starting point: expand each section with your copy + assets. Every generated Blade view includes a comment cross-linking to the full reference at https://docs.wirekit.app/blueprints/recipes/<name>.

Unknown templates fail-fast with a Levenshtein-ranked Did-you-mean hint covering both page and recipe families.

wirekit:component {name}

# 1. Implicit base derivation — strip the rightmost dash-segment and
#    verify it's a real WireKit component. `my-button` → `button`.
php artisan wirekit:component my-button

# 2. Explicit base — wins over derivation when both apply.
php artisan wirekit:component my-thing --base=card

# 3. --force overwrites an existing custom/{name}.blade.php.
php artisan wirekit:component my-button --force

# 4. --interactive prompts via choice() when derivation has no clear
#    match. Default ON when stdin is a TTY; pass --no-interaction to
#    suppress in CI.
php artisan wirekit:component customer-dashboard --interactive

Copies a WireKit base component's Blade file to resources/views/components/custom/{name}.blade.php so you can override classes, variants, and slot logic without publishing the entire views/vendor/wirekit/ directory (which copies ~109 files at once).

Flags:

  • --base=<component> — explicit base component to copy from. Wins over the implicit derivation chain below. Pass a flat name (button) or a dotted sub-name (card.header).
  • --force — overwrite an existing resources/views/components/custom/{name}.blade.php. Safe-by-default refuses to overwrite without this flag.
  • --interactive — force the choice() prompt even when stdin TTY detection misfires (Herd / Docker / WSL setups). Default is auto-detect: TTY → on; non-TTY (CI, piped) → off. When the prompt fires, it shows the ranked Levenshtein suggestions (up to 5 closest matches) plus a <cancel> sentinel; pressing return without a selection picks the top suggestion. Picking <cancel> aborts with FAILURE so the user can re-run with explicit --base=. The flag is symmetrical to Symfony's built-in --no-interaction — pass one OR the other, never both.

--base derivation rules (when --base is not passed):

  1. Right-segment strip: strip the rightmost dash-segment of the name and check if it names a real component. my-buttonbutton, custom-cardcard, derived-modalmodal. Verified against the package's blade-component directory.
  2. Levenshtein fallback: if the right-segment isn't a real component, fall back to a closest-match suggestion against ComponentRegistry::all(). Inside a TTY, the command prompts via choice() with the ranked candidates plus a <cancel> sentinel. Outside a TTY (or with --no-interaction), the command exits 1 with the suggestion list — you re-run with explicit --base=.
  3. No match found: the command fails with Could not derive a --base from '{name}'. Pass --base= explicitly. and prints the Did-you-mean suggestion list when one exists.

Worked examples:

# Implicit derivation — strip rightmost dash-segment
php artisan wirekit:component my-button
# Derives --base=button → copies button.blade.php
# Output: "ℹ Derived --base=button from 'my-button'."

# No derivation — name has no parent component to derive from
php artisan wirekit:component customer-dashboard
# Fails with "Could not derive a --base..." plus a Did-you-mean
# suggestion if any close match exists.

After scaffolding, use the component as <x-custom::{name}>.

For lighter customization, use WireKit::personalize() instead — see Customization. Scaffolding via wirekit:component is the right tool when you need to fork the Blade structure itself.

wirekit:publish-icons {preset}

php artisan wirekit:publish-icons heroicons
php artisan wirekit:publish-icons lucide --force

Publishes the SVG directory of a specific icon-set composer package to public/vendor/wirekit/icons/{preset}/. Refuses if the corresponding blade-ui-kit/blade-{preset}-icons (or equivalent) package is not installed and prints the exact composer require line as the fix.

Available presets: heroicons, heroicons-app, heroicons-marketing, lucide, phosphor, tabler.

wirekit:publish-fonts

php artisan wirekit:publish-fonts             # the families config/wirekit.php names
php artisan wirekit:publish-fonts --all       # every bundled family (5.8 MB)
php artisan wirekit:publish-fonts --prune     # …and delete families no longer configured
php artisan wirekit:publish-fonts --force     # overwrite even a family already up to date

Copies the font families named by fonts.sans / fonts.serif / fonts.mono into public/vendor/wirekit/fonts/. A typical two-family setup is roughly 430 KB against 5.8 MB for the whole tree.

Upgrade-safe by default. The command compares the bundled bytes against the published copy and only skips a family that is already up to date — after a composer update that ships new font bytes, an unforced run re-publishes the drifted families automatically (and names each one it updates), so the app stops serving the previous release's fonts. Safe to wire into composer post-autoload-dump. wirekit:verify also flags outdated published fonts, the same freshness check it already runs for wirekit.css / wirekit.js.

Flags:

  • --all — publish every bundled family instead of only the configured ones. The right answer when your app offers a font picker at runtime.
  • --prune — remove published families the config no longer names. Switching a family otherwise leaves the old one in public/ indefinitely, which is how a "slim" publish ends up larger than the all-or-nothing one after a few changes.
  • --force — overwrite unconditionally, even a family that is already up to date. Use it when you have hand-edited a published font file and want the bundled version back.

Why not the per-family publish tags? vendor:publish --tag=wirekit-font-inter works, but it means writing the family name in a second place. Change the font in config and the publish command silently keeps shipping the old one — or nothing. This command reads the config, so the name lives in exactly one place. That matters most for a template: a clone changes one line and its setup script keeps working.

Fonts are served even when they were never published — the package route (/wirekit/fonts/…) reads straight from the installed package. Publishing is a performance choice, not a correctness one: a static file beats a PHP round trip.

wirekit:glass install

php artisan wirekit:glass install

Publishes the Liquid Glass extension CSS to public/vendor/wirekit/wirekit-glass.css and prints the <x-wirekit::glass /> snippet to paste into your layout's <head>. The Liquid Glass extension is opt-in and adds a frosted-glass surface effect to overlay components on top of the Cupertino theme preset.

wirekit:editor-preset {preset}

php artisan wirekit:editor-preset             # prints the `basic` factory
php artisan wirekit:editor-preset full        # prints the `full` factory
php artisan wirekit:editor-preset full --write=resources/js/editor.js
php artisan wirekit:editor-preset --write=resources/js/editor.js --force

Scaffolds the window.wirekitEditor(config) factory that <x-wirekit::editor> calls at Alpine init, pre-wired for a chosen toolbar preset (the legacy window.tiptapEditor name still works as a deprecated alias). The editor ships no engine code — Tiptap is your peer dependency, exposed through this factory — and writing the factory by hand (forwarding every config.* callback, the security-correct Link config, the right extension set) is the one fiddly setup step. This command emits a ready-to-paste version straight from the documented factory contract.

The preset argument is basic (default — bold / italic / strike / link / lists, matching toolbar="basic") or full (adds underline, headings, quote, code block, history, matching toolbar="full"). The full preset additionally needs @tiptap/extension-underline, which StarterKit does not bundle — the emitted npm install line includes it. An unknown preset exits 1 with the valid list.

Flags:

  • --write=<path> — write the snippet to a file (relative to the project root, or an absolute path) instead of printing to stdout.
  • --force — overwrite the --write target if it already exists. Without it, the command refuses an existing file and exits 1.

After scaffolding, the command reminds you which JS bundle registers the editor glue (wirekit.js / wirekit-alpine.js, or wirekit-tiptap.js alongside wirekit.core.js). See the editor docs for the full factory config contract and the editorProps forwarding requirement.

wirekit:export-json

php artisan wirekit:export-json
php artisan wirekit:export-json --pretty
php artisan wirekit:export-json --public

Emits a machine-readable JSON manifest of every WireKit component on stdout: { version, generated_at, components: [{ name, tag, category, description, docs_url, props, slots, sub_components, component_kind }] }.

Flags:

  • --pretty — pretty-print (multi-line) instead of minified output.
  • --public — produces the manifest that docs.wirekit.app serves at its /components.json endpoint. General integrations should omit it; the default emits the full component inventory for your tooling.

The component_kind field disambiguates two distinct composition shapes:

  • "anonymous" — the component is an anonymous Blade file (resources/views/components/<name>.blade.php). Props come from a @props([...]) block; named template slots are valid composition.
  • "class" — the component is a class-based view component (a PHP class extending Illuminate\View\Component). Props come from the constructor signature; the template typically references public class properties as {{ $name }} expressions that are NOT developer-facing template slots. Currently the only class-based component is <x-wirekit-chart>.

Downstream AI tooling should branch on component_kind when generating composition code: anonymous components accept <x-slot:name> slots; class-based components accept only constructor-mapped props.

Consumed by:

  • The /components.json endpoint on docs.wirekit.app
  • AI tooling (Claude Code, ChatGPT Codex, Cursor, Aider, etc.) for prop-aware autocomplete
  • Design-system audits comparing component coverage across releases

The flag set bakes in JSON_HEX_TAG so user-controlled string values cannot break out of any consuming <script type="application/ld+json"> block.

wirekit:export-api-map

php artisan wirekit:export-api-map
php artisan wirekit:export-api-map --pretty
php artisan wirekit:export-api-map --public

Emits an AI-friendly hierarchical sitemap covering every WireKit surface: components, theme presets, font presets, icon presets, layouts, blueprints, recipes, and CLI commands. Superset of wirekit:export-json — designed for MCP servers, Claude Code, ChatGPT Codex, Cursor, Aider, and other AI tooling that needs a single entry point.

Flags:

  • --pretty — pretty-print (multi-line) instead of minified output.
  • --public — produces the sitemap that docs.wirekit.app serves at its /api-map.json endpoint. General integrations should omit it; the default emits the full sitemap for your tooling.

Output shape:

{
  "version": "1.x.x",
  "generated_at": "2026-04-26T15:00:00+00:00",
  "docs_base": "https://docs.wirekit.app",
  "groups": [
    { "id": "components",  "count": <N>, "items": [...] },
    { "id": "themes",      "count": <N>, "items": [...] },
    { "id": "fonts",       "count": <N>, "items": [...] },
    { "id": "icons",       "count": <N>, "items": [...] },
    { "id": "layouts",     "count": <N>, "items": [...] },
    { "id": "blueprints",  "count": <N>, "items": [...] },
    { "id": "recipes",     "count": <N>, "items": [...] },
    { "id": "commands",    "count": <N>, "items": [...] },
    { "id": "helpers",     "count": <N>, "items": [...] },
    { "id": "css-classes", "count": <N>, "items": [...] }
  ]
}

Counts are intentionally elided — the canonical numbers grow with every release. Run php artisan wirekit:export-api-map --pretty | jq '.groups[] | {id, count}' against your installed version for current values, or fetch the live JSON below for the released-at-tag snapshot.

Consumed by:

  • The /api-map.json endpoint on docs.wirekit.app
  • AI agents looking for one place to enumerate every WireKit doc

JSON_HEX_TAG is set so user-controlled string values cannot break out of consuming <script> blocks.

wirekit:class-by-area

php artisan wirekit:class-by-area
php artisan wirekit:class-by-area --format=full
php artisan wirekit:class-by-area --format=json
php artisan wirekit:class-by-area --area=blade --area=compiled

Inventories every Tailwind-class candidate across the five layers WireKit's component output is built from — Blade templates, PHP class strings, JS factory literals, the sample's compiled Tailwind output, and dist/wirekit.css's custom-CSS selectors — and reports both per-area counts and inter-area diffs.

Useful when you want to answer questions like:

  • "Which classes does Blade emit that Tailwind never generates a rule for?"
  • "Which compiled selectors have no source emission anywhere?"
  • "How many wirekit-namespaced custom selectors does dist/wirekit.css ship?"

The default --format=summary output is human-readable per-area counts plus 5 canonical diffs. --format=full prints the first 50 entries of every list. --format=json emits a machine-consumable structured report (integrate into CI dashboards, audit-history pipelines, or downstream tooling).

Flags:

  • --format=summary|full|json — output shape; default is summary
  • --area=blade|php|js|compiled|wirekit-css — restrict the analysis to specific areas (repeatable)

wirekit:cursor-rules

php artisan wirekit:cursor-rules
php artisan wirekit:cursor-rules --force   # overwrite existing

Publishes the package's .cursor/rules/wirekit.mdc file to your project's .cursor/rules/wirekit.mdc. Cursor and other AI editors with native .mdc support automatically pick up the rules for every *.blade.php and *.css file in the project — no manual configuration.

The rules file covers component invocation syntax, the variant system, design tokens, icon usage, layout primitives, accessibility defaults, Livewire integration patterns, browser-support baseline, and the full CLI. Refuses to overwrite an existing copy without --force.

wirekit:mcp-serve

php artisan wirekit:mcp-serve   # spawned by your editor / MCP client over stdio

Runs the WireKit Model Context Protocol (MCP) server. AI coding assistants and MCP clients spawn it as a local child process and talk JSON-RPC 2.0 over stdin/stdout to query the component catalog live while authoring — so the editor reads real prop signatures instead of guessing them.

It is a local, zero-hosting server: no port, no daemon, always version-matched to your installed WireKit. It exposes four read-only tools — search_components, list_components, get_component, and get_tokens — sourced from the shipped component registry and design tokens (nothing leaves your machine). Point your editor's MCP settings at php artisan wirekit:mcp-serve; it is not meant to be run interactively.

wirekit:boost-skills

php artisan wirekit:boost-skills          # write .boost/wirekit.json
php artisan wirekit:boost-skills --force  # overwrite / refresh an existing manifest

Publishes a Laravel Boost skill manifest to .boost/wirekit.json in your project — a typed bundle (every component with its real props + defaults, the theme presets, the customization decision tree, and the CLI) that an AI-augmented editor loads for WireKit-aware autocomplete.

The manifest is auto-generated from the installed package — the component registry, the PropsParser-derived @props, the theme-preset registry, and the registered commands — so it never drifts from your WireKit version. Re-run after upgrading WireKit to refresh it; it refuses to overwrite an existing manifest without --force, and carries a format-version so a future schema revision won't break a manifest you have already committed.