[FEATURE] Stable path to a plugin's installed version (or @import variable expansion), so orgs can ship versioned CLAUDE.md content in plugins

Status Open
Maintainer reply None cached
Activity 0 comments · opened Jul 28, 2026

Preflight Checklist

  • [x] I have searched existing requests and this feature hasn't been requested yet
  • [x] This is a single feature request (not multiple features)

(Filed via gh CLI before noticing this repo disables blank issues — body restructured after the fact to match the feature-request form. Apologies for the missing auto-applied enhancement label.)

Problem Statement

Our engineering org distributes a shared CLAUDE.md (team conventions, guardrail context) through a private plugin marketplace. Each engineer's ~/.claude/CLAUDE.md imports it straight out of the marketplace clone:

@~/.claude/plugins/marketplaces/<marketplace>/CLAUDE.md

That works, but the file is unversioned — it updates on every marketplace refresh, while everything else we ship (hooks, skills, agents) is version-pinned through plugins and gated by a version-bump CI check. We want the shared instruction layer to get the same treatment: ship inside a plugin, so instruction changes are bump-gated, atomic with the plugin behavior they describe, and rollbackable.

Two things block that today:

  1. Installed plugins land at a version-suffixed path — ~/.claude/plugins/cache/<marketplace>/<plugin>/<version>/ — and old versions are retained, so there is no stable on-disk path for "the currently-installed version of this plugin."
  2. @import lines in CLAUDE.md get no variable expansion. ${CLAUDE_PLUGIN_ROOT} exists only inside hook/command execution contexts, so an import can't reach the current version dynamically.

A static import pinned to .../0.2.4/CLAUDE.md goes silently stale on the next bump, which is worse than what we have.

Proposed Solution

Any one of these solves it (listed cleanest-last):

  • A stable current symlink in the plugin cache, maintained by the installer: ~/.claude/plugins/cache/<marketplace>/<plugin>/current/ → the installed version. Static imports could then target it.
  • Variable expansion in @import paths, e.g. @${CLAUDE_PLUGIN_ROOT:<plugin>@<marketplace>}/CLAUDE.md.
  • Native plugin memory: let a plugin bundle a CLAUDE.md that loads with memory authority (and propagates to subagents) when the plugin is enabled. This is the cleanest shape — plugins can already ship skills/commands/agents/hooks/MCP, and instruction content is the one distribution channel missing.

Alternative Solutions

  • Current approach: import from the marketplace clone (works, unversioned, updates on every refresh).
  • Considered and rejected: a SessionStart hook that maintains the symlink itself. It means instruction delivery depends on hook machinery — a disabled plugin or skipped hook leaves a dangling/stale symlink and the shared layer silently vanishes, the failure mode we adopted the marketplace-clone import to escape.
  • Also rejected earlier (spike evidence): injecting the instructions via a SessionStart hook's additionalContext — injected context carries lower authority than memory and does not propagate to subagents.

Priority

Medium - Would be very helpful

Feature Category

Configuration and settings

Use Case Example

  1. Platform team ships conventions + guardrail hooks as plugins in a private marketplace; a CI gate requires a version bump on every plugin change.
  2. A conventions change lands that describes new hook behavior.
  3. Today: the CLAUDE.md text can reach engineers before the hook version ships (instructions ride the clone, hooks ride the version pin) — we carry a standing rule that shared-layer text must not depend on unreleased plugin behavior.
  4. With this feature: the instruction text ships inside the same plugin version as the behavior it describes — atomic, rollbackable, and covered by the same CI gate.

View original on GitHub ↗