Permission Modes
Claude Code performs actions that affect your system — editing files, running commands, and more. The permission system controls how much freedom you give it.
Tool Approval Levels
Claude Code has different approval levels by tool type:
| Tool Type | Examples | Approval | "Don't ask again" Scope |
|---|---|---|---|
| Read-only | File read, Grep, Glob | Not required | - |
| Bash commands | Shell execution | Required | Persisted per project directory |
| File modifications | Edit, Write | Required | Until session ends |
6 Permission Modes
| Mode | Description | When to Use |
|---|---|---|
default | Asks for approval on first tool use | Normal development |
acceptEdits | Auto-approves file edits | Trusted local development |
plan | Analysis only, no edits/execution | Code exploration, architecture review |
auto | Classifier auto-approves/blocks | Long sessions, reducing prompt fatigue |
dontAsk | Only pre-approved tools, auto-denies rest | Restricted automation |
bypassPermissions | Skips all approval checks | Isolated containers/VMs only |
Switching Modes in Real-Time
During a session, press Shift+Tab or Alt+M to cycle through modes:
Default → Shift+Tab → Auto Accept → Shift+Tab → Plan → Shift+Tab → Auto → ...
For Auto mode to appear in the Shift+Tab cycle, you need the --enable-auto-mode flag at startup. Auto mode requires a Team plan or higher and Sonnet 4.6 or Opus 4.6 models.
Understanding Approval Options
In default mode, when Claude asks for approval:
Claude: I'll create auth/login.ts. Allow?
[y] Yes [n] No [a] Always allow this type [d] Don't allow
| Choice | Meaning |
|---|---|
y (Yes) | Allow this one time |
n (No) | Reject, Claude tries another approach |
a (Always) | Auto-allow this type for the session |
d (Don't allow) | Auto-reject this type for the session |
bypassPermissions disables all permission checks. Only use in isolated environments (Docker, VMs). Organization admins can block this mode via managed settings with disableBypassPermissionsMode: "disable".
Auto Mode — Classifier-Based Auto-Approval
Instead of manually approving every action, Auto mode uses a background classifier (Sonnet 4.6) to evaluate each tool call automatically. Unlike bypassPermissions, which allows everything, Auto mode judges whether each action fits the task context and only executes safe operations.
Requirements
| Requirement | Details |
|---|---|
| Plan | Team (launched), Enterprise/API (rolling out). Pro/Max not currently supported |
| Model | Sonnet 4.6 or Opus 4.6 only |
| Activation | CLI: --enable-auto-mode, Desktop/VS Code: enable in settings |
# Start in Auto mode from CLI
claude --enable-auto-mode --permission-mode auto
# Or start with the flag, then switch via Shift+Tab
claude --enable-auto-mode
Evaluation Order
Each tool call is evaluated in this order:
1. Matches an allow/deny rule → immediately allow/block
2. Read-only + file edits within working directory → auto-approve
3. Everything else → classifier evaluation
4. Classifier blocks → Claude tries an alternative approach
Default Block List
Actions the classifier blocks by default:
- Running downloaded code (
curl | bash, scripts from cloned repos) - Sending sensitive data to external endpoints
- Production deployments/migrations
- Bulk deletion from cloud storage
- IAM/repo permission changes
- Direct push to
mainbranch, force push - Irreversible deletion of files that existed before the session started
Actions the classifier allows by default:
- File operations within the working directory
- Installing dependencies declared in lock files
- Reading
.envand sending auth to those APIs - Read-only HTTP requests
- Pushing to the current branch or branches created by Claude
Run claude auto-mode defaults to see the full list of rules used by the classifier.
Fallback Behavior
If the classifier blocks 3 consecutive times or 20 total times in a session, Auto mode pauses and switches to manual approval. After manual approval, the counter resets and Auto mode resumes.
Auto Mode vs bypassPermissions
| Auto | bypassPermissions | |
|---|---|---|
| Safety checks | Classifier evaluates each action | None |
| Environment | Normal development | Isolated containers/VMs only |
| Token cost | Additional cost from classifier calls | Standard |
| Prompts | Only on fallback | None |
Auto mode is a research preview. It provides less protection than manual review. Use default mode for sensitive operations. Admins can disable this mode with disableAutoMode: "disable".
Managing Permission Rules
Use the /permissions command to view and manage current rules:
/permissions
Allow:
- Read(*)
- Edit(/src/**)
- Bash(npm test *)
Deny:
- Bash(rm *)
- Bash(git push *)
Evaluation order: deny → ask → allow. Deny always takes priority.
Permission Rule Syntax
Basic Format
Rules use the format ToolName or ToolName(specifier).
{
"permissions": {
"allow": [
"Read", // Allow reading all files
"Bash(npm run *)", // Any command starting with npm run
"Edit(/src/**/*.ts)" // Only edit TypeScript files under src/
],
"deny": [
"Bash(rm *)", // Block rm commands
"Bash(git push *)" // Block git push
]
}
}
Bash Rules: Wildcard Matching
* works as a glob pattern and can be used anywhere in the command:
| Rule | Matches |
|---|---|
Bash(npm run build) | Exactly npm run build only |
Bash(npm run *) | npm run test, npm run lint, etc. |
Bash(* --version) | node --version, npm --version, etc. |
Bash(git * main) | git checkout main, git merge main, etc. |
Bash(ls *) matches ls -la but not lsof. The space enforces a word boundary. Bash(ls*) matches both.
Claude Code recognizes shell operators like &&. Bash(safe-cmd *) will NOT allow safe-cmd && dangerous-cmd.
Read/Edit Rules: Gitignore-Style Patterns
File path rules follow the gitignore spec:
| Pattern | Meaning | Example |
|---|---|---|
//path | Filesystem absolute path | Read(//Users/alice/secrets/**) |
~/path | Home directory relative | Read(~/Documents/*.pdf) |
/path | Project root relative | Edit(/src/**/*.ts) |
path | Current directory relative | Read(*.env) |
{
"permissions": {
"allow": [
"Edit(/docs/**)", // Only allow editing under docs/
"Read(~/.zshrc)" // Allow reading home .zshrc
],
"deny": [
"Read(.env)", // Block reading .env files
"Edit(//etc/*)" // Block editing /etc/
]
}
}
* matches files within a single directory, ** recursively matches through subdirectories.
MCP Tool Rules
{
"permissions": {
"allow": [
"mcp__puppeteer", // All tools from puppeteer server
"mcp__github__github_list_repos" // Only specific tool from github server
]
}
}
Sub-Agent (Task) Rules
{
"permissions": {
"deny": [
"Agent(Explore)" // Disable Explore sub-agent
]
}
}
settings.json Hierarchy
Permission rules can be defined in multiple locations, with this priority:
Managed (Org) → CLI args → Local project → Shared project → User global
| Location | File | Priority |
|---|---|---|
| Organization managed | MDM/server policies | Highest |
| CLI arguments | --allowedTools, --disallowedTools | High |
| Local project | .claude/settings.local.json | Medium |
| Shared project | .claude/settings.json | Medium |
| Global user | ~/.claude/settings.json | Lowest |
Project settings override user settings. Even if user settings allow a tool, project settings can deny it.
Additional Directory Access
By default, Claude only accesses files in the working directory. To open additional directories:
# Add at startup
claude --add-dir /path/to/other-project
# Add during session
/add-dir /path/to/other-project
Permissions vs Sandboxing
Permissions and sandboxing are complementary:
| Permissions | Sandboxing | |
|---|---|---|
| Applies to | All tools | Bash commands only |
| How it works | Controls Claude's tool usage | OS-level file/network isolation |
| Defends against | Limiting Claude's decisions | Prompt injection bypass prevention |
Using both together implements defense-in-depth.
Get weekly Claude Code tips by email — real usage insights, delivered free. Subscribe →
Mode Selection Guide
What are you doing?
│
├─ Exploring/understanding a new codebase
│ → Plan mode (read-only)
│
├─ Fast local development, solo
│ → acceptEdits or default (git commit first)
│
├─ Long refactoring session, reducing approval fatigue
│ → Auto mode (classifier decides for you)
│
├─ Team project, critical code
│ → Default mode + project settings.json rules
│
├─ CI/CD, automation scripts
│ → Headless mode + allowedTools specified
│
└─ Isolated Docker/VM test environment
→ bypassPermissions (caution!)
Practical Configuration Examples
Safe Development Environment
{
"permissions": {
"allow": [
"Read",
"Edit(/src/**)",
"Bash(npm test *)",
"Bash(npm run lint *)",
"Bash(git diff *)",
"Bash(git status *)",
"Bash(git log *)"
],
"deny": [
"Bash(rm *)",
"Bash(git push *)",
"Bash(curl *)",
"Bash(wget *)",
"Edit(*.env)"
]
}
}
CI/CD Environment (Headless)
claude -p "Review this code" \
--allowedTools "Read,Grep,Glob" \
--disallowedTools "Bash,Edit,Write"