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
vanilla | fortal | |
|---|---|---|
| Design language | Compact neutral starting point | Radix Themes 3.3.0 parity surface |
| Theme | 15 semantic tokens | 277 tokens, Radix color scales, scaling, radius, and panel modes |
| Component axes | Small default vocabulary | Fortal's classic, solid, soft, surface, outline, and ghost vocabulary where applicable |
| Best for | A house system you intend to shape | Starting 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/remixAfter 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_cliRunning 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 vanillaThis writes two files and nothing else:
remix.yaml— your prefix, preset, and UI pathlib/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-runItems: 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.dartFor 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 --diff3. Add
remix add buttonButton 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:
flutter --version --machine— requires Flutter 3.44+flutter pub add— only for requirements you are actually missingflutter pub get, then verify the resolved versions inpubspec.lock- Write the authored files and update the managed barrel
dart formatthe files it wrotedart run build_runner build --build-filter=...— scoped to the generated targets onlydart 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>"| Key | Default | Rules |
|---|---|---|
schema | 3 | The only readable schema. Schemas 1–2 shipped in earlier prereleases and named no registry; such a project is reinitialized, not migrated. |
prefix | Ui | ASCII UpperCamel Dart identifier. Its lowercased form must not be a Dart reserved word. Remix and Mix are reserved for runtime dependencies. |
preset | vanilla | Preset selected across every configured registry. Choose vanilla or fortal at init. |
defaultRegistry | @remix | Configured namespace for bare item names. |
registries | official GitHub source | Each namespace records repository, path, requested ref and full commit revision. |
paths.ui | lib/ui | Project-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 editEvery 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 buttonThe 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.dartPlace 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.
| Preset | Scope | Theme values and modes |
|---|---|---|
vanilla | AcmeThemeScope | AcmeThemeData.light(), .dark(), and AcmeThemeMode |
fortal | AcmeScope | AcmeThemeData.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 --diffregistry 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/buttonBare 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 item | add | add --overwrite |
|---|---|---|
| Not installed | Installs it, reports Added | Installs it, reports Added |
| Fully installed | Successful no-op, reports Preserved | Re-renders, reports Updated |
| Partially installed | Error — refuses to guess | Re-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:
| Package | Required section |
|---|---|
remix, mix_annotations | dependencies |
mix_chart | dependencies when chart is installed |
remix_ui_icons | dependencies when icons is installed |
build_runner, mix_generator | either (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.
| Item | Surface you get | Axes |
|---|---|---|
icons | UiIcons | — |
accordion | UiAccordion | — |
avatar | UiAvatar | — |
badge | UiBadge | variant |
button | UiButton | variant, size |
callout | UiCallout | variant |
card | UiCard | — |
chart | UiLineChart, UiBarChart, UiPieChart | — |
checkbox | UiCheckbox, UiCheckboxGroupItem | — |
dashboard_demo | UiDashboardDemo, UiDashboardOverview | — |
dashboard_shell | UiDashboardShell | — |
data_list | UiDataList | — |
data_table | UiDataTable | — |
dialog | UiDialog | — |
disclosure | UiDisclosure | — |
divider | UiDivider | — |
icon_button | UiIconButton | variant, size |
link | UiLink | — |
menu | UiMenu | — |
popover | UiPopover | — |
progress | UiProgress | — |
radio | UiRadio | — |
segmented_control | UiSegmentedControl | — |
select | UiSelect | — |
sidebar | UiSidebar | — |
sidebar_layout | UiSidebarLayout | — |
skeleton | UiSkeleton | — |
slider | UiSlider | — |
spinner | UiSpinner | — |
switch | UiSwitch | — |
tabs | UiTabBar, UiTab, UiTabView | — |
textfield | UiTextField, UiTextArea | — |
toast | UiToast | variant |
toggle | UiToggle | variant, size |
toggle_group | UiToggleGroup | variant, size |
tooltip | UiTooltip | — |
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 chartIt 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 reruns64— invalid command or arguments1— 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 composerThese 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.