CLI Usage
fluxo-cli is a standalone npm package that vendors individual FluxoUI components into your project as plain source files — install fresh, refresh on demand, remove cleanly, never compromise your local edits. Your project never depends on the fluxo-ui library at runtime.
Why use fluxo-cli?
fluxo-cli is a separate npm package from the fluxo-ui library. Use it to cherry-pick individual components into your project as plain source files instead of installing the whole library as an npm dependency. Built for teams that need to vendor UI components — for compliance, customization, third-party-dep policies, or simply to own the code they ship.
Pick what you need, run it, get real .tsx files dropped into ./src/components/fluxo-ui/ (or wherever you point it). Re-run later to pull updates — your local edits are preserved unless you explicitly opt in to overwrite them. Remove components you no longer need with a single command.
Vendor In, Library Out
Copies real component source into your repo so you can edit, review and ship without an external dependency.
Transitive Resolution
Pulls every dependency a component needs — sub-components, hooks, utils, types, themes, even icon SVGs.
Smart Import Rewriting
Rewrites every relative import inside copied files so they resolve cleanly inside your project layout.
Drift-Aware Updates
Tracks SHA-256 checksums for every installed file. `update` warns before overwriting your local edits.
Interactive & Scriptable
Multi-select prompts when run from a TTY; fully argv/CI driven when piped or run with --force.
No Hidden Dependency
Components, theme variables and stylesheets all land in your repo. The CLI never installs the fluxo-ui npm package as a runtime dep.
SCSS or Plain CSS
Default install vendors .scss alongside .tsx. Pass --css to pre-compile to plain CSS so the project needs no Sass toolchain.
Running the CLI
The CLI ships as the fluxo-cli bin inside the standalone fluxo-cli npm package (separate from the fluxo-ui library). Run it with npx — no global install, no runtime dependency added to your project:
npx fluxo-cli add Button TextInputpnpm dlx fluxo-cli add Button TextInputyarn dlx fluxo-cli add Button TextInputPrerequisites
- Run from your project root (the directory with
package.json). - TypeScript is required — components are
.tsx. react,react-dom, andclassnamesin your dependencies.- A Sass compiler if you keep the default SCSS output. Pass
--cssto vendor pre-compiled CSS instead.
Theme variables, base styles, and per-component styles are vendored into your install root — you do not need to import anything from fluxo-ui at runtime. Import the generated styles/index.css from your install root once at your app entry to apply the theme tokens.
add command
Use add for first-time installs and to add new components later. It walks the dependency closure for everything you select, fetches the source from GitHub (inferred from the package's repository field) or a local clone, rewrites every relative import to land cleanly in your install root, vendors the shared theme stylesheets, writes each file atomically, and re-exports everything from <install-root>/index.ts.
Common invocations
# Add components by id (kebab-case or display name)
npx fluxo-cli add button text-input
# Add into a custom path
npx fluxo-cli add button --path ./app/ui/components
# Pre-compile SCSS to CSS at install time
npx fluxo-cli add button --css
# Skip every prompt and overwrite local edits
npx fluxo-cli add button --force
# Launch interactive picker (no ids on argv)
npx fluxo-cli addWhat you'll see
A typical successful run prints the resolved project root, install path, dependency closure, external package status, per-file write log, and the index re-exports it added:
[fluxo-cli add]
Project root: /work/my-app
Install path: ./src/components/fluxo-ui (created)
Resolving dependencies...
+ button
+ confirm-popover (transitive)
+ tooltip (transitive)
+ link (transitive, internal)
External packages required:
classnames (present)
react (peer (assumed available))
Writing 24 file(s) to ./src/components/fluxo-ui/
+ _eui-vars.scss
+ styles/index.css
+ styles/base-theme.css
+ styles/theme-blue.css
+ button/Button.tsx
+ button/Button.scss
+ confirm-popover/ConfirmPopover.tsx
...
Updating ./src/components/fluxo-ui/index.ts
+ component: ./button/Button
+ component: ./confirm-popover
+ component: ./tooltip/tooltip-api
Done. Wrote 24 file(s), 0 skipped, 0 conflicts.update command
Use update to refresh already-installed components from the source (default branch by default). Drift is computed per-file via SHA-256 checksums recorded in fluxo-ui.config.json, so the CLI knows which files you have edited locally and which still match the original source.
Common invocations
# Refresh every installed component (interactive picker pre-selects them)
npx fluxo-cli update
# Refresh only the listed ids
npx fluxo-cli update button modal
# Refresh everything and overwrite locally-edited files without asking
npx fluxo-cli update --force
# Move the install root and refresh in place
npx fluxo-cli update --path ./app/ui/componentsSample output with drift
When some files have been edited locally, the default behavior is to skip them and surface the list at the end of the run so you can review what was preserved:
[fluxo-cli update]
Project root : /work/my-app
Install path : ./src/components/fluxo-ui
Drift summary:
button : 1 modified, 0 missing, 0 added [locally modified]
modal : unchanged
tooltip : 0 modified, 1 missing, 0 added
Resolving dependencies...
Writing 14 file(s) to ./src/components/fluxo-ui/
+ tooltip/Tooltip.tsx (added missing)
~ modal/Modal.tsx (unchanged)
- button/Button.tsx (skipped, locally modified)
Files preserved due to local changes:
button/Button.tsx [locally-modified]
Re-run with --force to overwrite locally-edited files.remove command
Use remove to uninstall components you no longer need. The CLI deletes the component folder, removes the entry from fluxo-ui.config.json, and strips the matching export line from index.ts.
Common invocations
# Interactive picker — choose components to uninstall
npx fluxo-cli remove
# Remove specific components
npx fluxo-cli remove modal tooltip
# Skip the confirm prompt
npx fluxo-cli remove modal --forceReverse-dependency safety
Before deleting anything, the CLI checks every other installed component for a manifest dependency on the targets you asked to remove. If tooltip is still required by button and you didn't include button in the same command, removal oftooltip is blocked and the dependent components are listed so you know exactly why.
[fluxo-cli remove]
Reverse-dependency check
Cannot remove the following components — they are still required by other installed components:
• tooltip
↳ used by button (Button)
↳ used by autocomplete (Autocomplete)
To remove these too, include the dependent component(s) in the same `fluxo-cli remove` command.
Proceeding with 1 removable component(s) only.Successful removal
[fluxo-cli remove]
Removing components
- removed src/components/fluxo-ui/modal
- removed src/components/fluxo-ui/snackbar
Index updates
- removed export from index.ts: ./modal
- removed export from index.ts: ./snackbar
Summary
Removed 2 component(s): modal, snackbar
Hooks, utils, and shared modules were left in place — they may still be used by other components or by your own code.What is NOT removed
- Hooks, utils, shared modules, icon SVGs, and theme stylesheets are left in place. They may still be used by other components — or by your own code that imports them directly. Delete them yourself if you're sure they're orphans.
- Custom export lines you've added to
index.tsare preserved. Only the matching auto-generatedexport * from './<id>'lines are stripped.
Styles & themes
Every install vendors a complete styling bundle so your project never depends on the fluxo-ui npm package at runtime. The bundle includes the shared SCSS variables, the base theme stylesheet, and only the brand themes you actually selected.
Import the stylesheet once
After running fluxo-cli add, import the generated styles/index.css from your app entry. It pulls in base-theme.css plus every theme you opted into.
// Once at your app entry (e.g. main.tsx / app.tsx / _app.tsx):
import './components/fluxo-ui/styles/index.css';
// (replace ./components/fluxo-ui with your install path)Apply a theme by setting a class on <body> (or any ancestor): theme-blue, theme-lara, etc. Add mode-dark to flip into dark mode.
Pick the themes you actually use
The CLI does not dump every theme into your project. On the first add you'll see a multi-select prompt to choose which themes to vendor (default: blue). Your selection is recorded in fluxo-ui.config.json so future runs reuse it. Pass --themes on add or update to add more themes later.
# Pick themes interactively (multi-select shown on first add)
npx fluxo-cli add Button
# Specify themes on the command line (comma-separated)
npx fluxo-cli add Button --themes blue,lara
# Add a new theme to an existing install
npx fluxo-cli update --themes purple
# Compile SCSS to plain CSS at install time
npx fluxo-cli add Button --cssAvailable themes
bluelaragreenpurpleorangeindigoroseambertealemeraldfuchsiaslateWhat lands in your install root
./src/components/fluxo-ui/
_eui-vars.scss # shared SCSS variables, mixins, design tokens
styles/
index.css # entry point — import this once in your app
base-theme.css # CSS custom properties (always included)
theme-blue.css # only the themes you selected
theme-lara.css
button/
Button.tsx
Button.scss # @use '../eui-vars' as *;
modal/
Modal.tsx
Modal.scss
index.ts # auto-managed barrelSCSS or plain CSS?
The default vendor is SCSS — component .scss files plus _eui-vars.scss. Your project needs a Sass loader (Vite, Next.js, CRA, etc. all handle this with npm i -D sass).
Pass --css to compile every SCSS file to plain CSS at install time. The .tsx imports get rewritten from './Foo.scss' to './Foo.css' automatically. Useful for projects without a Sass toolchain.
Interactive flow
When you run the CLI from a TTY without arguments, it walks you through component selection, install path, and any conflicts. Under CI, piped input, or --force, every prompt short-circuits to a sane default so argv-driven usage stays scriptable.
Cancel-safe by design
Press Ctrl+C at any prompt to abort. The process exits with code 0, never partially writes (every file write is atomic via temp + rename), so the project is left in a consistent state. Re-running picks up exactly where you left off.
Flags & environment
All flags work on both add and update. Argv positional values are component ids (kebab-case slug or display name).
--path <dir>alias: -pInstall root. On `add`, this is where components land (default `./src/components/fluxo-ui`). On `update`, supplying `--path` rewrites the recorded path in `fluxo-ui.config.json`. Absolute paths inside the project root collapse to a relative form.
npx fluxo-cli add button --path ./app/ui/components--forcealias: -fSkip every prompt. Auto-selects every installed component for `update` when no argv ids are given. Overwrites locally-modified files without asking. Bypasses the TSX warning, path prompt, component selection, and per-component / per-file conflict prompts. A one-time warning banner is printed at the start.
npx fluxo-cli update --force--cssPre-compile every vendored .scss file (component styles plus the shared theme stylesheets) to plain .css at install time. Imports inside the generated .tsx files are rewritten from `./Foo.scss` to `./Foo.css` automatically. Use this in projects that do not have a Sass toolchain.
npx fluxo-cli add button --css--no-exportSkip rewriting the install-root index.ts entirely. Useful when you maintain a hand-curated barrel file and do not want the CLI to append re-exports.
npx fluxo-cli add button --no-export--no-export-hooksSuppress hook re-exports from the install-root index.ts. Components and utils still get exported.
npx fluxo-cli add button --no-export-hooks--no-export-utilsSuppress util re-exports from the install-root index.ts. Components and hooks still get exported.
npx fluxo-cli add button --no-export-utils--helpalias: -hPrint full usage including interactive flow notes, force-mode semantics, per-file resolver choices, and Ctrl+C abort. Available on the root command and after the subcommand.
npx fluxo-cli --helpEnvironment variables
| Variable | Purpose |
|---|---|
| FLUXO_UI_LOCAL_SOURCE | Absolute path to a local clone of the FluxoUI `src/` directory. When set, the CLI reads from disk instead of GitHub. Useful for offline installs, internal forks, or running from a feature branch. |
| FLUXO_UI_REF | Branch, tag, or commit SHA to fetch from when using the GitHub source provider (defaults to the package’s repo default branch). Set this when you need a reproducible install pinned to a specific revision. |
| GITHUB_TOKEN | Optional. Sent as the bearer token on raw-content requests so unauthenticated users hit higher GitHub API rate limits. Useful when running in CI. |
| HTTPS_PROXY / NODE_EXTRA_CA_CERTS | Standard Node networking knobs. Configure these when running behind a corporate proxy or with a self-signed certificate authority. |
Generated configuration
On the first add, the CLI writes afluxo-ui.config.json at the project root (next to package.json) and an index.ts at the install root. Both files are kept in sync on every subsequent run.
fluxo-ui.config.json
Stable, sorted JSON suitable for git diffs. Commit this file alongside your source.
{
"version": "1.0.0",
"path": "./src/components/fluxo-ui",
"components": {
"button": {
"name": "Button",
"version": "github:shridhar-tl/fluxo-ui@main",
"checksum": "8d4f...e102",
"files": [
{ "path": "Button.tsx", "checksum": "5c1a...771b" },
{ "path": "Button.scss", "checksum": "9e0d...2a44" }
],
"installedAt": "2026-05-02T10:23:11.491Z"
}
},
"lastUpdated": "2026-05-02T10:23:11.491Z"
}- path — install root, relative to the project root. Always written in forward-slash form so the file stays portable across hosts.
- components.<id>.files[*].checksum — SHA-256 of the file content with CR/CRLF normalized to LF.
updatecompares this against the on-disk file to detect drift. - components.<id>.checksum — rollup of all per-file checksums. Lets you tell at a glance whether a component matches the source release.
- version — provenance string (e.g.
github:owner/repo@branchorlocal:<path>). - Legacy filename support. If you previously had
fluxo-ui.json, the CLI keeps using that name on writes — it never silently migrates filenames.
Generated index.ts
The CLI parses the existing index, dedupes by specifier, and appends only the missing exports. Your own re-exports, comments, and side-effect imports are preserved.
// Auto-managed by 'fluxo-cli add' / 'fluxo-cli update'
// You can add your own re-exports below — they are preserved.
export * from './button/Button';
export * from './confirm-popover';
export * from './tooltip/tooltip-api';
export * from './hooks/useClickOutside';
export * from './types';
// Your custom additions stay untouched.
export { default as MyCustomBadge } from './my-custom-badge/MyCustomBadge';Hooks and utils that a component depends on are also re-exported by default. Pass --no-export-hooks or --no-export-utils to suppress just those, or --no-export to skip the index file entirely. Internal helpers (Link, Icon, editor-core, context) are flagged private and never appear in the index.
Conflict resolution
Every file the CLI is about to write is classified into one of five kinds. Two of them auto-write, one is a no-op, and the remaining two are conflicts that fire the per-file resolver. Decisions made via the batch options apply only within their kind so you stay in control even when answering a long stream of prompts.
| Kind | Detected when | Behavior |
|---|---|---|
new | No file at the target path on disk. | Writes the new file. Resolver is never consulted. |
unchanged | Target exists and its content already matches the new content (CR/CRLF normalized). | Skipped silently. The file is never touched, mtime stays the same. |
updated | Target exists, on-disk content matches the recorded checksum, but the new content differs (a real upstream change). | Writes the new file. Resolver is never consulted — there are no local edits to preserve. |
locally-modified | Target exists, on-disk content differs from the recorded checksum (you edited the file). | Default = Skip (preserve your edit). Force mode = Overwrite. In TTY mode the per-file resolver asks Overwrite / Skip / Overwrite all of this kind / Skip all of this kind. |
foreign | Target exists but no checksum is recorded (the file was added outside the CLI, often a leftover from a previous tool). | Default = Skip. Force mode = Overwrite. The per-file resolver tracks foreign decisions independently from locally-modified ones — Skip-all on one kind does not silence the other. |
Common scenarios
End-to-end recipes for the workflows the CLI is built around. Each one is copy-paste ready — no setup required beyond a project with a package.json.
Fresh install, custom path
Bootstrapping a brand-new project with a couple of components into a non-default path. The CLI creates the install root, writes both files, and emits `fluxo-ui.config.json` next to `package.json`.
# package.json already exists. No fluxo-ui.config.json yet.
npx fluxo-cli add button text-input --path ./app/ui/components
# Result on disk:
# ./app/ui/components/
# button/Button.tsx
# button/Button.scss
# text-input/TextInput.tsx
# ...
# index.ts (auto-generated)
# ./fluxo-ui.config.jsonAdd another component later
You shipped the project a month ago with Button and now need a Modal. The CLI re-uses the existing config, runs the dependency walk for Modal only, and appends the new exports to your existing index.
npx fluxo-cli add modal
# index.ts diff:
# + export * from './modal';
# + export * from './hooks/useFocusTrap';Refresh installed components without losing edits
Pull the latest source for everything you have installed. Drift is detected per file; locally-modified files are preserved by default and surfaced at the end of the run.
npx fluxo-cli update
# Files preserved due to local changes:
# button/Button.tsx [locally-modified]
#
# Re-run with --force to overwrite locally-edited files.Force-update everything (CI / scripted)
Run from a CI job after pulling the latest source. The force banner prints once, every prompt is bypassed, and any locally-modified file is overwritten and listed in the summary.
npx fluxo-cli update --force
# Locally-edited files overwritten (1):
# button/Button.tsxMove the install root
You decided to relocate `./src/components/fluxo-ui` to `./app/ui/components`. Running update with `--path` rewrites the recorded path in the config and reinstalls into the new location. The old directory is left untouched — delete it manually after verifying.
npx fluxo-cli update --path ./app/ui/components
# fluxo-ui.config.json now has "path": "./app/ui/components".
# After the move, remove the old folder yourself:
rm -rf ./src/components/fluxo-uiInstall from a local clone (no GitHub access)
Behind a firewall or working from a fork? Point the CLI at a local checkout of FluxoUI. The CLI uses the local provider exclusively and never touches the network.
# Linux/macOS
FLUXO_UI_LOCAL_SOURCE=/work/fluxo-ui-fork/src \
npx fluxo-cli add button modal
# PowerShell
$env:FLUXO_UI_LOCAL_SOURCE = "C:\work\fluxo-ui-fork\src"
npx fluxo-cli add button modalPin to a specific upstream revision
Lock your install to a tagged release or commit SHA so re-running update reproduces the exact same source.
FLUXO_UI_REF=v1.4.0 npx fluxo-cli update --force
# fluxo-ui.config.json records:
# "version": "github:shridhar-tl/fluxo-ui@v1.4.0"Remove a previously-installed component
There is no `remove` command — components are plain files in your repo. Delete the directory, drop the entry from the config, and remove the export line from `index.ts`. (You can also leave the entry in the config; future updates will simply ignore the missing folder if you skip when prompted.)
# 1. Delete the component folder
rm -rf ./src/components/fluxo-ui/timeline
# 2. Remove the export line from index.ts
# - export * from './timeline';
# 3. Remove the entry from fluxo-ui.config.json
# (or run `fluxo-cli update` and skip the missing-folder prompt)Error messages
Every failure path emits a typed, mode-tagged error with a concrete remediation hint. No raw stack traces, no indistinguishable add-vs-update wording. The exit code is always meaningful (1 for most errors, 2 for partial installs).
ConfigStateError
When: Project root, package.json, install root, or fluxo-ui.config.json is missing.
[fluxo-cli update] ConfigStateError: fluxo-ui.config.json was not found.
Hint: Run `fluxo-cli add <component>` first — it creates the config and installs the initial components. `update` only refreshes existing installs.Fix: Run `fluxo-cli add` first to bootstrap the config. On `update` errors about a missing install root, re-run with `--path <new-path>` or `--force` to recreate the directory in place.
UnknownComponentError
When: Every supplied component id is unknown to the manifest.
[fluxo-cli add] UnknownComponentError: No matching components for: my-button, foobar.
Hint: Run `fluxo-cli add` (without ids) to launch the interactive picker.Fix: Re-run without ids to use the interactive picker, or check the component table on the homepage for the exact id (kebab-case slug). Display names also match (e.g. `Button` and `button` both resolve).
SourceAccessError
When: The source provider (GitHub or local clone) cannot be reached. Probed BEFORE planning so you do not get spammed with per-file failures.
[fluxo-cli add] SourceAccessError: ENOTFOUND raw.githubusercontent.com.
Hint: Verify your internet connection. If GitHub is unreachable, set FLUXO_UI_LOCAL_SOURCE=<path-to-fluxo-ui-src> to install from a local clone.Fix: Check connectivity, configure HTTPS_PROXY / NODE_EXTRA_CA_CERTS for corporate networks, set GITHUB_TOKEN for higher rate limits on 403, or fall back to FLUXO_UI_LOCAL_SOURCE for fully-offline installs.
PartialInstallError
When: Zero files were written and the missing/unresolved counts cover the entire plan — the install never made progress.
[fluxo-cli add] PartialInstallError: 0 of 22 files written. 22 missing on source.
Hint: The source provider could not produce any of the planned files. Re-run with FLUXO_UI_REF=<branch|tag|sha> or check the manifest with `npm run generate-manifest`.Fix: Pin to a known-good ref via FLUXO_UI_REF, regenerate the manifest, or fall back to a local clone via FLUXO_UI_LOCAL_SOURCE. Exit code is 2 (distinct from 1 for other errors) so CI can branch on it.
Network classification
The source-provider probe maps Node fetch failures into actionable hints — ETIMEDOUT / ECONNRESET mention proxy/connectivity, TLS errors mention NODE_EXTRA_CA_CERTS, HTTP 404 mentions FLUXO_UI_REF, HTTP 403 mentions GITHUB_TOKEN, and HTTP 5xx links to githubstatus.com. Every hint nudges you toward the right knob without making you parse a stack trace.
FAQ
Do I still need the fluxo-ui npm package?
npx. Once components are vendored into your repo, you can remove fluxo-ui from dependencies entirely. You will still need the underlying peers like react, react-dom, and classnames.Can I edit the generated files?
fluxo-ui.config.json and preserved on future update runs unless you pass --force or explicitly choose Overwrite at the prompt.How do I get notified of upstream changes?
fluxo-cli update on a schedule (or as a CI job). The drift summary tells you which components have new upstream content vs your local edits before any file is touched — so the workflow is review, then commit.What about styles?
.tsx files and imported directly inside them. The shared _eui-vars.scss module and every theme stylesheet (base + per-color themes) are also vendored — into <install>/_eui-vars.scss and <install>/styles/. Import the generated styles/index.css once at your app entry. You never need to import anything from the fluxo-ui npm package at runtime.My project does not use SCSS — can I get plain CSS?
--css on add or update. The CLI compiles every .scss file to plain .css at install time, rewrites the corresponding import './Foo.scss' in the .tsx files to import './Foo.css', and skips the SCSS-only helpers. Your project only needs a CSS loader, no Sass toolchain.How do I add a brand-new component to my install?
npx fluxo-cli add <new-component>. Existing config is reused, only the new component (and its transitive deps) is fetched and written, and the export line is appended to your index.ts automatically.Why was my locally-edited file not overwritten when I ran update?
--force or explicitly choose Overwrite at the per-file prompt. The skipped files are listed under Files preserved due to local changes at the end of the run with a footer telling you how to override.Can I run the CLI without any network access?
FLUXO_UI_LOCAL_SOURCE to a local clone of FluxoUI (point it at the src/ directory). The CLI never falls back to the network when this env var is set, so it is safe in air-gapped environments.How do I script this in CI?
--force in CI: it bypasses every prompt, prints a single banner, and exits with a meaningful code. Errors are still surfaced with a hint and a non-zero exit so you can fail the pipeline cleanly.