--dangerously-skip-permissions does not bypass Edit permission prompts

Open 💬 24 comments Opened Mar 19, 2026 by AaronHallAttorney

Bug Description

Two related permission bugs when running claude --dangerously-skip-permissions:

Bug A: The --dangerously-skip-permissions CLI flag does not bypass Edit permission prompts. Claude still prompts for Edit approval when editing files in .claude/skills/.

Bug B: Selecting option 2 ("allow all edits during this session") does not persist — subsequent edits to files in different subdirectories prompt again.

Reproduction Steps

  1. Configure settings at all three levels (user, project, sub-project) with Edit in the allow list
  2. Launch: claude --dangerously-skip-permissions
  3. Execute a plan that edits multiple files across .claude/skills/auto/SKILL.md and .claude/skills/_email-common/classification.md
  4. Observe: Edit permission prompts appear ~10 times despite the flag

Settings Configuration

All three layers explicitly allow Edit:

| Level | File | defaultMode | Edit in allow? |
|-------|------|---------------|------------------|
| User | ~/.claude/settings.json | "default" | Yes (bare Edit) |
| Project | cc/.claude/settings.json | "default" | Yes (bare Edit + Edit(.claude/**)) |
| Local sub-project | cc/aaron/.claude/settings.local.json | "bypassPermissions" | Yes (bare Edit) |

User-level settings also has "skipDangerousModePermissionPrompt": true.

Suspected Root Cause

The project-level defaultMode: "default" appears to override the sub-project's defaultMode: "bypassPermissions". The settings merge logic seems to pick the most restrictive defaultMode from the hierarchy rather than the most specific (deepest) one.

Additionally, for Bug B: "Allow all edits in _email-common/" creates a scoped session rule. Subsequent edits to auto/SKILL.md (a different directory) don't match the scope — prompting again. The unscoped "allow all edits during this session" variant should work universally, but both scoped and unscoped options are offered inconsistently.

Workaround

Moving "defaultMode": "bypassPermissions" to the parent project settings (cc/.claude/settings.json) resolves the issue, but this is overly broad — it affects all sub-projects when only one should have bypass enabled.

Expected Behavior

  1. --dangerously-skip-permissions should bypass all tool permission prompts regardless of settings hierarchy
  2. When defaultMode: "bypassPermissions" is set at any level in the hierarchy that applies to the current working directory, it should be respected
  3. "Allow all edits during this session" (option 2) should persist for the entire session regardless of target directory

Environment

  • Platform: Windows 11 Pro (win32)
  • Shell: bash (Git Bash)
  • Claude Code: latest

View original on GitHub ↗

24 Comments

Perlover · 3 months ago

I also ran into this problem. I have version 2.1.79, and it's just terrible.

The thing is, I run the claude code with the option --dangerously-skip-permissions expecting it to silently do everything required for editing so that I can leave it running. However, with this option, it keeps stumbling over the .claude/skills directory in the project:

 Do you want to make this edit to SKILL.md?                                                                                                                                                                                                                                                                                   
 ❯ 1. Yes                                  
   2. Yes, allow all edits during this session (shift+tab)
   3. No                                                  

Every time, it asks for permission, and if you give any permission like 1) or 2), it switches from "bypass permissions on" mode to "accept edits on" mode, essentially disabling the mode set by the --dangerously-skip-permissions option!

This is just an awful bug, and it needs to be fixed as soon as possible because it prevents me from working properly.

Platform: Ubuntu 24.04
Shell: bash
Claude Code: 2.1.79

xlurie · 3 months ago

Confirmed on v2.1.79 (DevContainer, Linux) — .claude/skills/ and .claude/agents/
both prompt despite being documented as exempt.

Working workaround: binary patch to extension.js that auto-approves all protected
directory writes in bypassPermissions mode. Covers this bug since it matches
all .claude/ subpaths including the supposedly-exempt ones.

Patch details and script: https://github.com/anthropics/claude-code/issues/35942#issuecomment-4085692049

yurukusa · 3 months ago

/tmp/gh-comment-body.txt

Kretsche49 · 3 months ago

👍 Same issue here on macOS, Claude Code 2.1.81. Affects all open terminal sessions simultaneously. Filed #37181 before finding this duplicate.

none-ascetic · 3 months ago

Reproducing this on macOS, Claude Code with --dangerously-skip-permissions flag. Running two autonomous agent sessions (persona system) that need to write to .claude/, 03 Knowledge/, Daily Notes/, and other project paths. Both Edit and Write prompts still appear despite the flag being confirmed in process args (ps -p $PPID -o args=).

Workaround: adding blanket "Write", "Edit" to settings.local.json permissions.allow. But the flag should make the allowlist irrelevant.

Perlover · 3 months ago

I’m currently on version 2.1.83. In this version, the behavior has changed a bit with this option.

It still asks for permission to edit files like skills within the project, and it also asks for permission to create the skills directory—also within the project—under ~/.claude/skills.

But when I specify that I’m allowing it for the entire session, it stops asking for permission and continues working in the same “allow everything” mode.

Still, I don’t understand why, with the “dangerous mode” option, it needs to request permission for skills if that option allows it to do anything on the system. Why limit it specifically to skills then?

xlurie · 3 months ago

Update for v2.1.84: The patch script needed a fix — the minifier changed variable names (jB, let variable also changed). Updated the script to dynamically extract both variable names from the anchor pattern instead of hardcoding them. Works on 2.1.84 now.

How the patch works: In extension.js, find the pattern return{behavior:"allow",updatedInput:<VAR>};let <VAR2>=await this.sendRequest inside requestToolPermission. Insert a check before the let that tests file_path or command against /[\/\\]\.(?:git|claude|vscode|idea)[\/\\]/ — if it matches, return {behavior:"allow"} immediately. The variable names change with each release (minifier), so grep for the pattern dynamically.

Bug is still present in 2.1.84 — .claude/ paths still prompt in bypassPermissions mode.

TarekAloui · 3 months ago

Bumping this, it switches me to auto-accept each time I edit a file under ~/.claude/ which is disruptive to my flow! (am on bypass permissions and the permission still gets requested each time and auto changes to auto-accept mode, so I end up having to approve each file edit, the allow edits for this session doesn't even work)

lukemmtt · 3 months ago

After digging into the published bundles for 2.1.79 and 2.1.84, it is clear to me now that this behavior change we're discussing, in which we're seeing permission prompts on .claude/** edits even with --dangerously-skip-permissions, is an intentional choice by the Claude Code team.

The 2.1.78 changelog says it plainly: "Fixed .git, .claude, and other protected directories being writable without a prompt in bypassPermissions mode." Sounds intentional to me. Mechanically, they grouped .claude/** along with .git, .vscode, and .idea as protected paths; writes to any of those are routed through a separate approval flow that bypass mode doesn't short-circuit. I manually verified in my own environment that this is indeed the case.

I recognize the Claude Code team's intent here: in light of so many people daily-driving with --dangerously-skip-permissions, it might make sense to add an additional guardrail for the really sensitive directories driving the tool itself. But at the very least, I would expect them to add _another_ bypass flag or config property of some kind to TRULY skip all permissions.

It's particularly senseless to me that Claude now can't edit its own Skills without explicit permission; they're literally not even executable, they're just .md files... recipes.

sgeraldes · 3 months ago
After digging into the published bundles for 2.1.79 and 2.1.84, it is clear to me now that this behavior change we're discussing, in which we're seeing permission prompts on .claude/** edits even with --dangerously-skip-permissions, is an intentional choice by the Claude Code team. The 2.1.78 changelog says it plainly: _"Fixed .git, .claude, and other protected directories being writable without a prompt in bypassPermissions mode."_ Sounds intentional to me. Mechanically, they grouped .claude/** along with .git, .vscode, and .idea as protected paths; writes to any of those are routed through a separate approval flow that bypass mode doesn't short-circuit. I manually verified in my own environment that this is indeed the case. I recognize the Claude Code team's intent here: in light of so many people daily-driving with --dangerously-skip-permissions, it might make sense to add an additional guardrail for the really sensitive directories driving the tool itself. But at the very least, I would expect them to add _another_ bypass flag or config property of some kind to TRULY skip all permissions. It's particularly senseless to me that Claude now can't edit its own Skills without explicit permission; they're literally not even executable, they're just .md files... recipes.

Yeap, this is completely annoying! Any changes into the plans or workflows now throws Claude Code into normal mode and out of Bypass. So updating the spec on spec driven development, to mark a task complete or not, triggers this and throws claude to ask for permissions... this is unusable... looking at modifying the code myself or writing a plugin or hook...

sgeraldes · 3 months ago

Workaround using PermissionRequest hook (no binary patching needed)

Until this is properly fixed, a PermissionRequest hook can restore the bypass behavior. Since hooks persist regardless of mode changes, the auto-approve keeps working even after the bug switches you from bypassPermissions to acceptEdits.

PowerShell version (Windows):

Create ~/.claude/hooks/auto-approve-protected-dirs.ps1:

$output = @{
    hookSpecificOutput = @{
        hookEventName = "PermissionRequest"
        allow = $true
    }
} | ConvertTo-Json -Compress

Write-Output $output
exit 0

Bash version (Linux/macOS):

Create ~/.claude/hooks/auto-approve-protected-dirs.sh:

#!/bin/bash
echo '{"hookSpecificOutput":{"hookEventName":"PermissionRequest","allow":true}}'
exit 0

Then add to ~/.claude/settings.json:

{
  "hooks": {
    "PermissionRequest": [
      {
        "matcher": "",
        "hooks": [
          {
            "type": "command",
            "command": "pwsh -NoProfile -File \"~/.claude/hooks/auto-approve-protected-dirs.ps1\"",
            "timeout": 5
          }
        ]
      }
    ]
  }
}

(Replace the command with bash ~/.claude/hooks/auto-approve-protected-dirs.sh for Linux/macOS)

Why this works: The PermissionRequest hook fires on every permission prompt and returns allow: true before the UI can show the dialog. Since it's a hook (not tied to the permission mode), it keeps working even after the bug switches your mode from bypassPermissions to acceptEdits.

Security note: This has the same implications as --dangerously-skip-permissions — all permission requests are auto-approved. Remove the PermissionRequest block from settings.json to disable.

yurukusa · 3 months ago

A PreToolUse hook can auto-approve Edit even when --dangerously-skip-permissions doesn't:

jq -n '{hookSpecificOutput:{hookEventName:"PreToolUse",permissionDecision:"allow",permissionDecisionReason:"Edit auto-approved by hook (bypass workaround)"}}'
exit 0
{
  "hooks": {
    "PreToolUse": [{
      "matcher": "Edit",
      "hooks": [{ "type": "command", "command": "bash ~/.claude/hooks/force-allow-edit.sh" }]
    }]
  }
}

This is a 3-line hook that unconditionally auto-approves Edit operations. Hooks fire even when --dangerously-skip-permissions doesn't bypass Edit prompts — they're an independent permission layer.

lukemmtt · 3 months ago

I tried both of these proposed "hook" workarounds in my Claude Code CLI; neither of them worked for me.

Specifically, the PermissionRequest event proposed as a tie-in by @sgeraldes doesn't appear to be a real hook event, so the hook never fires.

Similarly, @yurukusa's PreToolUse hook doesn't seem to work for these protected paths in my environment. I confirmed via debug logging that the hook fires and returns permissionDecision: "allow" correctly, but the protected-dir prompt still appears. The hook output is ignored for .claude/** writes.

I assume you guys tested your workarounds before sharing here, so I welcome any feedback about what you might be doing differently than me, or what might be different in your environments.

sgeraldes · 3 months ago

My bad. I have so many plugins installed that is hard to know when something is not vanilla.
The permissions hook can be installed here: https://github.com/doobidoo/mcp-memory-service/tree/main/claude-hooks
It is part of the mcp-memory-service.
Scratch that as a workaround unless you want to install that one too.

sgeraldes · 3 months ago

2.1.88 just Added PermissionDenied hook that fires after auto mode classifier denials :)

lukemmtt · 3 months ago

Thanks for the note about the mcp-memory-service, I haven't installed that yet.

As for the new PermissionDenied hook, I'm not clear on why you've brought that up; that's not relevant to this bug that is the topic of discussion here, it's only for auto mode, as you said, which is completely different from --dangerously-skip-permissions. Unless you're advocating for auto mode over --dangerously-skip-permissions?

sgeraldes · 3 months ago

Update: Got the PermissionRequest hook working properly. The key was the correct JSON structure — the docs show it uses decision.behavior, not permissionDecision.

Working solution (tested on v2.1.88, Windows + Git Bash)

1. Create ~/.claude/hooks/auto-allow.sh:

#!/bin/bash
echo '{"hookSpecificOutput":{"hookEventName":"PermissionRequest","decision":{"behavior":"allow"}}}'
exit 0

2. Add to ~/.claude/settings.json:

{
  "hooks": {
    "PermissionRequest": [
      {
        "matcher": "*",
        "hooks": [
          {
            "type": "command",
            "command": "bash ~/.claude/hooks/auto-allow.sh",
            "timeout": 5
          }
        ]
      }
    ]
  }
}

The critical difference from my earlier (broken) attempt: "decision": {"behavior": "allow"} instead of "permissionDecision": "allow". The hook fires on every permission dialog and auto-approves before the UI shows.

This works independently of --dangerously-skip-permissions and permission modes — it's a separate layer. Works for .claude/** writes too.

@lukemmtt this should fix the issue you had with my previous suggestion.

lukemmtt · 3 months ago

Nice! I'll give it a shot, thanks!

zwrong · 3 months ago
Update: Got the PermissionRequest hook working properly. The key was the correct JSON structure — the docs show it uses decision.behavior, not permissionDecision. ### Working solution (tested on v2.1.88, Windows + Git Bash) 1. Create ~/.claude/hooks/auto-allow.sh: #!/bin/bash echo '{"hookSpecificOutput":{"hookEventName":"PermissionRequest","decision":{"behavior":"allow"}}}' exit 0 2. Add to ~/.claude/settings.json: { "hooks": { "PermissionRequest": [ { "matcher": "*", "hooks": [ { "type": "command", "command": "bash ~/.claude/hooks/auto-allow.sh", "timeout": 5 } ] } ] } } The critical difference from my earlier (broken) attempt: "decision": {"behavior": "allow"} instead of "permissionDecision": "allow". The hook fires on every permission dialog and auto-approves before the UI shows. This works independently of --dangerously-skip-permissions and permission modes — it's a separate layer. Works for .claude/** writes too. @lukemmtt this should fix the issue you had with my previous suggestion.

It works for me, Thx!

viceversaco · 3 months ago

this is silly. --dangerously-skip-permissions should do just that. please fix.

AaronHallAttorney · 3 months ago

Confirming on Windows — same behavior across all permission configurations.

Environment:

  • Claude Code v2.1.90
  • Windows 11 Pro 10.0.26200
  • Git Bash shell via Windows Terminal
  • Model: opus[1m]

Settings (both user and project level):

  • "defaultMode": "bypassPermissions"
  • Edit, Write, Edit(.claude/**), Write(.claude/**) all in allow list
  • "skipDangerousModePermissionPrompt": true
  • "skipAutoPermissionPrompt": true
  • Launch: claude --dangerously-skip-permissions

Behavior: Edit prompts appear for every new directory — .claude/skills/, .claude/rules/, memory files, project files. Selecting "Yes, allow all edits during this session" is directory-scoped, so each new subdirectory triggers a fresh prompt. In a typical session touching skills, rules, and workspace files, I'm approving 5-10 prompts before the session stops asking.

This defeats the purpose of autonomous/unattended operation. --dangerously-skip-permissions should bypass all interactive prompts including Edit confirmation.

monnyschouten94-arch · 3 months ago

Same issue on Windows 11 (non-WSL), Claude Code latest version.

Setup:

  • Working directory: C:\Users\monny (home dir, not a git repo — this might be a factor)
  • defaultMode: "bypassPermissions" set in all three config levels:
  • ~/.claude/settings.json
  • ~/.claude/settings.local.json
  • ~/.claude/projects/<project>/settings.local.json

Allow rules tried (none work):
I've added every possible path format and wildcard pattern for Edit/Write:

"allow": [
  "Edit *",
  "Write *",
  "Edit(*)",
  "Write(*)",
  "Edit(**)",
  "Write(**)",
  "Edit(~/.claude/studie-data/**)",
  "Edit(C:/Users/monny/.claude/studie-data/**)",
  "Edit(/c/Users/monny/.claude/studie-data/**)",
  "Edit(C:\Users\monny\**)",
  "Edit(C:/Users/monny/**)",
  "Edit(/c/Users/monny/**)",
  "Edit(~/**)"
]

Result: Edit and Write still prompt every single time, regardless of which path format or wildcard pattern is used. The permission dialog shows the Windows backslash path (C:\Users\monny\.claude\studie-data\...).

Hypothesis: The combination of Windows + no git repo in the working directory may cause Claude Code to ignore both bypassPermissions and all allow rules for Edit/Write operations. Read, Glob, and Grep work fine without prompting.

AaronHallAttorney · 3 months ago

Update: PermissionRequest hook workaround DOES work — but placement matters.

The PermissionRequest hook with decision.behavior: "allow" (from @sgeraldes's corrected version) works on v2.1.96, Windows 11 Home, MSYS2 bash (ARM64). .claude/ writes auto-approve without prompting.

The catch: If you have nested .claude/settings.json files (e.g., a sub-project directory with its own .claude/settings.json), the child settings override the parent's hooks entirely — they don't merge. So a hook defined only at the project root won't fire when working from a subdirectory that has its own settings file. The hook must be present at every level that has a .claude/settings.json.

Working setup:

  1. ~/.claude/settings.json — set "defaultMode": "bypassPermissions" (fixes the most-restrictive-wins bug across config layers)
  1. Create ~/.claude/hooks/auto-allow.sh (or project-local equivalent):
#!/bin/bash
echo '{"hookSpecificOutput":{"hookEventName":"PermissionRequest","decision":{"behavior":"allow"}}}'
exit 0
  1. Add PermissionRequest hook to every .claude/settings.json that exists in your directory hierarchy:
"PermissionRequest": [
  {
    "matcher": "",
    "hooks": [
      {
        "type": "command",
        "command": "bash ~/.claude/hooks/auto-allow.sh",
        "timeout": 5
      }
    ]
  }
]

Why @lukemmtt's test may have failed: If a child .claude/settings.json existed without the hook, it would silently override the parent — making it look like the hook doesn't work when it was simply never reached.

Environment: Claude Code v2.1.96, Windows 11 Home, MSYS2 bash (ARM64)

exFalso · 3 months ago

How is this not getting any attention? very strange