RemixRemix

Open Code

Install editable Remix component source into your app with the remix CLI

For a guided walkthrough with screenshots and runnable sample projects, start with Build a settings screen. This page is the command and configuration reference.

Open code copies a theme and component recipes into your application. From that moment your team owns those files: no wrapper, no subclass, and no package-level theme override standing between you and the source. Choose the small vanilla preset or the full Radix Themes-inspired fortal preset when you initialize the project.

Remix keeps everything that is genuinely hard: rendering, pointer and keyboard handling, focus management, accessibility semantics, and the loading/disabled interaction rules. The installed file only decides what things look like.

remix_cli has not been published. The hosted installation commands below apply after its first release. Until then, use the checkout installation described in the CLI README. The CLI has its own version and release schedule. Fortal preset does not add a remix_fortal dependency.

Choose a preset

vanillafortal
Design languageCompact neutral starting pointRadix Themes 3.3.0 parity surface
Theme15 semantic tokens277 tokens, Radix color scales, scaling, radius, and panel modes
Component axesSmall default vocabularyFortal's classic, solid, soft, surface, outline, and ghost vocabulary where applicable
Best forA house system you intend to shapeStarting from a complete Radix-like system

Both choices install local Dart under lib/, use Remix for behavior, and use the same add --diff / add --overwrite review workflow. They cannot be mixed inside one initialized source tree because their tokens and variant vocabularies are different.

Install

Before the first release, add the CLI from a checkout:

dart pub add "dev:remix_cli@{path: /path/to/remix/packages/remix_cli}"

Until Remix beta.10 is published, add this temporary pubspec_overrides.yaml to the application. Replace the path with your checkout:

dependency_overrides:
  remix:
    path: /path/to/remix/packages/remix

After both releases are available, remove this override and use the hosted installation below. Both presets require Remix ^1.0.0-beta.10.

Add the CLI as a project-local dev dependency so its version is pinned in your lockfile, not in a machine-global install:

flutter pub add dev:remix_cli

Running the CLI

The command is called remix. How you reach it depends on how it is installed:

# Project-local dev dependency (recommended)
dart run remix_cli:remix <command>

# Global install
dart pub global activate remix_cli
remix <command>

Prefer the project-local form to pin the CLI. Registry content is pinned independently to a GitHub commit in remix.yaml. Neither CLI upgrades nor ordinary installs advance that pin.

The examples below are written as remix <command> to match the tool's own usage output. If you are using the project-local form, prefix each one with dart run remix_cli:, for example dart run remix_cli:remix init.

$ remix --help
Install editable Remix UI source.

Usage: remix <command> [arguments]

Global options:
-h, --help       Print this usage information.
    --version    Print the remix_cli version.

Available commands:
  add        Install registry items and their dependencies.
  init       Initialize Remix source installation settings.
  registry   Register and pin GitHub registry sources.

Run "remix help <command>" for more information about a command.

1. Initialize

remix init --preset vanilla

This writes two files and nothing else:

  • remix.yaml — your prefix, preset, and UI path
  • lib/ui/ui.dart — a managed barrel with an export marker block
# remix.yaml
schema: 3
prefix: Ui
preset: vanilla
paths:
  ui: lib/ui
defaultRegistry: "@remix"
registries:
  "@remix":
    repository: btwld/remix
    path: registry
    ref: registry-stable
    revision: "<resolved-full-commit-sha>"

Choose the naming and location up front, because the prefix is baked into every identifier the CLI renders:

remix init --prefix Acme --preset fortal --ui-path lib/design_system

--prefix Acme produces identifiers such as AcmeButton and acmeButtonStyle. The prefix must be an UpperCamel Dart identifier whose lowercased form is not a reserved word, and the UI path must live under lib/. The prefixes Remix and Mix are reserved for runtime dependencies. The preset defaults to vanilla when omitted.

init is also a repair command. Run it again and it recreates whichever of the two files is missing, telling you exactly which one it touched:

Created remix.yaml; preserved lib/ui/ui.dart.

2. Preview before you write

Never let a generator surprise you. Both preview modes run the full preflight (path safety, dependency sections, registry resolution) and then stop before any file is written or any process runs.

remix add button --dry-run
Items: theme -> button
Dependencies: remix@^1.0.0-beta.10, mix_annotations@^2.2.0-beta.1, dev:build_runner@^2.10.1, dev:mix_generator@^2.2.0-beta.3
theme: missing; lib/ui/theme/tokens.dart, lib/ui/theme/theme_data.dart, lib/ui/theme/theme_scope.dart
button: missing; lib/ui/components/button.dart
Exports: theme/tokens.dart, theme/theme_data.dart, theme/theme_scope.dart, components/button.dart
Generated: lib/ui/components/button.g.dart

For the actual source, use --diff, which renders the proposed files, formats them, and shows a real git diff against what you have:

remix add button --diff

3. Add

remix add button

Button depends on Theme in the registry, so both are installed, dependencies first. The command then runs a fixed sequence and stops at the first failure:

  1. flutter --version --machine — requires Flutter 3.44+
  2. flutter pub add — only for requirements you are actually missing
  3. flutter pub get, then verify the resolved versions in pubspec.lock
  4. Write the authored files and update the managed barrel
  5. dart format the files it wrote
  6. dart run build_runner build --build-filter=... — scoped to the generated targets only
  7. dart analyze lib/ui
Added theme.
Added button.
Generated lib/ui/components/button.g.dart.

Then use it like any widget:

import 'package:flutter/widgets.dart';

import 'ui/ui.dart';

class SignUpButton extends StatelessWidget {
  const SignUpButton({super.key, required this.onPressed});

  final VoidCallback onPressed;

  @override
  Widget build(BuildContext context) {
    return UiButton.primary(label: 'Create account', onPressed: onPressed);
  }
}

Configuration

remix.yaml contains project settings and pinned named registry sources:

schema: 3
prefix: Ui       # type prefix for every generated identifier
preset: vanilla  # selected across every configured registry
paths:
  ui: lib/ui     # where installed source lives
defaultRegistry: "@remix"
registries:
  "@remix":
    repository: btwld/remix
    path: registry
    ref: registry-stable
    revision: "<resolved-full-commit-sha>"
KeyDefaultRules
schema3The only readable schema. Schemas 1–2 shipped in earlier prereleases and named no registry; such a project is reinitialized, not migrated.
prefixUiASCII UpperCamel Dart identifier. Its lowercased form must not be a Dart reserved word. Remix and Mix are reserved for runtime dependencies.
presetvanillaPreset selected across every configured registry. Choose vanilla or fortal at init.
defaultRegistry@remixConfigured namespace for bare item names.
registriesofficial GitHub sourceEach namespace records repository, path, requested ref and full commit revision.
paths.uilib/uiProject-relative, normalized, no traversal, must be under lib/. Symlinks that escape the package root are rejected.

Unknown keys are an error rather than a warning, so a typo fails loudly instead of silently reverting to a default:

$ remix init
FormatException: configuration has unknown keys: style.

The prefix drives two identifier casings at once. With prefix: Acme you get the type AcmeButton and the function acmeButtonStyle.

Choose prefix, preset, and paths.ui before your first add. The CLI will not rename, restyle, or move source it has already installed.

Running init with different values against an existing remix.yaml is a hard error, not a migration.

Editing remix.yaml by hand afterwards is worse, because installed state is tracked by file path, not by content. remix add button would still see lib/ui/components/button.dart on disk, report Preserved button., and leave the old prefix in place. To actually change a prefix you must rename the identifiers yourself, or delete the installed files and reinstall.

For example, an init that conflicts with the existing configuration reports:

FormatException: Existing remix.yaml does not match the requested prefix, preset, and UI path.

What lands in your app

lib/ui/
├── ui.dart                     # managed barrel — CLI owns the marker block
├── theme/
│   ├── tokens.dart             # token surface the recipe reads
│   ├── theme_data.dart         # light() / dark() / copyWith()
│   └── theme_scope.dart        # inherited scope
└── components/
    ├── button.dart             # the recipe — yours to edit
    └── button.g.dart           # generated adapter — do not edit

Every later add drops one more pair into components/ and extends the barrel's marker block. Existing authored source stays untouched. The focused build also includes every installed generated adapter, so a dependency change cannot remove an earlier generated part.

button.dart is a styler function plus two enums:

import 'package:flutter/widgets.dart';
import 'package:mix_annotations/mix_annotations.dart';
import 'package:remix/remix.dart';

enum UiButtonVariant { primary, secondary, outline, ghost, destructive }

enum UiButtonSize { small, medium, large }

@MixWidget(target: RemixButton.new)
ButtonStyler uiButtonStyle({
  UiButtonVariant variant = UiButtonVariant.primary,
  UiButtonSize size = UiButtonSize.medium,
  ButtonStyler style = const ButtonStyler.create(),
}) {
  return _base(size)
      .merge(_variantStyle(variant))
      .onDisabled(
        ButtonStyler().wrap(WidgetModifierConfig.opacity(0.5)),
      )
      .merge(style);
}

ButtonStyler _base(UiButtonSize size) => ButtonStyler().minHeight(
  switch (size) {
    UiButtonSize.small => 32,
    UiButtonSize.medium => 36,
    UiButtonSize.large => 40,
  },
);

ButtonStyler _variantStyle(UiButtonVariant variant) => switch (variant) {
  UiButtonVariant.primary => ButtonStyler().color(const Color(0xFF171717)),
  _ => ButtonStyler(),
};

@MixWidget generates UiButton into button.g.dart, including one named constructor per variant (UiButton.primary, .secondary, .outline, .ghost, .destructive).

The Fortal preset

Initialize Fortal once, then use the same item commands and ownership workflow:

remix init --prefix Acme --preset fortal
remix add button

The application receives AcmeScope, AcmeTokens, AcmeButton, and acmeButtonStyle; no installed identifier is named Fortal. Button brings its shared base_button recipe, while the theme arrives as a complete local layer:

lib/ui/
├── ui.dart
├── theme/
│   ├── theme.dart
│   ├── radix_colors.dart
│   ├── computed.dart
│   ├── control_styles.dart
│   ├── tokens.dart
│   ├── theme_data.dart
│   ├── theme_scope.dart
│   └── surface_frame.dart
└── components/
    ├── base_button.dart
    ├── button.dart
    └── button.g.dart

Place AcmeScope below the application host. For a routed WidgetsApp, wrap the child of WidgetsApp.builder with AcmeScope. Routes and dialogs then inherit its tokens and text defaults. The scope example lives in lib/ui/theme/theme_scope.dart.

These are application files, not forwarding wrappers around a package. The authored recipes and pinned Radix Themes 3.3.0 color data are copied from the same source used by the repository's parity suite. remix remains the behavior and styling-engine boundary; mix_annotations, build_runner, and mix_generator support adapter generation. icons additionally installs remix_ui_icons, and chart installs mix_chart. The preset adds no direct mix, naked_ui, or remix_fortal dependency.

The source is deliberately editable. Change the token map, add an accent or variant, or merge a one-instance styler last. Future CLI versions never merge over those decisions automatically: inspect remix add <item> --diff, then use --overwrite only when you want the new authored file wholesale.

Application host and appearance

Open Code documentation and runnable examples use WidgetsApp. For a routed application, install the generated theme scope in WidgetsApp.builder and pass its child through. That child is the Navigator; keeping the scope above it makes the active theme available to routes, dialogs, and overlays. See the complete routed host example.

The generated scopes expose theme, darkTheme, and mode. A root without arguments supplies the preset's light and dark defaults and follows the system. A nested scope inherits its parent's configured pair and active selection.

PresetScopeTheme values and modes
vanillaAcmeThemeScopeAcmeThemeData.light(), .dark(), and AcmeThemeMode
fortalAcmeScopeAcmeThemeData.light(), .dark(), and AcmeThemeMode

Use your configured prefix in place of Acme. The same parameters apply to both presets:

AcmeThemeScope(
  theme: const AcmeThemeData.light(),
  darkTheme: const AcmeThemeData.dark(),
  mode: AcmeThemeMode.system,
  child: child,
)

For Fortal, use AcmeScope in that example. Its theme constructors also accept accent, gray, radius, scaling, panel background, and background visibility. Set shared design options on both appearances when customizing the pair.

mode accepts system, light, and dark. The root reacts to platform brightness changes in system mode. An explicit mode overrides the system; a nested scope with no mode inherits the parent's active selection, even if a nearer MediaQuery reports a different system brightness. Nested scopes can explicitly select another mode from the inherited pair.

theme is the base and fallback. When you supply a custom theme without a darkTheme, it is used in both modes; colors are not automatically inverted. Supplying only darkTheme retains the inherited or generated light theme and does not force dark mode. Supplying neither retains both preset defaults.

Generated scopes take a child. Keep WidgetsApp.builder above the Navigator and use its child; no scope-specific builder constructor is required. To read the newly installed theme while building, put Flutter's Builder below the scope and use that callback's context.

The downloadable tutorial apps show the same API in both presets. Their generated theme files are editable application source; regeneration still preserves existing authored files unless you explicitly use --overwrite. The CLI installs the theme layer, not a complete app host or appearance picker. Selection controls and persistence belong to the application. The dashboard is a reference consumer of the same scope behavior.

The theme API has a hard cutoff: scope constructors accept theme, darkTheme, and mode. The default scope's data parameter, FortalScope's brightness parameter, and the config createScope shortcut have been removed. Use theme for a fixed theme and mode for appearance selection. Direct Fortal design options such as accent still override the supplied theme values.

The three levels of customization

Edit the recipe: change it for the whole app, permanently. It is your file.

Retheme a subtree: one copyWith restyles every button beneath it, because the recipe reads tokens and the scope decides what tokens resolve to:

import 'package:flutter/widgets.dart';

import 'ui/ui.dart';

Widget rounded(Widget child) => UiThemeScope(
  theme: const UiThemeData.light().copyWith(
    primary: const Color(0xFF4F46E5),
    radius: const Radius.circular(999),
  ),
  child: child,
);

Override one instance: style is merged last, so it beats the resolved recipe without forking it:

import 'package:flutter/widgets.dart';
import 'package:remix/remix.dart';

import 'ui/ui.dart';

Widget publishButton(VoidCallback publish) => UiButton.primary(
  label: 'Just this one',
  style: ButtonStyler()
      .color(const Color(0xFF7C3AED))
      .onHovered(ButtonStyler().color(const Color(0xFF5B21B6))),
  onPressed: publish,
);

State fragments merge by state, not by depth. An override that must beat the recipe's hover fill has to be declared as a hover fragment too; a bare .color(...) only replaces the idle one.

Updating

Registry content releases independently of the CLI. Update a pin explicitly, then review installed source; no automatic merge or installed-source lockfile is used.

remix registry update @remix
remix add button --diff

registry update resolves the recorded ref again; for the official registry that is registry-stable, the newest promoted commit. A SHA or tag pin resolves to the same commit, so move it with --ref <sha>, or return to the branch with --ref registry-stable.

Register additional public GitHub sources with the same preset:

remix registry add @company --repository owner/repo --path registry --ref v1
remix add @company/button

Bare dependencies resolve within their owning registry. Qualified dependencies require explicit registration; they cannot add or redirect sources. Cross-registry cycles, conflicting targets and incompatible package requirements fail before writes.

A project on schema 1 or 2 named no registry at all, so there is no pin to migrate. Delete remix.yaml, rerun remix init with the prefix, preset and UI path it recorded, then review with remix add button --diff; authored files and generated adapters are untouched either way. Restore a previously committed remix.yaml pin to roll back the source selection; installed files are not reverted.

--diff renders the new template, formats it, and runs a real git diff against what is on disk. If the output is empty you are current:

No authored-source differences.

If you have edited the recipe, the diff never comes back empty: it reports your own edits every time, whether or not the template moved. Read the hunks, not the exit state. To see the template alone, compare against a copy of the file you installed, or run the diff in a scratch project that has never been edited.

CLI updates do not change registry pins. add, --diff, and --dry-run fetch only the configured commits and never update configuration. Remote failures never substitute older or newer content. Private repositories, arbitrary HTTP sources, local registries and persistent offline caching are not supported.

If you like the upstream version, take it wholesale:

remix add button --overwrite

--overwrite replaces only the items you named. Already-installed registry dependencies are untouched, so updating Button never silently rewrites a Theme you have customized:

Preserved theme.
Updated button.

If you only want part of the upstream change, copy it out of the diff by hand. That is the intended workflow. The file is yours.

The Remix drift notice

Each registry revision is authored against one remix version, and the constraint it installs is a caret, so flutter pub upgrade can move you onto a later remix that these templates were never tested against. add reports that after it resolves your lockfile:

Resolved remix 1.0.0; this registry revision was authored against 1.0.0-beta.10. Your pin does not move on its own — run remix registry update @remix, then review with --diff.

Upgrading the CLI does not change the pin, so the notice names registry update. When the pin is a SHA or tag rather than registry-stable, it adds --ref <newer ref>, since a bare update would resolve the same commit.

It is a notice, not a failure. The install completes. A remix below the authored version is a different case and still fails outright, because the templates would not compile against it.

The notice needs a resolved lockfile, so it prints only on a real add. --dry-run and --diff stop before flutter pub get and never show it.

Reinstall behavior

State of the itemaddadd --overwrite
Not installedInstalls it, reports AddedInstalls it, reports Added
Fully installedSuccessful no-op, reports PreservedRe-renders, reports Updated
Partially installedError — refuses to guessRe-renders every file, reports Updated

A partial install is an error rather than a silent repair because the CLI cannot know whether the missing file was deleted on purpose. Use --diff to look, then --overwrite deliberately.

Generated adapters are not your problem. button.g.dart is regenerated whenever its authored source is rewritten or the adapter is missing, and the CLI verifies the file exists afterwards rather than assuming the build worked. The current mix_generator writes this. qualifiers that flutter_lints reports as infos, so exclude lib/ui/**/*.g.dart under analyzer: exclude: in analysis_options.yaml.

Removing an item

There is no remove command. Delete the files and the matching export lines from the managed block in lib/ui/ui.dart. The next add will treat the item as missing and reinstall it cleanly.

Dependency rules

The CLI checks your pubspec.yaml but never rewrites a declaration you already made. It adds only what is missing, and preserves hosted, path, Git, custom-hosted, and override declarations byte-for-byte.

Section placement is enforced, because the installed source lives under your lib/ and is compiled into anything that depends on your package:

PackageRequired section
remix, mix_annotationsdependencies
mix_chartdependencies when chart is installed
remix_ui_iconsdependencies when icons is installed
build_runner, mix_generatoreither (build-time only)

A runtime package declared only under dev_dependencies fails before any process runs or file is written:

$ remix add button
FormatException: remix is declared under dev_dependencies but installed source
imports it at runtime. Move remix to dependencies in pubspec.yaml and rerun.
No source was written.

Declaring the same package in both sections is rejected the same way. Fix your manifest and rerun; the CLI will not edit it for you.

Vanilla preset catalog

The official registry is deliberately small, and every item after theme depends on it:

theme installs tokens.dart, theme_data.dart, and theme_scope.dart, giving you UiTokens, UiThemeData, and UiThemeScope. Every component item installs one authored file plus its generated adapter under components/<item>.dart. Five items differ: icons installs app-owned icons.dart with no generated adapter; chart generates three adapters over mix_chart; data_table also pulls in checkbox, icon_button, and select, because its selection column, pager, and page-size control are those components; adding it installs all four; sidebar pulls in toggle and tooltip, because a destination is a toggle and a collapsed rail labels it with a tooltip. toast pulls in button and icon_button for its action and close control. sidebar_layout is a layout with no Spec or generated adapter; it pulls in sidebar to compose into its row and compact sheet. dashboard_shell composes those existing primitives into a host-controlled responsive shell. It installs no charts, tables, sample data, routes, or application entry point. dashboard_demo adds the full twelve-destination reference application: Overview, Chat, Customers, Orders, Settings, Charts, Actions, Forms & Inputs, Data Display, Overlays, Navigation, and Typography. Product content and navigation match across presets; each component gallery uses that preset's own public variants. The starter includes deterministic Agent flows, complete customer and order tables, all twelve chart cases, interactive galleries, appearance and notification chrome, and local toast feedback. Built-in chrome can be disabled; caller actions append to it and caller account content replaces the default. It leaves the application, routes, authentication, persistence, and backend search behavior with the host.

The registry requires Remix beta.10, which includes RemixSidebar and the Toast APIs. The installer rejects older resolved versions before it writes source.

ItemSurface you getAxes
iconsUiIcons—
accordionUiAccordion—
avatarUiAvatar—
badgeUiBadgevariant
buttonUiButtonvariant, size
calloutUiCalloutvariant
cardUiCard—
chartUiLineChart, UiBarChart, UiPieChart—
checkboxUiCheckbox, UiCheckboxGroupItem—
dashboard_demoUiDashboardDemo, UiDashboardOverview—
dashboard_shellUiDashboardShell—
data_listUiDataList—
data_tableUiDataTable—
dialogUiDialog—
disclosureUiDisclosure—
dividerUiDivider—
icon_buttonUiIconButtonvariant, size
linkUiLink—
menuUiMenu—
popoverUiPopover—
progressUiProgress—
radioUiRadio—
segmented_controlUiSegmentedControl—
selectUiSelect—
sidebarUiSidebar—
sidebar_layoutUiSidebarLayout—
skeletonUiSkeleton—
sliderUiSlider—
spinnerUiSpinner—
switchUiSwitch—
tabsUiTabBar, UiTab, UiTabView—
textfieldUiTextField, UiTextArea—
toastUiToastvariant
toggleUiTogglevariant, size
toggle_groupUiToggleGroupvariant, size
tooltipUiTooltip—

The fortal catalog contains every item above and adds base_button, code, heading, kbd, text, and typography. base_button and typography are shared authored recipes that arrive transitively with the components that use them. Fortal's component names use the configured prefix, so an Acme installation exposes AcmeSidebar, AcmeHeading, and AcmeText alongside its generated controls.

One add installs every named item plus shared dependencies once. The names above use the default Ui prefix; --prefix Acme gives you AcmeButton and friends. An axis is an enum the recipe declares, and a recipe whose axis is named variant also gets one named constructor per value, so UiBadge.destructive(label: 'Failing') works out of the box.

A parameter is not an axis. UiDivider takes an orientation, but it is a plain Flutter Axis the recipe accepts rather than an enum of its own, so it generates no named constructors.

Charts in the Vanilla preset

The Vanilla preset's chart is an optional extension with its own compact recipe:

remix add chart

It installs one editable recipe and generates UiLineChart, UiBarChart, and UiPieChart. Line series can draw lines or areas. Bar data can be grouped, stacked, or floating. A positive centerRadius makes a pie chart a donut.

mix_chart retains the hard contract: data validation, rendering, pointer interaction, transitions, tooltips, and chart semantics. Your copied file owns the axes, grid, shared series geometry, and tooltip appearance. Series colors come from the Theme's chart1 to chart5 tokens. A Theme installed by an earlier CLI build lacks them: add the five tokens to tokens.dart and theme_data.dart before adding chart.

Import chart data directly and give the chart finite dimensions:

import 'package:flutter/widgets.dart';
import 'package:mix_chart/mix_chart.dart';

import 'ui/ui.dart';

final chart = SizedBox(
  height: 240,
  child: UiLineChart(
    semanticsLabel: 'Weekly revenue',
    showMarkers: true,
    series: [
      LineSeries(
        id: 'revenue',
        label: 'Revenue',
        points: [
          ChartPoint(id: 'mon', x: 0, y: 18),
          ChartPoint(id: 'tue', x: 1, y: 31),
        ],
      ),
    ],
  ),
);

The palette is UiTokens.chart: chart1 to chart5 in series order. The shipped light and dark values keep each series' hue and clear 4.5:1 against the page background. Edit them in UiThemeData for a design-system change. Pass palette or style for a one-chart override. The UI barrel does not re-export mix_chart.

remix add icons also declares remix_ui_icons and gives you a small alias surface to evolve with the application. Import package:remix_ui_icons/remix_ui_icons.dart directly whenever you need the complete 318-icon catalog; static RemixIcons references remain tree-shakable.

Some Remix widgets are behavioral and carry no style, so the registry has nothing to render for them. RemixCheckboxGroup, RemixRadioGroup, RemixTabs, and RemixAccordionGroup are the four in this catalog: import them from package:remix/remix.dart and put the installed adapters inside.

toggle_group, segmented_control, menu, and select work the other way round. Their options are data, not widgets, and the parent's own recipe carries the option style, so one add covers the container and every row, and a row in a loop cannot be left unstyled.

One host note: an installed text field needs an Overlay ancestor once it takes focus, for its selection handles. MaterialApp, CupertinoApp, and any WidgetsApp with routes already provide one; a bare WidgetsApp(builder: ...) does not.

Exit codes

  • 0 — success, including help, version, dry-run, diff, and no-op reruns
  • 64 — invalid command or arguments
  • 1 — configuration, registry, dependency, process, generation, analysis, or filesystem failure

If generation or analysis fails after installation, the authored source stays on disk for inspection. Fix the reported problem and rerun the same command.

Agent surfaces in both presets

activity, answer, composer, execution, message, permission, plan, and transcript install unstyled, application-owned behavior source in either the Vanilla or Fortal preset. Each <component>_recipe item adds a complete preset-specific recipe bundle. The private authoring source (registry_source) is not a consumer dependency. The shared models files are exported from the local UI barrel; support helpers install transitively without barrel exports. Appearance remains host-owned.

dart run remix_cli:remix add composer

These surfaces use @MixableSpec. The CLI enables the supported Mix generator's opt-in spec-styler builder for their installed source paths in build.yaml, preserving other builder settings and comments. Explicit exclusions or disabled generation are reported before writes. --dry-run and --diff remain read-only. Agent recipes extend both existing presets; they do not constitute a third preset or claim Radix component parity.

Available styled items: activity_recipe, answer_recipe, composer_recipe, execution_recipe, message_recipe, permission_recipe, plan_recipe, and transcript_recipe. Each installs only its component and styled-control closure.

View page source on GitHub

On this page