Claude Code Permissions and Security
Configure permission modes, auto-approval rules, and security boundaries to keep autonomous file edits and commands safe.
~8 min read
One of the first questions any security-conscious engineer or business owner asks when looking at Claude Code is: "If this tool can edit files and run shell commands, how do I know it won't delete my database or push broken code to main?"
That concern is legitimate. An AI agent with terminal access is a powerful lever. Without permission boundaries, a misunderstood instruction could trigger an unintended git push or run a destructive cleanup script. Fortunately, Claude Code was designed with explicit permission tiers and allow/deny rules.
The default permission contract: reads are quiet, writes prompt
When you install Claude Code and open your first session, it starts in normal mode. In this mode, reading files inside your repository is silent. Claude opens files, reads documentation, and analyzes syntax without interrupting you.
Modifications, deletions, and shell command executions stop and prompt for explicit user confirmation. You inspect the proposed diff or shell command before approving.
The three operational permission modes
Claude Code supports three operational permission tiers. You can cycle between them mid-session by pressing Shift+Tab at the terminal prompt:
- Normal mode: Every file edit, deletion, and shell command asks for interactive confirmation. Safest for exploring unfamiliar codebases or reviewing junior developer pull requests.
- Auto mode: An autonomous classifier model reviews proposed actions before execution. Low-risk operations (formatting, running tests, local edits) proceed automatically, while high-risk commands (git push, rm -rf, network calls) still pause for your confirmation. This is the standard mode for subscribers after their initial session.
- Bypass mode: All tool calls execute without interactive prompts. Intended strictly for sandboxed containers and headless CI automation runners where no human is present to approve.
How auto mode evaluates actions
Auto mode does not give Claude a blank check. Instead, a lightweight secondary model evaluates each tool call before execution. If the action matches standard development workflows (such as editing a test file or running npm test), it auto-approves. If an action touches external endpoints, modifies git history, or removes directories, auto mode drops back to an interactive prompt.
Persistent permission configuration in settings.json
Answering approval prompts for routine commands like `npm test` or `git status` creates unnecessary friction. Instead of approving commands turn-by-turn, you can establish persistent rules in `.claude/settings.json`.
{
"permissions": {
"allow": [
"Bash(npm test*)",
"Bash(npm run lint)",
"Bash(git status)",
"FileEdit(src/**/*)"
],
"deny": [
"FileEdit(.env*)",
"FileRead(.env*)",
"Bash(git push*)",
"Bash(rm -rf*)"
]
}
}Notice the hierarchy: deny rules always take precedence over allow rules. Even if an allow rule matches `FileEdit(**/*)`, a deny rule targeting `.env*` blocks any edit or read of your environment file instantly without prompting.
Scoping tool patterns and skills
Permission patterns use the syntax `ToolName(pattern)`:
- Exact match: `Bash(npm test)` permits only that exact string. Any additional flags prompt for confirmation.
- Prefix match: `Bash(npm test*)` permits `npm test`, `npm test -- --watch`, and any other command starting with that prefix.
- Skill scoping: `Skill(commit)` or `Skill(deploy *)` allows you to control which skills run automatically vs which require an explicit user prompt.
Inspecting active permissions with /permissions
Whenever you start work on an important branch, run `/permissions` to verify which rules are currently in force.
Get new guides in your inbox
One task, one guide, done fast. Practical Claude Code skills, zero noise.


