Claude Permissions

Model

Tiers: allow / ask / deny. Evaluated deny → ask → allow; the first match wins and specificity doesn't matter: a broad Bash(aws *) deny beats a narrow Bash(aws s3 ls) allow. A PreToolUse hook can't bypass deny/ask rules, but a hook that exits 2 blocks even an allowed call. Allow/deny lists merge across settings files.

{
  "permissions": {
    "allow": ["Read(**)", "Write(./src/**)", "Bash(npm run *)"],
    "ask":   ["Bash(git commit *)"],
    "deny":  ["Bash(curl *)", "Read(~/.ssh/**)", "WebFetch(domain:bad.com)", "mcp__stripe", "Agent(Explore)"],
    "additionalDirectories": ["../shared-docs/"],
    "defaultMode": "acceptEdits",
    "disableBypassPermissionsMode": "disable"
  }
}

Rule syntax

Target Pattern Notes
Bash Bash(git * main), Bash(* --version) * anywhere; space matters: Bash(ls *) matches ls -la, not lsof. Trailing :* is equivalent (Bash(ls:*)) and only valid at the end. Same shape for PowerShell(...)
Read / Edit gitignore-style globs see prefixes below
WebFetch WebFetch(domain:github.com) exact host only; domain:*.example.com covers subdomains but not the apex. Bare WebFetch denies/asks every fetch, unlike domain:*
MCP mcp__server, mcp__server__*, mcp__server__tool
Subagent Agent(Explore) Also parameter forms like Agent(isolation:*)
Skill Skill(commit), Skill(deploy *) deny Skill to disable all skills
Bare name Read, Edit, Bash, WebFetch, mcp__stripe no parentheses = everything

Path prefixes for Read/Edit:

Prefix Meaning Example
// Absolute from filesystem root Read(//etc/hosts)
~/ Home Edit(~/.zshrc)
/ Project root Read(/src/**/*.ts)
none or ./ Current working dir Read(*.env)

Modes (permissions.defaultMode)

Mode Runs without asking
default (Manual) Reads only
acceptEdits Reads, file edits, simple fs commands (mkdir, mv, cp) inside the working dir
plan Reads only; no changes
auto Everything, with a background classifier reviewing actions
dontAsk Only pre-approved tools; anything that would prompt is denied (CI/scripts)
bypassPermissions Everything (isolated containers/VMs only)

--dangerously-skip-permissions

claude --dangerously-skip-permissions
claude --dangerously-skip-permissions -p "Fix all lint errors"

Use only in devcontainer/VM, CI, or very low-risk scoped work. Block it with disableBypassPermissionsMode: "disable".
Danger: with auto-approve, Claude can decide the sandbox is the obstacle and turn it off; npx can fetch and run arbitrary code, so a deny rule on it isn't enough.

Sandbox

Off by default. Enable with /sandbox or "sandbox": {"enabled": true}.

Dev containers

Install via the Dev Container Feature: "features": { "ghcr.io/anthropics/devcontainer-features/claude-code:1.0": {} } in .devcontainer/devcontainer.json (works in VS Code, Codespaces, JetBrains, Cursor). The :1.0 pins the install script, not Claude Code.

Headless tool limits

claude -p "run tests" --allowedTools "Bash(npm run test:*)" "Read"
claude -p "analyze" --disallowedTools "Bash(rm:*)" "Write"

Related: Claude Settings, Claude Hooks and Automation, Claude Fundamentals