Permissions duplicated in settings.local.json despite existing grants in settings.json

Resolved 💬 3 comments Opened Feb 24, 2026 by damian-giebas-solidstudio Closed Feb 27, 2026

Bug Description

When a user clicks "Always allow" on a permission prompt, Claude Code writes the permission to .claude/settings.local.json even when the exact same permission already exists in .claude/settings.json. This results in duplicate permission entries across the two files.

Steps to Reproduce

  1. Create a project with .claude/settings.json containing explicit permission grants, e.g.:

``json
{
"permissions": {
"allow": [
"Bash(grep:*)",
"Bash(ls:*)",
"Bash(wc:*)"
]
}
}
``

  1. Commit settings.json to the repo (it's not gitignored).
  2. Start a Claude Code session in that project.
  3. When Claude triggers a command that matches an already-granted permission (e.g. grep), in some cases it still prompts for permission.
  4. Click "Always allow".
  5. Observe that the permission is written to .claude/settings.local.json despite already being present in settings.json.

Observed Behavior

.claude/settings.local.json accumulates duplicate permissions that are already granted in .claude/settings.json.

Real-world example from a monorepo with submodules:

Root .claude/settings.json already contains:

"Bash(grep:*)", "Bash(grep *:*)"

Root .claude/settings.local.json also contains:

"Bash(grep:*)"

Same pattern in submodules — e.g. test-business-rules/.claude/settings.json grants Bash(wc:*) and Bash(ls:*), yet the same entries appear in its settings.local.json.

Expected Behavior

  • The "Always allow" write path should check whether the permission is already granted by settings.json before writing to settings.local.json.
  • If a permission is already covered by settings.json, the prompt should not appear in the first place.

Environment

  • Claude Code CLI (latest, installed via npm)
  • Linux (Ubuntu 24.04, kernel 6.8)
  • Project structure: monorepo with git submodules, each submodule has its own .claude/settings.json

Additional Context

This might be related to how permission resolution works across the settings hierarchy (project settings.json vs personal settings.local.json). It seems like the read path (checking if a permission is granted) and the write path (saving "Always allow" choices) may not share the same resolution logic — the write path appears to always target settings.local.json without consulting settings.json first.

View original on GitHub ↗

This issue has 3 comments on GitHub. Read the full discussion on GitHub ↗