CLI

The @blotch/dolan CLI copies UI components into your app, then tells you when they change and merges the updates for you. Run every command from your project folder.

npx @blotch/dolan <command> [options]
  • Once @blotch/dolan is a dependency (see installation), npx runs your installed copy. The shorter npx dolan <command> works too.
  • npx @blotch/dolan --help lists the commands, and <command> --help lists a command's options. --version prints the version.
  • Every command except info needs a dolan.config.json. Run init first.
CommandWhat it does
initSet up dolan and copy the theme files
addCopy components into your app
listShow installed components and their status
infoShow a component's files and dependencies
diffShow how your copy differs from the bundled source
outdatedList components that aren't up to date (exits 1 if any)
updateMerge the bundled source into your copies
removeDelete a component
ejectStop recording a component's file hashes
themeList theme files, or start a new one
doctorCheck your setup

Where updates come from

The CLI package contains the component source. It doesn't download anything. So "upstream" in every command means the source bundled with the @blotch/dolan version you have installed.

To get newer components, upgrade the CLI and then update:

npm install @blotch/dolan@latest
npx @blotch/dolan update

The CLI keeps two files at the project root. Commit both.

  • dolan.config.json: where components and theme files go. Paths are relative to the project folder.
  • dolan.lock.json: a hash of every copied file, as it was when dolan wrote it. Comparing it with your file and the bundled source tells dolan who changed what.
dolan.config.json
{
  "aliases": {
    "components": "src/components/ui",
    "theme": "src/styles"
  }
}

If your project has an .oxfmtrc.json and oxfmt installed, dolan formats the .ts files it writes with your settings.

init

npx @blotch/dolan init

Asks two questions, then sets up the project:

PromptDefault
Where should components be installed?src/components/ui
Where should theme files be installed?src/styles
  • Writes dolan.config.json. If one exists, it asks before overwriting (default No).
  • Copies default.css, dark.css and tailwind-plugin.ts into the theme folder. It overwrites them if they're already there, so running init again resets your theme edits.
  • Creates the components folder and prints the next steps. The printed @import path starts at the project root. From src/styles.css, it's ./styles/default.css.

Options: none.

add

npx @blotch/dolan add [components...]

Copies each component into <components>/<name>/. With no names, it shows a checklist.

  • Dependencies come too. Adding button also adds spinner, and the CLI prints what it added.
  • Imports are rewritten. cn() and the animation helpers are imported from @blotch/dolan/utils/cn and @blotch/dolan/utils/animate.
  • Unit tests are copied. Each component brings its <name>.test.ts.
  • Existing components are kept. If a folder already exists, it asks before overwriting (default No) and skips it otherwise.
  • npm packages are installed. If a component imports a package your package.json lacks, add installs it with your package manager (npm, pnpm, yarn or bun, detected from the lockfile). Today only chart and the chart presets need any: @tanstack/charts and d3-shape.
Argument or optionDescription
[components...]Component names. An unknown name stops the command and lists the valid ones.

list

npx @blotch/dolan list

Alias: ls. Prints each installed component with its status and file count. Only folders named after a known component count, so your own folders are ignored.

StatusJSON valueMeaning
up to dateup-to-dateYour copy matches the bundled source.
outdatedauto-updateYou haven't edited it, and the bundled source changed or added a file.
modifieduser-modifiedYou edited it, and the bundled source hasn't changed.
conflictconflictBoth changed, or dolan has no hash for a file that differs.
Argument or optionDescription
--jsonPrint { "components": [{ "name", "status", "fileCount" }] } instead.

info

npx @blotch/dolan info <component>

Prints a component's files, the components it depends on, and the components that use it. With a dolan.config.json, it also shows what's installed. It works without one.

Argument or optionDescription
<component>The component name.

diff

npx @blotch/dolan diff [component]

With a name, it prints every file that differs from the bundled source. Lines starting with - are yours, and lines starting with + are upstream. Without a name, it lists the changed components and asks which to show.

Argument or optionDescription
[component]Show this installed component only.

outdated

npx @blotch/dolan outdated

Lists the installed components that aren't up to date, using the statuses above. It exits with code 1 when there are any, so a CI job can fail on it. Components you edited count as well.

Argument or optionDescription
--jsonPrint { "components": [...] }, still exiting 1 if not empty.

update

npx @blotch/dolan update

Merges the bundled source into every installed component, file by file:

Your fileBundled sourceWhat update does
UnchangedChanged, or new fileAsks once whether to apply all of these (default Yes), then overwrites.
EditedUnchangedKeeps yours.
EditedChangedConflict. Asks per file: show the diff, keep yours, take upstream, or review it hunk by hunk.
  • No hash means conflict. A file with no recorded hash that differs from upstream is a conflict. That covers ejected components, and theme files you edited before your first update.
  • Theme files (default.css, dark.css, tailwind-plugin.ts) are merged the same way. Themes you made with theme aren't.
  • New dependencies are added. If a component's new version needs another component, update copies it in.
  • npm packages are installed the same way add does.
  • You're asked about a conflict once. After you choose, the lockfile records the new upstream hash. If you kept your version, the file shows as modified until upstream changes again.
Argument or optionDescription
-f, --forceOverwrite every file with upstream, discarding your changes. Wins over --selective.
-s, --selectiveReview every changed file one at a time, including your own edits. "Skip for now" asks again next run.

remove

npx @blotch/dolan remove <component>

Alias: rm. Deletes the component's folder and its lockfile entry.

  • If other installed components depend on it, it warns and asks first (default No).
  • It offers to remove dependencies that nothing else uses (default Yes). It looks one level deep, so remove deeper dependencies yourself.
  • It doesn't uninstall npm packages.
Argument or optionDescription
<component>An installed component.
-f, --forceSkip both questions: remove it even if others depend on it, and remove unused dependencies.

eject

npx @blotch/dolan eject <component>

Removes the component's file hashes from dolan.lock.json and leaves its files alone. It asks first (default No).

Warning

update, list, diff and outdated still read every folder named after a component, ejected or not. With no hash recorded, update treats each file that differs from upstream as a conflict and asks you, and update --force overwrites it. To hide a component from dolan, rename its folder and the imports that point at it.

Argument or optionDescription
<component>An installed component.
-f, --forceSkip the confirmation question.

theme

npx @blotch/dolan theme [name]

Without a name, it lists the .css files in your theme folder. With a name, it copies default.css to <theme folder>/<name>.css for you to edit. It stops if that file exists.

Import the new file in place of default.css. See Theming.

Argument or optionDescription
[name]Create a theme file with this name.

doctor

npx @blotch/dolan doctor

Runs these checks in order and exits with code 1 if any fail:

CheckIf it doesn't pass
dolan.config.json exists, is valid JSON and has components, utils and theme pathsFails and stops
The components and theme folders existFails
The theme folder has tailwind-plugin.ts, and default.css or dark.cssWarns
tailwind.config.ts or .js exists and mentions blotchPluginWarns
package.json lists @angular/core, @angular/common, @angular/platform-browser, @angular/router and @blotch/angular-lynxFails
package.json lists tailwindcssWarns
Every component folder is a known component, has all its files and has its dependenciesWarns

init doesn't write a utils path, and no other command reads one. To pass the first check, add "utils": "src/lib/utils" to aliases.

Options: none.