Claude Code Permissions: Deny, Allow & Ask Modes Explained
By Learnia Team
Claude Code Permissions: Deny, Allow & Ask Modes Explained
This article is written in English. Our training modules are available in French.
Claude Code can read files, execute commands, modify your codebase, and interact with external services. That power requires control. The permission system gives you granular authority over what Claude can do—from fully supervised sessions to autonomous automation.
Why Permissions Matter
Unlike chat-based assistants, Claude Code is an agentic tool. It doesn't just suggest—it acts. Without guardrails:
- →A misunderstood request could delete files
- →Tests might run against production
- →Credentials could be logged or exposed
- →Destructive commands could execute silently
The permission system prevents these scenarios while preserving Claude's ability to help.
The Three Permission Modes
Claude Code operates in one of three modes for each tool or command:
| Mode | Behavior | Use Case |
|---|---|---|
| Ask | Prompts before each action | Interactive development |
| Allow | Executes without prompting | Trusted operations |
| Deny | Blocks completely | Dangerous commands |
Ask Mode (Default)
Ask mode is the safest interactive option. Claude shows you what it wants to do and waits for approval:
Claude wants to run: npm install lodash
[y] Accept [n] Reject [e] Edit [Esc] Cancel
You can:
- →Accept (y): Run the command
- →Reject (n): Skip this action
- →Edit (e): Modify the command before running
- →Cancel (Esc): Cancel entirely
Allow Mode
Allow mode permits specific operations without prompts:
# Allow all npm commands
claude config add permissions.allow "Bash(npm:*)"
# Allow git operations
claude config add permissions.allow "Bash(git:*)"
# Allow file reads
claude config add permissions.allow "Read(*)"
Claude runs allowed commands immediately—no confirmation needed.
Deny Mode
Deny mode blocks operations completely:
# Block production database access
claude config add permissions.deny "Bash(psql:*prod*)"
# Block rm with -rf flag
claude config add permissions.deny "Bash(rm:-rf*)"
# Block curl to external URLs
claude config add permissions.deny "Bash(curl:*)"
Even if Claude tries to run a denied command, it fails immediately.
Permission Precedence
When multiple rules apply, Claude evaluates them in this order:
- →Deny — Checked first. If a deny rule matches, action blocked.
- →Allow — Checked second. If an allow rule matches, action permitted.
- →Ask — Default. If no rule matches, prompt the user.
Example:
# Allow all git commands
claude config add permissions.allow "Bash(git:*)"
# But deny force push
claude config add permissions.deny "Bash(git:push --force*)"
claude config add permissions.deny "Bash(git:push -f*)"
Result: Most git commands run freely, but force pushes are blocked.
Tool Types & Permission Patterns
Built-in Tools
| Tool | Description | Pattern Format |
|---|---|---|
| Read file contents | |
| Write/modify files | |
| Edit files | |
| Execute shell commands | |
| Browse URLs | |
| MCP server tools | |
Pattern Syntax
Patterns use glob-style matching:
| Pattern | Matches |
|---|---|
| Any single segment |
| Any path depth |
| Single character |
| Either a or b |
Examples:
# Allow reading any file
"Read(*)"
# Allow reading only src folder
"Read(src/**)"
# Allow npm and yarn
"Bash({npm,yarn}:*)"
# Allow git except specific commands
"Bash(git:*)" + deny "Bash(git:push --force*)"
Configuring Permissions
Interactive Configuration
> /permissions
Opens an interactive menu:
Current Permission Mode: ask
Allowed:
- Bash(npm:*)
- Bash(git:*)
- Read(*)
Denied:
- Bash(rm:-rf*)
- Bash(sudo:*)
[a] Add rule [r] Remove rule [m] Change mode [Esc] Exit
Command-Line Configuration
# Add allow rules
claude config add permissions.allow "Bash(npm:*)"
claude config add permissions.allow "Bash(git:*)"
# Add deny rules
claude config add permissions.deny "Bash(rm:-rf*)"
# View current permissions
claude config show permissions
# Remove a rule
claude config remove permissions.allow "Bash(npm:*)"
Settings File
Permissions live in
~/.claude/settings.json:
{
"permissions": {
"mode": "ask",
"allow": [
"Bash(npm:*)",
"Bash(git:*)",
"Read(*)",
"Edit(src/**)"
],
"deny": [
"Bash(rm:-rf*)",
"Bash(sudo:*)",
"Bash(curl:*)"
]
}
}
Project-Level Permissions
Add permissions to your project's
.claude/settings.json:
{
"permissions": {
"allow": [
"Bash(npm:*)",
"Bash(pytest:*)"
],
"deny": [
"Bash(npm:publish*)"
]
}
}
Project permissions merge with user permissions. Deny rules from either source take precedence.
Trust Levels
For quick configuration, use trust levels:
Default (Ask Everything)
claude config set permissions.mode "ask"
All operations require confirmation.
Auto-Accept Edits
claude config set permissions.mode "auto-edit"
File edits are automatically accepted; other operations still ask.
Full Auto
claude config set permissions.mode "auto"
All safe operations proceed automatically. Only potentially dangerous commands prompt.
Sandbox Mode
claude --sandbox
Runs in isolated environment:
- →Filesystem restricted to project
- →Network limited to localhost
- →No access to system commands
See Claude Code Best Practices: Security, Performance & Teams for sandbox details.
Session-Based Permissions
Grant temporary permissions for specific sessions:
Session Trust
When Claude requests an action, you can grant session-wide permission:
Claude wants to run: npm test
[y] Yes [Y] Yes, allow all npm commands this session
[n] No [Esc] Cancel
Pressing
Y (capital) adds a temporary allow rule for the session.
Dangerously Skip Permissions
For fully autonomous execution (CI/CD, automation):
claude --dangerously-skip-permissions
Warning: This bypasses all permission checks. Only use in:
- →Sandboxed environments
- →CI/CD pipelines
- →Fully controlled contexts
See Claude Code GitHub Actions: AI-Powered CI/CD Automation.
Common Permission Configurations
Web Developer
{
"permissions": {
"allow": [
"Read(*)",
"Edit(src/**)",
"Edit(public/**)",
"Bash(npm:*)",
"Bash(yarn:*)",
"Bash(pnpm:*)",
"Bash(git:*)",
"Bash(eslint:*)",
"Bash(prettier:*)"
],
"deny": [
"Bash(rm:-rf*)",
"Bash(npm:publish*)",
"Edit(.env*)"
]
}
}
Python Data Scientist
{
"permissions": {
"allow": [
"Read(*)",
"Edit(src/**)",
"Edit(notebooks/**)",
"Bash(python:*)",
"Bash(pip:*)",
"Bash(pytest:*)",
"Bash(jupyter:*)"
],
"deny": [
"Bash(rm:-rf*)",
"Edit(.env*)",
"Bash(pip:install --user*)"
]
}
}
DevOps Engineer
{
"permissions": {
"allow": [
"Read(*)",
"Edit(terraform/**)",
"Edit(ansible/**)",
"Bash(terraform:*)",
"Bash(ansible:*)",
"Bash(kubectl:get*)",
"Bash(kubectl:describe*)"
],
"deny": [
"Bash(kubectl:delete*)",
"Bash(terraform:destroy*)",
"Bash(rm:-rf*)",
"Edit(**/secrets/**)"
]
}
}
CI/CD Automation
{
"permissions": {
"allow": [
"Read(*)",
"Edit(*)",
"Bash(npm:*)",
"Bash(git:*)",
"Bash(gh:*)"
],
"deny": [
"Bash(rm:-rf /)",
"Bash(sudo:*)"
]
}
}
Used with
--dangerously-skip-permissions in controlled CI environments.
Security Best Practices
1. Start Restrictive
Begin with default ask mode. Add allow rules only for operations you trust completely:
# Start here
claude config set permissions.mode "ask"
# Add specific allows as needed
claude config add permissions.allow "Bash(npm:install)"
claude config add permissions.allow "Bash(npm:test)"
2. Always Deny Destructive Commands
claude config add permissions.deny "Bash(rm:-rf*)"
claude config add permissions.deny "Bash(sudo:*)"
claude config add permissions.deny "Bash(chmod:777*)"
claude config add permissions.deny "Bash(dd:*)"
3. Protect Sensitive Files
# Deny editing environment files
claude config add permissions.deny "Edit(.env*)"
claude config add permissions.deny "Edit(**/.env*)"
# Deny reading credentials
claude config add permissions.deny "Read(**/credentials*)"
claude config add permissions.deny "Read(**/*.pem)"
4. Restrict Production Access
# Block production database commands
claude config add permissions.deny "Bash(psql:*prod*)"
claude config add permissions.deny "Bash(mysql:*production*)"
# Block production deployments
claude config add permissions.deny "Bash(kubectl:*--context=prod*)"
claude config add permissions.deny "Bash(ssh:*prod*)"
5. Use Project-Specific Rules
Team projects should define permissions in
.claude/settings.json:
{
"permissions": {
"deny": [
"Bash(npm:publish*)",
"Bash(git:push --force*)",
"Edit(.env*)"
]
}
}
Commit this to version control so all team members share the same safety rules.
Hooks for Permission Control
Hooks provide another layer of control. Create custom validation:
// .claude/settings.json
{
"hooks": {
"PreToolUse": [
{
"matcher": "Bash",
"command": "python .claude/hooks/validate-command.py"
}
]
}
}
The hook script receives command details and can block execution:
# .claude/hooks/validate-command.py
import json
import sys
input_data = json.loads(sys.stdin.read())
command = input_data.get("tool_input", {}).get("command", "")
# Block any command targeting /etc
if "/etc" in command:
result = {
"decision": "block",
"reason": "Commands targeting /etc are not allowed"
}
else:
result = {"decision": "proceed"}
print(json.dumps(result))
Learn more: Claude Code Hooks: Automate Your Development Workflow
Debugging Permissions
View Applied Rules
claude config show permissions
Test a Pattern
Check if a specific command would be allowed:
claude permissions check "Bash(npm:publish)"
Output:
Command: Bash(npm:publish)
Result: DENIED
Matching rule:
deny: Bash(npm:publish*)
Source: ~/.claude/settings.json
View Permission Logs
Enable verbose logging:
claude --verbose
Shows permission checks in real-time:
[PERMISSION] Checking: Bash(npm:test)
[PERMISSION] Rule matched: allow Bash(npm:*)
[PERMISSION] Decision: ALLOW
Permissions in Automation
GitHub Actions
- name: Run Claude Code
run: |
claude --dangerously-skip-permissions -p "Fix failing tests"
env:
ANTHROPIC_API_KEY: ${{ secrets.ANTHROPIC_API_KEY }}
See Claude Code GitHub Actions: AI-Powered CI/CD Automation.
Headless Mode
claude --print --dangerously-skip-permissions -p "Analyze this codebase"
See Headless & Programmatic Claude Code: SDK & Automation.
MCP Tool Permissions
MCP servers add custom tools. Control them with patterns:
# Allow all tools from filesystem server
claude config add permissions.allow "mcp__filesystem__*"
# Deny destructive filesystem operations
claude config add permissions.deny "mcp__filesystem__delete_file"
# Allow specific GitHub operations
claude config add permissions.allow "mcp__github__get_pull_request"
claude config add permissions.deny "mcp__github__merge_pull_request"
Learn more: Model Context Protocol (MCP) for Claude Code: Complete Guide
Key Takeaways
- →
Default to Ask mode: Start supervised and grant permissions incrementally.
- →
Deny before Allow: Deny rules always take precedence, providing hard blocks on dangerous operations.
- →
Use patterns wisely: Glob patterns give flexibility—be specific to avoid over-permitting.
- →
Protect sensitive data: Always deny access to credentials, environment files, and production systems.
- →
Commit project permissions: Share safety rules via
in version control..claude/settings.json
Master AI Safety & Ethics
Permissions are just one aspect of responsible AI use. Learn the broader principles in our security module.
In our Module 8 — Safety & Ethics, you'll learn:
- →AI safety principles and best practices
- →Responsible disclosure and risk management
- →Ethical considerations in AI development
- →Building trust through transparency
Module 8 — Ethics, Security & Compliance
Navigate AI risks, prompt injection, and responsible usage.