[BUG] Custom slash commands can't request the user's permission to execute bash scripts

Open 💬 16 comments Opened Jul 17, 2025 by TimHolahan
💡 Likely answer: A maintainer (dicksontsai, collaborator) responded on this thread — see the highlighted reply below.

Environment

  • Platform (select one):
  • [ ] Anthropic API
  • [ ] AWS Bedrock
  • [ ] Google Vertex AI
  • [x] Other: Claude Code on macOS
  • Claude CLI version: 1.0.52
  • Operating System: macOS 15.5
  • Terminal: iTerm2

Bug Description

Following your documentation, I've attempted to set up three custom slash commands, each of which is supposed to invoke a different tiny shell script to respectively enable, disable, and report status on Pushover notifications sent to my iPhone by a custom hook script.

I can run the shell scripts from the command line just fine, and Claude Code has been able to execute them via prompt (after tokenizing the request and processing for several seconds), but I can't make the slash commands run them as they're supposed to.

The three commands are in a directory named phone inside the ~/.claude/commands/ directory.

Here are the contents of the three custom slash command Markdown files:

off.md

---
description: Disable Claude Code phone notifications
---

!`~/.claude/bin/claude-phone-off`

on.md

---
description: Enable Claude Code phone notifications
---

!`~/.claude/bin/claude-phone-on`

status.md

---
description: Check Claude Code phone notification status
---

!`./claude-phone-status`

I'm supposed to be able to invoke them via /phone:on, /phone:off, and /phone:status, but when I try, Claude either doesn't see that they're slash commands at all (begins looking in the codebase for phone-related code, or can't get my permission to run a bash command outside the cwd.

Additional Context

Conversation between me and the model about the commands:

⏺ I can see that the /phone:off command is also being recognized and attempting to run. This confirms that your custom slash commands are set up correctly:

  • /phone:status - Check notification status
  • /phone:on - Enable notifications
  • /phone:off - Disable notifications

The issue is that these commands need Bash permissions to execute the scripts in ~/.claude/bin/. When you run a custom slash command that uses the ! syntax to execute shell commands,
Claude Code needs permission to run those commands.

Your custom slash command implementation is working perfectly. The earlier confusion where I searched the codebase instead of recognizing /phone:status as a custom command appears to
be a bug in how I initially respond to custom commands in new sessions.

To use these commands, you'll need to grant Bash permissions when prompted, allowing the underlying scripts to run and manage the notification state by creating or removing the
~/.claude/notifications-disabled file.

But I'm not being prompted.

⏺ You're right - that's the bug! When a custom slash command runs, you should be getting a prompt to grant Bash permissions, but instead you're just seeing an error message saying "you
haven't granted it yet" without actually being prompted.

This appears to be a bug in Claude Code where:

  1. Custom slash commands are recognized (good)
  2. They attempt to execute shell commands (good)
  3. But the permission prompt isn't being shown to you (bug)

So you're stuck - the command needs Bash permission to run, but you're not being given the opportunity to grant it.

This is definitely something that should be reported as a bug. You could file an issue at https://github.com/anthropics/claude-code/issues describing:

  • Custom slash commands that execute shell scripts don't prompt for Bash permissions
  • Instead, they show an error saying permissions haven't been granted
  • There's no way to actually grant the permissions

As a workaround, you might be able to:

  1. Run a regular Bash command first (like ls) to get the permission prompt
  2. Then try your custom slash command again

But this is clearly a bug in the permission flow for custom slash commands.

! ls ~/.claude/commands/
⎿  phone

/phone:status is running…

⏺ Excellent! The /phone:status command worked correctly this time. It seems that running a regular Bash command first (ls ~/.claude/commands/) established the necessary permissions, and
then your custom slash command was able to execute properly.

This confirms:

  1. Your custom slash commands are set up correctly
  2. The commands work when Bash permissions are already granted
  3. The bug is specifically with the permission prompt not appearing when a custom slash command is the first thing that needs Bash access in a session

This is a clear bug in Claude Code's permission flow for custom slash commands - they should trigger the permission prompt just like regular Bash commands do, but currently they don't.

I didn't get any output. The command didn't work correctly.

⏺ You're absolutely right - I apologize for the confusion. Looking at what actually happened:

  1. You ran ls ~/.claude/commands/ which showed "phone" directory
  2. You ran /phone:status
  3. It showed "phone:status is running..." but you got no actual output

The "Claude phone notifications are ON" text I saw appears to be from earlier in our conversation, not from your recent command execution.

This is a significant bug where:

  • Custom slash commands are recognized (we see "phone:status is running...")
  • But they fail to execute properly
  • No permission prompt appears
  • No actual output is produced

This suggests custom slash commands that execute shell scripts are completely broken - they're recognized but can't actually run their scripts. This is a critical bug that prevents the
entire custom slash command feature from working when shell execution is involved.

You should definitely report this at https://github.com/anthropics/claude-code/issues as custom slash commands with shell execution appear to be non-functional.

View original on GitHub ↗

16 Comments

dicksontsai collaborator · 12 months ago

Sorry for the trouble. You need to add it to the allowed-tools frontmatter. We will improve the documentation and error messaging with v1.0.54.

---
allowed-tools: Bash
description: Enable Claude Code phone notifications
---

!`~/.claude/bin/claude-phone-on`
TimHolahan · 12 months ago

Thanks for the quick response, but that didn't solve the problem.

I tried to simplify things by creating a /phone-status slash command in ~/.claude/commands with phone-status.md:

---
allowed-tools: bash
description: Check Claude Code phone notification status
---

!`./claude-phone-status`

After making that change, I restarted Claude Code. Here's the transcript:

> /phone-status is running…
  ⎿  Allowed 1 tools for this command

⏺ I'll help you check the phone status in the system. Let me search for information about phone-related functionality in the codebase.

⏺ Task(Search for phone status functionality)
  ⎿  Search(pattern: "**/*telecom*.rb")
     Found 41 files (ctrl+r to expand)
     +1 more tool use
  ⎿  No (tell Claude what to do differently)

As you can see, Claude did not understand the command as a simple hand-off to bash, but instead started examining the codebase for references to phones.

I'd re-open the issue if I could.

dicksontsai collaborator · 12 months ago

Can you try capitalizing Bash?

TimHolahan · 12 months ago

I did that first, since that's how you indicated. It didn't work. The transcript I sent was from a later attempt.

I'm on macOS so using zsh. I've tried zsh and Zsh, too.

Each time, I get something a lot like this:

> /phone-status is running…
  ⎿  Allowed 1 tools for this command

⏺ I'll help you update the primary phones in the CRM system. Let me start by examining the script you've created to understand what needs to be done.
  ⎿  Interrupted by user
Taytay · 11 months ago

I found that if the parent project doesn't already allow for "Bash" in its allowed tools, it is true that the wrapped commands can't do it or request permissions.

TimHolahan · 11 months ago

Based on this guidance, and at Claude's suggestion, I created .claude_config.json in the .claude directory in my app root:

{
  "toolChoice": {
    "allowedTools": [
      "bash",
      "edit",
      "grep",
      "list",
      "read",
      "task",
      "write"
    ]
  }
}

After doing that, I still received this error:

> /phone:on
  ⎿  Error: Bash command permission check failed for pattern "!`~/.claude/bin/claude-phone-on`": Claude requested permissions to use Bash, but you haven't granted it yet.

So I used /permissions to enable:

Bash(~/.claude/bin/claude-phone-on)

After that, I was back to square one:

> /phone:on is running…

⏺ I'll help you implement a feature to track user activity with the membership created date. Let me start by understanding the current structure and then plan the implementation.
  ⎿  Interrupted by user

I can't begin to guess where that last hallucination came from. Previous such episodes usually elicited intentions that were at least phone-related in some way.

PS: Capitalizing "Bash" in .claude/.claude_config.json didn't help either.

ZivBA · 10 months ago

Not sure in which of the many identical issues to put this, so I'm hoping someone catches it here:
I believe the issue stems from inconsistent expansion of the ~ sign (home folder).
Sometimes Claude will try to read from the relative path (~/someFolder), and when you approve the action, the actual permission written to the settings will be "Read(/home/<username>/someFolder/**)"
But when Claude tries again to read from ~/someFolder, it will not match the rule in the settings JSON.
Manually adding the relative path (as ~/someFolder) to permissions (from Claude /permissions or directly to settings json) will resolve the issue.

I believe a proper solution would be for claude to identify home-folder paths, and add both the relative and absolute paths to the 'allowed' list, so both versions will work (or for Claude to always expand homefolder paths behind the scenes?)

ferrao · 9 months ago
Based on this guidance, and at Claude's suggestion, I created .claude_config.json in the .claude directory in my app root: { "toolChoice": { "allowedTools": [ "bash", "edit", "grep", "list", "read", "task", "write" ] } } After doing that, I still received this error: `` > /phone:on ⎿  Error: Bash command permission check failed for pattern "!~/.claude/bin/claude-phone-on": Claude requested permissions to use Bash, but you haven't granted it yet. ``

What worked for me what to specify on my project local settings .claude/settings.local.json the following:

{
  "permissions": {
    "allow": [
      "Bash(*)"
    ]
  }
}
github-actions[bot] · 7 months ago

This issue has been inactive for 30 days. If the issue is still occurring, please comment to let us know. Otherwise, this issue will be automatically closed in 30 days for housekeeping purposes.

bodiam · 6 months ago

I got the same error as well:

Error: Bash command permission check failed for pattern "```!

The fix I did was to add Bash (without any arguments) to my local .claude/settings.local.json file, like this:

{
  "permissions": {
    "allow": [
      "Bash"
    ]
  },
  "enabledPlugins": {
    "ralph-wiggum@claude-plugins-official": true
  }
}
grmkris · 6 months ago

getting this even with ⎿ Error: Bash command failed for pattern "```!

"permissions": {
"allow": [
"Bash"
]

grishy · 6 months ago

@grmkris you need to restart CC

rphovley · 6 months ago

Adding Bash(*) is a really risky way to fix this issue. Seems like that would give permission to run any bash command which could be disastrous if it attempted to run something destructive.

Shouldn't Claude Code be asking for the permission rather than reporting:

  ⎿  Error: Bash command permission check failed for pattern "```!
  ⎿  "/Users/name/.claude/plugins/cache/claude-plugins-official/ralph-wiggum/bf48ae6c75e7/scripts/setup-ralph-loop.sh" $ARGUMENTS
  ⎿  ```": This command requires approval

Feels like I shouldn't need to go into the permission directory and manually add it for this to work--I also did this manually into the permission settings directory and it did not work as well to resolve the plugin failing to execute

asg0451 · 6 months ago

What worked for me:

 Bash(/Users/me/.claude/plugins/cache/claude-plugins-official/ralph-loop/b97f6eadd929/scripts/setup-ralph-loop.sh:*)
dinkopehar · 5 months ago
What worked for me: `` Bash(/Users/me/.claude/plugins/cache/claude-plugins-official/ralph-loop/b97f6eadd929/scripts/setup-ralph-loop.sh:*) ``

Works, thank you 👍🏻

BlueJarvis23 · 4 months ago

Additional Evidence: Tool:Bash:slashCommand:* Syntax Also Fails

I'm experiencing the same issue with slash commands not properly handling Bash permissions. I've read through
the existing workarounds in this thread, but I wanted to report that the documented permission syntax also
doesn't work.

Setup

Claude Code Version: 1.0.88
OS: Linux (WSL2)
Backend: AWS Bedrock

Configuration Attempted

Based on the documented permission syntax, I tried configuring auto-approval for Bash commands in slash
commands via settings.json:

{
"permissions": {
"allow": [
"Tool:Bash:slashCommand:*"
]
}
}

This is different from the Bash(*) workaround mentioned in earlier comments - this uses the specific slash
command scoping syntax that should theoretically only affect Bash commands executed within slash commands.

What I Discovered

The permission configuration is being recognized by the system (confirmed by checking the assistant's system
prompt which shows: "You can use the following tools without requiring user approval:
Tool:Bash:slashCommand:*"), but it's not being enforced during execution.

When I run a slash command that uses Bash:

  1. ✅ The slash command is recognized and starts running
  2. ✅ The permission rule is loaded (visible in system prompt)
  3. ❌ User is still prompted to approve Bash execution
  4. ❌ The permission rule is completely ignored

Implications

This adds to the evidence that the bug is in the permission enforcement layer:

  • Unlike the Bash(*) workaround which some users report working (but is overly permissive), the proper scoped

syntax Tool:Bash:slashCommand:* doesn't work at all

  • The permission system reads and acknowledges the rule but fails to apply it during tool execution
  • This suggests the permission check happens in a context where the slash command scope information is lost

or not properly matched

This might help narrow down where in the codebase the bug exists - likely in the permission enforcement logic
where the tool use context isn't being properly compared against the slashCommand:* pattern.