iTranslated by AI

The content below is an AI-generated translation. This is an experimental feature, and may contain errors. View original article
🛡️

After Claude Code Deleted My Files, I Started Taking Permissions Seriously

に公開

Introduction

When I asked Claude Code to "refactor," it rewrote my .env file.

When I asked it to "fix the tests," it modified my production code instead of the test code.

I was tired of repeating "Don't touch this file" every single day.

That's when I took a deep dive into permission settings, and I discovered that Claude Code has a much more granular control mechanism than I imagined. In this article, based on the official documentation, I will explain the overall picture of permission settings and how to use them effectively.


Overview of the Permission Model

Claude Code tools have three levels of permissions.

Tool Type Examples Approval Required?
Read-only File Read, Grep, Glob No
Bash Commands Shell execution Yes
File Changes Edit, Write Yes

In short, Claude can read files silently, but any modifications or execution require approval. This is the default safety mechanism.


Permission Modes

The strictness of approval depends on the Claude Code launch mode.

Mode Description Best For
default Standard. Confirms on first use of each tool Normal development
acceptEdits Skips confirmation for file edits Trusted projects
plan File analysis only. No changes allowed Code reviews, research
dontAsk Automatically denies non-preapproved tools CI/CD, automation
bypassPermissions Skips all confirmations Container environments only

Check Current Settings with /permissions

You can enter the following during a session:

/permissions

A list of current Allow / Deny rules will be displayed, and you can add or edit them right there.


How to Write Allow / Deny Rules

Basic Syntax

ToolName
ToolName(specifier)

Three Rule Levels

Level Description
Allow Permits execution without confirmation
Ask Requests confirmation every time
Deny Completely rejects execution

Evaluation order: Deny → Ask → Allow (Deny is always the top priority)

Practical Configuration Example

{
  "permissions": {
    "allow": [
      "Bash(npm run lint)",
      "Bash(npm run test *)",
      "Bash(git commit *)"
    ],
    "deny": [
      "Bash(git push *)",
      "Bash(curl *)",
      "Read(./.env)",
      "Read(./.env.*)",
      "Read(./secrets/**)"
    ]
  }
}

Meaning of this configuration:

  • npm run lint, npm run test, and git commit can be executed without confirmation
  • git push and curl are completely blocked
  • Even reading .env files and the secrets/ folder is blocked

Wildcard Patterns

You can use * for glob matching.

{
  "permissions": {
    "allow": [
      "Bash(npm run *)",
      "Bash(* --version)",
      "Bash(* --help *)"
    ]
  }
}

File Path Patterns

There are four ways to write paths for Read and Edit rules.

Pattern Meaning Example
//path Absolute path on the filesystem Read(//Users/alice/secrets/**)
~/path Path from the home directory Read(~/Documents/*.pdf)
/path Path relative to the config file Edit(/src/**/*.ts)
path Path relative to the current directory Read(*.env)
  • * matches files in a single directory
  • ** matches directories recursively

Location and Priority of Configuration Files

Scope Location Shared
User settings ~/.claude/settings.json No
Project shared .claude/settings.json Yes (Git-managed)
Local only .claude/settings.local.json No
Admin settings System level IT deployment

Priority (Top is highest):

  1. Admin settings (non-overrideable)
  2. Command-line arguments
  3. Local settings
  4. Project shared settings
  5. User settings

Permission Settings for MCP Tools

You can also apply permission rules to tools added via MCP.

{
  "permissions": {
    "allow": [
      "mcp__github__search_repositories"
    ],
    "deny": [
      "mcp__puppeteer__*"
    ]
  }
}

MCP tool names follow the mcp__server_name__tool_name pattern. mcp__puppeteer__* can block all tools in the Puppeteer server.


Common Configuration Patterns

Pattern 1: Secure Development Environment

{
  "permissions": {
    "allow": [
      "Bash(npm run *)",
      "Bash(git add *)",
      "Bash(git commit *)",
      "Bash(git status)",
      "Bash(git diff *)"
    ],
    "deny": [
      "Bash(git push *)",
      "Bash(rm -rf *)",
      "Bash(curl *)",
      "Bash(wget *)",
      "Read(./.env)",
      "Read(./.env.*)",
      "Edit(./.env)",
      "Edit(./.env.*)"
    ]
  }
}

Pattern 2: Read-Only Review

{
  "permissions": {
    "deny": [
      "Edit(*)",
      "Write(*)",
      "Bash(*)"
    ]
  }
}

Blocks all modifications and execution. Only allows file reading and Grep. An environment dedicated to code review.

Pattern 3: Restricting Web Access

{
  "permissions": {
    "allow": [
      "WebFetch(domain:github.com)",
      "WebFetch(domain:docs.anthropic.com)"
    ],
    "deny": [
      "WebFetch(*)",
      "Bash(curl *)",
      "Bash(wget *)"
    ]
  }
}

Allows access only to specific domains. Blocks curl and wget to seal off potential workarounds.


Integration with Hooks

Combining this with Hooks makes it even more powerful.

  • Permission Settings: "Deny reading of .env" (static rule)
  • Hooks: "Return a warning message if someone attempts to edit .env" (dynamic processing)

If permission settings are a "wall," then Hooks are the "guard." For complex conditions that cannot be covered by static rules, use the PreToolUse hook in Hooks.


Summary

Point Content
Check command /permissions
Rule priority Deny → Ask → Allow
Config files ~/.claude/settings.json or .claude/settings.json
Wildcard * (be careful with space position)
Absolute path // prefix required
MCP tool mcp__server_name__tool_name

Things to remember:

Instead of telling it "don't touch" repeatedly,
make it "unable to touch" via permission settings.


References


GitHubで編集を提案

Discussion