allowed-tools does not pre-approve Read/Write for paths in the user's home directory (only ${CLAUDE_PLUGIN_ROOT} paths work)

Open 💬 1 comment Opened Jul 10, 2026 by oreos-and-ramen

Summary

A plugin skill's allowed-tools frontmatter successfully pre-approves Read/Write for paths under ${CLAUDE_PLUGIN_ROOT} (inside the plugin), but does not pre-approve them for paths in the user's home directory — in any syntax I could find. Every home-dir read/write prompts despite a matching-looking grant.

What works

allowed-tools: Read(${CLAUDE_PLUGIN_ROOT}/skills/practice/banks/*.json)

Reads of that path run silently, no prompt. ${CLAUDE_PLUGIN_ROOT} is substituted to the resolved absolute plugin path and matches the tool call.

What does NOT work

A skill that persists small per-user state to ~/.dql-tutor/progress.json (a home-dir location, deliberately outside the protected ~/.claude/). All of these grant forms still produce a permission prompt on both the Read (startup) and the Write (save):

allowed-tools: Write(~/.dql-tutor/progress.json) Read(~/.dql-tutor/progress.json)
allowed-tools: Write(${HOME}/.dql-tutor/progress.json) Read(${HOME}/.dql-tutor/progress.json)
allowed-tools: Write(**/.dql-tutor/progress.json) Read(**/.dql-tutor/progress.json)

In each case the tool-call header shows the correctly-resolved path (e.g. Read(/Users/name/.dql-tutor/progress.json)), and the prompt is the normal (bypassable) permission prompt — but it prompts every time regardless of the grant.

Expectation

The docs state ~/path is a supported anchor for Read/Edit permission patterns (e.g. Read(~/Documents/*.pdf) matching /Users/alice/Documents/*.pdf). Based on that, Write(~/.dql-tutor/progress.json) should pre-approve a write to that resolved path. It doesn't.

Impact

A skill that maintains per-user state in the home directory (the natural place for state that must persist across sessions and survive plugin reinstalls) cannot pre-approve its own state-file I/O, so the user is prompted on every session. ${CLAUDE_PLUGIN_ROOT} isn't a workaround because state written there is lost on reinstall and shared across users of the same install.

Repro

  1. Create a plugin skill with allowed-tools: Write(~/somedir/state.json) Read(~/somedir/state.json).
  2. Have the skill Read then Write that path.
  3. Observe both prompt for permission despite the grant.

Environment

  • Plugin loaded via claude --plugin-dir.
  • Possibly related: #76196 (allowed-tools only grants the first Bash use per session).

View original on GitHub ↗

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