How to add deny rules in Claude Code (settings.json examples)
Add a permissions.deny array to .claude/settings.json (or settings.local.json). Each entry is a rule like Read(./.env) or Bash(git push *). Claude Code checks deny before ask and allow, so a matching deny blocks the call even if an allow rule also matches.
Stats from the 2026-10-20 snapshot of public GitHub configs (methodology). Behavior checked against the official docs linked below.
Minimal example
{
"permissions": {
"deny": [
"Read(./.env)",
"Read(./.env.*)",
"Read(./secrets/**)",
"Edit(./.claude/**)",
"Write(./.claude/**)",
"Bash(git push *)",
"Bash(rm -rf *)"
]
}
}How precedence works
Rules are evaluated deny → ask → allow, and the first match wins regardless of how specific the rule is. A broad deny like Bash(aws *) blocks Bash(aws s3 ls) even if that is explicitly allowed. A bare tool name in deny (for example WebFetch) removes the tool entirely. Deny rules apply in every permission mode, including bypassPermissions.
Which rules to deny first
Secrets (Read(./.env), Read(./.env.*), Read(./secrets/**)), the settings directory (Edit(./.claude/**), Write(./.claude/**)), so the agent can't rewrite its own deny list, and irreversible commands such as git push and rm -rf. Use ask instead of deny for commands you want to approve case by case.
What public configs do
Of 4,831 unique public Claude Code configs with a permissions block, 85.6% have no deny rules. 24% allow a wildcard interpreter and 12.5% allow curl or wget to any URL, which are the cases where deny rules matter most.
What existing deny rules cover
Of the 694 unique configs that have deny rules: .env files 339 (48.8%), secrets / credentials paths 152 (21.9%), .claude settings 31 (4.5%), git push 292 (42.1%), rm (incl. rm -rf) 331 (47.7%). Only 5 cover all five. As a share of all 4,831 configs with permissions, only 7% deny .env.
Rule syntax note
Current docs write wildcards with a space, e.g. Bash(npm run *). Many existing configs use the older colon form, e.g. Bash(npm run:*).
FAQ
Do deny rules work in bypassPermissions mode?
Yes. Per the Claude Code docs, deny rules block in every mode, including bypassPermissions.
Where should team-wide deny rules go?
In .claude/settings.json committed to the repo, or in managed settings if your organization deploys them. Personal additions go in .claude/settings.local.json.