Claude Code
Claude Code permissions: allow, ask and deny rules, rule syntax and allowed tools
How do Claude Code permissions work, and how do I allow or block specific tools?
Claude Code checks every tool call against permission rules in your settings files. Rules go in permissions.allow, permissions.ask and permissions.deny, use the format Tool or Tool(specifier), and are evaluated deny first, then ask, then allow. Use /permissions to see every rule and the file it comes from, or pass --allowedTools and --disallowedTools for one session.
Allow, ask and deny
- Allow rules let Claude Code use the matching tool without asking you.
- Ask rules prompt for confirmation every time the matching tool is used.
- Deny rules block the matching tool.
- Order is deny, then ask, then allow. The first match wins and specificity does not change the order, so a broad deny like Bash(aws *) beats a narrower allow like Bash(aws s3 ls).
- A deny rule with a bare tool name, such as Bash, removes the tool from Claude's context. A scoped deny such as Bash(rm *) keeps the tool and blocks only matching calls.
Rules are enforced by Claude Code, not by the model. Instructions in CLAUDE.md shape what Claude tries to do but do not change what it is allowed to do.
Rule syntax by tool
- Whole tool: Bash, Read or WebFetch with no parentheses. Bash(*) is the same as Bash.
- Bash: Bash(npm run build) matches that exact command. Bash(npm run *) matches every npm script. Put the * after the subcommand: Bash(git log *) allows only git log, while Bash(git *) allows every git command.
- Bash(ls *) needs a space after ls, so it does not match lsof. Bash(ls:*) is an equivalent way to write the trailing wildcard.
- Read and Edit use gitignore patterns. Read(./.env) blocks the .env file in the current directory, Read(./secrets/**) blocks a folder. Use Edit rules, not Write rules, for paths no tool may change.
- Paths: //path is absolute from the filesystem root, ~/path is from your home folder, /path is relative to the settings file's project, and path or ./path is relative to the current directory.
- WebFetch: WebFetch(domain:example.com) matches example.com only. Add WebFetch(domain:*.example.com) for subdomains.
- MCP: mcp__github matches every tool from the github server, mcp__github__get_* matches its get_ tools, and mcp__github__create_issue matches one tool.
- Subagents: Agent(Explore) or Agent(my-custom-agent). Put one in deny to stop Claude from using that subagent.
Example settings
.claude/settings.json
{
"permissions": {
"allow": [
"Bash(npm run *)",
"Bash(git commit *)",
"WebFetch(domain:docs.example.com)",
"mcp__github__get_*"
],
"ask": ["Bash(git push *)"],
"deny": [
"Read(./.env)",
"Read(./secrets/**)",
"Bash(rm *)"
]
}
}Allow rules and additionalDirectories in a project's .claude/settings.json only take effect after you accept the workspace trust dialog for that folder. Deny and ask rules apply right away.
Allowed tools on the command line
- --allowedTools (or --allowed-tools): tools that run without prompting, using the same rule syntax.
- --disallowedTools (or --disallowed-tools): deny rules for this session. "mcp__*" removes every MCP tool.
- --tools: limits which built-in tools exist at all, for example "Bash,Edit,Read".
- --add-dir: adds working directories Claude can read and edit. Save them in permissions.additionalDirectories to keep them.
Terminal
claude -p "summarize recent changes" \ --allowedTools "Bash(git log *)" "Bash(git diff *)" "Read" \ --disallowedTools "Edit"
Which settings win
- A deny at any level cannot be allowed by another level. If user settings allow something and project settings deny it, it is denied, and the reverse is also true.
- Managed settings are highest. Even --allowedTools cannot override a managed deny, while --disallowedTools can add more restrictions.
- allowManagedPermissionRulesOnly makes managed settings the only source of permission rules.
- Set permissions.disableBypassPermissionsMode or permissions.disableAutoMode to "disable" to block those modes. They are most useful in managed settings.
Permission modes
Rules sit on top of the session's permission mode: default (Manual), acceptEdits, plan, auto, dontAsk or bypassPermissions. Set one with claude --permission-mode <mode> or permissions.defaultMode in settings. dontAsk denies anything that would prompt except tools your allow rules already approve. To run with no prompts at all, see the guide on allowing all commands in Claude Code.
Get Claude Code settings changes by email
When a setting, flag or permission rule in this guide changes, it goes in the weekly AgentAtlas update, checked against the vendor docs. One email a week.
Sources
More on Claude Code
More Claude Code guides
- Claude Code: allow commands without prompts (permission modes and allow rules)
- Claude Code telemetry and data retention: what is sent and how to turn it off
- CLAUDE.md: where it goes, how it loads, and how it works with AGENTS.md
- Claude Code hooks: format on save, block risky edits, get notified
- Claude Code subagents: create one, limit its tools, and call it
- Add MCP servers to Claude Code (claude mcp add, .mcp.json, scopes)
- Claude Code custom slash commands and skills (SKILL.md)
- Claude Code settings.json: file locations, precedence, and key settings
- Claude Code plugins and marketplaces: install, create, and share
- Claude Code headless mode: claude -p, --output-format json, --bare and CI flags
- Claude Code statusline: custom status bar in settings.json with context %, cost and git branch
- Claude Code /model: switch models, aliases (opus, sonnet, haiku, opusplan), ANTHROPIC_MODEL and effort
- Claude Code /cost and /usage: check token spend, usage limits and reduce costs
- Claude Code VS Code extension: install, shortcuts, settings and /ide (works in Cursor too)
Other guides
Reviewed Oct 13, 2026. Settings change often; the linked vendor docs are the source of truth.