feat(21st): replace the magic MCP with the @21st-dev CLI + skill pack

Upstream supersedes `@21st-dev/magic` with `@21st-dev/cli` (bin `21st`):
same endpoint, `21st login` in place of an API key, no MCP process loaded
into every session.

- install-plugins.sh Step 8.7: `npm i -g @21st-dev/cli` (pinned in
  plugins.lock.json), staged `21st skills install`, TTY-only login offer,
  pack disabled by default. update-all.sh 7.4 refreshes both.
- The documented `21st install-skill` cannot be used: the installer refuses
  to follow a symlink on the target path and `~/.claude/skills` is one. The
  install runs under a throwaway HOME and the result moves into
  skills-external/21st-* (gitignored), symlinked on demand.
- toggle-external.sh manages `21st` as a pack (names globbed from
  skills-external/21st-*, parked under plain names). `magic` is gone.
- The 5 design skills join design/web/web-full/full and MANAGED_EXTERNALS;
  21st-registry and 21st-design-sync stay parked. MANAGED_MCPS is now empty
  and profile.sh's dead magic branches are removed.
- Design gate: GATE-BLOCK gains `21st` (required-manual, magic's old slot)
  and `21st-ui-build`; PATH repair extended to the npm global bin.
- settings.json: the 4 mcp__magic__* ask entries go; the outward-facing
  21st verbs land in autoMode.soft_deny, the tier that holds under auto
  mode (LRN-153).
- Docs: README, CLAUDE.global.md, design-gate.md, profile SKILL.md,
  .env.example, .gitleaks.toml, link.sh. BDR-093, LRN-158.

Tests: profile-set-managed 17/17, make test green except 2 pre-existing
gitflow FAILs (gitleaks binary absent on this host), shellcheck clean.
This commit is contained in:
bastien
2026-09-22 02:53:31 +00:00
parent 413b35a913
commit 7c05f75eab
26 changed files with 515 additions and 195 deletions
+16 -21
View File
@@ -11,7 +11,7 @@
# Mechanism:
# - Skills (gstack/external/personal): symlink toggle skills/ ↔ skills-disabled/
# - Plugins: `claude plugin enable|disable <name>@<marketplace>`
# - MCPs: delegated to lib/toggle-external.sh for known servers (magic),
# - MCPs: advisory (none managed since BDR-093 — MANAGED_MCPS is empty),
# advisory otherwise
# - CLIs: advisory only (rtk, gsd, ctx7, graphify — installed externally)
# - `set` is SYMMETRIC on managed items (BDR-079): plugins, external packs
@@ -51,7 +51,6 @@ SKILLS_DIR="$REPO/skills"
DISABLED_DIR="$REPO/skills-disabled"
GSTACK_SRC="$REPO/skills-external/gstack" # gstack submodule — source of truth for gstack skills
PROFILES_DIR="$REPO/lib/profiles"
TOGGLE_EXTERNAL="$REPO/lib/toggle-external.sh"
ACTIVE_CACHE="$REPO/.active-profile" # statusline reads this — keep fast (single-line file, profile name only)
# Plugins that are toggle-managed by `set`. Anything NOT in this list is
@@ -73,13 +72,20 @@ MANAGED_EXTERNALS=(
frontend-design
design-motion-principles
impeccable
21st-ui-build
21st-ui-explore
21st-ui-review
21st-cli-use
21st-ai
)
# MCP servers that are toggle-managed by `set`, both ways (enable AND
# disable), delegated to lib/toggle-external.sh. Same allowlist doctrine.
MANAGED_MCPS=(
magic
)
# Empty since 2026-09-22: `magic` was the only entry and 21st.dev replaced
# its MCP server with a CLI + skill pack (the 5 design skills are managed as
# externals above). The `mcp` type itself stays supported — a profile can
# still list an MCP, it is then advisory rather than auto-toggled.
MANAGED_MCPS=()
# Plugins that MUST stay enabled — `set` will refuse to disable these even if
# they're not in the profile. (Defensive: belt-and-suspenders alongside
@@ -324,15 +330,12 @@ enable_skill() {
fi
;;
mcp)
# Advisory only. The delegation branch that lived here served `magic`,
# the single managed MCP; 21st.dev replaced it with a CLI (BDR-093), so
# MANAGED_MCPS is empty and nothing is auto-registered. Re-add a branch
# here the day a profile owns an MCP server again.
if [ "$(skill_status "$skill" mcp)" = "enabled" ]; then
: # already on
elif [ "$skill" = "magic" ] && [ -x "$TOGGLE_EXTERNAL" ]; then
# Known MCP — delegate to lib/toggle-external.sh which handles env vars.
if bash "$TOGGLE_EXTERNAL" enable magic 2>&1 | grep -qE "enabled|already"; then
ok "enabled MCP: magic"
else
info "MCP 'magic' could not be enabled (check .env for MAGIC_API_KEY)"
fi
else
info "MCP '$skill' not registered — run: claude mcp add $skill -- <command>"
fi
@@ -394,15 +397,7 @@ disable_skill() {
info "plugin '$skill' — manual: claude plugin disable $skill@<marketplace>"
;;
mcp)
if [ "$skill" = "magic" ] && [ -x "$TOGGLE_EXTERNAL" ]; then
if bash "$TOGGLE_EXTERNAL" disable magic 2>&1 | grep -qE "disabled|already"; then
ok "disabled MCP: magic"
else
info "MCP 'magic' — manual disable failed"
fi
else
info "MCP '$skill' — manual: claude mcp remove $skill"
fi
info "MCP '$skill' — manual: claude mcp remove $skill"
;;
cli)
: # never auto-uninstall CLIs