# Permission modes

Six modes decide how much Claude may do without asking. Pick the mode by what a mistake would cost, and put hard rules where the harness enforces them.

## One dial, six positions

Every session runs in one of six permission modes: `default`, `acceptEdits`, `plan`, `auto`, `dontAsk` and `bypassPermissions`. In the terminal, `Shift+Tab` cycles through default, acceptEdits and plan. Bypass appears in that cycle only if it was enabled at launch, and dontAsk never appears there.

You can also start in a mode with `--permission-mode <mode>`, or set `permissions.defaultMode` in settings. The question behind the dial is simple: how much do you want to be interrupted, and what happens if Claude is wrong?

## What each mode really allows

- `default` is the Manual mode. Claude reads freely, and asks before editing or running commands.
- `acceptEdits` approves file edits without asking. It also auto-approves `mkdir`, `touch`, `rm`, `rmdir`, `mv`, `cp` and `sed` inside the working directory. Note `rm` on that list.
- `plan` lets Claude read and propose. Edits stay blocked until you approve the plan.
- `auto` hands the decision to a classifier model that reviews each non-trivial action. The default classifier is Claude Sonnet 5.
- `dontAsk` is meant for unattended scripts, paired with `--allowedTools`.
- `bypassPermissions` skips prompts. Run it only in disposable containers.

Some paths stay protected even when edits are auto-approved: `.git`, `.claude`, `.vscode`, `.idea`, shell rc files and `.mcp.json`, among others, are never auto-approved for writes except in bypass.

**Question:** You switch to acceptEdits to move faster. What else becomes automatic inside the working directory?

- Nothing, only file edits
- Commands such as mkdir, rm, mv, cp and sed
- Every Bash command
- Network requests

**Answer:** Commands such as mkdir, rm, mv, cp and sed. acceptEdits also auto-approves a set of file commands including rm and sed inside the working directory, not only edits.


## Judgment versus a wall

Auto mode is the one to understand carefully, because it feels like a wall and is not one. A classifier makes a judgment on each action. Three consecutive blocks, or twenty in total, pause it and prompting resumes. Entering auto mode also drops blanket allow rules such as `Bash(*)`, while narrow ones such as `Bash(npm test)` stay.

Boundaries you state in chat, like "don't push", act as signals to the classifier. They are not stored as rules, so compaction can drop them. For a rule that must always hold, write a deny rule or a hook. Deny rules apply in every mode, including bypass, and allow rules have no effect in bypass.

Examples of rule syntax from the guide: `Bash(git push *)` and `Read(./.env)`. A `Read` deny also catches `cat .env`, but not a script that opens the file. That gap is what `/sandbox` closes with OS-level confinement.

> **Defaults differ by surface**
New terminal and VS Code sessions start in auto mode. `claude -p` and the Agent SDK default to `default` mode. A project settings file that sets `defaultMode` to `auto` or `bypassPermissions` is silently ignored; only user or managed settings honour it.


## How to pick

Start from the cost of a mistake, not from your patience.

- Unfamiliar repo, or a change near anything irreversible: `default`, and read each prompt.
- A refactor you will review in `/diff` afterwards: `acceptEdits`.
- A task where you want to agree on the approach first: `plan` (next lesson).
- Long work where prompts are the bottleneck: `auto`, with deny rules for what must never happen.
- A script with no human: `dontAsk` with a tight `--allowedTools`.

If prompts annoy you, fix the cause instead of loosening the mode. `/fewer-permission-prompts` scans your transcripts and writes a read-only allowlist to `.claude/settings.json`, and `/permissions` has a "Recently denied" tab where `r` retries a blocked action.

> **Narrow beats broad**
`Bash(pnpm tsc --noEmit)` as an allow rule removes a prompt you see every hour without opening the door to every command.


**Question:** You need a guarantee that Claude never runs git push. Where do you put it?

- Say it in chat
- Write it in CLAUDE.md
- Add a deny rule such as Bash(git push *)
- Use auto mode

**Answer:** Add a deny rule such as Bash(git push *). Chat boundaries and CLAUDE.md are judgment and can be lost. A deny rule is enforced in every mode.
