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.
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.
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/.
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.
{
"$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"
}
}
.claude/settings.jsonChecks
- 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 …orsh -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.
- deny
Read(.env)Reading.envunder the current directory. - deny
Read(.env.*)Reading.env.*under the current directory. - deny
Read(!.env.example)Except.env.exampleunder the current directory (carved out of the rules before it). - deny
Read(*.pem)Reading*.pemunder the current directory. - deny
Read(*.key)Reading*.keyunder the current directory. - deny
Read(secrets/**)Readingsecrets/**under the current directory. - deny
Read(~/.ssh/**)Reading~/.ssh/**in your home folder. - deny
Read(~/.aws/**)Reading~/.aws/**in your home folder. - deny
Read(~/.config/gcloud/**)Reading~/.config/gcloud/**in your home folder. - deny
Read(~/.azure/**)Reading~/.azure/**in your home folder. - deny
Read(~/.kube/**)Reading~/.kube/**in your home folder. - ask
Bash(git push *)Shell commands that start withgit push, andgit pushon its own. - ask
Bash(rm *)Shell commands that start withrm, andrmon its own. - allow
Bash(npm run *)Shell commands that start withnpm run, andnpm runon its own. - allow
Bash(npm test *)Shell commands that start withnpm test, andnpm teston its own. - allow
Bash(git add *)Shell commands that start withgit add, andgit addon its own. - allow
Bash(git commit *)Shell commands that start withgit commit, andgit commiton its own.
Everything stays in your browser. Nothing you type is sent anywhere.
Committed to the repository, so everyone who clones it gets it.
Checked in your browser against the Claude Code docs. Nothing is uploaded.
Results
Paste a file to check it.
Steps
How to use the Claude Code settings.json builder
- Pick a preset, or start from Clear, and choose where the file will live.
- Add or edit rules: allow runs without asking, ask always prompts, deny blocks.
- Set the starting mode, any locks, environment variables and the sandbox.
- Read the checks, then copy or download the file and save it where the tool says.
- 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 | Matches | Watch out |
|---|---|---|
| Bash(npm run *) | npm run build, npm run test --watch, and npm run on its own | Bash(npm run*) with no space also matches npm runner |
| Bash(git log * main) | git log --oneline main | Bash(git * main) matches every git subcommand, including git push origin main |
| Read(.env) | any .env at or below the current directory | Read deny rules don’t stop grep -r or a script that opens the file; add the sandbox |
| Read(//etc/hosts) | the absolute path /etc/hosts | In a project file, Read(/etc/hosts) means <project>/etc/hosts: one slash anchors at the project |
| Edit(/src/**) | files under src/ in the project root | Write(src/**) is never checked; Edit rules cover Write too |
| WebFetch(domain:docs.python.org) | fetches from that host only | WebFetch(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
{
"$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
{
"$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.
Related
Related tools
- Claude Code Hooks BuilderBuild and check settings.json hooks, with tested Bash and PowerShell scripts.
- CLAUDE.md GeneratorGenerate a CLAUDE.md and AGENTS.md for your project.
- MCP Config GeneratorBuild MCP server configs for Claude, Cursor, VS Code and Devin Desktop (Windsurf).
- Claude Code Error DatabaseExact Claude Code error messages with tested fixes.
- Model ID ReferenceCopy current API model IDs for Claude, GPT, Gemini and more.
- AI Token CounterCount tokens for GPT, Claude, Gemini, DeepSeek, Qwen and more.
- Context Window CheckerSee whether your text fits each model’s context window.