CLAUDE_PLUGIN_DATA is unnamespaced — plugins persisting it via CLAUDE_ENV_FILE pollute other plugins and skills
Summary
CLAUDE_PLUGIN_DATA is a shared, unnamespaced environment variable. When Claude Code runs a plugin hook, it sets CLAUDE_PLUGIN_DATA to that plugin's data directory. Plugins can then persist this into the session via CLAUDE_ENV_FILE. Because the variable name is not scoped to the plugin that set it, any other plugin or skill that reads CLAUDE_PLUGIN_DATA later in the same session will get the wrong path.
Reproduction
- Install the Codex plugin (
codex@openai-codex) — itsSessionStarthook callsCLAUDE_ENV_FILEto persistCLAUDE_PLUGIN_DATAinto the session - Also install any skill or plugin that reads
CLAUDE_PLUGIN_DATAto find its own state directory (e.g. gstack) - Start a new session — the later plugin/skill reads
CLAUDE_PLUGIN_DATAand gets the Codex plugin's data path
Why this matters
CLAUDE_ENV_FILE is the correct, documented mechanism for plugins to make env vars available to their skill scripts post-hook. The Codex plugin is using it correctly. The platform design issue is that CLAUDE_PLUGIN_DATA is a single shared name with no plugin-scoped namespace — so any plugin persisting it clobbers the value for every other plugin that reads it later.
Suggested fix
Namespace the variable by plugin ID: CLAUDE_PLUGIN_DATA_<PLUGIN_ID> (e.g. CLAUDE_PLUGIN_DATA_CODEX_OPENAI_CODEX). This is a breaking change, so a transition period where both the old and new names are set would ease migration. Alternatively, document that CLAUDE_PLUGIN_DATA is a hook-only variable and must not be persisted via CLAUDE_ENV_FILE — and provide a separate mechanism for plugins that need their data path available in skill scripts post-hook.
This issue has 1 comment on GitHub. Read the full discussion on GitHub ↗