Claude Code Permission Configuration
Claude Code uses a layered permission system to balance functionality and security, supporting fine-grained permission rules, permission modes, and sandbox policies to control what Claude can access and execute. Properly configured permissions allow the AI to complete tasks efficiently while preventing accidental operations from damaging code or leaking sensitive files.
Starting from Claude Code v1.1.1, the new permission configuration method is recommended. The old
toolsBoolean configuration is still supported, but it is recommended to migrate to the new permission rule syntax.
Permission System Overview
Claude Code's permission system categorizes operations into three types, with different default permission policies for each type:
| Tool Type | Example | Approval Required | Permanently Allowed Behavior |
|---|---|---|---|
| Read-Only Operations | File reading, Grep search | no | Not applicable |
| Bash Commands | Shell command execution | Yes | Permanent for each project directory and command |
| File Modifications | Edit/Write files | Yes | Until the end of the session |
Three Permission Actions
Each permission rule ultimately resolves to one of the following three actions:
| Action | Effect | Applicable Scenario |
|---|---|---|
"allow" |
Automatically runs without approval | Low-risk, high-frequency operations such as git status, npm run build |
"ask" |
Shows an approval prompt, letting you decide whether to allow | Operations with some risk, such as file writing, dangerous command execution |
"deny" |
Directly blocked, not executed and no prompt | Clearly disallowed dangerous operations, such as git push, rm -rf |
Rule priority: deny → ask → allow.The first matching rule wins, so deny rules always take precedence over allow and ask.
Permission Modes
Permission modes control whether Claude asks the user before performing actions. Different tasks require different levels of autonomy.
1. Six Available Modes
| Mode | Description | Best used for |
|---|---|---|
default |
Standard behavior: prompts for permission on first use of each tool | Onboarding, sensitive work requiring full supervision |
acceptEdits |
Automatically accept file edit permissions for the session, except for protected directories | Iterating on code under review |
plan |
Plan Mode: Claude can analyze but cannot modify files or execute commands | Exploring codebases, planning refactors |
auto |
Automatically approve tool calls with background security checks (research preview) | Long-running tasks, reducing prompt fatigue |
dontAsk |
Automatically reject tool calls unless pre-approved via permission rules | Locked-down environments, CI pipelines |
bypassPermissions |
Skip permission prompts, but writes to protected directories still prompt | Isolated containers and VMs only |
Protected directories note:Regardless of mode, writes to
.git、.vscode、.idea、.huskyand.claudewill never be automatically approved, except for.claude/commands、.claude/agentsand.claude/skills。
2. Switching Permission Modes
Switch during a session:pressShift+TabCycle through modesdefault → acceptEdits → plan → auto
Specify mode at startup:
claude --permission-mode plan claude --permission-mode bypassPermissions
Set as default mode (settings.json):
Example
"permissions": {
"defaultMode": "acceptEdits"
}
}
Permission Rule Syntax
1. Basic Format
Permission rules follow the formatToolorTool(specifier):
Example
"permissions": {
"allow": ["Bash", "WebFetch", "Read"],
"deny": ["Edit"]
}
}
2. Matching All Tool Usage
Rules without specifiers match all uses of that tool:
| Rule | Effect |
|---|---|
Bash |
Matches all Bash commands |
WebFetch |
Matches all network fetch requests |
Read |
Matches all file reads |
Edit |
Matches all file edits |
Bash(*)Equivalent toBash, both have the same effect.
3. Fine-Grained Control with Specifiers
Example
"permissions": {
"allow": [
"Bash(npm run build)", // Match exact commands
"Read(./.env)", // Match reading the .env file in the current directory
"WebFetch(domain:example.com)" // Match fetch requests to example.com
]
}
}
4. Wildcard Patterns
Bash rules support glob patterns with*wildcards; wildcards can appear anywhere in the command:
Example
"permissions": {
"allow": [
"Bash(npm run *)", // Matches npm run build, npm run test, etc.
"Bash(git commit *)", // Matches git commit -m "message", etc.
"Bash(git * main)", // Matches git checkout main, git merge main, etc.
"Bash(* --version)", // Matches any command with a --version argument
"Bash(* --help *)" // Matches any command with a --help argument
],
"deny": [
"Bash(git push *)" // Blocks all git push operations
]
}
}
Note the space before wildcards:
Bash(ls *)matchesls -labut does not matchlsof;Bash(ls*)matches both.
Tool-Specific Permission Rules
1. Bash Commands
| Rule | Matching examples |
|---|---|
Bash(npm run build) |
onlynpm run build |
Bash(npm run test *) |
npm run test、npm run test --coverage |
Bash(npm *) |
Any command starting with npm |
Bash(* install) |
Any command ending with install |
Bash(git * main) |
git checkout main、git merge main |
Important limitation:Bash permission patterns that attempt to constrain command arguments can be fragile. Options before the URL, different protocols, redirects, variables, extra spaces can all cause mismatches. It is recommended to use the WebFetch tool with
domain:permissions for URL filtering.
2. Read and Edit (File Operations)
File paths support multiple path prefix patterns:
| Pattern prefix | Meaning | Example |
|---|---|---|
//path |
Absolute path (from the filesystem root) | Read(//Users/alice/secrets/**)Matches/Users/alice/secrets/** |
~/path |
Home directory path | Read(~/Documents/*.pdf)Matches/Users/alice/Documents/*.pdf |
/path |
Relative to project root | Edit(/src/**/*.ts)Matches<project root>/src/**/*.ts |
pathor./path |
Relative to current directory | Read(*.env)Matches<cwd>/*.env |
Example
"permissions": {
"allow": [
"Edit(/docs/**)", // Allow editing files under the project's docs directory
"Read(~/.zshrc)", // Allow reading .zshrc in the home directory
"Edit(//tmp/scratch.txt)", // Allow editing temporary files at absolute paths
"Read(src/**)" // Allow reading files in the src subdirectory of the current directory
],
"deny": [
"Read(*.env)", // Block reading .env files (prevent secret leakage)
"Edit(//etc/**)" // Block editing system directory files
]
}
}
Note:Read and Edit deny rules do not apply in Bash subprocesses
cat .env. To obtain OS-level enforcement, enable the sandbox.
3. WebFetch (Network Requests)
Example
"permissions": {
"allow": [
"WebFetch(domain:github.com)", // Allow access to GitHub
"WebFetch(domain:api.example.com)" // Allow access to internal APIs
],
"deny": [
"WebFetch(domain:untrusted.com)" // Block access to untrusted domains
]
}
}
4. MCP (Model Context Protocol)
Example
"permissions": {
"allow": [
"mcp__puppeteer", // Allow any tools provided by the puppeteer server
"mcp__puppeteer__*" // Allow all tools from the puppeteer server
],
"deny": [
"mcp__puppeteer__puppeteer_navigate" // Block specific tools
]
}
}
5. Agent (Sub-agent)
Example
"permissions": {
"allow": [
"Agent(Explore)", // Allow using the Explore sub-agent
"Agent(Plan)" // Allow using the Plan sub-agent
],
"deny": [
"Agent(my-custom-agent)" // Block custom sub-agents
]
}
}
Working Directory Configuration
By default, Claude Code only allows access to the working directory at startup and its subdirectories. If you need to access paths outside the project directory, you must explicitly configure it.
1. Extended Access Methods
- During startup:Use
--add-dir <path>CLI arguments - During a session:Use
/add-dircommands - Persistent configuration:Add to settings.json
additionalDirectories
Example
"additionalDirectories": [
"~/projects/personal/**", // Allow access to personal project directories
"~/projects/work/**", // Allow access to work project directories
"~/dotfiles/**" // Allow access to configuration file directories
]
}
2. Exceptions
The following content remains accessible after setting additional directories, without requiring extra configuration:
.claude/skills/Skills in (with live reload).claude/settings.jsonPlugin settings in (onlyenabledPluginsandextraKnownMarketplaces)- CLAUDE.md files and
.claude/rules/(only whenCLAUDE_CODE_ADDITIONAL_DIRECTORIES_CLAUDE_MD=1is set)
Auto Mode
Auto Mode is a new mechanism introduced in Claude Code that replaces manual approval with a model-driven classifier, controlling risk as much as possible while ensuring efficiency.
1. Available Conditions
- Team, Enterprise, and API plans only
- Requires Claude Sonnet 4.6 or Claude Opus 4.6
- Not available on Haiku, claude-3 models, or third-party providers
- Admins must enable it in Claude Code admin settings
2. How It Works
Before each operation runs, a separate classifier model reviews the conversation and decides whether the operation matches the user's request.
Defense layers:
- Server-side probes scan incoming tool results
- The classifier never sees tool results, preventing injected instructions from influencing decisions
Operation evaluation order:
- Operations matching allow or deny rules are resolved immediately
- Read-only operations and file edits in the working directory are auto-approved (except for protected directories)
- Everything else is sent to the classifier
- If the classifier blocks, Claude receives the reason and attempts alternative methods
3. Classifier Default Behavior
| Operation Type | Behavior |
|---|---|
| Blocked by Default | |
| Downloading and executing code | curl | bashwait |
| Sending sensitive data to external endpoints | Data leakage risk |
| Production deployments and migrations | Production environment modifications |
| Large-scale deletions on cloud storage | Data loss risk |
| Granting IAM or repository permissions | Privilege escalation risk |
| Modifying shared infrastructure | Affects other users |
| Irreversibly destroying files | Files that existed before the session started |
| Destructive source control operations | Force pushes, direct pushes to main |
| Default allow | |
| Local file operations in the working directory | Within the safety scope |
| Install declared dependencies | Dependencies already in package.json |
| Read .env and send credentials | Send to matching APIs |
| Read-only HTTP requests | GET requests |
| Push to the started branch | Safe branch operations |
4. Auto Mode Configuration
Example
"autoMode": {
"environment": [
"Source control: github.example.com/acme-corp and all repos under it",
"Trusted cloud buckets: s3://acme-build-artifacts, gs://acme-ml-datasets",
"Trusted internal domains: *.corp.example.com, api.internal.example.com",
"Key internal services: Jenkins at ci.example.com, Artifactory at artifacts.example.com"
],
"allow": [
"Deploying to the staging namespace is allowed",
"Writing to s3://acme-scratch/ is allowed"
],
"soft_deny": [
"Never run database migrations outside the migrations CLI",
"Never modify files under infra/terraform/prod/: production infrastructure changes go through the review workflow"
]
}
}
5. Fallback Mechanism
If the classifier blocks operations 3 times in a row, or 20 times total in a session, automatic mode pauses and Claude Code reverts to prompting for each operation.
/permissions # 在 "最近拒绝" 选项卡查看被拒绝的操作
Relationship Between Sandbox and Permissions
Sandbox and permissions are complementary security layers that work together:
| Aspect | Permissions | Sandbox |
|---|---|---|
| Control target | Controls which tools Claude Code can use | Restricts the file system and network content accessible to Bash commands |
| Evaluation timing | Evaluated before any tool runs | Only applies to Bash commands and their subprocesses |
| Scope of application | All tools: Bash, Read, Edit, WebFetch, MCP, etc. | Only Bash commands |
1. Enabling Sandbox
/sandbox
Run/sandboxthe command to enable the sandbox; a menu will open to select the sandbox mode.
2. Configuring Sandbox
Example
"sandbox": {
"enabled": true,
"filesystem": {
"allowWrite": ["~/.kube", "/tmp/build"], // Allow writing to these paths
"denyWrite": ["~/important/**"], // Block writing to important directories
"denyRead": ["~/"] // Block reading the home directory
},
"network": {
"httpProxyPort": 8080, // HTTP proxy port
"socksProxyPort": 8081 // SOCKS proxy port
}
}
}
Defense in depth:Permissions and sandbox should be enabled simultaneously. Permission deny rules prevent Claude from attempting to access restricted resources, while sandbox restrictions prevent Bash commands from reaching resources beyond defined boundaries.
Extending Permissions with Hooks
PreToolUse hooks run before permission prompts and can:
- Deny tool calls
- Force a prompt
- Skip the prompt and let the call continue
Example
# PreToolUse hook example: intercept dangerous commands
COMMAND=$(cat | jq -r '.tool_input.command // empty')
if echo "$COMMAND" | grep -qE 'rm\s+(-[rf]+\s+)*(\/|~|\.\.\/)'; then
echo "BLOCKED: rm on sensitive path"
exit 2 # Exit code 2 blocks the tool call
fi
exit 0 # Allow to continue
Important:Skipping the prompt does not bypass permission rules. Deny and ask rules are still evaluated after the hook returns "allow". When a blocking hook exits with exit code 2, it stops the tool call before permission rules are evaluated.
Setting Priority
Claude Code settings take effect in the following priority order (from highest to lowest):
- Managed settings- Cannot be overridden by any other level (administrator control)
- Command-line arguments- Temporary session override
- Local project settings (
.claude/settings.local.json) - Shared project settings (
.claude/settings.json) - User settings (
~/.claude/settings.json)
Key rules:If a tool is denied at any level, no other level can allow it.
Practical Configuration Examples
Example 1: Conservative Mode (All Operations Require Approval)
Suitable for those new to Claude Code or when working on important projects:
Example
"permissions": {
"defaultMode": "default"
}
}
Example 2: Common Development Configuration (Read Operations Open, Command Execution Requires Approval)
Suitable for daily development: allow Claude to freely read and search code, but require confirmation when modifying files and executing commands:
Example
"permissions": {
"defaultMode": "acceptEdits",
"allow": [
"Bash(git status *)", // View git status
"Bash(git log *)", // View git log
"Bash(git diff *)", // View git diff
"Bash(npm run *)", // Run npm scripts
"Bash(npm test *)", // Run tests
"Bash(ls *)", // List directories
"Bash(grep *)" // Search content
],
"deny": [
"Bash(rm *)", // Delete files: block directly
"Bash(git push *)", // Push code: block directly
"Bash(mkdir / *)", // Create system directories: block directly
"Edit(*.env)" // Block editing .env files
]
}
}
Example 3: Locked Environment Configuration (Only Pre-approved Operations Allowed)
Suitable for CI pipelines or environments requiring strict control:
Example
"permissions": {
"defaultMode": "dontAsk",
"allow": [
"Read(*)", // Allow reading all files
"Bash(npm run build *)", // Allow build commands
"Bash(npm test *)" // Allow running tests
],
"deny": [
"Edit(*)", // Prohibit all file edits
"Bash(git *)", // Prohibit all git operations
"Bash(curl *)", // Prohibit network requests
"Bash(ssh *)" // Prohibit SSH connections
]
}
}
Example 4: Allowing Multi-Project Access
When Claude needs to work across multiple project directories:
Example
"permissions": {
"allow": [
"Edit(/src/**)", // Allow editing the src directory
"Edit(/docs/**)" // Allow editing the documentation directory
],
"deny": [
"Edit(/docs/**/*.md)" // Prohibit editing documentation files (read-only)
]
},
"additionalDirectories": [
"~/projects/personal/**", // Allow access to personal projects
"~/projects/work/**", // Allow access to work projects
"~/dotfiles/**" // Allow access to configuration files
]
}
Example 5: Using Sandbox to Restrict Bash Operations
Enabling the sandbox provides additional OS-level protection:
Example
"sandbox": {
"enabled": true,
"filesystem": {
"allowWrite": ["/tmp/build", "~/projects/myapp/**"],
"denyRead": ["~/secrets/**"]
},
"network": {
"httpProxyPort": 8080
}
},
"permissions": {
"allow": [
"Bash(*)", // Allow all commands within the sandbox
"WebFetch(domain:api.github.com)"
],
"deny": [
"WebFetch(domain:untrusted.com)"
]
}
}
Managed Settings (Administrator Configuration)
Administrators can deploy managed settings that cannot be overridden by user or project settings.
| Setting | Description |
|---|---|
allowManagedHooksOnly |
Prevent loading user, project, and plugin hooks |
allowManagedMcpServersOnly |
Only respect MCP servers from managed settings |
allowManagedPermissionRulesOnly |
Prevent user and project settings from defining permission rules |
sandbox.filesystem.allowManagedReadPathsOnly |
Only respect read paths from managed settings |
sandbox.network.allowManagedDomainsOnly |
Only respect allowed domains from managed settings |
permissions.disableBypassPermissionsMode |
Set to "disable" to prevent the use of bypassPermissions mode |
permissions.disableAutoMode |
Set to "disable" to prevent the use of auto mode |
Security Best Practices
- Start with restrictions: Start with the least privilege and expand as needed
- Use sandboxing: Sandboxes provide additional OS-level protection and should be enabled alongside
- Protect sensitive files: Use
denyrules to block access.env, key files, etc. - Restrict network access: Only allow access to necessary domains to prevent data leakage
- Avoid bypassPermissions: Use only in isolated environments (containers, VMs)
- Use auto mode's soft_deny: Provides security guidance without being overly restrictive
- Regularly review configurations: Review sandbox violation attempts and denied operations
Other extensionsSecurity warning:
bypassPermissionsThe mode does not provide protection against prompt injection or unintended actions. For a safer alternative that still maintains background security checks, use auto mode.