CLAUDE LABJP
WWDC — WWDC 2026 confirms Siri runs on Google Gemini; third-party handoff to ChatGPT is dropped, and Siri AI won't ship in the EU under the DMA at iOS 27BILLING — 6 days until the Jun 15 change: Agent SDK, headless Claude Code, GitHub Actions, and third-party agents move to API-rate monthly creditOUTAGE — claude.ai, Claude Code, and Cowork saw an outage (Jun). Scheduled runs are safest when built around fallbackModel and retriesDYNAMIC-WORKFLOWS — Dynamic workflows are on by default on Max/Team and the API, for codebase-wide bug hunts and independent verificationULTRACODE — Claude Code's new ultracode setting sits in the effort menu, fixing effort to xhigh while Claude decides when to run a workflowOPUS4.8 — Claude Opus 4.8 is settled in as the default across major plans, with stronger coding, agentic, and reasoning skillsWWDC — WWDC 2026 confirms Siri runs on Google Gemini; third-party handoff to ChatGPT is dropped, and Siri AI won't ship in the EU under the DMA at iOS 27BILLING — 6 days until the Jun 15 change: Agent SDK, headless Claude Code, GitHub Actions, and third-party agents move to API-rate monthly creditOUTAGE — claude.ai, Claude Code, and Cowork saw an outage (Jun). Scheduled runs are safest when built around fallbackModel and retriesDYNAMIC-WORKFLOWS — Dynamic workflows are on by default on Max/Team and the API, for codebase-wide bug hunts and independent verificationULTRACODE — Claude Code's new ultracode setting sits in the effort menu, fixing effort to xhigh while Claude decides when to run a workflowOPUS4.8 — Claude Opus 4.8 is settled in as the default across major plans, with stronger coding, agentic, and reasoning skills
Articles/Claude Code
Claude Code/2026-04-13Intermediate

Claude Code Tool Permissions: Custom Allow/Deny Policies

Learn how to control Claude Code tool permissions with allowedTools, disallowedTools, and settings.json. Includes project-specific permission patterns for frontend, backend, and read-only review scenarios.

Claude Code219tool permissionssecurity19settings.json2allowedToolsdevelopment environment2

After using Claude Code for a while, most developers hit the same tension: work near production data and every rm call feels risky, but lock things down too much and the constant permission dialogs slow everything down.

Claude Code's permission system is more configurable than most people realize. You can define project-specific allow and deny lists, and commit them to your repo so the whole team uses the same settings from day one. Here's how the system works and the patterns I actually use.

Understanding Claude Code's Permission Model

Claude Code's operations fall into four categories:

  • File operations: Read, Write, Edit
  • Bash execution: Shell commands via Bash
  • Web/browser: URL fetching, browser control
  • MCP: Access to external MCP servers

By default, most operations require a permission prompt. You can skip all prompts with --dangerously-skip-permissions, but that's not appropriate anywhere near real data. The better approach is to define exactly what's allowed.

CLI Flags for One-Off Sessions

The quickest way to customize permissions is via command-line flags:

# Whitelist: only allow these tools
claude --allowedTools "Read,Write,Edit,Bash(git status),Bash(git diff)"
 
# Blacklist: allow everything except these
claude --disallowedTools "Bash(rm),Bash(sudo)"

The Bash(command) syntax lets you control individual shell commands. Allowing Bash(git status) and Bash(git diff) but nothing else gives you an effectively read-only session — Claude can inspect code but can't modify anything or run arbitrary commands.

Flags are useful for one-off sessions, but for regular development you want the settings persisted.

Project-Level settings.json

Create .claude/settings.json in your project root and Claude Code picks it up automatically when started from that directory:

// .claude/settings.json
{
  "permissions": {
    "allow": [
      "Read",
      "Write",
      "Edit",
      "Bash(git *)",
      "Bash(npm run *)",
      "Bash(npx *)",
      "Bash(echo *)",
      "Bash(cat *)",
      "Bash(ls *)",
      "Bash(grep *)",
      "Bash(find *)"
    ],
    "deny": [
      "Bash(rm -rf *)",
      "Bash(sudo *)",
      "Bash(curl *)",
      "Bash(wget *)"
    ]
  }
}

Wildcards work: Bash(git *) permits all git subcommands. Committing this file means anyone who clones the repo gets appropriate permissions without any setup.

Permission Patterns by Project Type

Frontend development — lock down network commands:

{
  "permissions": {
    "allow": [
      "Read", "Write", "Edit",
      "Bash(git *)", "Bash(npm *)", "Bash(npx *)",
      "Bash(node *)", "Bash(ts-node *)"
    ],
    "deny": [
      "Bash(curl *)", "Bash(wget *)",
      "Bash(ssh *)", "Bash(scp *)"
    ]
  }
}

Backend API development — protect database commands:

{
  "permissions": {
    "allow": [
      "Read", "Write", "Edit",
      "Bash(git *)", "Bash(go *)", "Bash(make *)",
      "Bash(docker-compose up *)", "Bash(docker-compose down)"
    ],
    "deny": [
      "Bash(psql -c DROP *)",
      "Bash(redis-cli FLUSHALL)",
      "Bash(rm -rf /var/lib/*)"
    ]
  }
}

Code review only — true read-only mode:

{
  "permissions": {
    "allow": [
      "Read",
      "Bash(git log *)", "Bash(git diff *)", "Bash(git status)",
      "Bash(cat *)", "Bash(ls *)", "Bash(grep *)"
    ],
    "deny": ["Write", "Edit", "Bash(*)"]
  }
}

Note the order in the last example: allow lists specific Bash commands, then deny blocks all remaining Bash. The allow list takes precedence over the deny list for explicitly listed commands.

Global Defaults via ~/.claude/settings.json

For operations you never want Claude Code to perform, put them in ~/.claude/settings.json:

// ~/.claude/settings.json
{
  "permissions": {
    "deny": [
      "Bash(rm -rf /)",
      "Bash(sudo rm -rf *)",
      "Bash(format *)",
      "Bash(dd if=*)"
    ]
  }
}

Priority order: project-level .claude/settings.json overrides user-level ~/.claude/settings.json, which overrides defaults. Deny rules from both levels are merged — if either file denies something, it's denied.

Checking Active Permissions

During a Claude Code session, you can inspect what's currently allowed:

/permissions

This slash command lists all currently allowed and denied tools. Useful for verifying your settings file loaded correctly.

Common Pitfalls

Wildcards are broad. Bash(git *) allows git commit -m "anything" including commit messages you might not have reviewed. If you need to prevent commits, explicitly deny Bash(git commit *).

Scripts bypass command-level deny rules. If Bash(deploy.sh) is allowed but Bash(rm -rf *) is denied, the script can still run rm -rf internally. Be conservative about which scripts you allow.

MCP permissions are separate. MCP server access is controlled through mcpServers in settings.json, not through the allowedTools Bash mechanism. If you're using MCP tools, review that section separately.

Taking 10 minutes to set up a proper settings.json for each project eliminates most of the vague anxiety that comes with using an AI agent near important files — and makes it easier to use Claude Code more aggressively where it's actually safe to do so.

Share

Thank You for Reading

Claude Lab is ad-free, supported entirely by members like you. We publish practical guides daily with implementation code, benchmarks, and production-ready patterns. If you've found it useful, we'd love to have you on board.

  • Copy-paste ready implementation code
  • New advanced guides published daily
  • $5/mo or $10 for lifetime access
View Membership →

If you found this article helpful, a small tip ($1.50) would mean a lot to us. Your support helps keep this site ad-free and covers server and hosting costs.

Related Articles

Claude Code2026-03-29
Claude Code Auto Mode — Secure Automation Without Friction
Master Claude Code's new Auto Mode: how it works, its security model, when to use it, and how to enable it. Achieve safer automation with intelligent classifier-based action approval.
Claude Code2026-03-23
Claude Code MCP OAuth Guide — Securely Connect to Remote Servers
Learn how to use MCP OAuth authentication in Claude Code to securely connect to GitHub, Slack, and other remote servers. Covers OAuth 2.1, Dynamic Client Registration, and practical setup steps.
Claude Code2026-03-22
Claude Code × Docker — Accelerating Container Development
Learn how to combine Claude Code with Docker to streamline container setup, debugging, and optimization. From Dockerfile generation to docker-compose design and multi-stage build tuning.
📚RECOMMENDED BOOKS
Build a Large Language Model (From Scratch)
Sebastian Raschka
LLM Dev
Prompt Engineering for LLMs
Berryman & Ziegler
Prompting
AI Engineering
Chip Huyen
AI Eng
* Contains affiliate links
See all →