Field note
Claude Code Permission Prompts: Safe Settings
Constant permission prompts are Claude Code telling you that the allowlist does not match the work, and the fix is a short, specific set of rules rather than a blanket bypass.
Constant permission prompts are Claude Code telling you that the allowlist does not match the work, and the fix is a short, specific set of rules rather than a blanket bypass.
What the prompts are doing
Claude Code uses a tiered system. Reading files inside the working directory needs no approval. Shell commands ask, apart from a built-in set of read-only commands. File edits ask, and a "don't ask again" answer lasts until the session ends. Web fetches ask except for a set of pre-approved documentation domains.
Two facts shape everything else. First, these rules are enforced by Claude Code itself, not by the model, so an instruction in CLAUDE.md cannot grant or remove access. Second, rules are evaluated deny first, then ask, then allow, and the first match wins. A broad deny beats a narrow allow at any level, including project settings against user settings.
The modes and when each is safe
| Mode | What it does | Use it when |
|---|---|---|
default (Manual) | Prompts on first use of each tool | Day one, unfamiliar repositories, anything touching production data |
acceptEdits | Auto-accepts file edits and simple file-system commands in the working directory | You trust the edits and will review the diff before commit |
plan | Reads and explores but does not edit source files | Scoping a task before letting the agent change anything |
auto | A classifier reviews actions against your request instead of prompting | Available to some accounts; try it on a low-risk repository first |
dontAsk | Denies anything that would prompt instead of asking | Unattended runs where you have already allowlisted every needed tool |
bypassPermissions | Skips prompts, including writes to protected paths such as .git | Only inside a container or VM with nothing on it you cannot lose |
Switch modes with Shift+Tab during a session, or set defaultMode in a settings file. Start in plan mode for a new task, move to Manual to make the change, and reserve acceptEdits for repositories where the review gate is already in place.
Build the allowlist from observed commands
- Work in Manual mode for a week and note which prompts repeat. They will be the same handful: the test runner, the linter,
git status,git commit. - Open
/permissions. It lists every rule and the settings file each one came from, and changes apply from the next tool call. - Write rules for the exact commands you saw, with
*after the subcommand.Bash(npm run *)allows every npm script;Bash(git commit *)allows commits but not pushes. A rule with no*matches one exact command. - Add deny rules for the paths and actions the agent should never touch:
Read(./.env),Read(./secrets/**),Bash(git push *). AReaddeny also blocks edits and creation on that path. - Put team rules in
.claude/settings.jsonand commit it. Personal overrides go in.claude/settings.local.json, which stays out of git. Allow rules in the committed file apply only after each person accepts the workspace trust dialog for that folder.
A starting file for a Node project looks like this:
{
"permissions": {
"allow": ["Bash(npm run *)", "Bash(npm test *)", "Bash(git status)", "Bash(git diff *)", "Bash(git commit *)"],
"deny": ["Bash(git push *)", "Read(./.env)", "Read(./.env.*)", "Read(./secrets/**)"]
}
}
Expect to add a few rules in the first fortnight and then stop. If the list keeps growing, the agent is doing work the team has not agreed it should do.
What the admin should lock
For a business with several developers, some settings belong in managed settings that no user or project file can override:
permissions.disableBypassPermissionsModeset to"disable"so nobody can switch off prompts on a laptop that holds customer data.permissions.disableAutoModedoes the same for the classifier mode.allowManagedPermissionRulesOnlywhere the organisation, not the repository, must own the permission rules.- A deny list for reading credential files and for network commands that should not run from an agent session.
- Sandboxing where the platform supports it, which enforces file-system and network boundaries independently of the command text.
Managed settings have the highest precedence; a managed deny cannot be overridden by a flag or a project file. Deploy them through device management, then run /status on a developer machine to confirm the source shows as managed.
Signs the settings are wrong
- The same command still prompts. Usually the
*is in the wrong place. Claude Code matches everything before the first*literally, soBash(git * main)does not do what people expect. - An allow rule is ignored. A deny or ask rule at another level matches first.
/permissionsshows which file it came from. - A push written differently gets through. Bash rules match the command as written, so
git -C . pushis notgit push *. Use aPreToolUsehook for controls that must not depend on spelling. - Prompts vanish entirely. Someone started the session in bypass mode. Check which mode the session began in and whether managed settings should forbid it.
Permission rules answer "may the agent do this?"; they do not answer "should a person approve this?". The approval versus permission note draws that line, and our Claude Code workshop sets both up on your repository.