Description
When a skill defines allowed-tools in its SKILL.md frontmatter, the permission is reported as active but Bash commands matching the pattern are still denied.
Steps to Reproduce
- Create a skill with
allowed-tools defined:
---
name: speak
description: Speak aloud using macOS TTS
allowed-tools: Bash(say -v "Samantha":*)
---
- Add
Skill(speak) to the allow list in ~/.claude/settings.json:
{
"permissions": {
"allow": ["Skill(speak)", "Read"]
}
}
- Run:
claude -p 'demonstrate the speak skill' --output-format stream-json --verbose
Expected Behavior
The Bash command say -v "Samantha" "..." should be auto-allowed because:
Skill(speak) is in the allow list
- The skill's
allowed-tools grants Bash(say -v "Samantha":*)
Actual Behavior
The skill invocation succeeds and reports the correct allowedTools:
"tool_use_result": {
"success": true,
"commandName": "speak",
"allowedTools": ["Bash(say -v \"Samantha\":*)"]
}
But the subsequent Bash call is denied:
{
"type": "user",
"message": {
"content": [
{
"type": "tool_result",
"content": "This command requires approval",
"is_error": true
}
]
}
}
The command attempted matches the pattern exactly:
say -v "Samantha" "Hello Antony! This is a demonstration..."
Workaround
Adding Bash(say:*) directly to the global allow list works, but defeats the purpose of skill-scoped allowed-tools.
Environment
- Claude Code version: 2.0.75
- OS: macOS (Darwin 25.1.0)
- Mode:
-p (print/prompt mode)
Additional Notes
We also discovered that ~/.claude/settings.local.json doesn't seem to be a valid location for user settings — permissions placed there weren't loaded. Only ~/.claude/settings.json worked.
Description
When a skill defines
allowed-toolsin its SKILL.md frontmatter, the permission is reported as active but Bash commands matching the pattern are still denied.Steps to Reproduce
allowed-toolsdefined:Skill(speak)to the allow list in~/.claude/settings.json:{ "permissions": { "allow": ["Skill(speak)", "Read"] } }claude -p 'demonstrate the speak skill' --output-format stream-json --verboseExpected Behavior
The Bash command
say -v "Samantha" "..."should be auto-allowed because:Skill(speak)is in the allow listallowed-toolsgrantsBash(say -v "Samantha":*)Actual Behavior
The skill invocation succeeds and reports the correct
allowedTools:But the subsequent Bash call is denied:
{ "type": "user", "message": { "content": [ { "type": "tool_result", "content": "This command requires approval", "is_error": true } ] } }The command attempted matches the pattern exactly:
Workaround
Adding
Bash(say:*)directly to the global allow list works, but defeats the purpose of skill-scopedallowed-tools.Environment
-p(print/prompt mode)Additional Notes
We also discovered that
~/.claude/settings.local.jsondoesn't seem to be a valid location for user settings — permissions placed there weren't loaded. Only~/.claude/settings.jsonworked.