The old advice that “Claude Code asks before it edits files” is no longer true by default. On Pro, Max and Team plans, interactive terminal sessions start in auto mode, where a classifier reviews actions instead of you and Claude edits most files and runs most commands without a prompt. On other plans, Manual mode is the starting point.
1. Check the mode you’re in
The status bar names it: ⏸ manual mode on, ⏵⏵ accept edits on, ⏸ plan mode on,
⏵⏵ auto mode on, ⏵⏵ bypass permissions on.
2. Cycle with Shift+Tab
From auto the first press goes to default, then the cycle runs
default → acceptEdits → plan → back to default.
default(labeled Manual) — prompts on first use of each tool.acceptEdits— accepts edits and common filesystem commands in your working directory.plan— explores but doesn’t edit. See plan mode.auto— auto-approves with background safety checks.bypassPermissions— skips prompts. Containers and VMs only.
Set the starting mode with defaultMode in a settings file, or --permission-mode at launch.
3. Write rules that match
Rules are Tool or Tool(specifier). Memorize the wildcard trap: put the * after the
subcommand. Bash(git log *) allows only git log; Bash(git *) allows every git command,
git push included.
{
"permissions": {
"allow": ["Bash(npm run *)", "Bash(git commit *)", "Read", "Edit"],
"deny": ["Bash(rm *)", "Read(./.env)", "Read(./.env.*)"]
}
}
What it does: pre-approves npm scripts, commits and file access; refuses every rm and any
read of your env files. Bash(ls:*) is another way to write Bash(ls *).
Note the deny rule is Bash(rm *), not Bash(rm -rf *): a narrower one is sidestepped by any
other flag. Read and Edit rules use gitignore syntax, so Read(.env) matches at any depth.
4. Check what’s actually loaded
/permissions
What it does: lists every rule and the settings file it came from, and lets you add or remove one mid-turn. Which file to use is covered in Claude Code settings.json.
Verify it worked
Ask Claude to run one command you denied. It should refuse without prompting. If it asks
instead, your rule didn’t match — rules are enforced by Claude Code, not by the model, so no
amount of CLAUDE.md text changes what’s allowed. Real permissions
beat instructions every time.
Next: work across a whole repo safely.
Source: Configure permissions.