refactor!: drop shadcn-init, make shadcn-apply a plain forwarder - #182
Conversation
`shadcn-init` did three jobs and only the middle one was ours: scaffolding is what `shadcn init` already does, with its own eighteen options, and starting a dev server is not a theming tool's business. Removing it takes with it everything that existed to hold those together -- the `--preset b0 --template vite` defaults, the merge that injected them only where the user had not, and reading the project name back out of the merged argv to know where to `cd`. `shadcn-apply` keeps what it does and drops how it second-guessed you. Everything after a `--` now reaches `shadcn add` untouched, with no exception: `--print` and the `Plan`/`Step` model it required are gone, an option of ours written after the separator is forwarded rather than refused with an explanation, and `--shadcn-cli` no longer validates its argument. `--print` also took `specifiedThemeArgs()` and `Theme.args` with it, those having existed only to re-spell the given options into a printed line. The `--yes` on `shadcn add` stays, and owes nothing to `shadcn-init`: shadcn defaults its own to `false` and prompts on a `registry:theme` item, so without it the command hangs in CI. Ours goes first, so a forwarded `--no-yes` still wins on commander's last-one-wins. cli.shadcn.ts 598 -> 112, cli.options.ts 197 -> 156, its tests 550 -> 211. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01FtANJj1cbBZpj12mEXjgSN
…ts choices Two leftovers from the épure pass, both in `cli.ts`. `addChainOptions()` declared a single option and, since `shadcn-init` went, had a single call site -- where `addThemeOptions()` and `addSourceArgument()` each still have two, which is what earns them a function. It cost an export, a cross-file import and a third level of nesting to say `.option()` once. Inlined where the subcommand is declared, next to the `--shadcn` it is named around. `--format` maintained its list of values by hand in its own description, and answered anything else through a `default:` branch: `--format bananas` printed JSON without a word, where `--scheme banana` has always been refused by name. The list is now one `FORMATS` array behind `.choices()` and a `Format` union, so the help text is generated, the typo is refused, and the switch is exhaustive over what the option accepts -- a format can no longer be offered without being written, or written without being offered. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01FtANJj1cbBZpj12mEXjgSN
|
Deux nettoyages de plus, révélés par le premier passage —
# avant
$ material-theme-builder "#6750A4" --format bananas
{ "seed": "#6750A4", ... # du JSON, sans un mot
# maintenant
error: option '--format <type>' argument 'bananas' is invalid.
Allowed choices are json, css, figma, tailwind, shadcn, registry-item, flutter.
|
An épure pass over the two subcommands released yesterday in
3.3.0.shadcn-initgoes;shadcn-applystays and stops second-guessing you.−856 lines net.
cli.shadcn.ts598 → 112, its tests 550 → 211,cli.options.ts197 → 156.shadcn-initis removedIt did three jobs and only the middle one was ours. Scaffolding is what
shadcn initalready does — better, with its own eighteen options — and starting a dev server is not a theming tool's business.Everything that existed to hold those three jobs together goes with it: the
--preset b0 --template vitedefaults,mergeDefaults()/mentions()(which injected them only where you had written none yourself), andlastName()— reading the project name back out of the merged argv, scanning from the end to mirror commander's last-one-wins, so the chain knew where tocd.shadcn-applyis a plain forwarderSame mechanism, same output. What changed is the rule about the
--, which is now true without an asterisk: everything after the separator goes toshadcn adduntouched.--printis gone, and with it thePlan/Step/renderChain/quotemodel (~90 lines) that existed so the printed chain and the run chain could not disagree. On a singleshadcn addthere is nothing left to disagree about. It also tookspecifiedThemeArgs(),THEME_OPTIONSandTheme.argsincli.options.ts, which existed only to re-spell the given options into that printed line.--is no longer refused.refuseOwnOptions()/ownOptionIn()gone.shadcn-apply '#x' -- --scheme vibrantnow getserror: unknown option '--scheme'from shadcn. A worse message, and one rule instead of one rule plus an exception.--shadcn-clino longer validates its argument.parseShadcnSpec()gone; whatevernpxresolves, it runs.What stayed, and why
--yesonshadcn add— and it owes nothing toshadcn-init. Checked against the installed shadcn 4.18.0:adddefaults its own--yestofalse(unlikeinit, where it istrue) and prompts on exactly our item type:--no-yesstill wins on commander's last-one-wins.mtb.jsonguard and theprocess.on("exit")cleanup — this runs in a directory full of someone else's files, and that one is both written and deleted. Not intelligence about options; not leaving a scratch file behind.--scheme,--contrast, the overrides,--prefix,--no-fallback) — the reason the command exists rather than the published impersonal item.shadcn-apply—applyis now a verb borrowed from a command we do not call, but renaming would make the same migration cost twice in one major. The 30-line comment defending it is gone.Verified against the real CLI
Not just unit tests — the built binary against shadcn 4.18.0 in this repo:
shadcn-apply '#6750A4' -- --dry-run62 CSS variables added to src/styles/shadcn.css, exit 0-- --view src/styles/shadcn.css-- --scheme vibrantunknown option '--scheme'— forwarded, as intendedmtb.jsonshadcn addmtb.jsonleft behindpnpm run lgtmgreen: build, figma build, lint, format, exports, typecheck, 213 tests.Semver
Breaking on a surface published yesterday, so: changeset
major→4.0.0. Someone typingshadcn-initgets commander'sunknown command— no migration stub, that being exactly the complexity this PR removes. The3.3.0CHANGELOG entry stays as written; it is history.🤖 Generated with Claude Code
https://claude.ai/code/session_01FtANJj1cbBZpj12mEXjgSN