Plugin registry creates duplicate project-scope installs when project path drive-letter casing differs (Windows)

Resolved 💬 1 comment Opened Jul 15, 2026 by jrummell-elite Closed Jul 16, 2026

On Windows, ~/.claude/plugins/installed_plugins.json tracks project-scope plugin installs keyed by projectPath as a raw string, without normalizing casing. Windows drive letters are case-insensitive (P:\foo and p:\foo are the same location), but the registry treats them as different projects.

If Claude Code is launched from the same project directory with inconsistent drive-letter casing across sessions (e.g. P:\Projects\myapp vs p:\Projects\myapp), it creates a second, independent registry entry for the same plugin+project instead of recognizing it as the same install. Both entries then show as enabled simultaneously in claude plugin list, pointing at two different cached versions.

Impact: for plugins that register hooks, both versions' hooks run concurrently. In my case, an old cached version's Stop hook (which unconditionally returned {"decision": "block"} on a persistent failure, with no loop-guard) kept blocking every turn indefinitely — even after installing a newer version that fixed exactly that bug — because Claude Code never recognized the old install as superseded. Running claude plugin uninstall <plugin> --scope project did not reliably resolve it, since the uninstall command's path lookup is presumably subject to the same casing mismatch. Manually deleting the stale entry from installed_plugins.json fixed it.

I saw the same duplication pattern (one entry per casing variant) for several other unrelated plugins in the same project, so this looks systemic to how project paths are keyed, not specific to any one plugin.

Suggested fix: normalize/case-fold projectPath (at least the drive letter on Windows) before using it as a registry key, and make plugin uninstall/plugin list do the same lookup normalization.

View original on GitHub ↗

This issue has 1 comment on GitHub. Read the full discussion on GitHub ↗