Configure permissions
Control what Claude Code can access and do with fine-grained permission rules, modes, and managed policies.
Claude Code supports fine-grained permissions. Permission settings can be checked into version control and distributed to your organization.
Permission system
| Tool type | Example | Approval required |
|---|---|---|
| Read-only | File reads, Grep | No |
| Bash commands | Shell execution | Yes |
| File modification | Edit/write files | Yes |
Manage permissions
View and manage permissions with /permissions. Lists rules and which settings.json they come from.
- Allow — use the tool without manual approval
- Ask — prompt for confirmation
- Deny — prevent use
Rules are evaluated deny → ask → allow. First match wins.
A bare tool name like Bash removes the tool from Claude's context entirely. A scoped rule like Bash(rm *) blocks matching calls when attempted.
Permission rules are enforced by Claude Code, not the model. CLAUDE.md shapes what Claude tries; permissions control what is allowed.
Permission modes
Set defaultMode in settings. See Permission modes.
| Mode | Description |
|---|---|
default | Prompts on first use of each tool |
acceptEdits | Auto-accepts file edits and common fs commands in scope |
plan | Read-only exploration; no source edits |
auto | Auto-approve with background safety checks (research preview) |
dontAsk | Auto-deny unless pre-approved |
bypassPermissions | Skips all prompts — containers/VMs only |
bypassPermissions still prompts for rm -rf / and rm -rf ~. Set permissions.disableBypassPermissionsMode or permissions.disableAutoMode to "disable" in managed settings to block these modes.
Permission rule syntax
Format: Tool or Tool(specifier).
{
"permissions": {
"allow": [
"Bash(npm run *)",
"Bash(git commit *)",
"Bash(git * main)",
"Bash(* --version)"
],
"deny": [
"Bash(git push *)"
]
}
}Bash(*) is equivalent to Bash for matching all Bash commands.
Bash
Bash(npm run build)— exact commandBash(npm run test *)— prefix with word boundary at*Bash(git *)— matches multi-arg commands- Compound commands (
&&,|,;) — each part matched separately - Wrappers
timeout,nice,nohup,stdbufstripped before matching - Built-in read-only commands (
ls,grep,git status, etc.) often run without prompts
Denying entire Bash or WebFetch invalidates prompt cache on the next turn.
For URL restrictions in Bash, prefer WebFetch(domain:example.com) allow rules, deny curl/wget, or PreToolUse hooks — Bash(curl http://github.com/*) patterns are fragile.
Read and Edit
Patterns follow gitignore-style anchors:
| Pattern | Meaning |
|---|---|
//path | Absolute from filesystem root |
~/path | From home directory |
/path | Relative to project root |
path or ./path | Relative to current directory |
Edit applies to all built-in edit tools. Read rules apply to read tools, @file mentions, and IDE-shared context.
Deny on symlinks blocks if either the link path or target matches.
WebFetch
WebFetch(domain:example.com) matches fetch requests to that domain.
MCP
mcp__puppeteer, mcp__puppeteer__*, or mcp__puppeteer__puppeteer_navigate.
Agent (subagents)
Agent(Explore), Agent(Plan), Agent(my-custom-agent) in allow or deny arrays.
Extend permissions with hooks
PreToolUse hooks run before the permission prompt. Hook deny (exit code 2) blocks before rules are evaluated. Deny/ask rules still apply even if a hook returns allow.
Working directories
Default access is the launch directory. Extend with --add-dir, /add-dir, or permissions.additionalDirectories.
Additional directories grant file access, not full .claude/ config (except skills with live reload, limited plugin settings, and CLAUDE.md when CLAUDE_CODE_ADDITIONAL_DIRECTORIES_CLAUDE_MD=1).
How permissions interact with sandboxing
- Permissions — which tools and paths Claude Code may use
- Sandboxing — OS-level limits on Bash and child processes
Use both for defense-in-depth. With autoAllowBashIfSandboxed: true (default), sandboxed Bash may run without per-command prompts; explicit deny rules still apply.
Settings precedence
- Managed (cannot be overridden)
- Command line (
--allowedTools,--disallowedTools) - Local (
.claude/settings.local.json) - Project (
.claude/settings.json) - User (
~/.claude/settings.json)
If a tool is denied at any level, no other level can allow it.
Permission rules merge; deny from any scope blocks even when another scope allows.