Project-scoped plugins show as "Installed" in other projects, blocking re-installation

Resolved 💬 2 comments Opened Feb 27, 2026 by xiaolai Closed Mar 27, 2026

Summary

When a plugin is installed with project scope, it appears as "Installed" when viewing /plugins from any other project. Since it already shows as "Installed," there is no option to install it to the current project. This means a project-scoped plugin effectively cannot be installed into additional projects through the UI.

Steps to Reproduce

  1. Open Claude Code in Project A
  2. Run /plugins > browse a marketplace > install a plugin with project scope
  3. Open Claude Code in Project B
  4. Run /plugins > browse the same marketplace
  5. The plugin shows as "Installed" even though it was only installed for Project A
  6. There is no "Install to this project" option available

Expected Behavior

  • The plugin should only show as "Installed" if it is installed at user scope (global) or installed at project scope for the current project
  • When a plugin is project-scoped for a different project, the UI should offer an "Install to this project" option

Actual Behavior

The plugin shows as "Installed" regardless of which project you're in, with no way to install it to the current project.

Root Cause Analysis

~/.claude/plugins/installed_plugins.json stores all installations in a single registry. Each plugin key maps to an array of entries with scope and projectPath fields. The data model correctly supports multiple project-scoped installations — for example:

{
  "some-plugin@some-marketplace": [
    {
      "scope": "project",
      "projectPath": "/path/to/project-a",
      "version": "1.0.0"
    },
    {
      "scope": "project",
      "projectPath": "/path/to/project-b",
      "version": "1.0.0"
    }
  ]
}

The issue is in the UI layer: it checks whether the plugin key exists in the registry and marks it as "Installed," without filtering entries by whether projectPath matches the current working directory.

The check likely does:

isInstalled = pluginId in installedPlugins.plugins

Instead of:

isInstalled = installedPlugins.plugins[pluginId]?.some(
  entry => entry.scope === "user" || entry.projectPath === currentProjectPath
)

Secondary Issue: Duplicate Entries

The registry also accumulates duplicate entries for the same plugin + project combination. For example, a single plugin installed once to a project may end up with two identical entries in the array. This suggests the install action does not deduplicate before appending.

Environment

  • Claude Code v2.1.62
  • macOS (arm64)

View original on GitHub ↗

This issue has 2 comments on GitHub. Read the full discussion on GitHub ↗