Claude CodeClaude Code 2.1 · terminal and VS Code · macOS, Linux, Windows
Dashboard
0%
1
Curious builder0 XP earned · 300 to level 2
0 daysFinish a lesson to begin
Badge collection0 of 6 unlocked
32 small wins to finish your pathNext lesson →

settings.json

settings.json is a file of allow, ask and deny rules that answer permission prompts once instead of every time.

Last updated: 28 Sep, 2026 · Claude Code

A mode decides how much you are asked in general. Rules decide the specific answers, in a file, once.

Every time you choose allow this kind of thing from now on at a prompt, a rule gets written. Writing them yourself is the same thing without the clicking, and it can be committed so the whole team gets it.

json
{
  "permissions": {
    "allow": [
      "Bash(npm run *)",
      "Bash(git commit *)"
    ],
    "deny": [
      "Bash(git push *)"
    ]
  }
}

Three lists exist: allow never asks, ask always asks even in a permissive mode, and deny refuses outright. The documentation gives the order: rules are evaluated deny, then ask, then allow, and the first match decides. A more specific rule does not jump the queue, which is what makes a deny rule worth writing.

How a rule matches

The pattern is the tool name and, in brackets, what it may do.

RuleMatchesDoes not match
Bash(npm run build)Exactly that commandnpm run build --watch
Bash(npm run *)npm run build, npm run testnpm install
Read(./.env)Reading that file hereA .env in a parent directory
WebFetch(domain:example.com)Fetches to that domainAny other host

The gap worth knowing about is that these are patterns over the command text, not a boundary the operating system enforces, which is the next lesson. Bash(git push *) in the deny list stops git push origin main. It does not stop git -C . push origin main, because that is a different string. The documentation says so directly: permission rules reduce risk but do not form a security boundary.

Deny, then ask, then allow: the first match decides
no matchno matchno matchmatchmatchmatchA Bash callthe command textdeny rulesBash(git push *)ask rulesnone in this fileallow rulesBash(npm run *)The mode decidesnothing matchedRefusedAsks youRuns
Hover or tap a piece to see what it is and which lesson built it.
Trace a command

Pick one to watch it run, step by step.

Where the file goes

FileScope
.claude/settings.jsonThe project. Committed, so everyone gets it
.claude/settings.local.jsonYou, in this project. Gitignored
~/.claude/settings.jsonYou, everywhere
Managed settingsSet by an organisation, and not overridable

A sensible project file is short: allow the commands your team runs a hundred times a day, deny the two or three that should never happen without a person, and leave everything else to the mode.

Start with deny
Deny rules are the ones worth writing first, and they are worth writing even in a team where no one would push or read secrets deliberately. Bash(git push *) and Read(**/.env) cost nothing and prevent two common, costly mistakes.
Try it yourself
  • Add an allow rule for your test command and notice the prompts stop.
  • Add a deny rule for something, then ask Claude to do it and read what happens.

Little by little, you're building something great.