Claude Code Permissions

How allow lists, permission modes, and tool access controls work — and how to configure them for your workflow.

The Three Permission Modes

Every Claude Code session uses one of three permission models:

Mode How it works When to use
Default safest Claude prompts before any write, shell, or destructive operation. You approve/deny each. Interactive dev sessions. Always safe to start here.
Allow list recommended Pre-approved tools/patterns run without prompting. Everything else still asks. Reducing prompt fatigue while keeping control of dangerous operations.
--dangerously-skip-permissions use with care Bypasses ALL permission prompts. Claude runs any tool without asking. Isolated CI/CD pipelines only. Never in interactive sessions.

Setting Up an Allow List

Add an allowedTools array to your settings file. Claude auto-approves anything that matches without prompting.

Project allow list (.claude/settings.json)

Commit this to your repo so the whole team gets the same auto-approvals:

{
  "allowedTools": [
    "Read",
    "Glob",
    "Grep",
    "Bash(npm run **)",
    "Bash(git log **)",
    "Bash(git diff **)",
    "Bash(git status)"
  ]
}

User allow list (~/.claude/settings.json)

Applies to you across all projects. Good for personal workflow preferences:

{
  "allowedTools": [
    "Read",
    "Glob",
    "Grep",
    "Edit",
    "Bash(npm **)",
    "Bash(cargo **)",
    "Bash(python **)"
  ]
}

Pattern syntax

EntryWhat it allows
"Read"Any Read tool call (read any file)
"Bash"Any bash command — use with caution
"Bash(npm run **)"Only npm run <anything> commands
"Bash(git log **)"Only git log ... commands
"Bash(git diff **)"Only git diff ... commands
Tip: Run /fewer-permission-prompts inside Claude Code to auto-scan your recent session transcripts and generate an optimized allow list. It identifies which tools you always approve and adds them for you.

Permission Prompts at Runtime

When Claude needs to run a tool not in your allow list, it shows a prompt like:

Claude wants to run: Bash("git push origin main")
Allow? [y/n/always/never]

Using --dangerously-skip-permissions

This flag bypasses all permission prompts. Claude runs every tool — file deletes, shell commands, git pushes — without asking.

claude --dangerously-skip-permissions "refactor auth module and run tests"
Safe Unsafe
CI/CD Docker container (isolated)
Sandboxed VM with no sensitive data
Your dev machine with AWS credentials
Shared machines / SSH servers
Any machine with production access
Why the name? The verbose flag name is intentional — it forces you to think about what you're doing. If you find yourself typing it in an interactive session, that's a signal to use an allow list instead.

Hooks as a Second Safety Layer

Even with a broad allow list, you can use hooks to block specific dangerous commands. A PreToolUse hook that exits non-zero cancels the tool call before it runs.

{
  "hooks": {
    "PreToolUse": [{
      "matcher": "Bash",
      "hooks": [{
        "type": "command",
        "command": "bash -c 'echo \"$CLAUDE_TOOL_INPUT\" | grep -qE \"(rm -rf|git push --force|DROP TABLE)\" && exit 1 || exit 0'"
      }]
    }]
  }
}

This allows Bash broadly in the allow list but blocks rm -rf, force-push, and SQL drops.

Deny Lists

The inverse of an allow list: tools you never want Claude to use. Add them to bannedTools:

{
  "bannedTools": [
    "Bash(git push **)",
    "Bash(rm -rf **)"
  ]
}

Banned tools are blocked regardless of what you type at a permission prompt — Claude won't even ask.

Checking What's Currently Allowed

Run /config inside Claude Code to see the active settings for your current session, including the resolved allow list (merged from project + user settings).

Related Guides

More Claude Code Tools

⚡ Using Claude Code? 30 power prompts that 2× your output · £5 £3 first 10Get PDF £3 →