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 init

Options

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 command

add

Copies components in, with everything they need.

bunx delacour@latest add button input field
delacour add --all

It 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 command

list

Everything the registry holds. Works before native-components.json exists — which is exactly when you are deciding whether to run init.

delacour list

Options

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 command
delacour search sheet

Options

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 command

view

Prints an item's files, the components it copies in, and the packages it installs.

delacour view button
Button  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 tailwindcss

The 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 command

info

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 info

Options

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 command

update

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-run

add 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 fileWhat update does
Changed in the registry onlyReplaces it
Changed by you onlyLeaves it alone
Changed by both, on different linesMerges the two
Changed by both, on the same linesWrites both sides between conflict markers, and exits 1
New to the componentWrites it
Dropped from the componentLeaves 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@3ac4ac4

Keep 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.0

At 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 command

diff

Shows what update would change, and changes nothing.

delacour diff
delacour diff button

It 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 command

theme

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 theme

Or 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 -soft pairs or overlay, 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 declaring destructive-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 :root and 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 fontFamily takes 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 command

doctor

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 doctor

Options

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 command

mcp

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 command

skills

Installs the agent skill into whichever coding assistants this project uses. See Agent skills.

bunx delacour@latest skills

Nothing 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 command

Shared 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.

On this page