Skill !command preload permissions never persist - rule format mismatch
Description
When a plugin skill uses !command`` to run a preload script, the Bash permission check fails and approvals never persist. The saved permission rule uses a different format than the check expects, so even after user approval, subsequent invocations fail with the same permission error.
Reproduction
- Create a plugin skill with a
!preload:
---
name: my-skill
context: fork
agent: my-agent
allowed-tools:
- Bash(*/my-script.sh *)
---
!\`${CLAUDE_SKILL_DIR}/scripts/preload.sh\`
Do something with the preloaded data above.
- Install the plugin and invoke the skill
- Permission prompt appears — approve it
- Skill fails with:
Bash command permission check failed for pattern "!\/path/to/preload.sh\": This command requires approval - Invoke the skill again — same error, no prompt shown
Root Cause (from debug logs)
The permission system saves the rule with the plain path:
"ruleContent": "/Users/me/.claude/plugins/cache/my-plugin/1.0/skills/my-skill/scripts/preload.sh"
But the permission check matches against the !\...\ wrapped format:
Bash command permission check failed for command in /my-plugin:my-skill: /path/to/preload.sh
The formats never match, so the saved rule is never found during the check.
Additionally, on the first invocation:
- The Skill invocation permission is prompted and saved
- The Bash preload rule is created in the same tick
- But the
!command runs before the new rule takes effect (race condition)
Expected Behavior
- User approves the skill's
!command once - The approval persists across invocations
- Subsequent invocations of the same skill should not re-prompt
Environment
- Claude Code version: 2.1.76
- Platform: macOS Darwin 25.3.0
- Plugin installed at user scope
Impact
This makes !command` preloads in plugin skills unusable. The [skills documentation](https://code.claude.com/docs/en/skills.md#inject-dynamic-context) promotes !` commands for deterministic data injection, but the permission system prevents them from working in plugins.
Workaround
Currently there is no workaround. Skills must fall back to instructing the agent to load data via Read/Bash tools, which loses the deterministic preprocessing benefit of ! commands.
This issue has 3 comments on GitHub. Read the full discussion on GitHub ↗