Skip to main content
Advanced

Permissions & Sandbox

Configure permissions with wildcards, enable sandboxing, and secure your Claude Code sessions. Examples for dev, senior, and CI/CD profiles.

Controlling what Claude Code can do

By default, Claude Code asks for confirmation before every sensitive action: running a shell command, writing a file, calling an MCP. That's safe, but it breaks the flow.

The permissions system gives you granular control: you decide what runs automatically, what asks for confirmation, and what's blocked entirely. The sandbox adds another layer by isolating commands in a restricted environment.

The permissions system

Three permission levels

LevelBehaviorUse case
allowRuns automatically, no confirmationSafe, repetitive commands
askAsks for confirmation every timeModerately risky commands
denyBlocked, even if Claude requests itDangerous commands or sensitive data

Wildcard syntax

Permissions use a pattern system with wildcards:

{
"permissions": {
"allow": [
"Read(*)",
"Write(src/**)",
"Edit(src/**)",
"Bash(npm run *)",
"Bash(git status)",
"Bash(git diff *)",
"Bash(git log *)",
"mcp__github__*"
],
"ask": [
"Bash(git push *)",
"Bash(git commit *)",
"Bash(rm *)",
"Write(package.json)"
],
"deny": [
"Read(.env)",
"Read(.env.*)",
"Read(./secrets/**)",
"Bash(curl *)",
"Bash(wget *)"
]
}
}

Available patterns

PatternMatchesExample
*Any string (single level)Bash(npm run *) matches npm run dev, npm run build
**Any string (recursive)Write(src/**) matches src/a.ts, src/deep/b.ts
Exact textStrict match onlyBash(git status) matches only that command

Supported tools: Read, Write, Edit, Bash, mcp__* (all MCPs).

The /permissions command

Manage permissions interactively during a session:

# View current permissions
/permissions
# Add an allow permission
/permissions allow "Bash(npm run *)"
# Add a deny permission
/permissions deny "Read(.env)"

Changes made via /permissions are saved to .claude/settings.local.json (personal, gitignored).

The sandbox

What is the sandbox?

The sandbox isolates Claude Code's Bash commands in a restricted environment:

  • Read-only filesystem access (except the working directory)
  • No outbound network access
  • No system package installation
  • No file modifications outside the project

Enabling the sandbox

# Via the interactive command
/sandbox
# Via settings.json
{
"sandbox": {
"enabled": true
}
}

Sandbox + permissions: the combo

The sandbox and permissions are complementary:

  • The sandbox protects at the system level (isolation)
  • Permissions protect at the tool level (access control)

You can use both together for maximum control.

Permission profiles by context

Junior developer profile

Maximum security, confirmation for most actions:

{
"sandbox": { "enabled": true },
"permissions": {
"allow": [
"Read(*)",
"Bash(npm run dev)",
"Bash(npm run lint)",
"Bash(npm run test)"
],
"ask": [
"Write(*)",
"Edit(*)",
"Bash(git *)"
],
"deny": [
"Read(.env*)",
"Bash(rm -rf *)",
"Bash(git push --force *)",
"Bash(DROP *)"
]
}
}

Senior developer profile

High trust, minimal interruptions:

{
"sandbox": { "enabled": false },
"permissions": {
"allow": [
"Read(*)",
"Write(src/**)",
"Edit(src/**)",
"Bash(npm run *)",
"Bash(git status)",
"Bash(git diff *)",
"Bash(git log *)",
"Bash(git add *)",
"Bash(git commit *)",
"Bash(npx prettier *)",
"Bash(npx eslint *)",
"mcp__*"
],
"ask": [
"Bash(git push *)",
"Write(package.json)",
"Write(*.config.*)",
"Bash(rm *)"
],
"deny": [
"Read(.env*)",
"Read(./secrets/**)",
"Bash(git push --force *)",
"Bash(curl * | bash)"
]
}
}

CI/CD profile

Full automation, no interaction possible:

{
"sandbox": { "enabled": true },
"permissions": {
"allow": [
"Read(*)",
"Write(*)",
"Edit(*)",
"Bash(npm run *)",
"Bash(git *)"
],
"deny": [
"Read(.env*)",
"Bash(curl *)",
"Bash(wget *)",
"Bash(rm -rf /)",
"Bash(git push --force *)"
]
}
}

Auto mode (/permissions auto)

Auto mode uses a classifier that automatically evaluates the risk of each action:

# Enable auto mode
claude --permission-mode auto

In auto mode, Claude Code classifies each action as safe (runs automatically) or risky (asks for confirmation). You can adjust the threshold in settings.json:

{
"autoMode": {
"permissionLevel": "default"
}
}

Three levels: conservative (few auto-approvals), default (balanced), permissive (many auto-approvals).

Where to store permissions

FileSharedGitignoredUse case
.claude/settings.jsonYes (team)NoCommon project rules
.claude/settings.local.jsonNo (personal)YesPersonal preferences
~/.claude/settings.jsonNo (global)N/ADefaults for all projects

Next steps