Skip to content
AI Dev Toolkit.
Esc
  • AI Token CounterCount tokens for GPT, Claude, Gemini, DeepSeek, Qwen and more.Tool
  • LLM API Cost CalculatorEstimate per-request, daily and monthly API costs.Tool
  • AI Model ComparisonCompare prices, context windows and features across models.Tool
  • AI Model Pricing PagesSpecs, real costs and cheaper alternatives for popular models.Tool
  • Context Window CheckerSee whether your text fits each model’s context window.Tool
  • Subscription vs API CalculatorFind out whether a chat plan or the API is cheaper for you.Tool
  • GPU / VRAM CalculatorCheck how much VRAM a local model needs and which GPUs fit.Tool
  • Prompt Caching CalculatorEstimate savings from prompt caching.Tool

Coding Agents

Claude Code settings.json and permissions builder

Build a Claude Code settings.json with allow, ask and deny permission rules, a starting mode and sandbox settings, or paste your own file to find risky allows and rules that never match. It’s free and runs in your browser.

Start from a preset

Accepts edits, runs your npm scripts and commits without asking, asks before pushing or deleting, and denies reads of secret files (scripts can still open them without the sandbox). Shared with your team.

Committed to the repository, so everyone who clones it gets it.

Also accepts file edits and common file commands (mkdir, mv, cp) in your working directories.

An alias such as sonnet or opus, or a full model ID.

Add a rule

A command; * stands for any text. Adds Bash.

One rule per line.

Asks even in modes that would otherwise approve.

Checked first: a deny rule beats any allow rule, from any file.

Folders outside the project Claude may read and edit, e.g. ../shared-lib/.

Locks
Environment variables

Values are plain text in the file. Don’t put API keys here; use apiKeyHelper or your shell.

Sandbox (macOS, Linux, WSL2)

Hooks go in the same file, under a hooks key. This builder leaves them out: build and check them with the Claude Code hooks builder, which can merge them into this file, or read the hooks guide.

.claude/settings.json
{
  "$schema": "https://json.schemastore.org/claude-code-settings.json",
  "permissions": {
    "allow": [
      "Bash(npm run *)",
      "Bash(npm test *)",
      "Bash(git add *)",
      "Bash(git commit *)"
    ],
    "ask": [
      "Bash(git push *)",
      "Bash(rm *)"
    ],
    "deny": [
      "Read(.env)",
      "Read(.env.*)",
      "Read(!.env.example)",
      "Read(*.pem)",
      "Read(*.key)",
      "Read(secrets/**)",
      "Read(~/.ssh/**)",
      "Read(~/.aws/**)",
      "Read(~/.config/gcloud/**)",
      "Read(~/.azure/**)",
      "Read(~/.kube/**)"
    ],
    "defaultMode": "acceptEdits"
  }
}
Save as .claude/settings.json

Checks

  • Notepermissions.allow:Allow rules in a shared project file apply only after each person accepts the workspace trust dialog for the folder. Deny and ask rules apply right away.
  • NoteBash(git push *):An ask rule matches the command as Claude writes it: it doesn’t stop git -C . push. For a hard boundary, also turn on the sandbox.
  • NoteBash(rm *):An ask rule matches the command as Claude writes it: it doesn’t stop /usr/bin/rm … or sh -c 'rm …'. For a hard boundary, also turn on the sandbox.
  • Notepermissions.defaultMode:Conversations the VS Code extension starts don’t read the starting mode from project or local settings, only from user, managed and --settings files.

What each rule does

Claude Code checks deny first, then ask, then allow. The first match decides.

  • denyRead(.env)Reading .env under the current directory.
  • denyRead(.env.*)Reading .env.* under the current directory.
  • denyRead(!.env.example)Except .env.example under the current directory (carved out of the rules before it).
  • denyRead(*.pem)Reading *.pem under the current directory.
  • denyRead(*.key)Reading *.key under the current directory.
  • denyRead(secrets/**)Reading secrets/** under the current directory.
  • denyRead(~/.ssh/**)Reading ~/.ssh/** in your home folder.
  • denyRead(~/.aws/**)Reading ~/.aws/** in your home folder.
  • denyRead(~/.config/gcloud/**)Reading ~/.config/gcloud/** in your home folder.
  • denyRead(~/.azure/**)Reading ~/.azure/** in your home folder.
  • denyRead(~/.kube/**)Reading ~/.kube/** in your home folder.
  • askBash(git push *)Shell commands that start with git push, and git push on its own.
  • askBash(rm *)Shell commands that start with rm, and rm on its own.
  • allowBash(npm run *)Shell commands that start with npm run, and npm run on its own.
  • allowBash(npm test *)Shell commands that start with npm test, and npm test on its own.
  • allowBash(git add *)Shell commands that start with git add, and git add on its own.
  • allowBash(git commit *)Shell commands that start with git commit, and git commit on its own.

Everything stays in your browser. Nothing you type is sent anywhere.

Steps

How to use the Claude Code settings.json builder

  1. Pick a preset, or start from Clear, and choose where the file will live.
  2. Add or edit rules: allow runs without asking, ask always prompts, deny blocks.
  3. Set the starting mode, any locks, environment variables and the sandbox.
  4. Read the checks, then copy or download the file and save it where the tool says.
  5. To audit a file you already have, open the Check tab and paste it.

Method

How it works

Claude Code reads its settings from JSON files, and the file a setting sits in decides who it applies to. Your own ~/.claude/settings.json covers every project on your machine. A project’s .claude/settings.json is meant to be committed, so the whole team gets the same rules, and .claude/settings.local.json holds your personal overrides for that project. Organisations can deploy a managed-settings.json that nothing else can override.

Which settings file wins

When the same key is set in more than one place, the highest level wins: managed settings, then a file passed with claude --settings, then local, then the shared project file, then user settings. Lists such as permissions.allow are the exception: they merge across files, so each file adds rules without removing another’s. A few keys only work from some files. autoMode is read only from user or managed settings, and defaultMode values auto and bypassPermissions don’t take effect from a project file, so a repository you clone can’t switch your prompts off. The builder warns when a key can’t work in the file you picked.

How allow, ask and deny rules are evaluated

Every rule is a tool name, optionally with a specifier in parentheses: Bash, Bash(npm run *), Read(./.env). Claude Code checks deny rules first, then ask, then allow, and the first match decides. Specificity doesn’t matter, so Bash(aws *) in deny blocks aws s3 ls even if that exact command is allowed. A bare tool name in deny removes the tool from Claude’s context entirely. The rules are enforced by Claude Code, not by the model, which is what makes them different from instructions in CLAUDE.md.

Rule syntax for each tool

Bash rules match the command text, with * standing for any text. The space matters: Bash(ls *) matches ls -la and ls but not lsof. A trailing :* means the same as *, but only at the very end. Compound commands are split on &&, ||, ; and pipes, and each part must match on its own.

Read and Edit rules use gitignore patterns with four anchors: //path is absolute, ~/path is in your home folder, /path is relative to the project root in project and local settings (but ~/.claude in user settings), and a plain path is relative to the current directory. Edit rules cover every tool that edits files, and Read rules cover Grep and Glob, so path rules written on Write or Glob are never checked. WebFetch rules match the hostname with domain:, and MCP rules use mcp__server__tool, where a wildcard in an allow rule is only allowed after the server name.

What the presets block, and what they don’t

Block secrets denies .env files, keys, ~/.ssh and the AWS, Google Cloud, Azure and Kubernetes credential folders. That stops Claude’s file tools and commands that name the file, such as cat .env, but not a script that opens the file itself. The sandbox closes that gap only where it runs, and an unsandboxed retry still runs if you approve it. The docs don’t say how a bare name such as .env becomes a sandbox path, so check with /sandbox. Read-only uses dontAsk mode, not plan mode, because plan mode lets the auto mode classifier approve shell commands. Locked-down CI can’t hide secrets in the job’s environment from commands: deny them with sandbox.credentials, and pass --setting-sources user for a repository you didn’t write, so its hooks don’t run.

What the checker can and can’t tell you

The checker parses your file the way the docs describe, then reports four kinds of finding: problems (invalid JSON, malformed rules, rules that can never match), risky allows such as Bash(*), Bash(python *) or WebFetch(domain:*), warnings (unknown keys, keys the file can’t set, allow rules a deny rule overrides) and notes. It can’t see the rest of your setup: rules in other settings files, managed policy, hooks (check those with the hooks builder) and command-line flags all combine with this file. Run /permissions in Claude Code to see the merged list, and /status to see which files loaded.

One limit applies to every Bash rule. A deny rule such as Bash(curl *) stops the command as Claude usually writes it, but not /usr/bin/curl or sh -c 'curl …'. For a boundary that holds, turn on the sandbox, which enforces file and network limits at the operating-system level for every sandboxed shell command and its child processes, on macOS, Linux and WSL2. Everything here was checked against Claude Code’s documentation on 2026-10-13 (Claude Code v2.1.296); where a behaviour needs a minimum version, the finding says so.

Examples

Worked examples

Rule shapes, what they match, and the common mistake
RuleMatchesWatch out
Bash(npm run *)npm run build, npm run test --watch, and npm run on its ownBash(npm run*) with no space also matches npm runner
Bash(git log * main)git log --oneline mainBash(git * main) matches every git subcommand, including git push origin main
Read(.env)any .env at or below the current directoryRead deny rules don’t stop grep -r or a script that opens the file; add the sandbox
Read(//etc/hosts)the absolute path /etc/hostsIn a project file, Read(/etc/hosts) means <project>/etc/hosts: one slash anchors at the project
Edit(/src/**)files under src/ in the project rootWrite(src/**) is never checked; Edit rules cover Write too
WebFetch(domain:docs.python.org)fetches from that host onlyWebFetch(https://docs.python.org) never matches: use domain:
mcp__github__get_*the github server’s tools starting with get_mcp__* in an allow rule is skipped; name the server
Agent(Explore)the Explore subagent (use it in deny)In allow it does nothing: starting a subagent never asks

A team’s shared settings

.claude/settings.json
{
  "$schema": "https://json.schemastore.org/claude-code-settings.json",
  "permissions": {
    "allow": [
      "Bash(npm run *)",
      "Bash(npm test *)",
      "Bash(git add *)",
      "Bash(git commit *)"
    ],
    "ask": [
      "Bash(git push *)",
      "Bash(rm *)"
    ],
    "deny": [
      "Read(.env)",
      "Read(.env.*)",
      "Read(!.env.example)",
      "Read(*.pem)",
      "Read(*.key)",
      "Read(secrets/**)",
      "Read(~/.ssh/**)",
      "Read(~/.aws/**)",
      "Read(~/.config/gcloud/**)",
      "Read(~/.azure/**)",
      "Read(~/.kube/**)"
    ],
    "defaultMode": "acceptEdits"
  }
}

A locked-down CI run

ci-settings.json
{
  "$schema": "https://json.schemastore.org/claude-code-settings.json",
  "permissions": {
    "allow": [
      "Bash(npm ci)",
      "Bash(npm test)",
      "Bash(npm run lint)",
      "Bash(npm run build)"
    ],
    "deny": [
      "Read(.env)",
      "Read(.env.*)",
      "Read(!.env.example)",
      "Read(*.pem)",
      "Read(*.key)",
      "Read(secrets/**)",
      "Read(~/.ssh/**)",
      "Read(~/.aws/**)",
      "Read(~/.config/gcloud/**)",
      "Read(~/.azure/**)",
      "Read(~/.kube/**)",
      "WebFetch",
      "WebSearch",
      "Bash(curl *)",
      "Bash(wget *)",
      "Bash(git push *)"
    ],
    "defaultMode": "dontAsk",
    "disableBypassPermissionsMode": "disable",
    "blockReadsOutsideWorkingDirectories": true
  },
  "sandbox": {
    "enabled": true,
    "failIfUnavailable": true,
    "autoAllowBashIfSandboxed": false,
    "allowUnsandboxedCommands": false,
    "network": {
      "allowedDomains": [
        "registry.npmjs.org"
      ]
    }
  }
}

Run it with claude -p "run the tests" --settings ci-settings.json. In dontAsk mode anything not allowed is denied, and with auto-allow off the sandbox doesn’t widen that list.

FAQ

Frequently asked questions

Where is the Claude Code settings.json file?

There are three you edit: ~/.claude/settings.json for you in every project, .claude/settings.json in a project for the whole team (commit it), and .claude/settings.local.json for just you in one project. Organisations can add a managed-settings.json. Installing Claude Code creates none of them; create the file, or let /config and permission prompts create it. On Windows, ~ is %USERPROFILE%.

What is settings.local.json for?

Your personal overrides for one project, such as a different model or extra allow rules, without changing the file your team shares. It sits above .claude/settings.json in precedence. When you answer a Bash prompt with “Yes, and don’t ask again”, Claude Code saves the rule there and adds the file to your global git excludes. If you create it by hand, add it to .gitignore yourself.

Do deny rules override allow rules in Claude Code?

Yes. Claude Code checks deny rules first, then ask, then allow, and the first match decides; how specific a rule is doesn’t matter. A deny rule in any settings file blocks a call that another file allows, and an allow rule can’t carve an exception out of a deny. An ask rule likewise prompts even when a narrower allow rule matches the same call.

How do I stop Claude Code reading my .env file?

Add Read(.env) and Read(.env.*) to permissions.deny; bare file names match at any depth. That blocks Claude’s file tools and commands that name the file, such as cat .env, and also blocks edits to it. It doesn’t stop grep -r over a folder or a script that opens the file itself, so turn on the sandbox too (macOS, Linux and WSL2): it adds your Read deny paths to what sandboxed commands can’t read.

How do I stop Claude Code asking for permission every time?

Allow the specific commands you run often, such as Bash(npm run *), and start in acceptEdits so file edits don’t ask. Auto mode removes routine prompts and has a classifier check actions first. The sandbox with auto-allow runs sandboxed commands without prompts. bypassPermissions (the --dangerously-skip-permissions flag) skips prompts entirely and is only for isolated containers or VMs; Bash(*) in allow is just as broad.

Why isn’t my Claude Code permission rule working?

Common causes: a deny or ask rule elsewhere matches first; the rule names a path on Write or Glob, which are never checked (use Edit or Read); a single leading slash anchors at the project, not the filesystem root (use //); a WebFetch rule lacks domain:; or project allow rules wait until you trust the folder. Run /permissions to see every rule and its file, or paste the file into the checker above.

Which permission modes can defaultMode take?

default (shown as Manual), acceptEdits, plan, auto, dontAsk and bypassPermissions, with manual accepted as an alias for default. auto and bypassPermissions don’t take effect from project or local settings: set them in user settings or pass --permission-mode. Cloud sessions ignore dontAsk and bypassPermissions from settings files.