# Magic CLI

The Magic CLI is a `dowel` plugin that ships as part of the magic package, providing `magic:install`, the `make:*` generators and the preview and design commands through magic's bundled `dowel` executable (`dart run magic:dowel`).

- [Introduction](#introduction)
- [Installation](#installation)
- [Project Setup](#project-setup)
    - [install](#install)
- [Make Commands](#make-commands)
    - [make:resource](#makeresource)
    - [make:model](#makemodel)
    - [make:controller](#makecontroller)
    - [make:view](#makeview)
    - [make:repository](#makerepository)
    - [make:action](#makeaction)
    - [make:form](#makeform)
    - [make:test](#maketest)
    - [make:policy](#makepolicy)
    - [make:provider](#makeprovider)
    - [make:middleware](#makemiddleware)
    - [make:enum](#makeenum)
    - [make:event](#makeevent)
    - [make:listener](#makelistener)
    - [make:request](#makerequest)
    - [make:lang](#makelang)
    - [make:component](#makecomponent)
    - [previews:refresh](#previewsrefresh)
    - [design:sync](#designsync)
    - [design:lint](#designlint)
    - [DESIGN.md format](#designmd-format)
- [Related Documentation](#related-documentation)

## Introduction

Magic CLI is the command-line tool for Magic, modelled on Laravel's `php artisan`. It runs on [dowel](https://pub.dev/packages/dowel) and scaffolds controllers, models, views, actions and more with a single command.

## Installation

The Magic CLI ships as a `dowel` plugin bundled with the `magic` package, which exposes its own `dowel` executable. There is no separate install step: run commands via that executable. Once `magic:install` has scaffolded the app's `bin/dispatcher.dart`, `dart run magic:dowel` hands each call to it, so the commands of every plugin registered with `plugin:install` resolve through the same executable (and through `dart run dowel <command>` or the fast wrapper `bin/dowel`).

```bash
dart run magic:dowel <command> [arguments] [options]
```

Magic ships the `dowel` executable in its `pubspec.yaml`, so `dart run magic:dowel` works from any project that depends on magic, with no global activation or package-name substitution.

## Project Setup

### install

Initialises Magic in an existing Flutter project with the recommended directory structure and configuration.

```bash
dart run magic:dowel magic:install
```

This command:
1. Writes the config files: `lib/config/app.dart`, `view.dart` and `routing.dart` always, and `auth.dart`, `network.dart`, `cache.dart` and `logging.dart` unless skipped
2. Creates the starter service providers (`AppServiceProvider`, `RouteServiceProvider`), `lib/app/kernel.dart`, `lib/routes/app.dart` and a welcome view
3. Writes `lib/main.dart` with the Magic bootstrap
4. Creates `.env`, `.env.example` and `assets/lang/en.json`
5. Replaces the default `test/widget_test.dart` with a smoke test
6. Adds the `material_ui` and `wind_kit` dependencies, then has dowel scaffold `bin/dispatcher.dart` and `bin/dowel`, registers magic in `.dowel/plugins.json` and regenerates `lib/app/_plugins.g.dart`

#### Existing `lib/main.dart`

The default `flutter create` counter app is overwritten silently. Any other existing `lib/main.dart` prompts for overwrite, preserve, diff or cancel; with `--non-interactive` the command stops with an error instead.

| Flag | Effect |
|:---|:---|
| `--force` | Overwrite without asking |
| `--preserve` | Inject the Magic bootstrap into the existing `main()`; a synchronous `main()` is rejected with exit 1 |
| `--dry-run` | Print the staged operations without writing |

`--force` and `--preserve` together exit with code 2.

#### Excluding Features

You can exclude features you don't need with `--without-*` flags:

```bash
dart run magic:dowel magic:install --without-auth --without-cache
```

| Flag | What it skips |
|:---|:---|
| `--without-auth` | Auth config, `VaultServiceProvider`, `AuthServiceProvider` |
| `--without-network` | `config/network.dart`, `NetworkServiceProvider` |
| `--without-cache` | `config/cache.dart`, `CacheServiceProvider` |
| `--without-localization` | `LocalizationServiceProvider` |
| `--without-logging` | `config/logging.dart` |

The SQLite layer, encryption, the file picker and real-time broadcasting are separate plugin packages (`magic_local_storage`, `magic_encryption`, `magic_picker`, `magic_socket`), so the installer no longer carries flags for them. Add a plugin with `flutter pub add <package>` then `dart run magic:dowel plugin:install <package>`.

#### The `--with-devtools` flag

The optional debug trio (`magic_devtools` + `tapir` + `crumbs`) gives you the LLM-agent E2E driver (Tapir) and the runtime inspector (Crumbs). Pass `--with-devtools` to wire all three in a single command instead of the manual multi-step bootstrap:

```bash
dart run magic:dowel magic:install --with-devtools
```

When set, after the core install completes the command:

1. Adds `magic_devtools ^1.0.0`, `tapir ^1.0.0`, and `crumbs ^1.0.0` to `dependencies` (not `dev_dependencies`: `lib/main.dart` imports them, and the `!kReleaseMode` gate tree-shakes the subsystem out of release builds).
2. Wires the runtime setup into `lib/main.dart` under `!kReleaseMode` (debug and profile builds carry the tools, so a perf measurement runs on a profile build; release tree-shakes them): it imports `package:flutter/foundation.dart` (`show kReleaseMode`), `package:crumbs/crumbs.dart`, `package:magic_devtools/crumbs.dart`, `package:magic_devtools/magic_devtools.dart`, `package:magic_devtools/tapir.dart`, and `package:tapir/tapir.dart`; before `Magic.init(` it calls `TapirPlugin.install()`, `CrumbsPlugin.install()`, `CrumbsPlugin.registerWatcher(ExceptionWatcher())`, `CrumbsPlugin.registerWatcher(DumpWatcher())`, and `MagicPerfIntegration.install()`; after `Magic.init(` it calls `MagicCrumbsIntegration.install()` and `MagicTapirIntegration.install()`.

The wiring is idempotent and decided by call presence: an app already calling `MagicDevtools.installPre(` is left untouched, and a block whose call (`TapirPlugin.install(`, `CrumbsPlugin.install(`, `MagicPerfIntegration.install(`, `MagicTapirIntegration.install(`, `MagicCrumbsIntegration.install(`) is already in `lib/main.dart` is not written again, so re-running `magic:install --with-devtools` or running it after hand wiring never duplicates a watcher, a block or a dependency entry. It writes `MagicPerfIntegration`, not the `MagicDevtools` umbrella (`MagicDevtools.installPre()` / `installPost()` is the alternative to this wiring: do not mix the two). Then finish the setup by hand:

```bash
flutter pub get
dart run magic:dowel plugin:install tapir
dart run magic:dowel plugin:install crumbs
dart run magic:dowel tapir:install
dart run magic:dowel crumbs:install
dart run magic:dowel mcp:install
```

`mcp:install` surfaces the `tapir_*` and `crumbs_*` MCP tools. `tapir:install` and `crumbs:install` write single-tool blocks only, never `MagicDevtools` or `MagicPerfIntegration`, and each skips a block whose `TapirPlugin.install(` or `CrumbsPlugin.install(` call is already in `lib/main.dart`, so running them after `--with-devtools` writes nothing twice.

## Make Commands

All `make:*` commands support the `--force` flag to overwrite existing files. Nested paths are supported via slash syntax (e.g., `Admin/Dashboard`), which creates subdirectories automatically.

Commands that auto-append a suffix (Controller, View, Policy, ServiceProvider, Request, Repository, FormObject) handle duplicates gracefully: `make:controller UserController` will not produce `UserControllerController`.

`make:controller`, `make:view`, `make:repository`, `make:action`, `make:form` and `make:request` accept `--test`, which chains [make:test](#maketest) so the matching test lands in the same run. `--force` on the command forwards to the chained test, and a refused test write fails the command with exit 1.

### make:resource

Scaffolds a full CRUD vertical for one model, magic's analogue of Laravel's `make:model --all`:

```bash
dart run magic:dowel make:resource Monitor
dart run magic:dowel make:resource Monitor --no-views
dart run magic:dowel make:resource Monitor --no-model
dart run magic:dowel make:resource Monitor --force
```

For `Monitor` it writes, each through its own generator:

- the model, and its factory when `magic_local_storage` is installed (both kept when they already exist)
- `MonitorRepository`
- the `CreateMonitor`, `UpdateMonitor` and `DeleteMonitor` actions under `lib/app/actions/monitors/`
- `StoreMonitorRequest` and `UpdateMonitorRequest`
- `MonitorFormObject` (the `--resource` form)
- `MonitorController` (`--resource --actions`)
- the `MonitorsListView` and `MonitorFormView` views
- tests for the actions, the form and the controller

The run is all-or-nothing: every target path is checked first, and any clash other than a kept model or factory fails the run with nothing written unless `--force` is passed. The index and create route lines are printed for your `RouteServiceProvider.boot()`; the command never edits it.

#### Options

| Option | Description |
|:---|:---|
| `--no-views` | Stop after the data and write layers (no views, no printed routes) |
| `--no-model` | Leave the model and factory out |

### make:model

Creates an Eloquent-style model with optional related files:

```bash
dart run magic:dowel make:model User
dart run magic:dowel make:model Post --migration --controller --factory
dart run magic:dowel make:model Comment -mcf
dart run magic:dowel make:model Product -mcfsp
dart run magic:dowel make:model Order --all
```

#### Options

| Option | Shortcut | Description |
|:---|:---|:---|
| `--migration` | `-m` | Create a database migration (needs `magic_local_storage`) |
| `--controller` | `-c` | Create a controller |
| `--factory` | `-f` | Create a model factory (needs `magic_local_storage`) |
| `--seeder` | `-s` | Create a database seeder (needs `magic_local_storage`) |
| `--policy` | `-p` | Create an authorisation policy |
| `--all` | `-a` | Create migration, seeder, factory, policy, repository, and resource controller |

> [!NOTE]
> The migration, factory and seeder generators ship with the `magic_local_storage` plugin. Without it, each of those flags prints a hint naming the package and the rest of the run carries on.
>
> The `-mcfsp` shorthand combines all five flags: migration, controller, factory, seeder, and policy. The `--all` flag also writes the model's repository and makes the controller a `--resource --model=<Model>` controller reading through it. For the write layer and views as well, use [make:resource](#makeresource).

The model carries a static `fromMap(Map<String, dynamic>)` that hydrates it from raw API data. The command exits 1 when the model already exists and `--force` was not passed, without generating any companion.

**Output:** `lib/app/models/<name>.dart`

### make:controller

Creates a `MagicController` with a `Magic.findOrPut` singleton accessor that implements `SessionScoped`:

```bash
dart run magic:dowel make:controller User
dart run magic:dowel make:controller UserController
dart run magic:dowel make:controller Admin/Dashboard
dart run magic:dowel make:controller Post --resource
dart run magic:dowel make:controller Post --resource --model=Post --actions
dart run magic:dowel make:controller Uptime --timers --test
```

A `--resource` controller owns the read state as one `RepositoryQuery` over `<Model>Repository`: it exposes `items`, `ensureFresh()` (for a view's `RefetchesOnMount`) and `reload()`, and its `resetForSession()` clears the repository and refetches. Writes belong on a `MagicAction`, not on the controller.

#### Options

| Option | Shortcut | Description |
|:---|:---|:---|
| `--resource` | `-r` | Own a `RepositoryQuery` over the model's repository |
| `--model` | `-m` | The model a `--resource` controller reads (defaults to the controller's own name) |
| `--actions` | | Mix in `RunsActions` |
| `--timers` | | Mix in `OwnsTimers` |
| `--validates` | | Mix in `ValidatesRequests` and `CollapsesIndexedErrorKeys` |
| `--test` | | Also write the matching controller test |

The mixins are always written in one fixed order, whatever order the flags were passed in.

**Output:** `lib/app/controllers/<name>_controller.dart`

### make:view

Creates a view class: a `StatelessWidget` by default, or a `MagicStatefulView<T>` bound to a controller:

```bash
dart run magic:dowel make:view Login
dart run magic:dowel make:view LoginView
dart run magic:dowel make:view Auth/Register
dart run magic:dowel make:view Dashboard --stateful
dart run magic:dowel make:view Monitor --controller=Monitor
dart run magic:dowel make:view Monitors/List --controller=Monitor --list --form=MonitorFormObject
```

#### Options

| Option | Description |
|:---|:---|
| `--stateful` | Bind a `MagicStatefulView` to the controller derived from the view's name (`Dashboard` -> `DashboardController`), which has to exist |
| `--controller` | Bind the view to this controller (suffix optional); implies `--stateful` |
| `--list` | Add `RefetchesOnMount`; expects a `--resource` controller, which exposes `ensureFresh()` |
| `--form` | Add a State-owned form object field (suffix optional), disposed in `onClose`; implies `--stateful` |
| `--test` | Also write the matching view test |

**Output:** `lib/resources/views/<name>_view.dart`

### make:repository

Creates a `Repository<T>` subclass with a static `instance`, the row cache every screen reading the model shares:

```bash
dart run magic:dowel make:repository Monitor
dart run magic:dowel make:repository MonitorRepository --test
```

**Output:** `lib/app/repositories/<name>_repository.dart`

### make:action

Creates a `MagicAction`, the one place a write lives:

```bash
dart run magic:dowel make:action PauseMonitor
dart run magic:dowel make:action Monitors/PauseMonitor --test
dart run magic:dowel make:action Monitors/CreateMonitor --kind=create --model=Monitor
dart run magic:dowel make:action Monitors/UpdateMonitor --kind=update --model=Monitor
dart run magic:dowel make:action Monitors/DeleteMonitor --kind=delete --model=Monitor
```

Without `--kind` the action is an empty `handle()` skeleton. The write kinds:

- `create` fills and saves a new model from a validated field map.
- `update` takes `({String id, Map<String, dynamic> fields})`, saves the edit and writes it into `<Model>Repository`, answering null when the id no longer resolves.
- `delete` deletes the model and evicts it from `<Model>Repository`.

A refused save throws `ActionRequestFailed` (a `ValidationException` when the model carries field errors).

#### Options

| Option | Description |
|:---|:---|
| `--kind` | `create`, `update` or `delete`; requires `--model` |
| `--model` | The model the action writes |
| `--test` | Also write the matching action test |

**Output:** `lib/app/actions/<name>.dart`

### make:form

Creates a `MagicFormObject` (the `FormObject` suffix is appended; form widgets keep the `Form` name):

```bash
dart run magic:dowel make:form Monitor
dart run magic:dowel make:form Monitor --request=StoreMonitorRequest
dart run magic:dowel make:form Monitor --resource=Monitor
```

`--resource=<Model>` writes the full create/edit contract: an `editing` field, `initial` seeded from `editing?.toArray()`, a `request` choosing the Store or Update request, and a `persist` running `Create<Model>` or `Update<Model>`. After a create it reloads the `--resource` `<Model>Controller`, so it expects the controller [make:resource](#makeresource) writes beside it.

#### Options

| Option | Description |
|:---|:---|
| `--request` | The `FormRequest` class the form validates against |
| `--resource` | The model the form creates and edits |
| `--test` | Also write the matching form test |

**Output:** `lib/app/forms/<name>_form_object.dart`

### make:test

Creates a test skeleton mirroring where another generator writes its class, from `lib/` to `test/`:

```bash
dart run magic:dowel make:test Monitor --kind=controller
dart run magic:dowel make:test Monitors/PauseMonitor --kind=action
dart run magic:dowel make:test Monitor --kind=repository --force
```

The test imports the class as `package:<name>/...`, with `<name>` read from the project's `pubspec.yaml`.

#### Options

| Option | Description |
|:---|:---|
| `--kind` | `controller`, `action`, `form`, `repository`, `request`, `view` or `unit` |

**Output:** for example `test/app/controllers/<name>_controller_test.dart`

### make:policy

Creates an authorisation policy:

```bash
dart run magic:dowel make:policy Post
dart run magic:dowel make:policy PostPolicy
dart run magic:dowel make:policy Post --model=Post
dart run magic:dowel make:policy Admin/Dashboard
```

#### Options

| Option | Shortcut | Description |
|:---|:---|:---|
| `--model` | `-m` | The model the policy applies to |

**Output:** `lib/app/policies/<name>_policy.dart`

### make:provider

Creates a service provider class with `register()` and `boot()` stubs:

```bash
dart run magic:dowel make:provider Payment
dart run magic:dowel make:provider PaymentServiceProvider
```

The `ServiceProvider` suffix is appended automatically when omitted.

**Output:** `lib/app/providers/<name>_service_provider.dart`

### make:middleware

Creates a middleware class:

```bash
dart run magic:dowel make:middleware EnsureAuthenticated
dart run magic:dowel make:middleware Admin/RoleCheck
```

**Output:** `lib/app/middleware/<name>.dart`

### make:enum

Creates a string-backed enum with a `value`, a `label` and a `fromValue()` factory:

```bash
dart run magic:dowel make:enum MonitorType
dart run magic:dowel make:enum Status/OrderStatus
dart run magic:dowel make:enum IncidentSeverity --wire
```

`--wire` writes an enum mirroring a backend string value instead: an `unknown` fallback case, a `fromWire()` factory that never throws on an unrecognised value, and a `trans()`-backed `label` getter.

**Output:** `lib/app/enums/<name>.dart`

### make:event

Creates a dispatchable event class that extends `MagicEvent`:

```bash
dart run magic:dowel make:event UserLoggedIn
dart run magic:dowel make:event Auth/TokenRefreshed
```

**Output:** `lib/app/events/<name>.dart`

### make:listener

Creates an event listener class that extends `MagicListener<TEvent>`:

```bash
dart run magic:dowel make:listener AuthRestore
dart run magic:dowel make:listener AuthRestore --event=UserLoggedInEvent
dart run magic:dowel make:listener Auth/RestoreSession
```

#### Options

| Option | Shortcut | Description |
|:---|:---|:---|
| `--event` | `-e` | The event class the listener handles (defaults to `MagicEvent`) |

**Output:** `lib/app/listeners/<name>.dart`

### make:request

Creates a `FormRequest` subclass with a `const` constructor and a `rules()` override, which `MagicFormObject.request` and `ValidatesRequests.validateRequest` both accept:

```bash
dart run magic:dowel make:request StoreMonitor
dart run magic:dowel make:request StoreMonitorRequest --test
```

The `Request` suffix is appended automatically when omitted.

**Output:** `lib/app/validation/requests/<name>_request.dart`

### make:lang

Creates a language JSON file:

```bash
dart run magic:dowel make:lang tr
dart run magic:dowel make:lang es
dart run magic:dowel make:lang de --from=tr
```

`--from=<locale>` (default `en`) copies that file's key tree with each value verbatim, a complete catalogue for a translator; when it does not exist the new file is `{}`.

**Output:** `assets/lang/<locale>.json`

### make:component

Scaffolds an atomic component folder under `lib/ui/components/<name>/`, plus its widget test:

```bash
dart run magic:dowel make:component Avatar
dart run magic:dowel make:component Avatar --variants=intent,size
dart run magic:dowel make:component Panel --slots
dart run magic:dowel make:component Badge --no-preview
```

**Output** (for `Avatar`):

- `lib/ui/components/avatar/avatar.dart` (`class Avatar`, unprefixed PascalCase)
- `lib/ui/components/avatar/avatar.recipe.dart` (a `WindRecipe`, or a `WindSlotRecipe` under `--slots`, seeded with the requested `--variants` axes)
- `lib/ui/components/avatar/index.dart` (re-exports the component + recipe, NOT the preview)
- `test/ui/components/avatar/avatar_test.dart` (imports the barrel with a prefix, so a name like `Badge` stays unambiguous)
- `lib/ui/components/avatar/avatar.preview.dart` (a single public `AvatarPreview` matrix), only when the project already keeps a preview catalogue

The preview file, and the chained `previews:refresh` that lands it in `_previews.g.dart`, are written only when the project already has a `*.preview.dart` file or a `_previews.g.dart` index under `lib/`. `--preview` or `--no-preview` overrides that detection.

#### Options

- `--variants=a,b`: seed the named variant axes into the recipe (values left empty to fill in).
- `--slots`: scaffold a multi-part `WindSlotRecipe` instead of a single-element `WindRecipe`.
- `--preview` / `--no-preview`: force the preview file on or off.
- `--force`: overwrite an existing component.

### previews:refresh

Regenerates the dev-only preview catalog index from `*.preview.dart` files:

```bash
dart run magic:dowel previews:refresh
dart run magic:dowel previews:refresh --path=lib/ui/components
```

**Output:** `<scan-dir>/_previews.g.dart` (default scan dir `lib`).

Each `*.preview.dart` file must declare exactly ONE public `*Preview` class. The command validates the class name, fails fast on a slug collision, sorts deterministically, and writes atomically. The generated file returns a `List<PreviewEntry>` from the `previewEntries()` function (never a top-level const list) so the catalog tree-shakes from release builds. Feed it to the catalog via `MagicPreview.register(previewEntries())` (from `magic_devtools`).

#### Options

- `--path=DIR`: directory to scan for `*.preview.dart` files (default `lib`).

### design:sync

Generates the wind theme (semantic aliases + brand seed) from a `DESIGN.md`:

```bash
dart run magic:dowel design:sync
dart run magic:dowel design:sync --input=DESIGN.md --output=lib/config/wind_theme.g.dart
```

**Output:** a Dart source file exposing a `Map<String, String> designAliases` and a `Map<String, MaterialColor> designColors`. The aliases map carries the property-prefixed semantic keys (`bg-surface`, `text-fg`, `border-color-border`, ...) with arbitrary-hex light + `dark:` pairs (`'bg-surface': 'bg-[#f9f9ff] dark:bg-[#0f1419]'`), drop-in for `WindThemeData(aliases: designAliases)`. The brand `primary` `MaterialColor` carries a generated 50-900 ramp (seeded from the DESIGN.md `primary` light hex) for `WindThemeData.toThemeData()` Material interop.

The command is idempotent (byte-identical output on re-run for an unchanged DESIGN.md) and writes atomically via `.tmp` + rename. Do not hand-edit the generated file; re-run `design:sync` instead.

#### Options

- `--input=PATH`: path to the DESIGN.md source, relative to the project root (default `DESIGN.md`).
- `--output=PATH`: path for the generated wind theme file (default `lib/config/wind_theme.g.dart`).

### design:lint

Validates a `DESIGN.md` against the design rules:

```bash
dart run magic:dowel design:lint
dart run magic:dowel design:lint --input=DESIGN.md
```

The command exits nonzero only on an error-severity finding (a broken reference). Warnings and info notes are reported but do not fail the lint. Rules:

- **broken-ref** (error): a component references a token (`{colors.x}`, `{rounded.x}`, `{spacing.x}`) that does not resolve.
- **missing-primary** (warning): colours are defined but `primary` is absent.
- **unknown-key** (warning): a top-level YAML key looks like a typo of a schema key. The single-file `dark:` overlay lives inside `colors`, so it is never flagged.
- **section-order** (warning): markdown `##` sections appear out of canonical order.
- **missing-sections** (info): the optional `spacing` / `rounded` groups are absent.
- **orphaned-tokens** (warning): a custom colour token is defined but never referenced by any component (Material Design 3 baseline families are exempt).
- **contrast-ratio** (warning): a component `backgroundColor` / `textColor` pair falls below the WCAG AA minimum of 4.5:1.

#### Options

- `--input=PATH`: path to the DESIGN.md to validate, relative to the project root (default `DESIGN.md`).

### DESIGN.md format

`DESIGN.md` is the single source of truth for the app theme: a YAML front matter (machine-readable design tokens) followed by a markdown body (human-readable rationale; ignored by `design:sync`).

```markdown
---
name: Acme
colors:
  surface:
    light: "#f9f9ff"   # single-file dark: overlay per role
    dark: "#0f1419"
  fg:
    light: "#151c27"
    dark: "#e6e9f0"
  primary:
    light: "#7c3aed"   # the brand seed for the MaterialColor ramp
    dark: "#a78bfa"
  on-primary: "#ffffff"  # a bare hex is light-only (dark mirrors light)
typography:
  body-md:
    fontFamily: Plus Jakarta Sans
    fontSize: 16px
rounded:
  md: 8px
spacing:
  md: 16px
components:
  button-primary:
    backgroundColor: "{colors.primary}"   # {group.token} reference
    textColor: "{colors.on-primary}"
    rounded: "{rounded.md}"
    padding: "{spacing.md}"
---

## Overview
...
## Colors
...
```

Each colour role is either a bare hex scalar (light only; dark mirrors light) or a `{ light, dark }` overlay map. The semantic roles map onto the wind alias keys as: `surface`/`surface-container`/`surface-container-high` -> `bg-surface*`; `fg` (or `on-surface`)/`fg-muted`/`fg-disabled` -> `text-fg*`; `primary`/`on-primary`/`primary-container` -> `bg-primary` / `text-on-primary` / `bg-primary-container`; `accent` -> `bg-accent`; `border`/`border-subtle` -> `border-color-border*`; `destructive`/`on-destructive`/`destructive-container` -> `bg-destructive` / `text-on-destructive` / `bg-destructive-container`; `success`/`warning` -> `bg-success` / `bg-warning`.

This is a wind-flavored superset of the open DESIGN.md format: the single-file `dark:` overlay is the deliberate divergence that lets one document drive both light and dark wind aliases.

## Related Documentation

- [Installation](https://anilcancakir.com/magic/docs/getting-started/installation.md)
- [Directory Structure](https://anilcancakir.com/magic/docs/getting-started/directory-structure.md)
- [Service Providers](https://anilcancakir.com/magic/docs/getting-started/service-providers.md)
- [Repositories](https://anilcancakir.com/magic/docs/eloquent/repositories.md)
- [Authorization](https://anilcancakir.com/magic/docs/security/authorization.md)
