Note: This is a re-filing of #26150, which was incorrectly closed as a duplicate of #24657. These are different bugs:
Description
enabledPlugins defined in settings.local.json has no effect unless enabledPlugins also exists as a key in settings.json. This contradicts the documented settings merge behavior where local scope settings should apply independently and override broader ones.
The docs state:
Settings are merged, with more specific settings adding to or overriding broader ones.
And explicitly list enabledPlugins as valid in user, project, and local scopes.
For example, a user who enables plugins only in settings.local.json will see the /plugin Marketplaces tab correctly report their marketplace with plugins available (e.g., "11 available"), the Discover tab report "All available plugins are already installed," and the Installed tab report "No plugins or MCP servers installed" — all at the same time. There are no errors — plugins silently fail to load, and the only diagnostic signal is three tabs contradicting each other.
100% Reproduction
Setup: Install any plugin from a marketplace so it appears in installed_plugins.json.
Case 1: Local-only enabledPlugins (fails)
- Remove
enabledPlugins from ~/.claude/settings.json entirely
- Add
enabledPlugins to ~/.claude/settings.local.json with plugins set to true
- Restart Claude Code
/plugin > Installed tab: "No plugins or MCP servers installed"
/plugin > Discover tab: "All available plugins are already installed"
- Plugin skills/hooks/commands do not load
Case 2: Local overrides user (works)
- Set
enabledPlugins in ~/.claude/settings.json with all plugins false
- Set
enabledPlugins in ~/.claude/settings.local.json with all plugins true
- Restart Claude Code
/plugin > Installed tab: All plugins shown and enabled
- Plugin skills/hooks/commands load correctly
Root Cause
The settings merge for enabledPlugins only applies overrides to an existing key. If enabledPlugins is absent from settings.json, the local scope values are silently dropped rather than being introduced into the merged result.
Impact
- Users who configure
enabledPlugins exclusively in settings.local.json (as the docs suggest is valid) get silently broken plugins with no error
- The Discover and Installed tabs show contradictory information with no diagnostic signal
- Workaround: ensure
enabledPlugins exists in settings.json (even as {}), then local overrides work
Environment
- Claude Code version: 1.0.33+
- Platform: Linux (Ubuntu), also likely affects macOS/Windows
Description
enabledPluginsdefined insettings.local.jsonhas no effect unlessenabledPluginsalso exists as a key insettings.json. This contradicts the documented settings merge behavior where local scope settings should apply independently and override broader ones.The docs state:
And explicitly list
enabledPluginsas valid in user, project, and local scopes.For example, a user who enables plugins only in
settings.local.jsonwill see the/pluginMarketplaces tab correctly report their marketplace with plugins available (e.g., "11 available"), the Discover tab report "All available plugins are already installed," and the Installed tab report "No plugins or MCP servers installed" — all at the same time. There are no errors — plugins silently fail to load, and the only diagnostic signal is three tabs contradicting each other.100% Reproduction
Setup: Install any plugin from a marketplace so it appears in
installed_plugins.json.Case 1: Local-only enabledPlugins (fails)
enabledPluginsfrom~/.claude/settings.jsonentirelyenabledPluginsto~/.claude/settings.local.jsonwith plugins set totrue/plugin> Installed tab: "No plugins or MCP servers installed"/plugin> Discover tab: "All available plugins are already installed"Case 2: Local overrides user (works)
enabledPluginsin~/.claude/settings.jsonwith all pluginsfalseenabledPluginsin~/.claude/settings.local.jsonwith all pluginstrue/plugin> Installed tab: All plugins shown and enabledRoot Cause
The settings merge for
enabledPluginsonly applies overrides to an existing key. IfenabledPluginsis absent fromsettings.json, the local scope values are silently dropped rather than being introduced into the merged result.Impact
enabledPluginsexclusively insettings.local.json(as the docs suggest is valid) get silently broken plugins with no errorenabledPluginsexists insettings.json(even as{}), then local overrides workEnvironment