Commands
Every command, and the flags they share.
delacour <command> [components...] [options]Every command that reads the registry also takes --registry, --ref, --offline and --cwd.
The blocks below are that command's own --help.
`--ref` will not read `main` in your terminal
The blocks below are printed from a working tree. A published build bakes in the commit it was
released against, so the default your copy prints is a SHA — which is what keeps a version reading
the registry it shipped with. Pass --ref develop to opt into what has landed since.
init
Sets the project up and writes native-components.json. Covered in full at
Setting up a project.
bunx delacour@latest initOptions
Usage: delacour init [options] [components...]
set this project up and write native-components.json
Arguments:
components components to add straight away
Options:
-y, --yes accept every default without asking
-d, --defaults use the default layout without asking
-f, --force rewrite an existing native-components.json
-s, --src <dir> base directory for source files
--package-name <name> put the components in a shared package with this name
--package-path <dir> where that package goes, relative to the workspace root
(default: "packages/ui")
--install install the packages the components need, without asking
--no-install write the files and install nothing
--silent print nothing but errors
--registry <url> registry to read from: a URL, github:owner/repo, or a
local path
--ref <ref> git ref to read the registry at (default: "main")
--offline use only what is already cached
-c, --cwd <path> directory to work in (default: the current directory)
-h, --help display help for commandadd
Copies components in, with everything they need.
bunx delacour@latest add button input fielddelacour add --allIt sets the project up if it has to
A project with no native-components.json is not an error. add runs init
first — writing the config, wrapping Metro, pointing Tailwind at the components, copying the theme
and the root provider in — and then adds what you asked for. That happens in a script, in CI and
over MCP as readily as in a terminal, so add is the only command most projects ever need.
Pass --no-init to be told instead. A build that should never reconfigure a checkout wants it;
almost nothing else does.
What happens, in order
The order is deliberate: resolve the dependency graph, plan every file, ask once about conflicts, write, then report what the components need from npm. Installing first would leave a project holding new native dependencies and no components if you answered "no" to the overwrite prompt.
A file already on disk with byte-identical content is not a conflict — that is the normal state of
a utility two components share. Non-interactively, a genuine difference is an error naming the
files rather than a silent overwrite; pass --overwrite when you mean it.
What it needs installed
Every add ends with the packages the components need, whether or not anything is missing:
● Needs 14 external packages, 2 not here yet:
│ bunx expo install react-native-teleport react-native-keyboard-controller
│ already installed — cn, react-native-reanimated, react-native-svg, tailwind-variants, …The missing ones are shown as commands rather than as a list of names, because the command is the part that is not obvious — and they are spelled for the package manager this project is actually on.
Then it asks. --install answers yes without asking, --no-install answers no, and a run with
nobody to ask — a script, CI, an agent — installs nothing and prints the commands instead. Copying
source into your repository is local and reversible; running your package manager is neither.
Dependencies are split three ways
expo install for native modules and anything pinned to the SDK, your package manager for plain
JavaScript, and registryDependencies — which are other components to copy, not packages to
install.
Install into the app, not the shared package
If your components live in a package several apps share, the packages still belong to the app.
A native module resolved from two places registers twice and breaks at runtime — which is why add
runs the install from the app root, and records the same packages as peerDependencies on the
shared package rather than as dependencies.
Options
Usage: delacour add [options] [components...]
copy components into this project
Arguments:
components components to add
Options:
-a, --all add every component
-o, --overwrite replace files that differ
-y, --yes accept every default without asking
-s, --src <dir> base directory for source files, when setting the project up
--install install the packages the components need, without asking
--no-install write the files and install nothing
--no-init error instead of writing native-components.json when this
project has none
--silent print nothing but errors
--registry <url> registry to read from: a URL, github:owner/repo, or a local
path
--ref <ref> git ref to read the registry at (default: "main")
--offline use only what is already cached
-c, --cwd <path> directory to work in (default: the current directory)
-h, --help display help for commandlist
Everything the registry holds. Works before native-components.json exists — which is exactly when
you are deciding whether to run init.
delacour listOptions
Usage: delacour list|ls [options]
list what the registry holds
Options:
--json print JSON
--registry <url> registry to read from: a URL, github:owner/repo, or a local
path
--ref <ref> git ref to read the registry at (default: "main")
--offline use only what is already cached
-c, --cwd <path> directory to work in (default: the current directory)
-h, --help display help for commandsearch
delacour search sheetOptions
Usage: delacour search [options] <query>
search the registry
Options:
--json print JSON
--registry <url> registry to read from: a URL, github:owner/repo, or a local
path
--ref <ref> git ref to read the registry at (default: "main")
--offline use only what is already cached
-c, --cwd <path> directory to work in (default: the current directory)
-h, --help display help for commandview
Prints an item's files, the components it copies in, and the packages it installs.
delacour view buttonButton button
A pressable action composed from parts, with variants, sizes and a loading state.
files ui/button/button.tsx
ui/button/index.ts
…
copies in styles, cn, tv, color, use-theme-color, icon, compose-refs, merge-props, pressable, spinner, text
needs installing
bunx expo install react-native-gesture-handler react-native-pulsar react-native-reanimated react-native-svg react-native-worklets uniwind
bun add cn tailwind-merge tailwind-variants tailwindcssThe install lines cover the whole closure, not the item's own dependencies. button declares
only tailwind-variants; it renders icon, which needs react-native-svg, and pressable, which
needs Gesture Handler. Listing an item's own packages would under-report what add installs by
exactly the ones you are deciding about.
Options
Usage: delacour view [options] <name>
show one item and what it pulls in
Options:
--json print JSON
--registry <url> registry to read from: a URL, github:owner/repo, or a local
path
--ref <ref> git ref to read the registry at (default: "main")
--offline use only what is already cached
-c, --cwd <path> directory to work in (default: the current directory)
-h, --help display help for commandinfo
The resolved config and what was detected: package manager, Expo and React Native versions, whether
Uniwind and Tailwind are installed, the workspace and app roots, and the path aliases found in
tsconfig.json. Start here when the CLI is writing files somewhere you did not expect.
delacour infoOptions
Usage: delacour info [options]
show the resolved config and what was detected
Options:
--json print JSON
--registry <url> registry to read from: a URL, github:owner/repo, or a local
path
--ref <ref> git ref to read the registry at (default: "main")
--offline use only what is already cached
-c, --cwd <path> directory to work in (default: the current directory)
-h, --help display help for commandupdate
Brings the components you copied up to what the registry holds now, and keeps your edits.
bunx delacour@latest update
bunx delacour@latest update button
bunx delacour@latest update --dry-runadd records where each file came from in native-components.lock.json:
the registry ref, and a hash of the text as the registry served it. That is what lets update tell
the two histories apart — the registry's, which may have fixed something, and yours, which may have
changed something.
| The file | What update does |
|---|---|
| Changed in the registry only | Replaces it |
| Changed by you only | Leaves it alone |
| Changed by both, on different lines | Merges the two |
| Changed by both, on the same lines | Writes both sides between conflict markers, and exits 1 |
| New to the component | Writes it |
| Dropped from the component | Leaves it and says so. --prune deletes it, if you never edited it |
An edit is never overwritten. A conflict looks the way git's do, because your editor already knows what to do with one:
<<<<<<< local
const padding = 12;
=======
const padding = 6;
>>>>>>> registry@3ac4ac4Keep the side you want, delete the markers, and that file is done.
It updates to the ref your CLI was published from, so bunx delacour@latest update is the
whole upgrade: the newest CLI, and the registry it shipped against.
Your formatter
A project with a formatter will have run it over the copied files, and after that every line
differs from the registry's. So before comparing anything, update runs your formatter over
the registry's side — Biome or Prettier, whichever the project configures, from your own
node_modules and with your own config. A file you only reformatted counts as untouched, and an
update arrives already in your style.
It only ever runs a formatter you have installed. With none, it falls back to ignoring layout —
whitespace, quotes, semicolons, trailing commas — when deciding whether a file was edited.
--no-format skips the formatter.
Uncommitted changes
A merge rewrites a file you edited. If that edit was never committed there is no way back to it, so
update asks before merging into a file with uncommitted changes — and with no one to ask, skips
it and names it. --force merges anyway. Replacing a file you never touched needs no such care.
Components copied before the lock existed
They have no entry to merge from. update records every such file that still matches the registry,
and leaves the rest alone. If you know the ref they were copied from, name it and they merge like
any other:
delacour update --base v0.1.0At a terminal you do not have to know that in advance. When a run skips files for this reason it
finishes, shows what it did, and then asks what to do with them: leave them, merge them from a ref
you type in, or replace them with the registry's copy. Replacing drops your edits to those files,
so it asks again before touching one with uncommitted changes. Under --yes, --json, in CI and
over MCP nothing is asked and the files stay skipped.
Options
Usage: delacour update [options] [components...]
bring copied components up to the registry, merging with your edits
Arguments:
components components to update, or every one in this project
Options:
-n, --dry-run show what would change and write nothing
--base <ref> the ref to merge from, for files copied before the lock
existed
--prune delete untouched files their component no longer has
-f, --force merge into files with uncommitted changes
--no-format compare without running the project's formatter
-y, --yes accept every default without asking
--install install any packages the updated components need, without
asking
--no-install write the files and install nothing
--json print JSON
--silent print nothing but errors
--registry <url> registry to read from: a URL, github:owner/repo, or a local
path
--ref <ref> git ref to read the registry at (default: "main")
--offline use only what is already cached
-c, --cwd <path> directory to work in (default: the current directory)
-h, --help display help for commanddiff
Shows what update would change, and changes nothing.
delacour diff
delacour diff buttonIt prints the plan update applies rather than a comparison of its own, so the two cannot disagree.
For a file the lock knows, that is the registry's change by itself — your edits are not in the
diff, because they are not what moved. For a file with no lock entry there is nothing to tell the
two apart, so both sides are printed and no winner is picked.
Options
Usage: delacour diff [options] [name]
show what an update would change in the files you copied
Arguments:
name one component, or every installed one
Options:
--silent print nothing but errors
--registry <url> registry to read from: a URL, github:owner/repo, or a local
path
--ref <ref> git ref to read the registry at (default: "main")
--offline use only what is already cached
-c, --cwd <path> directory to work in (default: the current directory)
-h, --help display help for commandtheme
Brings a theme across from a web app. Paste a shadcn or tweakcn globals.css over theme.css
and run it with nothing else:
delacour themeOr name the source and it writes theme.css for you:
delacour theme ./src/app/globals.css
delacour theme https://tweakcn.com/r/themes/<id>
pbpaste | delacour theme -With no source the command reads theme.css where it sits. A file already in the shape Uniwind
reads is left alone, so running it twice is safe; a file in neither shape is named rather than
guessed at. delacour doctor fails on a theme.css still in shadcn's shape, so a forgotten run is
caught before a build.
The palette these components paint from is shadcn's, name for name, so a globals.css or a tweakcn
export is already almost the right file. What it is not is readable. Uniwind takes a theme only
from @variant light / @variant dark; a literal .dark { … } is registered as a utility class
named dark and contributes nothing — no error, no warning, and a dark theme that never arrives.
So the command rewrites the wrapper, and three other things besides:
- Fills the gaps. shadcn has no
elevated,tertiary,success/warning/info, the-softpairs oroverlay, and components here paint with all of them. Each is written as an expression over a token your theme does define, so it follows your palette instead of falling back to the library's. shadcn v4 also stopped declaringdestructive-foreground, which every destructive control here paints its label with; that and the shadow scale are filled in too. - Balances the two themes. A shadcn theme routinely sets something in
:rootand omits it from.dark. Uniwind refuses to build that — "All themes must have the same variables" — so anything declared once is copied across. - Keeps one family name per font. React Native's
fontFamilytakes a single name with no fallback list, so"Inter, ui-sans-serif, system-ui"resolves to nothing and quietly falls back to the system sans. The first real family is kept and the rest reported.
It writes theme.css in your configured styles directory, asking first. --dry-run prints the CSS
instead and needs no project at all, so you can see what a theme becomes before adopting it.
A derived corner step in the source — --radius-sm, --radius-lg — is dropped and reported. Here
every corner is a multiple of one --radius, so carrying your own steps would pin them at one size
and fight the scale. Setting --radius alone retunes them all. See
Theming.
Options
Usage: delacour theme [options] [source]
convert theme.css in place, or bring a shadcn or tweakcn theme across from a web
app
Arguments:
source a CSS file, a URL, or `-` to read stdin — optional; with no
source, theme.css is converted where it sits
Options:
-c, --cwd <path> directory to work in (default: the current directory)
--dry-run print the CSS instead of writing it
-y, --yes replace theme.css without asking
--silent print nothing but errors
-h, --help display help for commanddoctor
Checks that the app is wired up for these components. Every check is a failure mode that produces no error on its own — see Troubleshooting. Exits non-zero when a check fails, so it works in CI.
delacour doctorOptions
Usage: delacour doctor [options]
check that this Expo app is wired up for these components
Options:
-c, --cwd <path> directory to work in (default: the current directory)
--json print JSON
--fast skip the checks that shell out to the Expo CLI
--silent print nothing but errors
-h, --help display help for commandmcp
Runs as an MCP server over stdio so a coding agent can browse and add components. See Agents.
Options
Usage: delacour mcp [options]
run as an MCP server, so an agent can browse and add components
Options:
-c, --cwd <path> directory to work in (default: the current directory)
--registry <url> registry to read from
--ref <ref> git ref to read the registry at
-h, --help display help for commandskills
Installs the agent skill into whichever coding assistants this project uses. See Agent skills.
bunx delacour@latest skillsNothing is fetched — the files are bundled into the binary, so a run works offline and installs the skill that matches the version of the CLI this project is pinned to.
Options
Usage: delacour skills [options] [skills...]
install the agent skill, so a coding assistant uses the real components
Arguments:
skills which skills to install — all of them by default
Options:
--agent <agent...> which assistants to install for; detected from the project
by default (choices: "claude", "cursor", "opencode",
"codex", "all")
--scope <scope> where to install (choices: "project", "user", default:
"project")
--list print what is available and where it would go
-f, --force replace a skill that is already there
-c, --cwd <path> directory to work in (default: the current directory)
--silent print nothing but errors
-h, --help display help for commandShared options
--cwd decides which native-components.json applies: the nearest one, walking upwards. The walk
stops at the repository root — past it lie your other projects.
See The registry for pinning a ref and pointing at a fork.