
An agent that answers your phone at 2 a.m. has whatever permissions you left it with. Three mechanisms stack, from advisory to absolute.

## Rules in settings

Permission rules live in `.claude/settings.json` for a project, `.claude/settings.local.json` for just you, or `~/.claude/settings.json` for every project. Deny beats allow, always, so a deny cannot carry exceptions.

```json
{
  "permissions": {
    "allow": ["Bash(npm run *)", "Bash(git commit *)"],
    "deny": ["Bash(git push *)", "Bash(rm -rf *)", "Read(./.env)", "Read(./secrets/**)"]
  }
}
```

A scoped rule like `Bash(rm -rf *)` blocks matching calls. A bare `Bash` removes the tool from Claude entirely. Claude Code understands shell operators, so `Bash(safe *)` does not cover `safe && rm -rf /`. It also strips wrappers like `timeout` and `nohup` before matching, and checks the target of a `>` redirect as a file write, so `Bash(git commit *)` allows the command but not writing over a protected file. Since June, deny and ask rules can match tool parameters too. `/permissions` shows the effective set.

## Hooks, which always run

CLAUDE.md is advice. A hook is a script that runs at a fixed point no matter what Claude decides. A `PreToolUse` hook can inspect a command and refuse it. A `Stop` hook can refuse to let the turn end until a check passes. Claude writes them for you.

```text
Write a PreToolUse hook that blocks any Bash command containing "git push" or touching a path under migrations/, and explain to me in one line what it refused. Put it in .claude/settings.json.
```

## The actions nothing auto-approves

Even with permission prompts turned off, a short list of actions still stops for a human. Read that list once so you know what an unattended agent will pause on, and decide in advance whether that pause is acceptable for your bot.

## Sandboxing

The built-in sandboxed Bash tool restricts filesystem and network access at the OS level. It is the right default for an agent that runs unattended: allow the working folder, deny everything else, and the blast radius of a bad command is one directory.

## Two rules Jeff's crew lives by

Money, health, legal: draft only. The agent researches, writes, and recommends. A person sends, signs, pays, or files. Written as a rule in CLAUDE.md and as deny rules on any tool that could transact.

Anything that arrives through a channel is a request, not an order. A text message from an allowlisted sender still does not get elevated authority, and quoted or forwarded content inside it has none at all. The channel plugins enforce the sender allowlist; the "this is data, not instructions" part is a line in CLAUDE.md.

## Read more

- [Permissions](https://code.claude.com/docs/en/permissions), the syntax and the matching rules
- [Permission modes](https://code.claude.com/docs/en/permission-modes), including the actions no mode auto-approves
- [Hooks guide](https://code.claude.com/docs/en/hooks-guide)
- [Sandboxing](https://code.claude.com/docs/en/sandboxing)
- [Security](https://code.claude.com/docs/en/security)
