[BUG] --dangerously-skip-permissions does not bypass "edit its own settings" prompt for .claude/ directory writes

Status Fixed / completed
Reported on v2.1.81
Maintainer reply None cached
Activity 13 comments · opened Mar 23, 2026 · closed Apr 24, 2026

Preflight Checklist

  • [x] I have searched existing issues and this hasn't been reported yet
  • [x] This is a single bug report (please file separate reports for different bugs)
  • [x] I am using the latest version of Claude Code

What's Wrong?

When running Claude Code with --dangerously-skip-permissions, writes to files inside ~/.claude/ still trigger a permission prompt:

Do you want to make this edit to .md?

  1. Yes

❯ 2. Yes, and allow Claude to edit its own settings for this session

  1. No

This happens every new session, defeating the purpose of the flag.

## Steps to Reproduce

  1. Configure settings.json with "defaultMode": "bypassPermissions" and "skipDangerousModePermissionPrompt": true
  2. Launch with claude --dangerously-skip-permissions
  3. Use any skill that writes files to ~/.claude/ (e.g., session-handoff, save-plan, or auto-memory)
  4. The "edit its own settings" prompt appears despite the flag

## Expected Behavior

--dangerously-skip-permissions should bypass ALL permission prompts, including writes to .claude/ directory. The flag name itself implies full bypass.

## Actual Behavior

A hardcoded "protected directory" check for .claude/ overrides the --dangerously-skip-permissions flag. The user must manually approve once per session
(option 2).

## Environment

  • Claude Code version: 2.1.81
  • OS: Windows 11 Pro
  • Settings: defaultMode: "bypassPermissions", skipDangerousModePermissionPrompt: true
  • Multiple plugins/skills enabled that write to ~/.claude/

## Impact

This breaks autonomous workflows and CI/CD usage where no human is present to approve. It also creates friction for power users who have explicitly opted into
full bypass mode.

What Should Happen?

When --dangerously-skip-permissions flag is active, ALL permission prompts should be bypassed — including writes to the .claude/ directory. The flag name
explicitly says "dangerously skip permissions", so no permission check should override it. Currently a hardcoded "protected directory" check for .claude/ still
triggers the "edit its own settings" prompt every session, which defeats the purpose of the flag and breaks autonomous/unattended workflows.

Error Messages/Logs

Steps to Reproduce

  1. Set "defaultMode": "bypassPermissions" and "skipDangerousModePermissionPrompt": true in ~/.claude/settings.json
  2. Launch Claude Code with claude --dangerously-skip-permissions
  3. Trigger any action that writes a file inside ~/.claude/ (e.g., a plugin skill writing a .md file, auto-memory saving to ~/.claude/projects/*/memory/, or

session-handoff creating a handoff file)

  1. A permission prompt appears: "Do you want to make this edit to <file>.md? 1. Yes / 2. Yes, and allow Claude to edit its own settings for this session / 3. No"
  2. This happens on every new session, regardless of the flag

Claude Model

None

Is this a regression?

Yes, this worked in a previous version

Last Working Version

_No response_

Claude Code Version

2.1.81 (Claude Code)

Platform

Anthropic API

Operating System

Windows

Terminal/Shell

Windows Terminal

Additional Information

_No response_

View original on GitHub ↗

16 Comments

github-actions[bot] · 5 months ago

Found 3 possible duplicate issues:

  1. https://github.com/anthropics/claude-code/issues/37029
  2. https://github.com/anthropics/claude-code/issues/35718
  3. https://github.com/anthropics/claude-code/issues/36923

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

yurukusa · 5 months ago

Same as #37253 and #37157 — \~/.claude/\ is a hardcoded protected directory that even \--dangerously-skip-permissions\ won't bypass. This is by design to prevent the model from modifying its own hooks and settings.
Workaround — a PreToolUse hook that auto-approves writes to specific \.claude/\ subdirectories:
\\\bash
INPUT=\$(cat)
TOOL=\$(echo "\$INPUT" | jq -r '.tool_name // empty' 2>/dev/null)
FILE=\$(echo "\$INPUT" | jq -r '.tool_input.file_path // empty' 2>/dev/null)
[[ "\$TOOL" != "Edit" && "\$TOOL" != "Write" ]] && exit 0
case "\$FILE" in
*/\.claude/commands/*|*/\.claude/skills/*|*/\.claude/agents/*|*/\.claude/rules/*)
jq -n '{"hookSpecificOutput":{"hookEventName":"PreToolUse","permissionDecision":"allow","permissionDecisionReason":".claude subdirectory auto-approved"}}'
exit 0 ;;
esac
exit 0
\
\\
This selectively allows writes to safe subdirectories while keeping \hooks/\ and \settings.json\ protected.

adelfino69 · 5 months ago

Additional findings — PreToolUse hooks also cannot bypass this

After investigating the workaround suggested in the comments (PreToolUse hook with permissionDecision: "allow"), I confirmed that it does not work either.

What I tried

  1. Created a PreToolUse command hook that returns:
{
  "hookSpecificOutput": {
    "permissionDecision": "allow",
    "permissionDecisionReason": ".claude subdirectory auto-approved"
  }
}
  1. Hook was correctly configured in settings.json with matcher Edit|Write
  2. jq available, script executable, correct JSON output verified

Result

The "Do you want to make this edit? / Yes, and allow Claude to edit its own settings for this session" prompt still appears despite the hook returning allow.

Root cause analysis

The .claude/ self-edit protection operates at a separate layer from the permission system:

| Layer | What controls it | Can be bypassed? |
|---|---|---|
| Permission rules | settings.json allow/deny lists | Yes (via --dangerously-skip-permissions) |
| PreToolUse hooks | Hook scripts returning permissionDecision | Yes (hooks can override) |
| Built-in self-edit protection | Hardcoded in source | No — nothing bypasses this |

The self-edit protection for .claude/ fires after hooks, overriding any permissionDecision: "allow" from PreToolUse hooks. This means:

  • --dangerously-skip-permissions → still prompts ❌
  • defaultMode: "bypassPermissions" → still prompts ❌
  • skipDangerousModePermissionPrompt: true → only skips the initial warning, not per-edit prompts ❌
  • PreToolUse hook with permissionDecision: "allow" → still prompts ❌

Impact

This affects all users with plugins/skills that write to ~/.claude/ (auto-memory, session-handoff, save-plan, insights, etc.). The prompt appears every new session, requiring manual approval via option 2.

Suggestion

Either:

  1. Make --dangerously-skip-permissions truly bypass everything (the flag name implies this)
  2. Or add a setting like "allowSelfEdit": true that explicitly opts into bypassing the self-edit protection
  3. Or at minimum, allow PreToolUse hooks to override it — the user has already explicitly configured the hook, showing intent

Environment

  • Claude Code: 2.1.81
  • OS: Windows 11 Pro
  • All permission bypass options configured and verified
yurukusa · 5 months ago

@adelfino69 Thanks for testing this so thoroughly. Your analysis is correct — my workaround was wrong for the .claude/ self-edit case.
The key finding from your table is that the built-in self-edit protection runs after PreToolUse hooks and overrides the allow decision. So even a correctly configured hook returning permissionDecision: "allow" gets ignored for .claude/ writes.
To clarify for others reading: PreToolUse hooks with permissionDecision do work for overriding protection on .git/ and .vscode/ directories (the other hardcoded protected paths). The .claude/ self-edit check is a separate, unhookable layer that none of the current bypass mechanisms can reach.
Agree that option 1 or 3 from your suggestions would resolve this cleanly.

saidelike · 5 months ago

Idea... Have you tried adding a permission in your project or globally in the settings.json?

  "permissions": {
    "allow": ["Edit(/.claude/path/to/what/you/want/**)"]
  },

Or using Read(), Write(), etc.

adelfino69 · 5 months ago

I can confirm this doesn't work either. My settings.json already has the most permissive configuration possible:

{
  "permissions": {
    "allow": ["Read", "Edit", "Write", "Glob", "Grep", "..."],
    "defaultMode": "bypassPermissions"
  },
  "skipDangerousModePermissionPrompt": true
}

Edit and Write are allowed without any path restrictions, plus bypassPermissions mode is active. Adding "Edit(~/.claude/**)" would be redundant — unrestricted "Edit" already covers every path.

The self-edit prompt for .claude/ still appears every session.

This confirms @yurukusa's analysis: the .claude/ protection is a hardcoded layer that operates independently of the entire permissions system. No combination of settings can bypass it.

yurukusa · 5 months ago

PreToolUse can't bypass the built-in protected-directory check because it runs before those checks — the "allow" gets overridden downstream.
PermissionRequest runs after the built-in checks, so it sticks:

{
  "hooks": {
    "PermissionRequest": [
      {
        "matcher": "Edit|Write",
        "hooks": [
          {
            "type": "command",
            "command": "bash ~/.claude/hooks/allow-claude-dir.sh"
          }
        ]
      }
    ]
  }
}

~/.claude/hooks/allow-claude-dir.sh:

INPUT=$(cat)
FILE=$(echo "$INPUT" | jq -r '.tool_input.file_path // empty' 2>/dev/null)
if [[ "$FILE" == *".claude/"* ]]; then
    jq -n '{hookSpecificOutput:{hookEventName:"PermissionRequest",decision:{behavior:"allow"}}}'
fi
exit 0

Confirmed working in #37836, #36044, #36282.

jasonswearingen · 5 months ago

I tested the allow-claude-dir.sh and it is NOT working. claude 2.1.81 on windows. pretty frustrating.

interconnectedMe · 5 months ago

Hitting this constantly. I have hooks and agents that legitimately need to edit files in .claude/hooks/ and .claude/skills/, and the permission prompt interrupts every single operation. When I'm away from the screen the prompt times out and registers as a rejection, which derails the entire workflow. Please give us a way to allowlist specific .claude/ subdirectories.

saidelike · 5 months ago
Hitting this constantly. I have hooks and agents that legitimately need to edit files in .claude/hooks/ and .claude/skills/, and the permission prompt interrupts every single operation. When I'm away from the screen the prompt times out and registers as a rejection, which derails the entire workflow. Please give us a way to allowlist specific .claude/ subdirectories.

Did you try the allow-claude-dir.sh trick above?

openclosure · 5 months ago

This completely allows all edits for me, no need for a script.

    "PermissionRequest": [
      {
        "matcher": "Edit|Write",
        "hooks": [
          {
            "type": "command",
            "command": "printf '{\"hookSpecificOutput\":{\"hookEventName\":\"PermissionRequest\",\"decision\":{\"behavior\":\"allow\"}}}'"
          }
        ]
      }
    ]
adelfino69 · 5 months ago

Confirmed working on Windows 11 — printf inline is the cleanest solution.

After several days of testing every possible bypass (documented earlier in this thread), I can confirm that @openclosure's PermissionRequest + printf approach fully resolves the issue on Windows.

What works

Tested writes to ~/.claude/plans/, ~/.claude/projects/*/memory/, and other .claude/ subdirectories — no permission prompt appeared.

Full working settings.json (Windows 11, Claude Code 2.1.86)

For anyone struggling with this on Windows, here's the minimal configuration that works:

{
  "permissions": {
    "defaultMode": "bypassPermissions"
  },
  "skipDangerousModePermissionPrompt": true,
  "hooks": {
    "PermissionRequest": [
      {
        "matcher": "Edit|Write",
        "hooks": [
          {
            "type": "command",
            "command": "printf '{\"hookSpecificOutput\":{\"hookEventName\":\"PermissionRequest\",\"decision\":{\"behavior\":\"allow\"}}}'",
            "timeout": 5
          }
        ]
      }
    ]
  }
}

Key points:

  • defaultMode: "bypassPermissions" + skipDangerousModePermissionPrompt: true handle all normal permission prompts
  • The PermissionRequest hook handles the .claude/ self-edit prompt specifically — this is the one that nothing else can bypass
  • printf works natively in Git Bash on Windows — no need to install jq or create external scripts
  • The timeout: 5 is optional but recommended to avoid hanging if something goes wrong

Why the script-based approach failed on Windows

@jasonswearingen reported that allow-claude-dir.sh didn't work on Windows (claude 2.1.81). I can confirm the same — I had @yurukusa's script configured in my settings.json but the prompt kept appearing every session.

The likely root cause: when Claude Code invokes bash on Windows (Git Bash), the shell environment may not have jq in its PATH, or the $(cat) stdin pipe behaves differently. The script fails silently (no output) → Claude falls back to the built-in prompt.

The printf inline approach eliminates all external dependencies — no jq, no separate .sh file, no stdin parsing. It just returns the allow decision directly.

Important: PermissionRequest vs PreToolUse

This is the key technical detail that took us a while to figure out. There are two different hook events, and only one works for this:

| Hook event | When it runs | Can bypass .claude/ self-edit? |
|------------|-------------|----------------------------------|
| PreToolUse | Before permission checks | ❌ No — the self-edit protection runs after and overrides it |
| PermissionRequest | After built-in checks, when a prompt would be shown | ✅ Yes — it intercepts the prompt before the user sees it |

If you're using PreToolUse with permissionDecision: "allow", switch to PermissionRequest with decision: { behavior: "allow" }. Note the different JSON structure too.

Summary of all approaches tested

| Approach | Works? | Why |
|----------|--------|-----|
| --dangerously-skip-permissions | ❌ | .claude/ self-edit protection is a separate hardcoded layer |
| defaultMode: "bypassPermissions" | ❌ | Same reason |
| permissions.allow: ["Edit", "Write"] (unrestricted) | ❌ | Permission allow lists don't override self-edit protection |
| PreToolUse hook returning permissionDecision: "allow" | ❌ | Runs before the self-edit check — gets overridden downstream |
| PermissionRequest hook with external bash script + jq | ⚠️ | Works on Linux/macOS, but unreliable on Windows (silent jq/stdin failures) |
| PermissionRequest hook with inline printf | ✅ | Runs after the self-edit check, no external dependencies, cross-platform |

Note on scope

This hook approves all Edit|Write operations that trigger a permission prompt, not just .claude/ writes. If you want to be more selective, you could wrap the printf in a bash conditional — but if you're already in bypassPermissions mode, the only prompts reaching PermissionRequest should be the .claude/ self-edit ones anyway.

Thanks to @yurukusa for identifying PermissionRequest as the correct hook event and explaining the execution order, and @openclosure for the elegant printf simplification.

That said, I still think this should be fixed upstream — --dangerously-skip-permissions should mean what it says. But at least we have a solid, copy-pasteable workaround now.

jasonswearingen · 4 months ago

@chrislloyd the issue still exists as of v 2.1.126, please reopen.

EDIT: I upgraded to latest and now the issue is gone, so not sure. either way, yeah okay to keep closed.

saidelike · 3 months ago
@chrislloyd the issue still exists as of v 2.1.126, please reopen.

Shouldn't it be fixed since that version actually?

https://github.com/anthropics/claude-code/blob/main/CHANGELOG.md#21126

jasonswearingen · 3 months ago

I upgraded to latest and now the issue is gone, so not sure. either way, yeah okay to keep closed.

github-actions[bot] · 2 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.