Claude Code permissions: settings.json allow, ask, deny
Claude Code reads its permission rules from .claude/settings.json. Tick what the agent may do without asking, what it must ask about, and what it must never touch. The page writes the file for you. It runs in your browser and sends nothing.
Your settings file
Save it as .claude/settings.json in the project. If the file exists, add the permissions block to it. Claude Code reloads the file when it changes. The start mode applies to new sessions.
5 allow, 2 ask and 33 deny rules.
{
"$schema": "https://json.schemastore.org/claude-code-settings.json",
"permissions": {
"allow": [
"Bash(npm run *)",
"Bash(npm test *)",
"Bash(git add *)",
"Bash(git commit *)",
"WebSearch"
],
"ask": [
"Bash(git push *)",
"Bash(npm publish *)"
],
"deny": [
"Read(.env)",
"Edit(.env)",
"Read(.env.*)",
"Edit(.env.*)",
"Read(secrets/**)",
"Edit(secrets/**)",
"Read(*.pem)",
"Edit(*.pem)",
"Read(*.key)",
"Edit(*.key)",
"Read(~/.ssh/**)",
"Edit(~/.ssh/**)",
"Read(~/.aws/**)",
"Edit(~/.aws/**)",
"Read(~/.config/gcloud/**)",
"Edit(~/.config/gcloud/**)",
"Read(~/.kube/**)",
"Edit(~/.kube/**)",
"Read(~/.netrc)",
"Edit(~/.netrc)",
"Read(~/.npmrc)",
"Edit(~/.npmrc)",
"Read(~/.git-credentials)",
"Edit(~/.git-credentials)",
"Read(~/.config/gh/**)",
"Edit(~/.config/gh/**)",
"Read(~/.zsh_history)",
"Edit(~/.zsh_history)",
"Read(~/.bash_history)",
"Edit(~/.bash_history)",
"Bash(sudo *)",
"Bash(git push --force *)",
"Bash(git push -f *)"
]
}
}
allow, ask, deny and defaultMode
The permissions block in .claude/settings.json holds three lists of rules and a start mode. A rule is a tool name, or a tool name with a pattern in brackets: Bash(npm run test *), Read(./.env), WebFetch(domain:docs.python.org). Deny wins over ask, and ask wins over allow.
allow
Claude Code uses these without asking. Bash(npm run test *) runs npm run test with any arguments. Bash(npm run test:*) means the same. In a project file, allow rules take effect only after you accept the trust dialog for the folder.
ask
Claude Code asks you each time, even when an allow rule matches too. Use it for commands that are fine sometimes but leave your machine, such as Bash(git push *) or Bash(npm publish *).
deny
Claude Code never does these, and no allow or ask rule opens them again. Read(./.env) blocks the .env file in the project folder; Read(.env) blocks every .env at or under the project folder. A bare tool name such as WebFetch removes the tool.
defaultMode
The permission mode a new session starts in. A project's settings can set:
default: ask before edits and commands.acceptEdits: edit files and runmkdir,mvand the like in the project without asking; still ask before other commands.plan: read and plan, no edits.dontAsk: never ask; refuse anything that would need your yes.
bypassPermissions skips every prompt, except the few actions no mode auto-approves. auto and bypassPermissions do not take effect from a project's settings or settings.local.json: set them in ~/.claude/settings.json, or start Claude Code with --permission-mode. "disableBypassPermissionsMode": "disable" stops anyone from starting the project in bypass mode.
A full settings.json example
A project where Claude Code edits files and runs the tests on its own, asks before it pushes or publishes, and never touches secrets:
{
"$schema": "https://json.schemastore.org/claude-code-settings.json",
"permissions": {
"defaultMode": "acceptEdits",
"allow": [
"Bash(npm run test *)",
"Bash(npm run lint)",
"Bash(git diff *)",
"Bash(git commit *)",
"WebFetch(domain:docs.python.org)"
],
"ask": [
"Bash(git push *)",
"Bash(npm publish *)"
],
"deny": [
"Read(./.env)",
"Edit(./.env)",
"Read(secrets/**)",
"Edit(secrets/**)",
"Read(~/.ssh/**)",
"Edit(~/.ssh/**)",
"Bash(sudo *)"
],
"disableBypassPermissionsMode": "disable"
}
}
How the rules work
- Commands match the command text Claude Code is about to run. Claude Code splits
&&,;and pipes, and every part must match on its own. A trailing*also matches the bare command:Bash(npm test *)coversnpm test. - Paths follow
.gitignorepatterns. A bare file name like.envmatches at any depth under the project folder.~/.ssh/**is in your home folder./src/**issrcin the project, not on the disk root; write//for that.
What these rules do not stop
The rules bind Claude Code's own tools and the shell commands Claude Code recognizes, such as cat and sed. They do not bind a program that opens files by itself. A Python script can still read a denied .env. A deny rule for curl * does not stop /usr/bin/curl or sh -c 'curl …', and one for git push --force * does not stop git push origin main --force. For a hard limit on files and network, turn on Claude Code's sandbox. It applies the same limits to every command at the operating system level.
With Angelia
Angelia runs Claude Code for each WhatsApp or Telegram chat, in that chat's own profile folder. It writes the deny rules for you: angelia compile <profile> --write puts them into the profile's .claude/settings.json.
- Every profile is denied, for reading and editing: your credential folders and files (
~/.ssh,~/.aws,~/.gnupg,~/.config/gh,~/.netrc,~/.npmrc, shell history and more); Angelia's own secrets; each CLI's transcripts; the other profiles' folders. A credential folder stays open only to a profile whoseadd_dirsnames it. - A skill or MCP server the profile may not use is denied too. A denied skill is also taken out of the profile's skills folder, because a deny rule does not stop a skill typed as
/name. Angelia removes only the links it made there; a denied skill you put there by hand stops compile until you move it. - Angelia changes only the entries it wrote. Your own rules in the same file stay.
- Angelia starts no agent for a profile that was never compiled, or whose compiled deny rules were removed since.
- The same limit applies: the rules hold the file tools, not every program.
sandbox: trueon a profile turns on Claude Code's sandbox for it.
Sources
- Configure permissions, Claude Code docs: rule syntax, order, path patterns, limits.
- Claude Code settings: where the files live and how they combine.
- Settings reference, permission settings: every key under
permissions.
Checked against the docs on 30 October 2026. Claude Code changes often. If a rule behaves differently, the docs win.
Try Angelia
curl -fsSL https://useangelia.com/install | sh
It checks the release's signature, then a wizard pairs your first chat. Free and open source (MIT). How it works · Security model · GitHub