Bash permission allow rules not honored — "don't ask again" doesn't persist

Status Fixed / completed
Maintainer reply None cached
Activity 4 comments · opened Mar 24, 2026 · closed Mar 24, 2026

Bug Description

Bash permission allow rules in settings.local.json and ~/.claude/settings.json are not being applied. Selecting option 2 ("Yes, and don't ask again for: X") writes the rule to the file but does not prevent future prompts — even within the same session, on the very next command.

Reproduction Steps

  1. Have Bash(gcloud functions:*) in .claude/settings.local.json under permissions.allow
  2. Run a command like: gcloud functions logs read my-function --project=my-project --region=us-central1 --limit=50
  3. Get prompted with the 3 options (Yes / Yes, and don't ask again / No)
  4. Select option 2: "Yes, and don't ask again for: gcloud functions:*"
  5. Claude runs the command successfully
  6. Claude immediately runs another gcloud functions logs read ... command in the same turn
  7. Gets prompted again despite option 2 just being selected

Configuration

~/.claude/settings.json:

{
  "permissions": {
    "allow": [
      "Bash(gcloud functions:*)"
    ]
  }
}

.claude/settings.local.json (project-level, written by option 2):

{
  "permissions": {
    "allow": [
      "Bash(gcloud functions logs read:*)",
      "Bash(gcloud functions describe:*)",
      "Bash(gcloud functions:*)",
      "Bash(gcloud:*)"
    ]
  }
}

All four rules exist — narrow and broad — and none are honored.

Expected Behavior

  • Permission rules in settings.local.json and ~/.claude/settings.json should auto-allow matching Bash commands without prompting
  • At minimum, selecting option 2 should persist within the current session

Actual Behavior

  • Every gcloud functions logs read command prompts for approval regardless of allow rules
  • Option 2 does not persist even within the same session/turn
  • This has been happening for months across many sessions

Environment

  • macOS (Darwin 25.3.0)
  • Claude Code CLI
  • Multiple gcloud prefix rules tested: gcloud:*, gcloud functions:*, gcloud functions logs read:*, gcloud functions logs read *

View original on GitHub ↗

4 Comments

yurukusa · 6 months ago

The allow rules use glob patterns that can be broken by flags Claude adds (like -C /path). A PreToolUse hook is more reliable for auto-approving read-only commands:

COMMAND=$(cat | jq -r '.tool_input.command // empty' 2>/dev/null)
[ -z "$COMMAND" ] && exit 0
BASE=$(echo "$COMMAND" | awk '{print $1}')
case "$BASE" in
    gcloud|aws|az|kubectl|docker|terraform)
        if echo "$COMMAND" | grep -qE '(logs|describe|get|list|show|info|status|read|inspect)'; then
            echo '{"decision":"approve","reason":"Read-only cloud CLI"}'
        fi ;;
esac
exit 0

This works because hooks inspect the actual command text rather than relying on glob pattern matching, which breaks when Claude adds extra flags.
For a broader solution covering 50+ read-only commands (cat, ls, grep, git log, etc.):

npx cc-safe-setup --install-example auto-approve-readonly
github-actions[bot] · 6 months ago

Found 3 possible duplicate issues:

  1. https://github.com/anthropics/claude-code/issues/18846
  2. https://github.com/anthropics/claude-code/issues/20449
  3. https://github.com/anthropics/claude-code/issues/37263

This issue will be automatically closed as a duplicate in 3 days.

  • If your issue is a duplicate, please close it and 👍 the existing issue instead
  • To prevent auto-closure, add a comment or 👎 this comment

🤖 Generated with Claude Code

P-Lloret · 6 months ago

Thanks @yurukusa your PreToolUse hook approach worked perfectly. The glob patterns were indeed breaking because Claude prepends source .../activate && to commands, which breaks the prefix match.

Implemented your suggestion with a script that strips chain prefixes before matching read-only subcommands (logs read, describe, list, etc.) for gcloud/gsutil/bq. Auto-approves instantly now.

For anyone finding this: the key insight is that Bash(gcloud:*) permission rules use literal prefix matching against the full command string, so any prepended source, cd, or && chain breaks the match. A PreToolUse hook that parses the actual command is the reliable solution.

Closing, this is a workaround but it fully solves the UX problem.

github-actions[bot] · 6 months ago

This issue has been automatically locked since it was closed and has not had any activity for 7 days. If you're experiencing a similar issue, please file a new issue and reference this one if it's relevant.