[BUG] Project-scope plugin installs are unremovable: uninstall says "enabled at project scope", disable says "already disabled" (still repro on v2.1.199; #62966 stale-closed)
Summary
A plugin registered at project scope cannot be removed through any documented command sequence:
claude plugin uninstall <name>@<market>refuses with
Plugin "<name>@<market>" is enabled at project scope (.claude/settings.json, shared with your team). To disable just for you: claude plugin disable <name>@<market> --scope local
- The suggested command
claude plugin disable <name>@<market> --scope localrefuses withalready disabled at local scope;--scope projectlikewise reportsalready disabled at project scope.
The two guards contradict each other, producing a deadlock. This is the same symptom as #62966, which was closed as stale (NOT_PLANNED) by github-actions on 2026-06-28 with an invitation to open a new issue if still relevant. It is still fully reproducible on v2.1.199 — and on Windows, whereas #62966 was reported on macOS.
Environment
- Claude Code: 2.1.199 (also reproduced on 2.1.198 earlier the same day)
- OS: Windows 11 Pro 25H2 (build 26200), PowerShell 7.6.3
- Reproduced with:
superpowers@superpowers-marketplace(project 5.1.0 / user 6.1.1) andskill-codex@skill-codex
Steps to reproduce
- Have a plugin registered at project scope in
~/.claude/plugins/installed_plugins.json(entry with"scope": "project", "projectPath": "<proj>"). In our case these were legacy registrations created by earlier installs. - Ensure the plugin appears in no
enabledPluginsmap: not in<proj>/.claude/settings.json, not in<proj>/.claude/settings.local.json, not in~/.claude/settings.json(verified by grep), and no per-project entry in~/.claude.json. - From the project directory run
claude plugin uninstall <name>@<market>→ rejected: "is enabled at project scope (.claude/settings.json…)". - Run the suggested
claude plugin disable <name>@<market> --scope local→ rejected: "already disabled at local scope". Same for--scope project. - Repeat step 3 → same rejection. No documented path removes the registration.
Expected vs actual
- Expected: either
uninstallremoves a project-scope installation (optionally after a confirmation), ordisableclears whatever state the uninstall guard reads. Error messages should not contradict each other. - Actual: uninstall's guard appears to read the install registry (treating a project-scope installation as implicitly enabled), while disable reads the settings maps — so each command claims the other's state.
Two additional findings while working around this
uninstalltargets user scope first, regardless of cwd. With the same plugin installed at both user (6.1.1) and project (5.1.0) scope, runningclaude plugin uninstallfrom the project directory (after removing its settings enablement) removed the user-scope 6.1.1 installation and left both stale project-scope 5.1.0 entries. Surprising and effectively data-losing (the newest install disappears first).- Registry parsing is silently all-or-nothing. While repairing the registry by hand we learned that every value in the
pluginsmap must be an array; if a single entry is written as a plain object,claude plugin list --jsonreturns[](the entire registry is treated as invalid) with exit 0 and no diagnostic. A per-entry tolerance or an explicit parse error would make recovery much easier.
Workaround (for others hitting this)
Back up and edit ~/.claude/plugins/installed_plugins.json directly: remove the "scope": "project" entries for the affected plugin, keep the value an array, keep the user-scope entry. After that, plugin list and per-project enabledPlugins behave as expected.
Related
- #62966 — identical uninstall/disable contradiction (macOS, stale-closed NOT_PLANNED 2026-06-28; this issue confirms it is still present on 2.1.199/Windows)
- #70655 — umbrella report of connected plugin-management issues (scope flag, duplicate entries)