Skip to content

[BUG] bypassPermissions v2.1.81: .claude/skills/ not exempt from protected directory prompt despite documentation #37157

@usorama

Description

@usorama

Description

The permissions documentation states:

Writes to .claude/commands, .claude/agents, and .claude/skills are exempt and do not prompt, because Claude routinely writes there when creating skills, subagents, and commands.

However, in v2.1.81, .claude/skills/ is not exempt from the protected directory prompt. Edits to files under .claude/skills/** trigger the "Do you want to make this edit?" prompt with the "Yes, and allow Claude to edit its own settings for this session" option — even with bypassPermissions mode active.

Root Cause (from source analysis)

The exemption function in the bundled binary only includes two of the three documented paths:

// Actual code in v2.1.81 binary (decompiled):
function sXT() {
    return [...nCK.filter(d => d !== ".git"), ".claude/commands", ".claude/agents"]
}
// Returns: [".vscode", ".idea", ".claude/commands", ".claude/agents"]
// MISSING: ".claude/skills"

The docs promise .claude/skills is exempt, but the code doesn't include it.

Steps to Reproduce

  1. Set "defaultMode": "bypassPermissions" in settings
  2. Have a skill with scripts under .claude/skills/<name>/scripts/
  3. Ask Claude to edit any file under .claude/skills/
  4. Actual: Permission prompt appears
  5. Expected: No prompt (skills are documented as exempt)

Impact

This is particularly disruptive for projects that use .claude/skills/ extensively for automation, agent workflows, and domain-specific tooling. Every new session requires manual approval for the first .claude/skills/** edit, breaking autonomous claude -p --dangerously-skip-permissions workflows.

Related Issues

Environment

  • Claude Code version: 2.1.81
  • OS: macOS (Darwin 25.3.0, arm64)
  • Shell: zsh
  • Settings: bypassPermissions + skipDangerousModePermissionPrompt: true

Suggested Fix

Add .claude/skills to the sXT() exemption function to match the documented behavior:

function sXT() {
    return [...nCK.filter(d => d !== ".git"), ".claude/commands", ".claude/agents", ".claude/skills"]
}

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