Plugin update defaults to user scope, fails for project-scoped-only plugins
Description
The Update button in Settings → Plugins (and the bare claude plugin update <plugin> CLI command) always checks/updates at user scope, even when the plugin is only installed at project scope. This makes it impossible to update a project-scoped-only plugin from the UI — it fails every time with a scope-mismatch error, even though the same Settings panel correctly displays Scope: Project (shared) for that plugin.
Environment
- Claude Code version: 2.1.204 (macOS, Darwin 25.5.0)
- Plugin:
ievo@ievo-skills(marketplaceievo-skills, githubievo-ai/skills) - Installed at
projectscope via.claude/settings.json→"enabledPlugins": {"ievo@ievo-skills": true} - No
user-scope installation of this plugin exists (confirmed viaclaude plugin list)
Steps to reproduce
- Have a plugin enabled only at
projectscope (viaenabledPluginsin the project's.claude/settings.json), with nouser-scope install of the same plugin. - Open Settings → Plugins → select the plugin → click Update (a new version is available upstream).
- Observe the toast:
Failed to update plugin.
Or via CLI, from the project root:
$ claude plugin update ievo@ievo-skills
Checking for updates for plugin "ievo@ievo-skills" at user scope…
✘ Failed to update plugin "ievo@ievo-skills": Plugin "ievo" is not installed at scope user
Root cause
claude plugin update defaults its -s/--scope flag to user (per claude plugin update --help):
Options:
-s, --scope <scope> Installation scope: user, project, local, managed
(default: user)
The Settings UI's Update button appears to invoke the same code path without passing the plugin's actual installed scope, even though the same panel already knows and displays the correct scope (Project (shared)).
Passing the scope explicitly works fine:
$ claude plugin update ievo@ievo-skills --scope project
Checking for updates for plugin "ievo@ievo-skills" at project scope…
✔ Plugin "ievo" updated from 0.47.4 to 0.49.3 for scope project (/path/to/project). Restart to apply changes.
Log evidence from ~/Library/Logs/Claude/main.log:
2026-07-08 07:49:00 [info] [CCDMarketplacePluginManagerCLI] Updating plugin: ievo@ievo-skills
2026-07-08 07:49:04 [info] [HostCLIRunner] Command completed with exit code 1
2026-07-08 07:49:04 [error] [CCDMarketplacePluginManagerCLI] Failed to update plugin: Checking for updates for plugin "<plugin>@other" at user scope…
✘ Failed to update plugin "<plugin>@other": Plugin "ievo" is not installed at scope user
Secondary (cosmetic) bug
The error message text itself shows a literal, un-interpolated placeholder — "<plugin>@other" — instead of the real plugin id and scope ("ievo@ievo-skills" / project), even though the preceding info-level log line correctly logs Updating plugin: ievo@ievo-skills. This doesn't change the underlying failure but makes the toast/error confusing to debug.
Expected behavior
The Settings UI Update button (and claude plugin update <plugin> when run without an explicit -s/--scope flag) should resolve/update at the plugin's actual installed scope, not unconditionally default to user. At minimum, the error message should name the real plugin id and scope instead of the placeholder <plugin>@other.
Workaround
Run claude plugin update <plugin> --scope project (or whatever scope the plugin is actually installed at) explicitly from the project root, then restart Claude Code to apply the change.