Claude Code is Anthropic's official AI coding agent, used by developers at companies from startups to Fortune 500. Learn more →
Claude Code ConfigurationHow to Set Up Claude Code Permissions
Control exactly what Claude can and cannot do. From permission modes to allowed tools to directory access, here is everything you need to configure Claude Code safely.
Claude Code permissions are controlled through three modes (Default, Auto-accept Edits, and Plan Mode) plus allow/deny rules for specific tools and paths. You configure them in your settings files or toggle them live with Shift+Tab. Once set up, every session respects your rules automatically.
This guide covers all three permission modes, how to configure allowed and denied tools, directory access controls, and security best practices to keep your codebase safe.
What Are Claude Code Permissions?
Claude Code permissions control what actions Claude can take during a session. They work at two levels:
- Permission modes: Global settings that control how Claude asks for approval (always ask, auto-approve edits, or read-only)
- Permission rules: Specific allow/deny lists for individual tools and paths
Together, these let you fine-tune Claude's behavior from fully autonomous to completely locked down, depending on your needs.
Why this matters: Get permissions right once, and every Claude session respects your rules automatically. No more approving the same safe commands repeatedly, and no more worrying about accidental access to sensitive files.
The Three Permission Modes
Claude Code has three main permission modes. Press Shift+Tab to cycle through them during a session.
| Mode | File Edits | Shell Commands | When to Use |
|---|---|---|---|
| Normal | Asks permission | Asks permission | Default for most work |
| Auto-Accept | Auto-approves | Asks permission | Trusted editing tasks |
| Plan Mode | Blocked | Blocked | Analysis and planning only |
Normal Mode (Default)
Claude asks for confirmation before every file edit and shell command. You see exactly what Claude wants to do and approve each action.
Use this when:
- Working on unfamiliar code
- Running commands that could have side effects
- You want to review every change before it happens
Auto-Accept Mode
Claude automatically applies file edits without asking, but still prompts before running shell commands. This speeds up editing workflows while maintaining safety for potentially destructive operations.
Use this when:
- You trust Claude's direction and want faster iteration
- Doing large refactoring tasks
- The code is version-controlled and easy to revert
Note: Auto-Accept only auto-approves file edits. Shell commands, web fetches, and other tools still require confirmation unless you configure specific allow rules.
Plan Mode
Claude operates in read-only mode. It can read files, search code, and analyze your project, but cannot make any changes. Perfect for exploration and planning before execution.
Use this when:
- Exploring an unfamiliar codebase
- Planning complex changes before committing to an approach
- You want Claude's analysis without any risk of modification
Setting the Default Permission Mode
You can set your preferred starting mode in settings.json:
{
"permissions": {
"defaultMode": "acceptEdits"
}
}
Available values:
"default"- Normal mode (ask for everything)"acceptEdits"- Auto-Accept mode"plan"- Plan mode (read-only)
You can also start Claude with a specific mode from the command line:
claude --permission-mode plan
Configuring Allowed and Denied Tools
Permission rules let you pre-approve safe operations and block dangerous ones. They go in your settings.json file.
Basic Structure
{
"permissions": {
"allow": [
"Bash(npm run lint)",
"Bash(npm run test *)",
"Read(./src/**)"
],
"deny": [
"Bash(rm -rf *)",
"Bash(curl *)",
"Read(./.env)"
],
"ask": [
"Bash(git push *)"
]
}
}
Rule Evaluation Order
Rules are checked in this order:
- Deny - If matched, block immediately (highest priority)
- Ask - If matched, prompt for confirmation
- Allow - If matched, proceed without asking
The first matching rule wins. A deny rule always takes precedence over an allow rule for the same pattern.
Permission Syntax
| Format | Example | Matches |
|---|---|---|
| Tool only | Bash or Bash(*) |
All Bash commands |
| Exact match | Bash(npm run build) |
Only npm run build |
| Wildcard | Bash(npm run *) |
npm run test, npm run lint, etc. |
| Path glob | Read(./src/**) |
All files under ./src/ |
Wildcard tip: Space before * matters. Bash(ls *) matches ls -la but not lsof. Bash(ls*) matches both.
I documented my full permissions and security setup in a free guide — it covers everything from initial configuration to daily workflows.
Available Tools
| Tool | Permission Format | Example |
|---|---|---|
| Bash | Bash(command) |
Bash(npm run test *) |
| Read | Read(path) |
Read(./.env) |
| Edit | Edit(path) |
Edit(./src/**) |
| MultiEdit | MultiEdit(path) |
MultiEdit(./src/**) |
| Write | Write(path) |
Write(./src/**) |
| NotebookEdit | NotebookEdit(path) |
NotebookEdit(./notebooks/**) |
| WebFetch | WebFetch(domain:host) |
WebFetch(domain:github.com) |
| WebSearch | WebSearch |
WebSearch |
| Task | Task |
Task |
| MCP | mcp__server__tool |
mcp__github__create_issue |
Note: Glob, Grep, LS, and AskUserQuestion do not require permissions since they have no side effects.
Real-World Permission Examples
Safe Development Workflow
Allow common dev commands, block destructive operations:
{
"permissions": {
"allow": [
"Bash(npm run *)",
"Bash(yarn *)",
"Bash(git status)",
"Bash(git diff *)",
"Bash(git log *)",
"Bash(git add *)",
"Bash(git commit *)",
"Bash(* --version)",
"Bash(* --help)"
],
"deny": [
"Bash(rm -rf *)",
"Bash(git push --force *)",
"Bash(git reset --hard *)",
"Bash(curl *)",
"Bash(wget *)"
],
"ask": [
"Bash(git push *)"
]
}
}
Protect Sensitive Files
Block access to credentials and secrets:
{
"permissions": {
"deny": [
"Read(./.env)",
"Read(./.env.*)",
"Read(./secrets/**)",
"Read(./**/credentials.json)",
"Read(~/.aws/**)",
"Read(~/.ssh/**)",
"Edit(./.env)",
"Edit(./.env.*)"
]
}
}
Restrict to Source Code Only
Only allow edits within the src directory:
{
"permissions": {
"allow": [
"Edit(./src/**)",
"Edit(./tests/**)"
],
"deny": [
"Edit(./package.json)",
"Edit(./package-lock.json)",
"Edit(./.github/**)"
]
}
}
Directory Permissions
By default, Claude Code can only access files within your current working directory. To allow access to related directories:
{
"permissions": {
"additionalDirectories": [
"../docs/",
"../shared-utils/",
"~/templates/"
]
}
}
This is useful for monorepos or when you need to reference files outside the current project.
Settings File Locations
Claude Code reads settings from multiple locations, with higher precedence settings overriding lower ones:
| Scope | Location | Shared | Use Case |
|---|---|---|---|
| Managed | /etc/claude-code/ (Linux) or /Library/Application Support/ClaudeCode/ (macOS) |
Yes (IT) | Organizational policies |
| User | ~/.claude/settings.json |
No | Personal preferences |
| Project | .claude/settings.json |
Yes (git) | Team standards |
| Local | .claude/settings.local.json |
No (gitignored) | Personal overrides |
Managed settings have the highest precedence and cannot be overridden. Use these for enforcing company-wide policies.
The Dangerous Skip Permissions Flag
Claude Code has a flag for fully autonomous operation:
claude --dangerously-skip-permissions
This bypasses all permission checks. Claude runs commands without asking, edits files automatically, and operates completely unattended.
Warning: This flag is dangerous. Only use it in isolated environments like Docker containers without internet access. Never use it with production code, sensitive data, or when connected to external services.
You can disable this flag entirely for your organization:
{
"permissions": {
"disableBypassPermissionsMode": "disable"
}
}
Security Best Practices
1. Start Restrictive, Open Up As Needed
Begin with Normal mode and minimal allow rules. Add permissions as you discover safe patterns in your workflow.
2. Always Deny Sensitive Files
Create deny rules for .env, credentials, API keys, and SSH keys. This protects against accidental exposure.
3. Use Project-Level Settings for Teams
Put team-agreed permissions in .claude/settings.json and commit it to git. Everyone gets the same safety rails.
4. Be Careful with Bash Wildcards
Bash patterns that constrain arguments are fragile. Bash(curl http://github.com/ *) will not match curl -X GET http://github.com/... because flags come before the URL.
5. Review Before Enabling Auto-Accept
Only use Auto-Accept mode when your code is version-controlled and you can easily revert unwanted changes.
Hooks: Automated Permission Enforcement
Claude Code supports lifecycle hooks that add another layer of control beyond static permission rules. Hooks are configured in your settings.json file and run custom scripts at key moments.
PreToolUse Hooks
PreToolUse hooks fire before Claude executes any tool. You can use them to modify tool inputs, inject additional context, or block execution entirely. This is useful for enforcing security policies automatically.
{
"hooks": {
"PreToolUse": [
{
"matcher": "Bash",
"hooks": [
{ "type": "command", "command": "~/.claude/hooks/validate-bash.sh" }
]
}
]
}
}
PostToolUse Hooks
PostToolUse hooks fire after a tool completes. Common uses include running linters after file edits and sending notifications after long operations.
{
"hooks": {
"PostToolUse": [
{
"matcher": "Edit",
"hooks": [
{ "type": "command", "command": "npx prettier --write $CLAUDE_FILE_PATH" }
]
}
]
}
}
Key difference: Permission rules are static allow/deny lists. Hooks are dynamic scripts that can inspect the actual command or file path and make decisions programmatically. For most users, permission rules are sufficient. Hooks are for advanced control.
When to Use Each Mode
| Scenario | Recommended Mode | Why |
|---|---|---|
| Learning a new codebase | Plan Mode | Read-only exploration is safe |
| Bug fixing with unclear scope | Normal Mode | Review each change carefully |
| Refactoring with clear plan | Auto-Accept | Speed up trusted edits |
| Running build/test scripts | Normal + allow rules | Pre-approve safe commands |
| Working with sensitive data | Normal + deny rules | Block access to secrets |
Common Mistakes
- Overly broad allow rules:
"allow": ["Bash"]allows any command. Be specific about what you are approving. - Forgetting deny rules for secrets: Always explicitly deny
.envand credential files, even if you think you will not ask Claude about them. - Not using project settings: If you are on a team, share permissions via
.claude/settings.jsonso everyone has the same safety configuration. - Skipping Plan Mode for complex work: When making changes that touch many files, start in Plan Mode to understand the scope before executing.
- Using skip-permissions casually: The
--dangerously-skip-permissionsflag should only be used in isolated, throwaway environments.
FAQ
Can I have different permissions for different projects?
Yes. Put project-specific settings in .claude/settings.json within each project. These override your global user settings.
How do I see what permissions are active?
Run /permission in Claude Code to view current permission rules and their sources.
Do permissions apply to MCP tools?
MCP (Model Context Protocol) tools have their own permission system. Configure MCP permissions separately in your MCP server settings.
Can I reset to default permissions?
Delete your settings files and Claude Code returns to default behavior. User settings are at ~/.claude/settings.json.
What happens if allow and deny conflict?
Deny always wins. If a pattern matches both an allow and deny rule, the action is blocked.
Related Guides
- How to Use Plan Mode - deep dive into read-only analysis
- Keyboard Shortcuts in Claude Code - including Shift+Tab for mode switching
- How to Use CLAUDE.md Files - project configuration
- What Is Claude Code? - the fundamentals
Free: The AI Growth Breakdown
See how one business went from 0 to 600 daily visitors in 14 days using AI. The exact tools and results.
Get the Free Breakdown →