Claude Code keeps asking for permission? Fix it without --dangerously-skip-permissions
Approving npm test for the fortieth time is just noise. Claude Code has everything you need to silence the boring prompts and keep the dangerous ones. It is just spread over three files and six modes.
SHORT ANSWER
Put the commands you always approve in permissions.allow (for example Bash(npm run *)), the ones that must always stop in ask or deny, and choose a permission mode that fits the task: acceptEdits for heavy editing, auto for routine work, plan for reading. Rules are checked deny → ask → allow, so a deny can never be overridden. Use /permissions to see where every rule comes from. Keep --dangerously-skip-permissions for throwaway containers.
Why Claude Code asks so often
In the default mode (labeled Manual in the CLI), Claude Code prompts the first time it uses each tool, and asks again for every shell command it has not been allowed to run. The prompt is the moment you can stop a wrong rm or an accidental git push, so it is worth keeping. The trouble is that it also fires for the hundred harmless things an agent does in a session.
Three things decide whether you see a prompt: the rules in your settings files, the permission mode you are in, and the answers you gave earlier with “Yes, and don’t ask again”. Fixing the noise means tuning all three.
Claude Code v2.1.283 and later starts interactive terminal and VS Code sessions in auto mode, on every plan and provider. In auto mode a background classifier checks commands and network requests against what you asked for, instead of prompting for routine actions. If you are still seeing a prompt for everything, check the status bar: “⏸ manual mode on” means you are in the default mode.
Allow, ask and deny rules
Rules live under permissions in a settings file. This example is straight from Anthropic’s settings reference:
allow: runs without asking.ask: always asks, even in modes that would otherwise approve it.deny: never runs.
The order is the important part: deny, then ask, then allow. The first match wins, and specificity doesn’t change the order. An allow rule cannot carve an exception out of a deny rule, and if a tool is denied at any level, no other level can allow it. Rules are enforced by Claude Code itself, not by the model, so writing “never push” in CLAUDE.md does not do the same thing as a deny rule.
How to write a rule
| Rule | What it matches |
|---|---|
Bash(npm run *) | npm run build, npm run test --watch, but not npm install |
Bash(git log *) | Only git log …. Compare Bash(git *), which allows every git command. |
Bash(ls:*) | Same as Bash(ls *): :* is another way to write a trailing wildcard |
Read(./.env) | Reading that file. Read and Edit rules use gitignore patterns |
Edit(//Users/alice/notes/**) | An absolute path. A single leading / is relative to the settings file, so absolute paths need // |
WebFetch(domain:example.com) | Only example.com. Add WebFetch(domain:*.example.com) for subdomains |
mcp__github__* | Every tool from the github MCP server. Rules with parentheses after mcp__ are skipped |
On Windows, PowerShell rules use the same shape as Bash rules.
Which settings file to use
| Scope | File | Use it for |
|---|---|---|
| User | ~/.claude/settings.json (Windows: %USERPROFILE%\.claude\settings.json) | Your own habits, in every project |
| Project, shared | .claude/settings.json | Rules the whole team should get (commit it) |
| Project, local | .claude/settings.local.json | Your personal rules for one repo (not committed) |
| Managed | managed-settings.json and other managed sources | Company policy; nothing can override it |
Precedence, highest first: managed, command line, project local, shared project, user. List keys such as permissions.allow are combined across files, not replaced. Two details trip people up:
- Settings files are strict JSON: a
//comment or a trailing comma is a syntax error, and the whole file is ignored. - Allow rules in a shared project file only apply after each teammate trusts the folder. Deny and ask rules apply right away.
Most edits apply to the running session without a restart, including permissions and hooks. To see what actually loaded, run /status (the Setting sources line) or /permissions, which lists every rule and the file it came from.
What “Yes, and don’t ask again” really saves
Answering a prompt with “don’t ask again” writes a rule for you in .claude/settings.local.json at the root of the git repository. How long it lasts depends on the tool:
| Tool | Remembered |
|---|---|
| Bash commands | Permanently, per repository and command |
| File edits | Until the session ends |
| WebFetch | Permanently, per repository and domain |
So if Claude keeps asking to edit files every new session, that is by design: file-edit approvals are per session. Use acceptEdits mode or an Edit(...) allow rule instead. And if a command keeps asking even after “don’t ask again”, look for an ask rule in a project or managed file. An allow rule in your local file doesn’t outrank it.
Permission modes, and when to use each
| Mode | What it does | Good for |
|---|---|---|
default (Manual) | Prompts on first use of each tool | Unfamiliar repos, risky work |
acceptEdits | Accepts file edits without asking | Long refactors you will review in git |
plan | Reads and plans, doesn’t change anything | Exploring a codebase, designing a change |
auto | No routine prompts; a classifier checks commands and network requests first | Day-to-day work |
dontAsk | Doesn’t prompt | Scripts and automation |
bypassPermissions | Skips prompts, including writes to .git and .claude | Isolated containers or VMs only |
Press Shift+Tab to cycle modes. From auto, the first press goes to default, then default → acceptEdits → plan. Set a starting mode with permissions.defaultMode; note that auto and bypassPermissions only take effect from user or managed settings, not from a project file.
Some things always prompt, in every mode including bypass: explicit ask rules, questions Claude asks you, and rm on critical paths, among others. Admins can switch the risky modes off with permissions.disableBypassPermissionsMode or permissions.disableAutoMode set to "disable".
About --dangerously-skip-permissions
--dangerously-skip-permissions is the same as --permission-mode bypassPermissions. Anthropic’s docs are blunt: only use it in isolated environments like containers, VMs or dev containers without internet access. It refuses to run as root on Linux and macOS, and once you accept the warning it sets skipDangerousModePermissionPrompt in your user settings.
If what you actually want is “stop asking about boring things”, auto mode plus a few allow rules gets you there without giving up the prompts that matter.
The sandbox: fewer prompts with a safety net
Claude Code can run shell commands in a sandbox. It is off by default; turn it on with /sandbox or sandbox.enabled: true. One sandbox mode approves sandboxed commands automatically, the other still asks. The sandbox covers shell commands only: file tools, MCP servers and hooks run outside it.
It runs on macOS, Linux and WSL2. On native Windows the sandbox doesn’t run, and commands run unsandboxed. That is another reason to keep a short ask list there.
A setup that works
This is a reasonable starting point for a JavaScript project. Adjust the commands to your stack:
- Start with an allow list of read-only and test commands.
- Put anything that leaves your machine (push, publish, deploy) in
ask. - Deny secrets outright.
- Work in auto or acceptEdits, and drop to plan mode when you are exploring.
- Every few days, open
.claude/settings.local.jsonand prune the rules “don’t ask again” added.
When the prompts that remain are in the wrong place
After tuning, you should only be asked about things that deserve a decision. The remaining problem is where the question appears: in a terminal tab behind your browser, where the agent can wait twenty minutes before you notice.
Pet Island moves those questions to a small island at the top of your screen. When Claude Code needs permission, the request appears there with the command or the diff, and you allow, deny or always allow it without switching windows. Claude Code’s questions and plans work from the island too, and if the island is closed, Claude Code simply falls back to asking in the terminal.
FAQ
How do I stop Claude Code from asking permission for every command?
Add the commands you trust to permissions.allow in ~/.claude/settings.json, for example "Bash(npm run *)", and use auto or acceptEdits mode. Keep risky commands in permissions.ask so they still stop.
Why does Claude Code ask again for file edits after I said don’t ask again?
File-edit approvals only last until the session ends. Use acceptEdits mode or an Edit(...) allow rule if you want edits approved across sessions.
Can an allow rule override a deny rule?
No. Rules are checked deny, then ask, then allow, and the first match wins. A tool denied at any level cannot be allowed elsewhere.
Is --dangerously-skip-permissions safe?
Anthropic recommends it only in isolated environments such as containers or VMs without internet access. It also skips prompts for writes to .git and .claude.
Where does “Yes, and don’t ask again” save the rule?
In .claude/settings.local.json at the root of the git repository.
Does the Claude Code sandbox work on Windows?
Not on native Windows; commands run unsandboxed there. It runs on macOS, Linux and WSL2.
Sources
Every setting and behavior on this page was checked against these pages on October 26, 2026. Agents change fast; if something no longer matches, the official page wins.
- Claude Code docs: Configure permissions
- Claude Code docs: Permission modes
- Claude Code docs: Settings
- Claude Code docs: Settings reference
- Claude Code docs: Sandboxing