Plugin install scope in installed_plugins.json doesn't match actual accessibility via enabledPlugins
Summary
When a plugin is installed via an npx registry with a specific scope (project or local) and projectPath, the plugin is recorded in ~/.claude/plugins/installed_plugins.json with that scope restriction. However, the plugin files are stored globally in ~/.claude/plugins/cache/, and the plugin is added to enabledPlugins in ~/.claude/settings.json — which makes it accessible from all projects, regardless of the recorded scope.
Current Behavior
1. Plugin storage is always global
All plugin files are stored in ~/.claude/plugins/cache/<registry>/<plugin-name>/<hash>/, regardless of the install scope. For example:
~/.claude/plugins/cache/claude-plugins-official/frontend-design/2cd88e7947b7/skills/frontend-design/SKILL.md
2. installed_plugins.json records scope + projectPath
{
"frontend-design@claude-plugins-official": {
"name": "frontend-design",
"registry": "claude-plugins-official",
"scope": "local",
"projectPath": "/Users/user/Work/project-a/folder",
"version": "..."
}
}
This suggests the plugin should only be active for project-a/folder when scope is local.
3. settings.json enabledPlugins overrides scope
{
"enabledPlugins": {
"frontend-design": true
}
}
This makes the plugin callable from any project directory, contradicting the scope recorded in installed_plugins.json.
4. Claude CLI confirms global access
Running claude from any project directory allows calling skills from the "local"-scoped plugin — it works from /Users/user/Work/project-b/, /Users/user/Work/project-c/, etc., not just from the recorded projectPath.
Expected Behavior
One of:
- Option A: If a plugin is installed with
scope: "local"orscope: "project", it should only be accessible from the matchingprojectPath. TheenabledPluginsentry should either not be created for scoped plugins, or should include scope metadata. - Option B: If
enabledPluginsis meant to make plugins globally accessible, theninstalled_plugins.jsonshould not record misleadingscope/projectPathvalues, or the scope should be set to"user"for globally-enabled plugins.
Impact
Third-party tools (like configuration UIs) that read installed_plugins.json to determine which plugins are active for a given project cannot rely on the scope/projectPath fields, since the actual accessibility is determined by enabledPlugins in settings.json. This creates a discrepancy between "where the plugin was installed from" and "where the plugin is actually usable."
Reproduction
- Navigate to a project directory, e.g.
/path/to/project-a - Install a plugin with local scope:
claude plugin add frontend-design --scope local - Verify
installed_plugins.jsonrecordsscope: "local"andprojectPath: "/path/to/project-a" - Navigate to a completely different project:
cd /path/to/project-b - The plugin's skills are still callable from project-b
Environment
- Claude Code CLI
- macOS / Linux
- Plugin system v2 format (
installed_plugins.json)
This issue has 2 comments on GitHub. Read the full discussion on GitHub ↗