Claude Code permissions are allow, ask and deny rules plus a permission mode that decide which tool calls run without a prompt; you manage them with /permissions or the permissions key in settings.json, and Claude Code, not the model, enforces them (Configure permissions).
Applies to: Claude Code documentation, Configure permissions page as published on October 27, 2026. Last checked: October 27, 2026.
On this page
What asks by default
In Manual mode, Claude Code’s tiered system asks before these actions (Configure permissions):
| Tool type | Example | Approval required | “Yes, and don’t ask again” behavior |
|---|---|---|---|
| Read-only | File reads, Grep | No, within the working directory and additional directories | N/A |
| Bash commands | Shell execution | Yes, except a built-in set of read-only commands | Permanently per repository and command |
| File modification | Edit/write files | Yes | Until session end |
| Web fetch | WebFetch | Yes, except a built-in set of preapproved documentation domains | Permanently per repository and domain |
| Web search | WebSearch | Yes | Permanently per repository |
When an approval is saved permanently, Claude Code writes the rule to .claude/settings.local.json at the root of the git repository, so it applies to later sessions anywhere in that repository, including subdirectories and worktrees. File-modification approvals are not saved (Configure permissions).
Allow, ask and deny rules
Run /permissions to see every rule and the settings.json file it comes from (Configure permissions):
- Allow rules let Claude Code use the tool without manual approval.
- Ask rules prompt every time Claude Code tries to use the tool.
- Deny rules prevent Claude Code from using the tool.
Rules are evaluated in the order deny, then ask, then allow, and the first match wins regardless of specificity. A broad deny such as Bash(aws *) blocks aws s3 ls even if Bash(aws s3 ls) is allowed (Configure permissions).
A deny rule with a bare tool name such as Bash removes the tool from Claude’s context entirely; a scoped rule such as Bash(rm *) keeps the tool and blocks matching calls (Configure permissions).
The docs’ note on enforcement: “Permission rules are enforced by Claude Code, not by the model. Instructions in your prompt or CLAUDE.md shape what Claude tries to do, but they don’t change what Claude Code allows” (Configure permissions). For what CLAUDE.md is for, see CLAUDE.md best practices.
Rule syntax
Rules use the form Tool or Tool(specifier). Examples from the Configure permissions page:
| Rule | Effect |
|---|---|
Bash | Matches all Bash commands |
Bash(npm run build) | Matches the exact command npm run build |
Read(./.env) | Matches reading the .env file in the current directory |
WebFetch(domain:example.com) | Matches fetch requests to example.com |
mcp__puppeteer__* | Matches all tools from the puppeteer MCP server |
Agent(Explore) | Matches the Explore subagent |
The docs’ example configuration runs npm scripts and git commits without asking and refuses commands that begin with git push (Configure permissions):
{
"permissions": {
"allow": [
"Bash(npm run *)",
"Bash(git commit *)"
],
"deny": [
"Bash(git push *)"
]
}
}
The page notes that a push written another way, such as git -C . push, is not matched by that deny rule (Configure permissions).
Where the * goes
A * in a Bash rule matches any text, including spaces. Anthropic warns: “Put the * after the subcommand.” Bash(git log *) allows only git log commands, while Bash(git *) allows every git command (Configure permissions). Selected rows from the docs’ table:
| You write | Matches | Doesn’t match |
|---|---|---|
Bash(npm run *) | npm run build, npm run test --watch, npm run | npm install |
Bash(ls *) | ls -la, ls | lsof |
Bash(ls*) | ls -la, lsof |
Bash(ls:*) is an equivalent way to write Bash(ls *); the :* form is only recognized at the end of a pattern (Configure permissions).
Files, web and MCP
To stop Claude’s file tools from reading secrets, add Read deny rules such as Read(./.env) or Read(./secrets/**). A .claudeignore file has no effect, so its entries belong in Read deny rules (Configure permissions).
WebFetch(domain:example.com) matches only example.com; add WebFetch(domain:*.example.com) for subdomains. For MCP, mcp__<server>__* matches every tool from a server and mcp__<server>__<tool> matches one tool (Configure permissions). This configuration from the docs denies every MCP tool:
{
"permissions": {
"deny": [
"mcp__*"
]
}
}
For adding servers, see Claude Code MCP.
Permission modes
Set defaultMode in a settings file to choose the mode sessions start in (Configure permissions). The modes from the docs:
| Mode | What it does |
|---|---|
default | Prompts on first use of each tool; labeled Manual in the CLI, IDE extensions and desktop app |
acceptEdits | Accepts file edits and common filesystem commands such as mkdir, touch, mv and cp in the working directory or additionalDirectories |
plan | Reads files and runs read-only shell commands but doesn’t edit source files |
auto | Runs without routine prompts; a background classifier checks actions such as shell commands and network requests first |
dontAsk | Auto-denies every call that would otherwise prompt; pre-approved tools still run |
bypassPermissions | Skips permission prompts, except for actions no mode auto-approves |
Anthropic’s warning on bypassPermissions: Claude Code skips prompts “including for writes to protected paths such as .git and .claude”, and you should “only use this mode in isolated environments like containers or VMs where Claude Code can’t cause damage”. To block it, or auto mode, set permissions.disableBypassPermissionsMode or permissions.disableAutoMode to "disable" in any settings file (Configure permissions). For the CLI flag version, see claude --dangerously-skip-permissions.
Settings scopes and precedence
Permission rules follow the general settings precedence, with managed settings highest. If a tool is denied at any level, no other level can allow it: a managed deny cannot be overridden by --allowedTools, and a user-level deny blocks a project-level allow (Configure permissions). Rules that should apply across all your projects go in ~/.claude/settings.json (or $CLAUDE_CONFIG_DIR/settings.json) (Configure permissions).
permissions.allow rules and additionalDirectories in a project’s .claude/settings.json apply only after you accept the workspace trust dialog for that folder; deny and ask rules apply without it. A claude -p run or SDK session never shows the dialog, so project allow rules are not used there (Configure permissions).
Working directories, hooks and sandboxing
By default Claude can access files in the directory where you launched it. Extend that with --add-dir <path> at startup, /add-dir during a session, or additionalDirectories in settings (Configure permissions).
PreToolUse hooks run before the permission prompt and can deny a call, force a prompt or let it proceed, but they don’t bypass deny and ask rules (Configure permissions). See Claude Code hooks.
Permissions control which tools Claude Code can use; sandboxing adds OS-level limits on what shell commands can reach. Anthropic recommends using both “for defense-in-depth” (Configure permissions). See Claude Code sandbox.





