Skip to content

Permission Precedence

Claude Code uses a layered permission system. Understanding how these layers interact prevents unexpected behavior when combining allow, ask, and deny rules.

Permissions are defined at three levels:

LayerLocationScope
Tool-levelpermissions.allow, permissions.ask, permissions.denyEntire tool (e.g., Bash)
Content-levelpermissions.allow, permissions.ask, permissions.denySpecific tool invocations (e.g., Bash(rm *))
Skill frontmatterallowed-tools: in SKILL.mdTools available within a skill

Content-level rules override tool-level rules. More specific patterns take priority over less specific ones.

The evaluation order is:

1. deny (content-level) ← highest priority
2. ask (content-level)
3. allow (content-level)
4. deny (tool-level)
5. ask (tool-level)
6. allow (tool-level) ← lowest priority

Consider this configuration in .claude/settings.json:

{
"permissions": {
"allow": ["Bash"],
"ask": ["Bash(rm *)"]
}
}

Behavior: All Bash commands run without prompting, except commands matching rm *, which trigger a permission prompt.

CommandRule MatchedResult
Bash(ls -la)allow: ["Bash"] (tool-level)Runs automatically
Bash(npm test)allow: ["Bash"] (tool-level)Runs automatically
Bash(rm -rf dist/)ask: ["Bash(rm *)"] (content-level)Prompts for approval
Bash(rm temp.txt)ask: ["Bash(rm *)"] (content-level)Prompts for approval

The content-level ask for Bash(rm *) overrides the tool-level allow for Bash because content-level rules are more specific.

Note: Prior to Claude Code v2.1.27, allow: ["Bash"] would allow all Bash commands regardless of content-level ask rules. This was fixed so that content-level rules always take precedence.

FileApplies ToManaged By
~/.claude/settings.jsonAll projects (user-level)User
.claude/settings.jsonThis projectsequant (package-managed)
.claude/.local/settings.jsonThis project (overrides)User
SKILL.md frontmatterWithin a specific skillSkill author
{
"permissions": {
"deny": ["Read(./.entire/metadata/**)"]
}
}
---
allowed-tools:
- Bash(npm run deploy:*)
- Bash(gh workflow run:*)
---

Skill allowed-tools pre-approve tools while the skill is active: a matching command runs without a permission prompt. They do not override project or user-level deny rules.

Sequant’s own skills grant only the commands their instructions run. No skill grants bare Bash, Bash(*), a wildcard straight after a tool such as Bash(git *), or a runner wildcard such as Bash(npx tsc:*). Since #1292, no skill pre-approves Bash(<tool>:*) for gh api, rm, mv, find, sed or cp either: /qa no longer grants gh api (which also allowed gh api -X DELETE), /clean no longer grants rm or find and moves files only into docs/archive/ and scripts/archive/, and /setup grants cp, cat and sed only for the files it writes or reads. src/lib/__tests__/skill-allowed-tools-gate.test.ts enforces this (#1287, #1292). When you run a skill by hand, any other command it needs asks for permission first. Phases started by sequant run use bypassPermissions, so they do not prompt.

Allow a tool but restrict dangerous operations

Section titled “Allow a tool but restrict dangerous operations”
{
"permissions": {
"allow": ["Bash"],
"ask": ["Bash(rm *)", "Bash(git push *)"],
"deny": ["Bash(rm -rf /)"]
}
}
{
"permissions": {
"deny": ["Read(.env)", "Read(.env.local)", "Read(**/credentials.*)"]
}
}

Some pre-tool.sh refusals apply only when a phase agent runs under sequant run (the SEQUANT_ORCHESTRATOR environment variable is set); interactive sessions are untouched.

  • Background tasks are refused — a Monitor tool call, or a Bash call with run_in_background: true, is blocked with HOOK_BLOCKED: Background tasks never notify a phase agent. Inside a phase the completion notification never arrives: the phase ends the moment the agent’s turn ends, and any work still uncommitted is stranded. Run long commands in the foreground with a timeout instead (timeout 600 npm test 2>&1 | tail -80), after a WIP commit. If an exec phase still ends with uncommitted changes, sequant commits them as chore(#N): wip checkpoint … before reporting the failure.