claude --dangerously-skip-permissions: what it really does, and the safer setup

It is not the all-or-nothing switch everyone describes. Knowing exactly what it still stops is the difference between using it deliberately and using it hopefully.

The kitstarter robot walking through an open gate while one barrier stays down beside it

--dangerously-skip-permissions tells Claude Code to stop asking permission before it runs tools. You add it to the command, the prompts go away, and the agent works uninterrupted. That is the honest one-line answer, and it is why the flag is popular: the prompts are genuinely annoying. But the flag is not a single switch that turns safety off, and almost every article about it says it is. There are documented exceptions that still stop you, and there are rules that keep working even while it is active. Those two facts are the whole post.

What --dangerously-skip-permissions actually does

It sets the permission mode to bypassPermissions. In fact --permission-mode bypassPermissions is the canonical form of the same thing, and the scary-sounding flag is the alias people actually type. In that mode Claude Code skips the routine permission prompts for tool calls and, deliberately, disables its protected-path safety checks. That last part is real and it is the reason for the word dangerously.

What it does not do is switch everything off. Several things still stop the agent even with the flag on, and they are documented, not folklore. This is the table that most pages ranking for this term are missing:

The actionWhat happens with the flag onVerdict
An ordinary tool callA file edit, a normal shell command, a fetch. This is the whole point of the flag: no prompt, it just runs.skipped
Protected-path checksThe safety checks on sensitive paths are switched off by design in this mode. Other permission modes keep them. This is what makes bypass different in kind, not just in volume.skipped
A deny ruleA matching deny rule in settings.json blocks the call anyway. Deny is evaluated in every mode, so it is the one control that survives the flag.still blocks
An explicit ask ruleA matching ask rule still prompts you, in every mode, including this one. So does an MCP tool marked requiresUserInteraction.still asks
rm -rf / and rm -rf ~A circuit breaker still prompts on these specific commands. It is a very short list, not a safety net.still asks
Command substitutionCommands containing $(), backticks, or <() still prompt, because their real content is not knowable until the shell expands them.still asks
Running as root or sudoOn Linux and macOS it refuses to start at all: "--dangerously-skip-permissions cannot be used with root/sudo privileges for security reasons".refuses
The flag is a coarse instrument with a few documented exceptions. Only one row is a control you configure yourself, and it is the deny rule.

Why people reach for it, and why that is reasonable

The case for the flag is better than its critics admit. Approving the same harmless ls for the fiftieth time is not security, it is a ritual. Worse, it is actively corrosive: a prompt you approve reflexively has stopped being a decision. By the time the one dangerous call arrives, you have trained yourself for a month to hit yes without reading. That is not a hypothetical, it is how prompt fatigue works everywhere it exists.

So people who reach for --dangerously-skip-permissions are responding to a real problem. The flag is also genuinely the right call in one situation: a throwaway sandbox or a disposable container where the blast radius is a directory you were going to delete anyway. Claude Code even skips the circuit-breaker prompt automatically inside a recognized sandbox, which tells you what the flag was designed for. The mistake is not using it. The mistake is using it in a repo you care about because the prompts were annoying.

What it actually costs you

Here is the sentence worth keeping. **Skipping permissions removes the prompt without adding any judgment.** The prompt was never the point; the decision behind it was. Silence the prompt and that decision does not move somewhere better, it stops happening. A bad rm -rf or a force-push to shared history now runs with nothing between the agent and your work, and you find out afterwards.

And notice what the exception list above really tells you. The things that still stop you are a handful of hardcoded string patterns. rm -rf / prompts. rm -rf ./src does not. The circuit breaker is not a model of what matters to you, it is a short blocklist of the most famous ways to destroy a machine. Your repo is not on it. Treating that list as a safety net is the actual risk, more than the flag itself.

The kitstarter robot clipping a padlock onto one drawer of a filing cabinet while the drawers above it stay wide open
A deny rule locks the one thing you meant. Everything else stays open.

The safer setup: rules that are specific instead of a switch that is total

The real alternative is not "turn the prompts back on and suffer." It is to answer the permission question once, in writing, so it stops being asked. Claude Code reads a permissions block from settings.json with three lists: allow for what should never prompt, ask for what always should, deny for what must never run. Run /permissions in a session to see the rules you have and which file each one came from.

That is the trade the flag gets wrong. The flag removes every prompt including the ones you wanted. Rules remove only the prompts you have decided about, which is why the fatigue goes away without the judgment going with it. The syntax is Tool(specifier), and these are the forms worth knowing:

Bash(npm run test:*)prefix match, space-boundary enforced. Every npm test command runs without a prompt.
Bash(ls *)matches ls -la, does not match lsof. The space is a word boundary. Bash(ls*) would match both.
Read(./.env)a path relative to the working directory. Gitignore-style syntax, so Read(/src/**) is relative to the settings file's root and Read(//Users/you/secrets/**) is a real absolute path.
Edit(src/**)scope edits to the tree you meant. The most useful single allow rule most projects can write.
WebFetch(domain:example.com)one domain. domain:*.example.com covers subdomains but not the bare domain itself.
mcp__puppeteer__*every tool from one MCP server. Drop the suffix and mcp__puppeteer means the same thing.
Bash(run_in_background:true)parameter matching, available on deny and ask rules only. Handy for the calls you never want fired off unattended.
Seven forms that cover most real projects. Write the four that match your repo and the prompt fatigue that sent you to the flag is mostly gone.

The part the docs are honest about, and most blog posts are not

Bash rules that try to constrain arguments are fragile, and the documentation says so outright. A rule like Bash(curl http://github.com/ *) looks like it restricts curl to GitHub. It does not survive options placed before the URL, a different protocol, a redirect, a variable, or an extra space. Write allow rules for commands you trust, not for arguments you are trying to police. If the question is really "can this argument hurt me", the answer is a deny rule, not a clever allow.

Two more mechanics worth having. Claude Code understands shell operators, so Bash(safe-cmd *) does not green-light safe-cmd && other-cmd: the recognized separators are &&, ||, ;, |, |&, & and newlines, and every subcommand must match a rule on its own. And a few process wrappers are stripped before matching (timeout, time, nice, nohup, stdbuf, bare xargs), while others are not, so npx, docker exec, direnv exec and friends need rules of their own.

So what should you actually do

Four moves, in the order that pays off fastest:

  1. Write the deny rules first. Deny is evaluated in every mode, including bypass, and a deny in any scope beats an allow in any other. It is the only control that still holds if you or a teammate ever reaches for the flag, which makes it the highest-value thing in this whole post.
  2. Allow the boring things by name. Your test command, your build, your linter, your dev server. This is where the prompt fatigue actually comes from, and four Bash(...) allow rules usually remove most of it.
  3. Use auto mode rather than bypass. auto is the documented middle ground: far fewer prompts, but background safety checks still run. If your reason for the flag is "too many prompts", this is the answer to that reason. Set it once as defaultMode instead of typing a flag you will forget you typed.
  4. If it is a team repo, take the flag off the table. disableBypassPermissionsMode set to disable in managed settings blocks the mode outright, and managed settings cannot be overridden by a command-line argument. Managed beats CLI beats local project beats project beats user, in that order.

What we ship, and the one rule behind it

kitstarter takes the same position, in code rather than advice, and the interesting part is that our two PreToolUse hooks make **opposite** calls. clarity.mjs matches file edits and, while a vague build request is still unconfirmed, returns a real permissionDecision: "deny", so the agent physically cannot write code before the goal is agreed. safety-guard.mjs matches Bash, watches for genuinely destructive commands, prints a warning and then gets out of the way. It calls process.exit(0), and its own header says why: a kit that hard-blocks your commands gets uninstalled.

The rule that decides which is which: block where being wrong is expensive and the friction is low, warn everywhere else. Building the wrong feature for twenty minutes costs a lot and asking one question first costs seconds, so that is a hard deny. Shell commands are where real, varied, legitimate work happens, so a hard block there would be a wall between you and your own machine, and it earns a warning instead. Both hooks fail open: if they throw, they stay silent and let the call through, because a safety net that breaks your session is worse than no safety net. That is the same judgment the flag asks you to skip. It is worth making once.

Use --dangerously-skip-permissions in a sandbox you can destroy. In a repo you care about, spend twenty minutes writing deny rules and four allow rules, and the reason you wanted the flag mostly disappears. If you want that thinking already done, it is what kitstarter ships. Worth reading next: the fuller argument on deciding permissions instead of skipping them, where the settings.json file lives, and how hooks enforce a rule the model cannot skim past.

Common questions

What does --dangerously-skip-permissions do in Claude Code? It sets the permission mode to bypassPermissions, so Claude Code stops prompting before routine tool calls and turns off its protected-path safety checks. It is not a total bypass: deny rules, explicit ask rules, MCP tools marked requiresUserInteraction, and a circuit breaker on commands like rm -rf / all still stop the agent.

Is --dangerously-skip-permissions safe to use? In a throwaway sandbox or a disposable container, yes, and that is what it was designed for. In a repo you care about, no. It removes the prompt without adding any judgment, and the things that still stop it are a short list of hardcoded patterns like rm -rf /, not a model of what matters in your project.

What still stops Claude Code when the flag is on? Deny rules and explicit ask rules from settings.json are evaluated in every mode including bypassPermissions. MCP tools marked requiresUserInteraction still prompt. A circuit breaker still prompts on rm -rf /, rm -rf ~, and commands containing command substitution. On Linux and macOS it refuses to start under root or sudo.

What is the safer alternative to --dangerously-skip-permissions? Write permission rules instead of using a switch. Put deny rules in settings.json for what must never run, allow rules for the commands you run constantly, and set defaultMode to auto, which is the documented middle ground with far fewer prompts but background safety checks still running. On a team repo, disableBypassPermissionsMode blocks the mode outright.

Do hooks still run with --dangerously-skip-permissions? The documentation does not state whether PreToolUse hooks execute or can return a deny decision in bypassPermissions mode, so we will not claim either way. What is documented is that deny and ask rules are evaluated regardless of what a hook returns, which is why a deny rule, not a hook, is the control to rely on if the flag might be in play.

Keep the judgment, lose the prompts

kitstarter ships the permission rules, the PreToolUse hooks, and the ask-first clarity lock already tuned, so your agent stops interrupting you over an ls and still stops before the thing you would have regretted. For Claude Code, Codex, and Antigravity.

Get the kit · $20 $29Read the docs