anthropics / anthropics/claude-code
[BUG] macOS desktop app ignores project-level `enabledPlugins` — every project shows an identical plugin list (CLI and Windows work)
- Dominant language
- Python
- Stars
- 145k
- Forks
- 23.1k
- PR merge metrics
- PR metrics pending
Description
### Preflight Checklist
- [x] I have searched [existing issues](https://github.com/anthropics/claude-code/issues?q=is%3Aissue%20state%3Aopen%20label%3Abug) and this hasn't been reported yet
- [x] This is a single bug report (please file separate reports for different bugs)
- [x] I am using the latest version of Claude Code
### What's Wrong?
The Claude desktop app on macOS resolves `enabledPlugins` **only** from the user-level `~/.claude/settings.json`. It ignores `enabledPlugins` declared in a project's `.claude/settings.json` and `.claude/settings.local.json`, even though it correctly honours other keys from those same files.
The visible result is that the plugin menu (`+` → Plugin) shows an identical list in every project, regardless of each project's own plugin configuration. There is no error and no warning — the project-scoped plugins are simply absent.
The CLI on the same machine, launched from the same directory with the same config files, merges all levels correctly and registers all the plugins. The Windows desktop app also behaves correctly.
## Environment
- Claude desktop app `1.24012.9` (Electron 42.7.0, Node 24.18.0), macOS arm64
- Claude CLI on the same machine: works correctly (control case)
- Claude desktop app on Windows: works correctly (control case)
## Reproduction
Two projects with deliberately different plugin configurations.
**Project A** (`crosscms`) — `/.claude/settings.json`:
```json
{
"enabledPlugins": { "marketing-skills@marketingskills": true }
}
```
`/.claude/settings.local.json`:
```json
{
"enabledPlugins": { "laravel@laravel": true, "impeccable@impeccable": true }
}
```
**Project B** — no project-level `enabledPlugins` at all.
**User level** — `~/.claude/settings.json`:
```json
{ "enabledPlugins": { "mattpocock-skills@mattpocock": true } }
```
`~/.claude/plugins/installed_plugins.json` contains the matching install records with the correct values:
- `mattpocock-skills@mattpocock` — `"scope": "user"`, no `projectPath`
- `marketing-skills@marketingskills` — `"scope": "project"`, `projectPath` = project A
- `impeccable@impeccable` — `"scope": "local"`, `projectPath` = project A
- `laravel@laravel` — `"scope": "local"`, `projectPath` = project A
Steps:
1. Open project A in the macOS desktop app.
2. Click `+` in the composer, then `Plugin`.
3. Open project B and repeat.
## Actual behaviour
Both projects show an identical submenu containing only `mattpocock-skills` — the sole plugin enabled at user level. Every plugin enabled through a project-level settings file is silently missing from project A.
## Ruled out during diagnosis
- **Not a path-resolution mismatch.** `pwd` and `pwd -P` in the project directory return a string identical to the stored `projectPath`. No symlink or firmlink indirection (the project is not under an iCloud-synced folder), no case difference, and no drive letters on macOS. This distinguishes it from #74912.
- **Not a corrupted or unparseable config.** `installed_plugins.json` parses as valid JSON, and the plugin payloads are present under `~/.claude/plugins/cache/`.
- **Not a bad scope record.** The install records carry the correct `scope` and `projectPath`, and the CLI reads the same file successfully.
- **Not a general failure to read project settings.** The `permissions` entries from the very same two project files are applied correctly by the desktop app. Only `enabledPlugins` is dropped.
- **Affects both scopes.** `scope: "project"` and `scope: "local"` entries fail identically.
## Impact
Per-project plugin configuration is unusable from the macOS desktop app. Users who scope plugins per project — the documented purpose of the `--scope project` flag, and a workflow the CLI supports today — see none of them in the GUI, with no signal that the configuration was ignored. The only way to make a plugin visible in the app is to promote it to user scope, which forces it on for every project.
## Related
- #74612 — the same divergence reported for the VS Code extension on Windows. I added the macOS desktop-app evidence there as a comment; filing this separately because the affected surface and platform are different.
- #74912 — proposes case-sensitive `projectPath` comparison (Windows drive letters) as the cause. That explanation cannot cover this case, since the paths here match exactly.
- #62174 — closed as not planned, treating per-project `enabledPlugins` as a feature request. The CLI does honour project-level values today, so the desktop app is inconsistent with shipped behaviour rather than missing a feature.
### What Should Happen?
The macOS desktop app should merge `enabledPlugins` across user, project and local settings files, exactly as the CLI does when launched from the same directory.
Concretely, for the setup above:
- Project A's plugin menu should list `marketing-skills`, `laravel`, `impeccable` and `mattpocock-skills`.
- Project B's plugin menu should list only `mattpocock-skills`.
Failing that, the app should at minimum surface a warning when it encounters `enabledPlugins` in a project settings file that it is not going to honour, rather than dropping it silently.
### Error Messages/Logs
```shell
```
### Steps to Reproduce
Prerequisite: two projects, A and B, with different plugin configurations.
1. In project A's directory, create `.claude/settings.json`:
```json
{
"enabledPlugins": { "marketing-skills@marketingskills": true }
}
```
2. In the same directory, create `.claude/settings.local.json`:
```json
{
"enabledPlugins": { "laravel@laravel": true, "impeccable@impeccable": true }
}
```
3. Leave project B with no project-level `enabledPlugins`.
4. Enable exactly one plugin at user level in `~/.claude/settings.json`:
```json
{ "enabledPlugins": { "mattpocock-skills@mattpocock": true } }
```
5. Confirm the install records exist and are correct in `~/.claude/plugins/installed_plugins.json` (`scope` = `project` / `local`, `projectPath` = project A's absolute path).
6. Verify the CLI behaves correctly: `cd` into project A and run `claude plugin list`. All four plugins are reported.
7. Open project A in the macOS desktop app. Click `+` in the message composer, then `Plugin`.
8. Observe: the submenu lists only `mattpocock-skills`. The three project-level plugins are missing, with no error or warning.
9. Open project B and repeat step 7. The submenu is identical, despite the two projects having different configurations.
Control checks that isolate the failure:
10. Confirm the app does read those same project files: the `permissions` entries from step 1 and 2 are applied in project A's sessions. Only `enabledPlugins` is dropped.
11. Confirm there is no path mismatch: `cd` into project A and run `pwd && pwd -P`. Both print a string identical to the `projectPath` stored in `installed_plugins.json`.
### Claude Model
None
### Is this a regression?
Yes, this worked in a previous version
### Last Working Version
Exact version unknown — worked correctly until roughly four releases before 1.22209.3 (build babe11)
### Claude Code Version
Claude desktop app for macOS 1.24012.9 (Electron 42.7.0, Node 24.18.0). The bundled Claude Code runtime on the same machine handles the same config correctly when used from the CLI, which is the control case for this report.
### Platform
Anthropic API
### Operating System
macOS
### Terminal/Shell
Terminal.app (macOS)
### Additional Information
**Note on scope.** This is the Claude desktop app for macOS, not the Claude Code CLI. I am filing it here because the repository tracks desktop-app issues (e.g. #72025, #72179), and because the defect is precisely a divergence from Claude Code's own documented behaviour: the CLI honours project-level `enabledPlugins` and the desktop app does not, on the same machine, in the same directory, reading the same files.
**Previous report.** I filed #79376 earlier describing the user-visible symptom. That report was auto-closed as `invalid` by the triage bot without human review. It was also based on an incorrect root-cause guess on my part — I described the app as showing plugins belonging to *other* projects, when in fact it shows only user-scoped plugins and drops project-scoped ones entirely. This report supersedes it with the corrected diagnosis and the control checks that establish it.
**Relationship to #74612.** That report describes the same divergence for the VS Code extension on Windows. I have added the macOS desktop-app evidence there as a comment. Filing separately here because the affected surface and platform differ, and because the leading hypothesis in that thread (#74912, case-sensitive drive-letter comparison in `projectPath`) cannot explain the macOS case, where the paths match exactly.
Screenshots of the plugin submenu in both projects, and the full contents of `installed_plugins.json`, are available on request. Project and plugin paths in this report have been anonymised; the plugin names are the real ones.
Contributor guide
No contributing guide indexed for this repository
Research direction
Start by reproducing the behavior with .claude/settings.json, .claude/settings.local.json, ~/.claude/settings.json, and ~/.claude/plugins/installed_plugins.json, then compare the desktop app's plugin loading with `claude plugin list` from project A. Done means project A shows all four enabled plugins while project B shows only the user-level plugin, with the existing permission handling preserved.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- electron, macos, node.js
- Domain
- desktop, devtools, tooling
- Issue type
- Bug
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Active
- Clarity
- Mostly clear
- Newbie friendliness
- 58/100