# Allow and deny rules: where they live

Course: Claude Code: Pro Level — https://zero2vibecode.com/learn/claude-code-pro
Canonical URL: https://zero2vibecode.com/learn/claude-code-pro/1-2-allow-deny-rules
Verified against: Claude Code v2.1.292 (2026-10-15)
Last updated: 2026-10-15

Permission rules live in settings files, and the file decides who a rule applies to — you everywhere, the whole team, or just you in this project. Deny rules are checked first.

In the last lesson you picked a mode — an overall level of trust. Permission rules are finer: they say which specific actions Claude may take without asking, and which are always off-limits.

## What a rule looks like

Rules live in the `permissions` block of a settings file:

```json
{
  "permissions": {
    "allow": ["Bash(npm test)"],
    "deny": ["Read(./.env)", "Read(./.env.*)"]
  }
}
```

- `allow` — what is fine without asking: here, running `npm test`;
- `deny` — what is never allowed: here, reading `.env` files, where secrets live.

Inside a session, `/permissions` shows the rules currently in force, and `/status` shows which settings files were picked up.

## Which file applies to whom

This is the key point. The same rule means different things in different files:

| File | Applies to | What goes here |
|---|---|---|
| `~/.claude/settings.json` | you, in every project | your personal habits |
| `.claude/settings.json` (committed) | the whole team in the project | shared rules: what must not be read, which commands are allowed |
| `.claude/settings.local.json` (not in git) | you, in this project | your exceptions |
| managed settings | the whole organization | policy that cannot be overridden |

When you answer "Yes, and don't ask again" to a command, the permission is saved in `settings.local.json` — your personal exception, not a team rule.

## Who wins

If one key is set in several files, the higher level wins: managed settings, then the command line, then local, then the shared project file, then user. But **rule lists** — `allow`, `deny` — do not overwrite each other; they add up.

Within the rules, the order is fixed: **first `deny`, then `ask`, then `allow`**, and the first match decides. That is why a deny cannot be accidentally overridden by an allow in another file.

**Careful.** 
The Read(./.env) rule stops Claude's read tools and familiar commands like cat, but not a script that opens the file itself. Closing that gap fully is what the sandbox is for — the next lesson. And none of this makes secrets in the repository safe: .env still does not get committed.

**Practice in the terminal.** Create a .claude folder and put a settings.json in it with the rules: allow Bash(npm test), deny Read(./.env). The JSON is easiest to write on one line with echo inside single quotes.

**Build your own file.** 
In the [settings builder](https://zero2vibecode.com/claude-code-settings-builder?preset=safe), tick what Claude may do without asking and what it may never do, and you get a ready settings.json with a note on every line.
