Claude Code permissions: safe auto-approval with defaultMode/allow/deny
Remove repeated prompts while still blocking risky actions — verified live.
Fewer prompts, but block the risky stuff
Claude Code asks for approval on writes and shell commands by default. `permissions` in `settings.json` lets you auto-approve routine actions while still blocking dangerous ones.
The permissions object
`allow`, `deny`, `ask`, `defaultMode` (behavior for anything unmatched), and `additionalDirectories`.
{
"permissions": {
"defaultMode": "acceptEdits",
"allow": ["Read", "Edit", "Bash(npm test)"],
"deny": ["Bash(rm -rf*)", "Bash(git push --force*)"],
"additionalDirectories": ["/Users/you/Downloads"]
}
}Valid defaultMode values
`default`, `acceptEdits`, `plan`, `dontAsk`, and `bypassPermissions` (isolated environments only). `acceptEdits` is a reasonable everyday default.
Live-tested: does deny really block?
In a test project with `deny: ["Bash(rm -rf*)"]`, running `claude -p` and asking it to run `rm -rf` returned: "Permission to use Bash with command rm -rf ... has been denied." The command never ran.
A gotcha we hit live: workspace trust
On a first-time project folder, Claude Code warned the workspace wasn't trusted and ignored some `allow` entries. You need to run it interactively once and accept the trust dialog (or set `hasTrustDialogAccepted` in `~/.claude.json`) before `allow` fully applies.
Permissions vs hooks
`permissions.deny` is a flat declarative rule; a `PreToolUse` hook can inspect context dynamically. Use `deny` for simple always-block patterns, hooks when you need to look at the actual command.