You added an allow rule so a command would stop asking — but it still prompts every time. Or you added a deny rule, or set bypassPermissions, and the behavior didn't change. The frustrating part is that a permission rule that silently doesn't match is worse than no rule at all: you keep working believing you are guarded, when you are not. Here are the causes that actually produce this, in the order worth checking, and how to confirm each.
Before changing anything, run /permissions in Claude Code. It shows the effective, merged rules and the exact form Claude is matching against. Almost every "my rule is ignored" case is a mismatch between what you wrote and what /permissions actually shows — so this is your ground truth. Match the rule you expect against the list there; if it's absent or in a different form, one of the causes below explains it.
On Windows, Claude Code normalizes paths to a POSIX-style form before matching a rule. A path like C:\Users\alice\project is matched as /c/Users/alice/project. So a rule you wrote with backslashes, or a UNC path like \\server\share, will never match the normalized form — and the action falls through to a prompt every time.
/permissions rather than guessing. The normalized form for a given drive/UNC path isn't always obvious, so copy it from /permissions and build your rule from that.
Rules are merged from several files, and a higher-precedence layer can override what you just edited. Roughly, from highest to lowest precedence:
| Layer | Where |
|---|---|
| Enterprise / managed policy | system-managed settings |
| Command-line flags | flags passed to the claude invocation |
| Project (local, untracked) | .claude/settings.local.json |
| Project (shared) | .claude/settings.json |
| User | ~/.claude/settings.json |
A deny in a higher layer beats an allow you added lower down, and a forgotten rule in .claude/settings.local.json can quietly shadow your project file. /permissions shows the merged result; if your rule isn't winning, find which file actually contributes the conflicting entry.
A rule only fires when both the tool name and the pattern match what Claude is about to do.
Bash(npm run test:*) matches npm run test:unit but not a bare npm test. Too-specific patterns match nothing.Edit — matches all uses of that tool. If a bare rule "does nothing," that's a sign the active mode isn't the one you think (see Cause 4), not that the pattern is wrong.Bash), not a tool named after the program — check the tool name in /permissions or in the permission prompt itself.defaultModeIf you set defaultMode (e.g. acceptEdits or bypassPermissions) in settings.json but still get prompts, the surface you're using may be overriding it. In the VS Code extension, the mode selected in the UI (for example "Edit automatically", which is acceptEdits) takes precedence over the settings.json default, and bypassPermissions is additionally gated behind the extension's own toggle (claudeCode.allowDangerouslySkipPermissions) — until that toggle is on, a settings.json bypass won't take effect.
Turning on a blanket bypass to stop prompts removes every guard at once, including the ones catching genuinely destructive actions. A narrower setup — acceptEdits for routine edits plus a deny list for the handful of irreversible operations — keeps the prompts off where they're noise and on where they matter.
skipDangerousModePermissionPrompt only hides the warningIf you set skipDangerousModePermissionPrompt expecting it to stop per-action confirmations, that's the wrong lever: it suppresses the warning shown when you enter dangerous mode, not the action confirmations themselves. Worse, once it's set, the warning that you're running without guards stops appearing — so it removes a safety reminder without giving you the behavior you wanted.
Changes to settings.json (and to hooks) made while Claude Code is already running may not take effect until you restart the session. If you edited a rule and nothing changed, restart Claude Code and re-check with /permissions.
A rule that now appears in /permissions is matching; but the most reliable check is behavioral — trigger the exact action once and confirm it is allowed/denied/prompted as you intended. The whole point of a permission rule is that it does something when it matters, and the only way to know is to see it act once.
Want guards that enforce at the tool layer regardless of prompt-mode confusion?
npx cc-safe-setup
Free, MIT hooks that block destructive and irreversible actions before they run — independent of which UI mode is active.
Based on Anthropic's public permissions and settings documentation and reproduced reports. Permission behavior can vary by version and surface (CLI vs VS Code extension); /permissions is the ground truth on your machine — check the official docs for the latest. cc-safe-setup is an independent open-source project, not affiliated with Anthropic.