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/wirekitentry in your.gitignore. Use this when your deploy pipeline does NOT runvendor:publish --tag=wirekit-assets --forceand 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 inconfig/wirekit.phpcharts.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 thewirekit:doctorreminder when the tier iscommercialoroem. 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 inapp.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.logbefore-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:
- Publishes
config/wirekit.php(overridable defaults for every component) - Publishes
dist/wirekit.cssanddist/wirekit.jstopublic/vendor/wirekit/ - Adds
public/vendor/wirekit/to your.gitignore - Prints the layout snippet to paste into your Blade master view
- When
--font=<key>is passed: publishes the bundled font CSS topublic/vendor/wirekit/fonts/and injects an idempotent override block intoresources/css/app.csssetting 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=cupertinoalone disables prompts) --no-interactionis 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.packagecovers the WireKit install itself (asset publishing / config / directives / Tailwind source / token alignment / Alpine cleanup — checks 1–14 below).environmentcovers 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 missingpublic/vendor/wirekit/*.{css,js}assets by runningvendor:publish --tag=wirekit-assets --forceand re-checking. Useful right after a fresh clone (wherepublic/vendor/wirekit/is.gitignoredand 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--fixalternative 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)
- Assets published (
wirekit.css/wirekit.jsinpublic/vendor/wirekit/) - Asset freshness (md5 hash matches package source)
- Tailwind
@sourcedirective scanning the package views - Config file published (
config/wirekit.php) - Blade directives present (
@wirekitStyles+@wirekitScripts) - Alpine.js available (skipped on Livewire v4+ which bundles Alpine)
- Bundle config valid (
scripts.bundleisfullorcore) - Published views not stale (warns if
views/vendor/wirekit/exists with file count) - Font assets published when a custom font preset is configured
- CSS
@importanti-pattern detection (warn ifwirekit.cssis@import-ed inapp.css) - Optional dependencies (Chart.js adapter, bacon-qr-code)
- 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, …). Skipsvar(...)references. - 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. - 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 adestroy()lifecycle method, AND adisconnect()call inside an observer callback without a preceding null-guard. Both produce silentTypeErrorconsole errors after Livewire morph / conditional render / SPA navigation. Respects a// wirekit-doctor: cleanup-okopt-out comment marker for intentional patterns the heuristic doesn't recognize.
Environment-tier checks (run with default or --tier=environment)
- Compiled-views freshness — detects when
resources/views/mtimes exceedstorage/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 actionablephp artisan view:clearfix. 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 carryaria-label→ ERROR (WCAG 2.1 "Buttons must have discernible text").- Any element with
role="dialog"orrole="alertdialog"that doesn't carryaria-labeloraria-labelledby→ ERROR (WCAG 4.1.2 + ARIA APG dialog pattern). - Any element with
role="img"that doesn't carryaria-labeloraria-labelledby→ ERROR (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, parsesresources/css/app.cssfor--color-wk-*token overrides under:rootand.darkblocks (accepting both the bare and:where(...)wrapped selector forms), then computes WCAG 2.1 contrast ratios for the canonical token pairings (accentas text onbg,accent-fgonaccent— the primary-button label pairing —text-mutedonbg,danger-fgondanger, etc.). Reports PASS / WARN / FAIL / EXEMPT per pairing × mode. Catches the bug class where a developer customizes--color-wk-accentwithout 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 focusring, plus the statefulborder-error/border-successonbg) are hard-checked at 3:1, while the resting decorative borders (border,border-strongonbg) are reported as advisoryINFO (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 settingWIREKIT_DOCTOR_THEME_CONTRAST=1in 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=jsonconvention 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 ofsans,serif,mono. Unknown categories fail-fast with a Levenshtein-ranked Did-you-mean hint.--as=count|slugs|categories|json— emit a machine-readable format.countfor shell-script consumption,slugsfor pipe-into-grep,categoriesfor the list of available categories,jsonfor the full per-preset metadata (each entry carrieskey/label/family/category/installfields).--format=...— alias for--as. Matches the--format=jsonconvention 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 definebolt?" lookups).json→ array of{key, count, active, requires, aliases}entries. Thealiasesfield is the full mapping;requirescarries 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). Includesname,tag,category,description,docs_url,props[](full prop records withdefault,default_normalized,comment), andsub_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 likeintnet→intentsurface 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/endblock already exists inapp.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 existingresources/views/components/custom/{name}.blade.php. Safe-by-default refuses to overwrite without this flag.--interactive— force thechoice()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):
- Right-segment strip: strip the rightmost dash-segment of the name and check if it names a real component.
my-button→button,custom-card→card,derived-modal→modal. Verified against the package's blade-component directory. - 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 viachoice()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=. - 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 inpublic/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--writetarget if it already exists. Without it, the command refuses an existing file and exits1.
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.jsonendpoint. 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 extendingIlluminate\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.jsonendpoint 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.jsonendpoint. 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.jsonendpoint 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 issummary--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.