Feature request: expose CLAUDE_PLUGIN_ROOT as shell env var in Bash tool context

Resolved 💬 1 comment Opened Apr 15, 2026 by cborantwilio Closed May 25, 2026

Problem

When plugins invoke scripts from SKILL.md via the Bash tool, the only way to locate the plugin root is to navigate relative to CLAUDE_SKILL_DIR:

uv run --directory "${CLAUDE_SKILL_DIR}/../.." python scripts/my_script.py args...

This is verbose, fragile (assumes skills are always exactly 2 levels deep), and repeated on every single command line in every skill. For a plugin like disciplined-agile-delivery with 30+ skills and 70+ script invocations, this boilerplate dominates the SKILL.md content.

CLAUDE_PLUGIN_ROOT already exists and is expanded in hooks.json and plugin.json config files, but it is not available as a shell environment variable when the Bash tool executes commands.

Proposed Solution

Inject CLAUDE_PLUGIN_ROOT as an environment variable in the Bash tool's execution context when running within a plugin skill. The variable should contain the absolute path to the plugin's installation directory (same value that's expanded in config files).

Impact

Every skill invocation becomes:

uv run --directory "$CLAUDE_PLUGIN_ROOT" python scripts/my_script.py args...

Or even simpler if combined with --project:

uv run --project "$CLAUDE_PLUGIN_ROOT" python "$CLAUDE_PLUGIN_ROOT/scripts/my_script.py" args...

Benefits:

  • No relative path gymnastics (../../)
  • No assumption about skill directory depth
  • Consistent with how CLAUDE_SKILL_DIR is already injected
  • Enables cleaner permission patterns (e.g., Bash(uv run --directory $CLAUDE_PLUGIN_ROOT *))

Current Workaround

Skills use ${CLAUDE_SKILL_DIR}/../.. which assumes the skill is at plugins/<name>/skills/<skill>/SKILL.md. This works but is ugly, repetitive, and breaks if the directory structure changes.

Environment

  • Claude Code CLI
  • uv 0.11.x for Python plugin dependency management
  • Affects any plugin with Python/Node scripts invoked from SKILL.md

View original on GitHub ↗

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