Enabling a plugin writes all its transitive dependency plugins into the consumer's settings.json enabledPlugins
Environment: Claude Code 2.1.177 (macOS)
Summary
When a user enables a plugin that declares dependencies (in particular a "dependencies-only" convenience bundle that carries no skills of its own), Claude Code resolves the dependency tree and persists each resolved plugin as its own name@marketplace: true key in the enabling user's enabledPlugins. Only the plugin(s) the user explicitly chose should be recorded; transitive/inner dependencies should be resolved transparently at load time, not materialized into the consumer's settings.
Steps to reproduce
- In a marketplace, create plugin
Awith"dependencies": ["B"], and pluginBwith"dependencies": ["C"]. - Enable only plugin
Avia/plugin. - Inspect
~/.claude/settings.json→enabledPlugins.
Expected
- Only the explicitly-enabled plugin (
A) is written toenabledPlugins. - Its dependencies (
B,C) are resolved transparently at load time. - If
Alater changes its dependency set, the resolved set tracks it automatically — no stale entries left behind in the user's settings.
Actual
- Every transitive dependency is written individually into
enabledPlugins(A,B,C) — including plugins the user never explicitly selected. /reload-pluginsreflects this, reporting resolved dependencies being added.- The list no longer reflects user intent; it reflects a flattened, frozen snapshot of the dependency graph.
Impact
settings.jsonis polluted with plugins the user didn't choose, obscuring intent.- Stale entries persist when a plugin's dependency set changes (e.g. a dependency that was merged into another plugin remains listed/enabled).
- Defeats the purpose of a "single entry" convenience bundle and complicates team-level (
.claude/settings.json) curation.
Suggested fix
Persist only explicitly-enabled plugins in enabledPlugins; resolve dependencies transparently at load time (treat dependency-enabled plugins as derived state, not persisted state). Optionally distinguish "user-enabled" vs "dependency-enabled" so the latter can be recomputed and pruned automatically.