${CLAUDE_SKILL_DIR} not substituted in SKILL.md frontmatter hook commands

Resolved 💬 3 comments Opened Mar 19, 2026 by farzadshbfn Closed May 4, 2026

Preflight Checklist

  • [x] I have searched existing issues and this hasn't been reported yet
  • [x] This is a single bug report (please file separate reports for different bugs)
  • [x] I am using the latest version of Claude Code

What's Wrong?

The Available string substitutions docs list ${CLAUDE_SKILL_DIR} as available for skills:

${CLAUDE_SKILL_DIR} — The directory containing the skill's SKILL.md file. Use this in bash injection commands to reference scripts or files bundled with the skill, regardless of the current working directory.

However, ${CLAUDE_SKILL_DIR} is not substituted when used in SKILL.md frontmatter hook commands. The literal ${CLAUDE_SKILL_DIR} string is passed to the shell, where it resolves to empty (since it's not a real env var), causing the command to fail.

What Should Happen?

${CLAUDE_SKILL_DIR} should be resolved to the skill's directory in hook commands defined in SKILL.md frontmatter, just like it is in the skill body. This is critical for portable/publishable skills that bundle scripts.

Steps to Reproduce

  1. Create a skill with a script and a frontmatter hook referencing it:
my-skill/
├── SKILL.md
└── scripts/
    └── validate.py
---
name: my-skill
description: "Test skill with hook"
hooks:
  PostToolUse:
    - matcher: "Write|Edit|Bash"
      hooks:
        - type: command
          command: "uv run ${CLAUDE_SKILL_DIR}/scripts/validate.py"
---
  1. Symlink the skill into a different project: ln -s /path/to/my-skill .claude/skills/my-skill
  1. Invoke the skill and trigger a matching tool (e.g., Edit a file)
  1. The hook command fails because ${CLAUDE_SKILL_DIR} is not substituted — the shell receives the literal string, which expands to empty since there's no such env var.

Expected: The hook command resolves to uv run /path/to/my-skill/scripts/validate.py
Actual: The hook command resolves to uv run /scripts/validate.py (or similar), and fails

Why This Matters

Skills that bundle helper scripts (validators, analyzers, etc.) need a way to reference those scripts from hook commands. Without ${CLAUDE_SKILL_DIR} working in frontmatter hooks, there's no portable way to do this — hardcoded paths break when the skill is consumed from a different project.

This is distinct from:

  • #17688 (skill hooks not triggering in plugins)
  • #9354 (${CLAUDE_PLUGIN_ROOT} in plugin command markdown)

Claude Code Version

2.1.79

Platform

Anthropic API

Operating System

macOS

Terminal/Shell

Terminal.app

View original on GitHub ↗

This issue has 3 comments on GitHub. Read the full discussion on GitHub ↗