--- id: "0018" date: 2026-07-03 status: Accepted supersedes: superseded-by: affected-paths: [] affected-components: [] migration_confidence: medium migration_source: "docs/memory-system/03-architecture-decisions.md### ADR-018 — Plugin renames must update the marketplace manifest, not just the directory and settings.json" --- # 0018 — Plugin renames must update the marketplace manifest, not just the directory and settings.json ## Context The `memory` plugin directory was renamed to `os-vault` (git rename, `plugins/memory/` → `plugins/os-vault/`), the `~/.claude/plugins/os-vault` symlink was updated, and `settings.json`'s `enabledPlugins` was flipped to `os-vault@local-plugins`. Despite this, no `os-vault` slash commands (skills) were available in-session. Root cause: the `local-plugins` marketplace manifest (`~/.claude/plugins/.claude-plugin/marketplace.json`) — which explicitly lists each plugin's `name`/`source` rather than auto-discovering the directory — still declared only `memory`/`./memory`, and `installed_plugins.json` still held a stale install record for `memory@local-plugins`. Hooks kept firing throughout (they're wired by absolute path directly in `settings.json`, bypassing plugin resolution entirely), which masked the break — everything looked healthy except the skills/slash-commands. ## Decision A local-plugin rename/move is a three-file operation: (1) the plugin directory or symlink, (2) the marketplace manifest entry (`name` + `source`), (3) `settings.json` `enabledPlugins`. After all three, run `claude plugin marketplace update ` to re-validate, `claude plugin install @` to create the new install record, and `claude plugin uninstall @` to drop the stale one — then verify with `claude plugin list` and `claude plugin details @` (skills/agents/hooks inventory). Documented as a standing procedure in `CLAUDE.md` under "Renaming or moving a local plugin." - **Rationale**: The marketplace manifest is the actual source of truth for what plugins exist under a directory-source marketplace — the directory listing itself is not consulted for plugin identity. Because hooks are independently wired by path, they give a false signal that the plugin is fully operational; skill/slash-command registration must be checked separately via `claude plugin details`. ## Consequences Renaming a local plugin is now a documented three-file operation (directory/symlink, marketplace manifest entry, settings.json enabledPlugins) followed by marketplace update, install of the new record, and uninstall of the stale one, verified via `claude plugin details`. This was necessitated because the memory→os-vault rename left skills unavailable despite hooks still firing, since hooks are wired by absolute path and gave a false signal of full functionality while the marketplace manifest (the actual source of plugin identity) still pointed at the old name. ## Alternatives rejected **Rely on directory listing / auto-discovery** — not how `local-plugins` (a directory-source marketplace) resolves plugins; the manifest is authoritative. **Skip the install/uninstall refresh, just fix the manifest** — leaves a stale cached install record in `installed_plugins.json` under the old name, which is confusing and can mask a future rename of the same kind. - **Consequences / ongoing contracts**: any future rename of `os-vault` (or a new local plugin) must touch the marketplace manifest, not just `settings.json`. `claude plugin details @` is the verification step to run after any plugin registration change — it surfaces the skill/agent/hook inventory that a passing hook test would not.