Claude --dangerously-skip-permissions: What It Does and How to Set Up Permissions Safely
The dangerous permission prompt is usually the convenient one.
Your coding agent asks whether it can run commands without asking again. You are halfway through a bug. You have already approved git status, bun test, and one harmless file read. You click "allow for this session" because confirming every command is annoying, and ten minutes later the agent has enough authority to install a package, read an environment file, send a request anywhere on the internet, and push a branch if you forgot what was in your shell.
Nothing bad may happen. That does not make it a good security model.
claude --dangerously-skip-permissions starts Claude Code in bypassPermissions mode. Permission prompts and safety checks are switched off, so every tool call runs immediately, including writes to protected paths like .git and .claude. Deny rules still apply. Anthropic's docs say to use it only inside isolated containers or VMs.
An agent is not just a text editor with opinions. Once it can act, its effective permission is the combination of every tool you gave it. Read access to the repo plus a shell plus your credentials plus network access is not four small permissions. It may be enough authority to inspect, modify, and send out everything the current user can reach.
The goal is not to make agents useless. The goal is to give them the narrowest set of abilities that completes the task in front of them, then widen it deliberately when the task changes.
What --dangerously-skip-permissions actually does
The flag is the same thing as claude --permission-mode bypassPermissions. Here is what the docs say about the details, checked on October 22, 2026:
- Allow rules stop mattering. Everything is allowed already. Deny rules still block, which is the useful part for the setup later in this post.
-
A few things still prompt. Tools matched by an explicit
askrule,AskUserQuestion, MCP tools that require user interaction, and recognizedrmandrmdirremovals of critical paths. -
Protected paths are writable. In every other mode, writes to
.git,.claude,.bashrcand.mcp.jsonare prompted, routed to a classifier, or denied. Here they just happen. - Plan mode is not enforced. In an interactive terminal session with bypass available, Claude is still told to plan without editing, but an edit or shell command it attempts during planning runs without a prompt.
- Prompt injection gets no extra protection. The docs say the mode offers no protection against prompt injection or unintended actions.
-
You get one warning. The first interactive session shows a dialog asking you to accept responsibility. Accepting sets
skipDangerousModePermissionPrompttotruein~/.claude/settings.json. Declining exits. -
Root is refused. On Linux and macOS, Claude Code will not start in this mode as root or under sudo, unless it detects a recognized sandbox. The error reads
--dangerously-skip-permissions cannot be used with root/sudo privileges for security reasons.
The name is accurate. It is not a faster approval button. It removes the only checkpoint between a confused model and your shell, which is why the rest of this post is about narrowing what that shell can reach.
The permission modes, briefly
Claude Code has six permission modes. You set one at startup with claude --permission-mode <mode>, as a default with permissions.defaultMode in a settings file, or cycle through some of them with Shift+Tab in the terminal.
| Mode | What runs without a prompt | Best for |
|---|---|---|
default (Manual) |
Reads only | Reviewing every action yourself |
acceptEdits |
Reads, file edits and common filesystem commands such as mkdir, touch, mv, cp
|
Iterating on code you are reviewing |
plan |
Reads | Exploring a codebase before changing it |
auto |
Everything, with background safety checks | Long tasks without prompt fatigue |
dontAsk |
Reads in working directories and pre-approved tools. Anything that would prompt is denied | Locked-down CI and scripts |
bypassPermissions |
Everything | Isolated containers and VMs only |
If your problem is prompt fatigue rather than a throwaway environment, look at auto before you reach for the dangerous flag. The docs recommend it when you want far fewer prompts with background safety checks still running. It shows up in the Shift+Tab cycle only when it is available for your account.
When It's Safe: Containers, Worktrees and Throwaway VMs
The docs name the safe place directly: containers, VMs, or dev containers, ideally without internet access, where Claude Code cannot damage your host. I would put it like this.
Safe enough:
-
A container or dev container with only the project mounted. No home directory, no SSH keys, no cloud credentials, and ideally restricted network. This is the setup the docs use in their own example for unattended runs:
claude -p "<prompt>" --dangerously-skip-permissionsinside a container. - A throwaway VM you can delete afterwards, with a scoped token for the one thing it needs.
- CI runners that start clean and hold nothing but the checkout and a scoped credential. See sandboxing AI-generated code execution for the isolation options.
Not safe on its own:
-
A git worktree. Worktrees are great for running parallel Claude Code sessions (
claude --worktree feature-authcreates one under.claude/worktrees/, and my git worktree guide covers the commands). But they isolate file edits and branches, nothing else. The worktree docs are explicit that checks cover edits and git commands, and that a command likecpor a shell redirect is treated like any other shell command under your permissions and sandbox settings. A worktree still runs as you, with your network, your SSH agent and your environment variables. Use worktrees to keep sessions from colliding, not as a security boundary. -
Your daily laptop. Anything reachable by your user is reachable by the agent:
~/.ssh,~/.aws, browser profiles, every repo you have checked out. - A machine where you are logged in to production tooling. One injected instruction plus a logged-in CLI is enough.
If you want a middle ground on your own machine, Claude Code has a built-in OS-level sandbox for shell commands (turn it on with /sandbox or sandbox.enabled). It restricts which files and network domains those commands can reach, on macOS, Linux and WSL2. It covers shell commands only: Claude's file tools, MCP servers and hooks run outside it. That is a real improvement over nothing, and it is not the same as putting the whole process in a container.
The Level 7 rule from the ladder below still applies inside a container: do not put production credentials in there just because the box is disposable. A disposable environment protects your host, not the services your credentials reach.
The Permission Question Nobody Asks
Before enabling an agent, ask one question in a very literal way:
What could it read, change, execute, or send if it made the worst plausible decision while following an untrusted instruction?
That last clause matters. An agent that browses an issue, a webpage, a dependency README, or a support ticket may encounter text that tries to redirect it. It does not need to be a malicious hacker note. A misleading install command or a stale docs page can do enough damage when the agent has broad permissions.
The model cannot reliably infer a safe authorization boundary from the task alone. Research into coding-agent permission boundaries has found the same uncomfortable pattern: models can omit a permission required by a task while also granting unrelated sensitive permissions. More reasoning does not make that tradeoff disappear. Authorization needs to come from policy and tooling, not the agent's confidence.
That is just least privilege, applied to a new kind of collaborator.
The Access Ladder: Least-Privilege Access for Coding Agents
I think about agent access in seven levels. Start at the lowest level that makes the task possible. Move up only when the next level has a clear, named reason.
Level 1: Read the working tree
The agent can inspect the project files, configuration, and relevant logs. It cannot change anything.
This is enough for code review, explaining a system, making a plan, diagnosing a failing build, and locating the likely source of a bug. It is the right default when somebody asks, "What is wrong?" rather than, "Fix it."
The trap at this level is scope. Reading the repository is not the same thing as reading your whole home directory. A project folder often contains more than code: local exports, test fixtures, screenshots, customer samples, and accidentally committed secrets. Mount only the directory the task needs.
Level 2: Edit the working tree
The agent can create and change files inside the project, but it cannot run arbitrary commands.
This is suitable for a content change, a small refactor, a documentation update, or a component you will review manually. It is more powerful than it sounds. File writing can modify configuration, CI workflows, scripts, and code that runs later, so treat it as a real change permission rather than a harmless drafting permission.
Keep package manifests and CI configuration in the review scope even if the task seems unrelated. Dependency changes are code changes with a delayed execution path.
Level 3: Run a constrained local command set
The agent can run the checks that prove its change works: type checking, unit tests, a formatter, a local build, or a narrowly scoped development server.
This is where I draw the first hard boundary. bun run build and bun test are not the same category as an unrestricted terminal. Know which package manager the repository uses. Know what the scripts run. Do not assume a test command is harmless because it has the word test in it. A project script can execute migrations, call a remote service, rewrite snapshots, or do anything else a shell command can do.
Use an allowlist for predictable commands. Let the agent propose everything else. This creates a little friction, and the friction is doing work for you.
Level 4: Local browser and localhost
The agent can open the application it is running, inspect the rendered UI, and test a local flow. It cannot log into external services or browse arbitrary sites.
Visual verification belongs here. A code change that looks right in a diff can be broken in the browser. This level is still local: the agent can test localhost, capture the error, and go back to the source without carrying your authenticated browser profile along with it.
Keep the distinction between local browser access and your daily browser profile. The second one includes every active session you have forgotten about. Your inbox, GitHub, banking tab, billing dashboard, and customer admin panel are not test fixtures.
Level 5: Narrow outbound network access
The agent can reach a listed domain for a concrete reason. Maybe it needs official framework docs, a package registry, or a staging API endpoint.
The right setting is not "internet access". It is an allowlist of domains, methods, and where possible paths. An agent changing a React component does not need the ability to post to Slack, download a binary from an arbitrary release page, or call every service reachable from your laptop.
This is also where you should make a decision about package installation. Dependency installation is remote code execution from a supply chain you did not author. It may be warranted, but it deserves its own approval, a pinned version, and a look at whether a small local utility solves the problem instead.
Level 6: Source control and third-party tools
The agent can create a branch, commit code, open a pull request, read an issue tracker, or call an MCP server.
Give read and write access separately. Reading a GitHub issue does not require pushing to main. Reading a calendar does not require creating an event. Searching a CRM does not require exporting every contact.
This is where tool design becomes access control. In my guide to agent tool design, I argued that tool schemas need to state what they do and when not to use them. Permissions need the same clarity. A tool called manage_repository is a permission accident waiting to happen. create_pull_request_from_current_branch is a much narrower promise.
If a tool offers a write action, make the write target visible before it runs. The model should not be the only place where the difference between reading a record and deleting it exists.
Level 7: Deployments, customer data, and production
The agent can affect real users or access secrets.
This is not a normal default. It should be an exceptional, task-specific permission with a human confirmation at the final boundary. A staging deployment is not production. A read-only production query is not a write. A token that may access one test project is not a token that can access every customer account.
The word "production" hides too much. Break it down into deploy, read logs, read metrics, read data, write data, rotate credentials, and change infrastructure. An agent may need exactly one of those. Giving it the bundle because a dashboard offers one API key is a design failure, not a necessity.
Secrets Are Not Agent Input
The cleanest rule I have found is this: agents need access to a capability, not the secret that represents it.
Do not paste API keys into prompts. Do not let the agent print environment files to prove it found the configuration. Do not attach a production .env to a context window. Once a secret becomes model input, you have widened the exposure from a process boundary to every system that handles the conversation.
Use short-lived, scoped credentials injected into the execution environment. Prefer a service identity that can call one staging endpoint over your own personal token. Rotate the credentials when the task finishes if they were minted for it. Log the action, but never log the secret.
This is less dramatic than it sounds. Most of the time it means creating a narrower token once instead of reusing the convenient admin token forever.
A Permission Set Should Expire
Long-lived approval is where convenience turns into permission creep.
The task that needed package registry access last Tuesday does not prove the next task needs it. The temporary database credential that made a migration review easier does not belong in a reusable configuration. Agents are unusually good at turning a small convenience into a repeated action because they follow the environment we leave behind.
Make permission state part of the cleanup:
- remove temporary tokens
- stop local servers
- revoke network exceptions
- remove copied fixtures containing customer data
- review changed workflow files and package manifests
- record what the agent was allowed to do when it mattered
That last point helps incident response and ordinary debugging. When a surprising change lands, you want to know whether the agent could have made it, not reconstruct the answer from a vague chat transcript.
Claude Code Permissions: A Recommended settings.json
Here is a starting point I would use for ordinary application work, not a copy of any one machine's config. It follows the ladder: reads and local checks are allowed, installs and pushes need a decision, secrets and network downloads are blocked.
{
"permissions": {
"allow": [
"Bash(bun run test *)",
"Bash(bun run typecheck)",
"Bash(bun run lint *)",
"Bash(git status)",
"Bash(git diff *)",
"Bash(git log *)"
],
"ask": [
"Bash(bun add *)",
"Bash(bun install *)",
"Bash(git commit *)"
],
"deny": [
"Read(./.env)",
"Read(./.env.*)",
"Read(./secrets/**)",
"Bash(git push *)",
"Bash(rm -rf *)",
"Bash(curl *)",
"Bash(wget *)"
]
}
}
Save it as .claude/settings.json in the project to share it with the team, or in ~/.claude/settings.json for your own defaults. Swap bun for your package manager and adjust the script names to match your package.json.
A few things to know before you rely on it:
- Order matters. Rules are evaluated deny first, then ask, then allow, and the first match wins. A broad deny can't be carved out by a narrower allow.
-
Deny survives bypass mode. Even with
--dangerously-skip-permissions, deny rules still block. If you must run in bypass mode inside a container, a deny list like this is your remaining safety net. -
The
*placement matters. Put it after the subcommand.Bash(git log *)allowsgit logcommands only, whileBash(git *)allows every git command. -
Bash patterns are not a hard boundary. The docs warn that Bash rules that constrain arguments are fragile, and that a deny on
curldoes not match/usr/bin/curlorsh -c 'curl ...'. For network restrictions that must hold, pair deny rules with the sandbox network allowlist. -
Read deny rules cover Claude's file tools and recognized file commands like
catandhead. They do not stop a script that opens the file itself. A.envyou really need protected should not be on the machine. -
There is no
.claudeignore. Per the docs, it has no effect. UseReaddeny rules. - Precedence is deny-wins across scopes. If user settings allow something and project settings deny it, it is denied. Managed settings sit on top of everything.
For other agents, the same ideas apply even though the syntax differs: allowlist the checks, make installs and pushes explicit, and keep secrets out of reach. Securing AI agents in production goes deeper on the production side.
The Default Setup I Would Use Today
For ordinary application work, I would start an agent with project-only file access, edit permission, a small allowlist of local checks, and localhost browser access. No external browser profile. No arbitrary network. No deployment. No production data. No Git write access until the change has passed review.
Then I would grant more only in response to a need I can name. "It needs to read the official Next.js documentation" is a reason. "It might be useful" is not.
That setup does not prevent every bad outcome. Nothing does. It reduces blast radius, makes approvals meaningful, and keeps one confused instruction from becoming a company-wide event.
An agent that must ask before doing something consequential is not less autonomous in the way that matters. It is working inside a boundary you understand.
Frequently Asked
Is --dangerously-skip-permissions safe? Not on a normal development machine. It turns off permission prompts and safety checks, and the docs say it gives no protection against prompt injection. It is reasonably safe inside a container or throwaway VM that holds only the project and a scoped credential, with deny rules still in place. Anything the agent can reach from there, it can use.
How do I turn off --dangerously-skip-permissions? Exit the session and start Claude Code again without the flag, or with claude --permission-mode default. If you made it the default, remove "defaultMode": "bypassPermissions" from your user settings. To see the warning dialog again, remove skipDangerousModePermissionPrompt from ~/.claude/settings.json. Administrators can block the mode for everyone with "permissions": { "disableBypassPermissionsMode": "disable" } in managed settings, and claude --restricted refuses it (v2.1.248 or later).
What is the difference between --dangerously-skip-permissions and auto mode? Both reduce prompts. Bypass mode removes the checks entirely. Auto mode runs background safety checks on actions and only prompts when needed. Anthropic's docs point to auto mode when you want fewer prompts without giving up the checks.
Do deny rules still work with --dangerously-skip-permissions? Yes. The docs say deny rules still block in bypass mode and allow rules have no effect. Tools matched by an explicit ask rule still prompt too. That is why a deny list for secrets and pushes is worth keeping even in a container.
Why does Claude refuse --dangerously-skip-permissions as root? On Linux and macOS, Claude Code refuses to start in this mode as root or under sudo, because root makes a mistake far more destructive. The check is skipped inside a recognized sandbox. The docs recommend their dev container, which runs as a non-root user.
Should a coding agent have access to my .env file? Usually no. Give it the required capability through a scoped, temporary environment instead. Secrets should not be copied into prompts, logs, or model context.
Is it safe to enable unrestricted terminal commands for a coding agent? Only in an isolated environment with no sensitive files, credentials, or broad network access. In a normal development machine, allow predictable checks and require approval for the rest.
Can I let an agent deploy to production? Only for a tightly defined deployment path with a final human confirmation, scoped credentials, and clear rollback. Deployment access should not imply access to production data or infrastructure administration.
Top comments (0)