Skip to content

[BUG] permissions from user settings.json is NOT applied at project level #5140

Open

Description

@siraj-samsudeen

Environment

  • Platform (select one):
    • Other: Claude Code on macOS with VS Code
  • Claude CLI version: 1.0.68 (Claude Code)
  • Operating System: macOS Darwin 23.6.0
  • Terminal: Terminal App

Bug Description

User-level permissions in ~/.claude/settings.json are not being enforced
during command execution, even though they appear as loaded in the
/permissions command. The same permissions work correctly when placed in
project-level .settings.local.json but fail when moved to user-level
settings.

Steps to Reproduce

  1. Copy working permissions from a project's .settings.local.json to
    user-level ~/.claude/settings.json:
    {
    "permissions": {
    "allow": [
    "mix:",
    "mcp__serena__
    ",
    "mcp__context7__",
    "Bash(ls:
    )",
    "Bash(find:)",
    "Bash(grep:
    )",
    "Bash(sqlite3:)",
    "Bash(mkdir:
    )",
    "Bash(cp:)",
    "Bash(mv:
    )",
    "Bash(git add:)",
    "Bash(git push:
    )",
    "Bash(git checkout:)",
    "Bash(git stash show:
    )",
    "Bash(git stash pop:)",
    "Bash(git fetch:
    )",
    "Bash(git stash push:)",
    "Bash(git merge:
    )",
    "Bash(git cherry-pick:)",
    "Bash(python:
    )",
    "Bash(python3 -m pip install:)",
    "Bash(npm install:
    )",
    "Bash(npx playwright test:*)"
    ]
    }
    }
  2. Open a project in VS Code with Claude Code
  3. Run /permissions - it correctly shows all permissions as loaded
  4. Try to run any allowed command (e.g., mix --version)
  5. Claude Code still asks for permission despite the command being in the
    allow list

Expected Behavior

  • I want a way to allow the mcp of serena to execute all its commands without asking for explicit permission each time.
  • Commands in the user-level allow list should execute without requiring
    approval
  • User-level permissions should work identically to project-level
    permissions
  • If /permissions shows a command as allowed, it should not require
    approval

Actual Behavior

  • All commands require manual approval even when listed in user-level
    permissions
  • /permissions command shows the permissions as loaded but they are not
    enforced
  • The exact same permissions work when placed in project
    .settings.local.json but not in ~/.claude/settings.json
  • MCP wildcard permissions (e.g., mcp__serena__*) also don't work at the
    user level

Additional Context

  • These permissions were originally auto-generated by Claude Code (not
    manually written) - I just copied them from .settings.local.json to the user-level settings.json
  • This significantly impacts workflow as every command requires manual
    approval across all projects

Activity

  1. changed the title [-][BUG][/-] [+][BUG] permissions from user settings.json is NOT applied at project level[/+] on Aug 5, 2025
  2. github-actions commented on Aug 5, 2025

    @github-actions
  3. wangkanai commented on Aug 7, 2025

    @wangkanai

    This permissions issue may be related to #5314 - PostToolUse hooks not triggering for Edit operations on .cs files.

    The problem in #5314 involves hooks configured in .claude/settings.json not being executed despite proper syntax and verbose mode being enabled. If permissions from user settings.json are not being applied at the project level as described in this issue, it could explain why PostToolUse hooks fail to execute.

    Our hook configuration includes:

    {
      "enableAllProjectMcpServers": true,
      "verbose": true,
      "hooks": {
        "PostToolUse": [...]
      }
    }

    If the settings.json configuration isn't being properly applied at the project level, the hook system might not be receiving the configuration needed to execute hooks after Edit/MultiEdit/Write operations.

  4. Sergiodelahoz commented on Aug 12, 2025

    @Sergiodelahoz

    I'm having the same issue! in MacOS, using claude code, user/.claude/settings.json allow list and deny list commands are completely ignored. It is a bit annoying to deal with this.

  5. tonydehnke commented on Aug 30, 2025

    @tonydehnke

    Same here on MacOS. Would love a real fix.

  6. vhardy commented on Sep 22, 2025

    @vhardy

    Same problem on my end. I am trying to run grunt commands from Claude and it keeps asking for permission even though I ask CC to add it to the allow list.

  7. tiagoefreitas commented on Nov 4, 2025

    @tiagoefreitas

    Same issue, and its extra annoying with plan mode as it does not respect the bypass permissions that I set when launching the cli. The global bypass permissions should be a setting, not a mode. So I tried to workaround by adding permissions and it doesn't use them.

  8. vhardy commented on Nov 5, 2025

    @vhardy

    @tiagoefreitas Not sure if this will apply to your situation, but you may want to check /status when in Claude code to see if there were issues loading the settings file. I discovered that it does not proactively report issues with settings files, so it will silently ignore those with typos for example. But if you run /status, then you'll see a message if there was an issue with one of your settings (it was my .claude/settings.json in my case). Then it took a little trial and error to understand where there was a typo because the message did not give details, but I was able to sort it out. I hope this helps.

  9. Sean10 commented on Nov 5, 2025

    @Sean10

    @tiagoefreitas Not sure if this will apply to your situation, but you may want to check /status when in Claude code to see if there were issues loading the settings file. I discovered that it does not proactively report issues with settings files, so it will silently ignore those with typos for example. But if you run /status, then you'll see a message if there was an issue with one of your settings (it was my .claude/settings.json in my case). Then it took a little trial and error to understand where there was a typo because the message did not give details, but I was able to sort it out. I hope this helps.

    According to your advise, I fixed my problem.

    # check whether settings.json is invalid
    /status
    
    # claude provide where is invalid
    /doctor
  10. 7 remaining items

  11. tonydehnke commented on Dec 29, 2025

    @tonydehnke

    This still keeps coming back up. We really could use some attention from the team to fix permissions @bcherny

  12. tiagoefreitas commented on Dec 31, 2025

    @tiagoefreitas

    between this and claude not reading the user .mcp.json, cc is getting frustrating to use

  13. mrgoonie commented on Jan 5, 2026

    @mrgoonie

    None of these following settings.json works:

    With double slashes (at the beginning):

    {
      "permissions": {
        "allow": [
          "Write(//private/tmp/test-workspaces/permission-test.txt)"
        ]
      }
    }

    With a single slash (at the beginning):

    {
      "permissions": {
        "allow": [
          "Write(/private/tmp/test-workspaces/permission-test.txt)"
        ]
      }
    }

    At /private/tmp/test-workspaces/.claude/settings.json and /private/tmp/test-workspaces/.claude/settings.local.json

    {
      "permissions": {
        "allow": [
          "Write(*)"
        ]
      }
    }

    At ~/.claude/settings.json and ~/.claude/settings.local.json:

    {
      "permissions": {
        "allow": [
          "Write(*)"
        ]
      }
    }

    claude was being started at /private/tmp/test-workspaces/

    But it always ask for permissions when writing to /private/tmp/test-workspaces/permission-test.txt (although it was pre-approved)

    Image

    I don't want to run claude with --dangerously-skip-permissions flag. But running claude without it is quite frustrating now...

    Wondering how is it working at Anthropic? @bcherny

  14. mrgoonie commented on Jan 5, 2026

    @mrgoonie

    deny is also not working:

    /private/tmp/clawk-workspaces/1/.claude/settings.json:

    {
      "permissions": {
        "deny": [
          "Write(permission-test.txt)",
          "Write(*)"
        ]
      }
    }

    Start claude or claude --dangerously-skip-permissions:

    Image

    claude still write out permission-test.txt

  15. jwhartley commented on Jan 8, 2026

    @jwhartley

    Solution Found: Path Format Issue

    After extensive testing, I found that user-level permissions DO work - the issue is the path format.

    Root Cause

    Single-slash paths like /Users/james/** are interpreted as relative paths from the settings file location, not absolute paths.

    The Fix

    Use double-slash // for absolute paths:

    {
      "permissions": {
        "allow": [
          "Read(//Users/james/**)",
          "Write(//Users/james/github/**)",
          "Edit(//Users/james/github/**)"
        ]
      }
    }

    Verification

    1. Updated ~/.claude/settings.json with // paths
    2. Started fresh session (not -r)
    3. All Read/Write/Edit operations work without prompts

    This is documented in #6881 but easy to miss. The single-slash format that Claude Code itself generates when you accept prompts may be contributing to the confusion.

    Additional Note

    Path-restricted Bash commands like Bash(rm:/tmp/**) also don't work reliably. Use wildcards Bash(rm:*) with deny rules instead.

  16. arnonmoscona commented on Feb 5, 2026

    @arnonmoscona

    Got tired of waiting for fixes. Created https://github.com/arnonmoscona/toolguard as an enhanced drop-in replacement to the native permissions system using hooks. As far as I can tell it is syntax-compatible, but it has more features and allows also new matching patterns. The simplest setup is just to setup the hook as documented, but you can go far beyond if you want. I will add a new feature soon to overcome some of the annoying behaviors I find around permissions.

    I'd welcome any feedback, comments, PRs. This is new, to treat it carefully. "works on my machine" is not really good enough, but I am one guy with one machine. So there's that...

  17. yurukusa commented on Mar 21, 2026

    @yurukusa

    Workaround — hooks in user settings.json are enforced regardless of project settings:

    While permission rules may not cascade correctly from user to project level, hooks defined in ~/.claude/settings.json do apply globally to all projects.

    {
      "hooks": {
        "PreToolUse": [{
          "matcher": "Bash",
          "hooks": [
            { "type": "command", "command": "bash ~/.claude/hooks/destructive-guard.sh" },
            { "type": "command", "command": "bash ~/.claude/hooks/branch-guard.sh" }
          ]
        }]
      }
    }

    Hooks bypass the permission system entirely — they run before tool execution and exit 2 to hard-block, regardless of what project-level settings say.

    Quick install: npx cc-safe-setup — writes hooks to ~/.claude/hooks/ and registers them in user-level ~/.claude/settings.json. Works across all projects.

  18. yurukusa commented on Mar 29, 2026

    @yurukusa

    User-level permissions in ~/.claude/settings.json don't reliably apply at project level — this is a known issue. Hooks are the fix because they always propagate:

    INPUT=$(cat)
    COMMAND=$(echo "$INPUT" | jq -r '.tool_input.command // empty' 2>/dev/null)
    [ -z "$COMMAND" ] && exit 0
    CLEAN=$(echo "$COMMAND" | sed 's/#.*$//' | tr '\n' ' ')
    PARTS=$(echo "$CLEAN" | sed 's/\s*&&\s*/\n/g; s/\s*||\s*/\n/g; s/\s*;\s*/\n/g; s/\s*|\s*/\n/g')
    ALL_SAFE=true
    while IFS= read -r part; do
        part=$(echo "$part" | sed 's/^\s*//;s/\s*$//')
        [ -z "$part" ] && continue
        BASE=$(echo "$part" | awk '{print $1}')
        case "$BASE" in
            cd|ls|cat|head|tail|grep|rg|find|stat|wc|du|tree|file|which) ;;
            echo|printf|true|false|test|export|env|date|sleep) ;;
            sort|uniq|cut|tr|awk|sed|jq|yq|tee|xargs) ;;
            git|npm|npx|node|yarn|python|python3|pip|make|cargo) ;;
            mkdir|touch|pwd) ;;
            *) ALL_SAFE=false; break ;;
        esac
    done <<< "$PARTS"
    if [ "$ALL_SAFE" = true ]; then
        jq -n '{hookSpecificOutput:{hookEventName:"PreToolUse",permissionDecision:"allow",permissionDecisionReason:"User-level permission (hook)"}}'
    fi
    exit 0
    {
      "hooks": {
        "PreToolUse": [{
          "matcher": "Bash",
          "hooks": [{ "type": "command", "command": "bash ~/.claude/hooks/user-level-permissions.sh" }]
        }]
      }
    }

    Hooks defined in ~/.claude/settings.json fire in every project. Unlike permission patterns, hook execution doesn't have the user/project level scoping bug. This is the reliable way to enforce user-level permissions across all projects.

  19. arnonmoscona commented on Apr 23, 2026

    @arnonmoscona

    FYI toolguard is now at 0.3.0 - while takeover mode is nominally in alpha state, it's been working perfectly for me for a while. So this issue does not really affect me any more and I have a much more flexible permissions configuration.

    https://github.com/arnonmoscona/toolguard](https://github.com/arnonmoscona/toolguard%5D(https://github.com/arnonmoscona/toolguard))

  20. boringstud-io commented on Jul 22, 2026

    @boringstud-io

    On claude.ai/code (cloud sessions incl. scheduled Routines), claude.ai connector tools (Notion MCP) prompt for permission on every call with only “Allow once” — no persistent option. We verified that ALL documented mechanisms are ignored for connector tools: (1) setting every Notion tool to “Always allow” in the connector’s tool-permission settings, (2) permissions.allow: ["mcp__Notion"] in the repo’s .claude/settings.json, (3) a PreToolUse hook returning permissionDecision: "allow" for mcp__Notion__.*. In all three cases a fresh cloud session still prompted for a simple Notion fetch. Scheduled runs hang indefinitely on these prompts.

  21. yozerpp commented on Oct 10, 2026

    @yozerpp

    I worked to create a design document between 11 pm and 2 am in Friday for claude to analyse sample input/outputs, pages it needs to automate and the architectural design, and make an implementation plan. Only to find out, at the fing morning, that all agents stopped after 10 minutes to ask me to run a db query.

    Sacrifice of my sleep to move this newly assigned task forward turned out to be for nothing thanks to Claude. F that.

    Edi: if this happens a couple more times until end of the month, I'm out.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions