claude plugin list reports a plugin enabled with an installPath that no longer exists; payload is never re-materialized

Status Open
Reported on v2.1.215
Maintainer reply None cached
Activity 1 comment · opened Jul 20, 2026

Summary

claude plugin list --json reports a plugin as "enabled": true with an
installPath that no longer exists, when the plugin's payload under
<CLAUDE_CONFIG_DIR>/plugins/cache/<marketplace>/<plugin>/<version>/ has been
removed. Running the CLI again does not re-materialize it, so a plugin the
operator believes is installed contributes none of its skills.

Enablement and the materialized payload are tracked independently and never
reconciled, and there is no claude plugin doctor / verify to ask about the
second one.

Reproduction

export CLAUDE_CONFIG_DIR=$(mktemp -d)
MKT=$(mktemp -d)
mkdir -p "$MKT/.claude-plugin" "$MKT/plugins/demo/.claude-plugin" "$MKT/plugins/demo/skills/demo-skill"

cat > "$MKT/.claude-plugin/marketplace.json" <<'JSON'
{ "name": "repro", "owner": { "name": "repro" },
  "plugins": [{ "name": "demo", "source": "./plugins/demo", "description": "fixture" }] }
JSON
cat > "$MKT/plugins/demo/.claude-plugin/plugin.json" <<'JSON'
{ "name": "demo", "version": "1.0.0", "description": "fixture" }
JSON
printf -- '---\nname: demo-skill\ndescription: fixture skill.\n---\nDemo.\n' \
  > "$MKT/plugins/demo/skills/demo-skill/SKILL.md"

claude plugin marketplace add "$MKT"
claude plugin install demo@repro

ls "$CLAUDE_CONFIG_DIR/plugins/cache/repro/demo/1.0.0/skills/demo-skill/SKILL.md"   # exists

# Remove only the payload; the enablement record survives.
rm -rf "$CLAUDE_CONFIG_DIR/plugins/cache/repro/demo/1.0.0"

claude plugin list --json
#   [{"id":"demo@repro","enabled":true,
#     "installPath":"<CLAUDE_CONFIG_DIR>/plugins/cache/repro/demo/1.0.0"}]   <- path does not exist

claude plugin list          # running the CLI again does not re-materialize it
ls "$CLAUDE_CONFIG_DIR/plugins/cache/repro/demo/1.0.0" 2>&1
#   No such file or directory

claude plugin install demo@repro re-materializes the payload, and is
idempotent.

Impact

Any automation that provisions plugins into a scoped CLAUDE_CONFIG_DIR and
uses plugin list to decide whether an install is needed will skip the install
in exactly the state where it is required. Every command exits 0 and every
status field says healthy, so the failure only surfaces later as "the model
doesn't know about the skill".

We hit the identical defect in the Codex CLI
(https://github.com/openai/codex/issues/34321) and filed this because the cache
layout and the enabled-vs-materialized split are the same in both.

Workaround

Stat the payload instead of trusting plugin list:

ls "$CLAUDE_CONFIG_DIR/plugins/cache/<marketplace>/<plugin>"/*/skills/*/SKILL.md

and run claude plugin install <id> unconditionally when it is missing.

Suggested fixes

  1. Have plugin list stat installPath and report the divergence rather than

"enabled": true.

  1. Reconcile on load: re-materialize an enabled plugin whose cached payload is

absent.

  1. Add a supported claude plugin doctor / plugin list --verify so automation

has a command to call instead of reading the cache directory layout.

Environment

  • Claude Code CLI 2.1.215, Linux
  • Local file-based marketplace (also reproduces with a git marketplace)

View original on GitHub ↗

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