Latticereference

CLI

The lattice CLI scaffolds rbxts/react projects and manages @lattice-ui packages, their peers, and providers.

lattice-uiStable directionimport lattice

The lattice CLI is a Node tool for Lattice UI projects. It scaffolds new rbxts/react games, installs primitive packages together with their required peers and providers, and audits an existing project for missing dependencies. It is published to npm as lattice-ui and exposes two equivalent binaries: lattice and lattice-ui.

Use the CLI when you want package selection, peer resolution, and project health checks handled for you instead of editing package.json by hand.

Running the CLI

The CLI requires Node 20+. Run it on demand with npx — no install needed:

Terminal window
npx lattice-ui <command> [options]

Or install it globally to get the shorter lattice binary:

pnpm add lattice-ui
Terminal window
npm i -g lattice-ui
lattice <command> [options]

Both binaries (lattice and lattice-ui) run the same program. Run lattice help for the built-in usage summary or lattice version to print the installed version.

Help

Every command has its own help page as of 0.7.0, and three spellings reach it:

Terminal window
lattice add --help
Terminal window
lattice help add

A malformed run reaches it too — lattice add --bogus --help prints the add page rather than complaining about the unknown option first. -h works everywhere --help does.

A command’s page lists its usage, its own options, and its examples. For add, remove, and upgrade it also lists every available component and preset — previously the only way to see that list was to start an interactive run and read the prompt.

Global options

PropTypeDescription
--help, -hflagPrint usage. As the first argument it short-circuits any command; after a command name it prints that command's page.
--version, -vflagPrint the installed CLI version.
--verboseflagStream debug logging, per-file copy output, and the package manager's own output live instead of buffering it.
--yes, -yflagAccept defaults and skip prompts. Accepted by every command that prompts.

An unknown option is a usage error, but not a bare one: the CLI suggests the closest valid name and points at the relevant help page.

Unknown option for add: --prest
Did you mean --preset?
Run `lattice add --help` to see the supported options.

The same suggestion machinery covers command names, component names, and preset names, so lattice add dialogg proposes dialog rather than failing blankly. Component and preset names are validated before a package manager is resolved — previously a typo could surface an unrelated package-manager error first whenever more than one manager was installed.

Terminal behavior

VariableEffect
NO_COLORDisables colored output when set to any non-empty value. Wins over FORCE_COLOR.
FORCE_COLORForces color through a pipe. Any value except 0 enables it.
NO_HYPERLINKDisables OSC 8 hyperlinks.
FORCE_HYPERLINKForces hyperlinks on. Any value except 0 enables it.

Color previously keyed off TTY detection alone. It now honors the NO_COLOR/FORCE_COLOR contract first, then falls back to TTY detection, and TERM=dumb always disables it.

Project paths and package names are printed as OSC 8 hyperlinks so they are clickable in terminals that support them. Paths are shortened against the working directory and ~. Hyperlinks are off automatically under CI and outside a terminal, since a few terminals print the raw escape sequence rather than ignoring it.

Output

Each run prints as one connected flow: a vertical gutter threads the header, each titled block, and the closing verdict together, with tree branches for the rows inside a block and the elapsed time on the last line. This replaced the five ceremonial sections every command used to print — counts now live in the heading of the block they describe, so doctor no longer states its warning count three times, and the ? glyph is gone from informational lines where it read as a question.

Commands also report which package manager they resolved and why.

While a progress spinner is running, the package manager’s own output is buffered and surfaced only if the command fails. Inherited output used to interleave with the animation, scattering spinner frames through the install log. Pass --verbose to stream it live instead.

Interactive prompts

Selection prompts are keyboard-driven as of 0.7.0. They previously took a comma-separated list of numbers, and an answer that failed to parse aborted the whole command instead of re-asking.

KeyAction
/ , or k / jMove the cursor
SpaceToggle the highlighted option
aSelect all
nSelect none
EnterConfirm
Ctrl-C or EscCancel

The list scrolls when it is taller than the terminal, keeping the cursor in view. Cancelling restores the cursor and takes the terminal out of raw mode — Ctrl-C previously exited before the restore could run, leaving the cursor hidden.

Commands

CommandPurpose
createScaffold a new project from the rbxts template.
initAdd Lattice to an existing project.
addInstall component packages plus their peers and required providers.
removeRemove selected component packages.
upgradeUpgrade installed @lattice-ui/* packages.
doctorAudit lockfiles, peers, and provider expectations.
help / versionPrint usage or the CLI version.

create

Scaffolds a new project into an optional [project-path] (defaults to the current directory) from the rbxts template.

Terminal window
npx lattice-ui create my-game --pm npm --git --no-lint
PropTypeDescription
[project-path]positionalTarget directory for the new project. At most one is accepted; defaults to the current directory.
--yes, -yflagAccept defaults and skip interactive prompts.
--pm<pnpm | npm | yarn>Force a package manager instead of auto-detecting one.
--gitflagInitialize a git repository in the new project.
--template<rbxts>Project template to scaffold from. Currently rbxts.
--lintflagInclude the lint setup. Conflicts with --no-lint.
--no-lintflagSkip the lint setup. Conflicts with --lint.

init

Initializes Lattice inside an existing project. Unlike create, it accepts no positional path and no --git/--no-lint flags, and it supports --dry-run.

Terminal window
npx lattice-ui init --dry-run

init is also the migration path off the 0.6.1 rename. Before merging the template it rewrites any pre-0.6.1 package names in dependencies/devDependencies to their react- replacements (@lattice-ui/dialog@lattice-ui/react-dialog, @lattice-ui/core@lattice-ui/react-runtime), resolving a version for each replacement it has to add. Dropping the old name matters: leaving both in the manifest makes the old and new copies resolve side by side, which npm then rejects on peer resolution.

If the install fails, init and create roll their file changes back rather than leaving a half-written scaffold for the next run to merge on top of.

PropTypeDescription
--yes, -yflagAccept defaults and skip prompts.
--dry-runflagShow what would change without writing files.
--pm<pnpm | npm | yarn>Force a package manager instead of auto-detecting one.
--template<rbxts>Template to initialize from.
--lintflagInclude the lint setup.

add

Installs one or more component packages along with everything they need. Pass component names directly (comma- or space-separated) and/or --preset groups. With no names or presets and without --yes, add prompts you to pick presets and components interactively. Run lattice add --help to see every available component and preset without starting a run.

Terminal window
npx lattice-ui add dialog,toast --preset overlay

For each selected component the CLI gathers its npm package, its peers (@rbxts/react, @rbxts/react-roblox), and any required providers, then installs the set minus whatever is already present. Optional providers are reported as suggestions but not installed. After a real run it points you at doctor.

context-menu and motion were missing from the registry before 0.7.0, so lattice add context-menu and lattice add motion failed with “Unknown component”. Both resolve now.

PropTypeDescription
[name...]positionalComponent names to add. Comma-separated lists are split (e.g. dialog,toast).
--preset<preset...>Add every component in a preset. Repeatable and comma-separated.
--pm<pnpm | npm | yarn>Force a package manager instead of auto-detecting one.
--yes, -yflagSkip the install confirmation prompt.
--dry-runflagPrint the planned install command without changing anything.

remove

Removes the selected component packages. Accepts the same selection inputs and flags as add.

Terminal window
npx lattice-ui remove dialog --dry-run
PropTypeDescription
[name...]positionalComponent names to remove (comma- or space-separated).
--preset<preset...>Remove every component in a preset.
--pm<pnpm | npm | yarn>Force a package manager.
--yes, -yflagSkip the confirmation prompt.
--dry-runflagPreview the changes without applying them.

upgrade

Upgrades installed @lattice-ui/* packages. Same selection inputs and flags as add and remove. Pre-0.6.1 package names are skipped rather than upgraded — their dist-tags no longer move, so run init to rewrite them to their react- replacements first.

Terminal window
npx lattice-ui upgrade --dry-run
PropTypeDescription
[name...]positionalSpecific packages to upgrade. Omit to consider all installed @lattice-ui packages.
--preset<preset...>Upgrade every component in a preset.
--pm<pnpm | npm | yarn>Force a package manager.
--yes, -yflagSkip the confirmation prompt.
--dry-runflagPreview the upgrade without applying it.

doctor

Audits the project and reports issues without changing anything, then finishes with recommended commands. It checks for:

CheckLevel
Missing or duplicated lockfilewarn
A packageManager field that disagrees with the resolved managerwarn
No @lattice-ui component packages installed at allwarn
A pre-0.6.1 package name that no longer receives releaseserror
A typescript major other than the one roblox-ts compiles withwarn
An @lattice-ui package that is installed but not in the CLI registrywarn
A missing peer, or a missing optional providerwarn
A missing required providererror

Errors exit non-zero; warnings do not.

Terminal window
npx lattice-ui doctor
PropTypeDescription
--pm<pnpm | npm | yarn>Force the package manager used for the audit instead of auto-detecting.

Presets

Presets are named bundles of components so you can install a related set in one go with --preset.

PresetComponents
overlaypopover, tooltip, dialog, toast
formcheckbox, radio-group, switch, text-field, textarea

Package manager resolution

When --pm is omitted, the CLI resolves a package manager automatically from the project lockfile or installed managers; pass --pm <pnpm|npm|yarn> to override that choice. doctor surfaces resolution problems: a missing lockfile, multiple lockfiles, or a packageManager field that does not match the resolved manager.

The resolved manager is also pinned into the project. create and init record it as a devEngines.packageManager entry, and add, remove, and upgrade reapply the pin before they touch dependencies — if the pin names a different manager than the one this run uses, the CLI warns and repins. The pin is what keeps a project scaffolded with pnpm from being quietly installed with npm: both managers refuse to install when the pin names the other one.

Dry runs

init, add, remove, and upgrade all accept --dry-run. A dry run prints the exact package-manager command it would run and reports what it would do, which is the safest way to preview a change before committing to it.

Before 0.7.0 a dry run closed by claiming work it had not done — lattice add --dry-run reported “Added components: …” and “Installed packages: 4” despite changing nothing, and remove and upgrade did the same.