Operations 11 min read

Mastering Claude Code Permissions: A Complete Guide to settings.json

This guide explains how to configure Claude Code’s settings.json file at global, project, and local levels, defining allow, deny, and ask rules, default modes, safe command lists, and hooks, enabling seamless team‑shared permissions and eliminating repetitive permission prompts during development sessions.

Code Mala Tang
Code Mala Tang
Code Mala Tang
Mastering Claude Code Permissions: A Complete Guide to settings.json

Claude Code users often encounter repeated permission prompts—up to 30 times per session—when editing files or running tests, which disrupts their workflow.

File Location

There are three levels for the settings.json file, similar to CLAUDE.md:

~/.claude/settings.json           → Global (applies to every project)
.claude/settings.json             → Project (shared in git)
.claude/settings.local.json       → Local (personal, git‑ignored)

Global settings define the desired permissions, project settings are shared among the team, and local settings override without being committed.

Rules from different levels are merged. If the global setting allows "Bash(npm *)" but the project setting denies "Bash(npm publish)", both rules apply, and denial always takes precedence over allowance.

60‑Second Permission System

Three arrays control all behavior:

{
  "permissions": {
    "allow": [],
    "deny": [],
    "ask": []
  }
}

allow – Claude will execute the tool without asking.

deny – Claude is strictly prohibited from using the tool.

ask – Claude will always ask for permission.

Evaluation order is deny → ask → allow; the first matching rule wins, and for the same tool a deny rule overrides an allow rule.

Rule format uses the tool name or a pattern, e.g.:

"Bash"              → All bash commands (dangerous)
"Bash(npm install)" → Only npm install
"Bash(npm run *)"   → Any npm run script
"Bash(git *)"       → Any git command
"Write(src/**)"     → Write only under src/
"Read(.env*)"       → Read any .env file

Note the space before the asterisk; Bash(ls *) matches ls -la but not lsof. Wildcards are global patterns, not regular expressions.

Five Permission Modes

Instead of setting individual rules, you can choose a default mode:

{
  "permissions": {
    "defaultMode": "default"
  }
}
default          → Ask for all dangerous actions
acceptEdits      → Auto‑approve file edits, still ask for bash commands
plan             → Read‑only mode, no changes allowed
dontAsk          → Deny all actions not explicitly allowed
bypassPermissions → Allow everything (use only in containers/CI)

During a session you can cycle between default, acceptEdits, and plan with Shift+Tab , without touching any configuration files.

Allow List (Safe Commands)

These are the commands you run dozens of times daily and want Claude to execute without prompting, saving 5–10 minutes per session:

{
  "permissions": {
    "allow": [
      "Read",
      "Glob",
      "Grep",
      "LS",
      "Bash(npm run *)",
      "Bash(npm install *)",
      "Bash(npm test *)",
      "Bash(npx tsc *)",
      "Bash(npx vitest *)",
      "Bash(git status)",
      "Bash(git diff *)",
      "Bash(git log *)",
      "Bash(git add *)",
      "Bash(git commit *)",
      "Bash(git checkout *)",
      "Bash(git branch *)",
      "Write(src/**)",
      "Edit",
      "MultiEdit"
    ]
  }
}

Read‑related operations are fully open; bash commands are limited to specific npm and git actions; write access is confined to the src/ directory.

Deny List (Safety Net)

These commands can cause real damage and must always be blocked:

{
  "permissions": {
    "deny": [
      "Read(.env*)",
      "Read(**/secrets/**)",
      "Write(.env*)",
      "Write(production.*)",
      "Write(.github/workflows/*)",
      "Bash(rm -rf *)",
      "Bash(sudo *)",
      "Bash(git push *)",
      "Bash(git merge *)",
      "Bash(npm publish *)",
      "Bash(docker *)",
      "Bash(curl * | sh)",
      "Bash(wget *)"
    ]
  }
}

Claude can read, write, and test code, but it can never read secrets, push to remote repositories, recursively delete files, or run commands with sudo.

Adding Hooks in settings.json

Hooks live in the same file. After each edit they automatically format code and run checks:

{
  "hooks": {
    "PostToolUse": [
      {
        "matcher": "Write(*.py)",
        "hooks": [
          {
            "type": "command",
            "command": "python -m black $file"
          }
        ]
      },
      {
        "matcher": "Write(*.ts)",
        "hooks": [
          {
            "type": "command",
            "command": "npx prettier --write $file"
          }
        ]
      }
    ]
  }
}

Every .py file is automatically formatted with Black, and every .ts file with Prettier, without any manual steps.

Team‑Shared Settings

Place the project‑level configuration in .claude/settings.json and commit it to git. All team members inherit the same permissions:

{
  "permissions": {
    "allow": ["Read","Glob","Grep","Bash(npm run *)","Bash(npm test *)"],
    "deny": ["Read(.env*)","Bash(npm publish *)","Bash(rm -rf *)","Write(production.*)"],
    "defaultMode": "acceptEdits"
  }
}

New members clone the repository, open Claude Code, and everything is pre‑configured—no prompts for routine commands and no risk of accidentally allowing dangerous commands such as Bash(rm -rf *).

Anthropic’s Boris Cherny uses this exact approach: a shared settings.json that pre‑approves everyday commands and blocks risky ones.

Full File (Copy‑Paste Ready)

A typical Node.js/TypeScript project’s complete settings.json can be copied to ~/.claude/settings.json for global use or to .claude/settings.json for project‑specific use:

{
  "permissions": {
    "allow": [
      "Read","Glob","Grep","LS","Edit","MultiEdit","Write(src/**)","Write(tests/**)","Write(docs/**)",
      "Bash(npm run *)","Bash(npm install *)","Bash(npm test *)","Bash(npx tsc *)","Bash(npx vitest *)",
      "Bash(npx prettier *)","Bash(npx eslint *)","Bash(git status)","Bash(git diff *)","Bash(git log *)",
      "Bash(git add *)","Bash(git commit *)","Bash(git checkout *)","Bash(git branch *)",
      "Bash(cat *)","Bash(head *)","Bash(tail *)","Bash(wc *)","Bash(find *)","Bash(echo *)"
    ],
    "deny": [
      "Read(.env*)","Read(**/secrets/**)","Write(.env*)","Write(production.*)","Write(.github/workflows/*)",
      "Write(package-lock.json)","Bash(rm -rf *)","Bash(sudo *)","Bash(git push *)","Bash(git merge *)",
      "Bash(git rebase *)","Bash(npm publish *)","Bash(docker *)","Bash(curl * | sh)","Bash(wget *)",
      "Bash(chmod *)","Bash(chown *)"
    ],
    "defaultMode": "acceptEdits"
  },
  "hooks": {
    "PostToolUse": [
      {
        "matcher": "Write(*.ts)",
        "hooks": [{"type": "command","command": "npx prettier --write $file"}]
      },
      {
        "matcher": "Write(*.tsx)",
        "hooks": [{"type": "command","command": "npx prettier --write $file"}]
      }
    ]
  }
}

Copy the file and adjust the Write scopes to match your folder structure.

Before / After Comparison

BEFORE settings.json: 30‑40 permission prompts per session; manual approval needed for each npm install; accidental allowance of dangerous commands like rm -rf; each new team member configures everything manually; workflow interrupted every two minutes.

AFTER settings.json: 0‑3 prompts per session; routine commands run instantly; dangerous commands blocked at configuration level; a single shared file gives every teammate the same pre‑configured permissions; workflow remains uninterrupted.

Setting up takes about two minutes, after which every session runs faster.

Thank you for reading 🙏🏼

Original Source

Signed-in readers can open the original source through BestHub's protected redirect.

Sign in to view source
Republication Notice

This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactadmin@besthub.devand we will review it promptly.

workflowteam collaborationhookspermissionsClaude Codesettings.json
Code Mala Tang
Written by

Code Mala Tang

Read source code together, write articles together, and enjoy spicy hot pot together.

0 followers
Reader feedback

How this landed with the community

Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.