Claude Code permissions, explained: modes, sandbox and --dangerously-skip-permissions
We make AI Bridge, a Mac app that runs these command-line agents side by side. We do not sell any of them, are not affiliated with their makers, and none of them paid for or reviewed this guide. We use them every day.
The six permission modes
The modes run from Manual, which asks before almost everything, to bypassPermissions, which asks before almost nothing. The mode sets the baseline; your allow, ask and deny rules sit on top of it.
| Mode (config value) | What runs without asking | Best for |
|---|---|---|
Manual (default) | Reads only | Sensitive work, unfamiliar code |
acceptEdits | Reads, file edits, and mkdir, touch, rm, mv, cp and sed inside your working directory | Iterating on code you review afterwards with git diff |
plan | Reads and exploring; no edits to your source until you approve a plan | Understanding a codebase before changing it |
auto | Everything, with a classifier checking risky actions first | Long tasks with fewer interruptions |
dontAsk | Reads and pre-approved tools; anything that would prompt is refused | CI and scripts |
bypassPermissions | Everything, apart from a short list of checks no mode skips | Isolated containers and VMs only |
The mode that asks first is labelled Manual in the CLI and the editors; its config value is still default, and manual works as an alias. Note that accept-edits mode also approves rm inside your working directory.
Some things hold in every mode:
- Deny rules block, including in
bypassPermissions. - Some actions are never auto-approved: anything an explicit ask rule names,
rmorrmdiraimed at a critical path such as your home directory or the project folder, and tools that need you to answer a question. - Protected paths such as
.git,.claude,.vscode,.mcp.jsonand your shell profiles are never written without a check, except inbypassPermissions.
How to switch modes and set a default
Press Shift+Tab to cycle modes in a running session, pass --permission-mode when you start one, or set permissions.defaultMode in a settings file to change where sessions start.
From auto, the first Shift+Tab goes to Manual, then accept edits, then plan, then back to auto. The status bar says which you are in: ⏸ manual mode on, ⏵⏵ accept edits on, ⏸ plan mode on or ⏵⏵ auto mode on. dontAsk never appears in the cycle, and bypassPermissions appears only if the session was started with it enabled.
claude --permission-mode plan
claude --permission-mode default # Manual
claude --permission-mode acceptEditsTo make every session on your machine start in Manual, put this in ~/.claude/settings.json:
{
"permissions": {
"defaultMode": "default"
}
}A repository can’t start you in bypass
A project’s .claude/settings.json can set any starting mode except two: Claude Code ignores auto and bypassPermissions there, so a repository you clone cannot put you into bypass mode. If you want auto as your own default, set it in ~/.claude/settings.json. The VS Code extension reads its own setting, claudeCode.initialPermissionMode, which doesn’t accept auto.
Auto mode, the starting mode since late September 2026
In auto mode a second model, the classifier, reviews each action that could do damage before it runs, instead of asking you. It is now where new terminal and VS Code sessions start when nothing else sets a mode.
The sources disagree slightly on when: Claude Code’s changelog lists the change in version 2.1.284 on 28 September 2026, while the permission-modes page names 2.1.283. Either way, if you updated in the last few weeks and stopped seeing prompts, this is why.
Reads and edits inside your working directory are approved straight away. Shell commands, network requests and everything else go to the classifier. By default it blocks, among others:
- downloading and running code, such as
curl | bash; - force pushes, production deploys and migrations, and sending secrets to outside endpoints;
git reset --hard,git clean -fdand other commands that discard uncommitted work;terraform destroyand similar teardown of infrastructure;- starting another agent loop without approval or a sandbox, for example one launched with
--dangerously-skip-permissions.
It allows local file work, installing the dependencies your lock files declare, read-only HTTP requests and pushing to branches of the repository you are in. A blocked action shows a notice and lands in the Recently denied tab of /permissions, where r retries it with your approval. After three blocks in a row, or twenty in a session, auto mode pauses and Claude Code goes back to asking you.
Two details catch people out:
- Broad allow rules are set aside. On entering auto mode, rules that amount to “run anything”, such as
Bash(*),Bash(python*)or package-manager run commands, stop applying until you leave it. Narrow rules such asBash(npm test)keep working. - Boundaries you state are not stored. Telling Claude “don’t push” makes the classifier block pushes, but it rereads that from the conversation each time, and context compaction can drop the message. For a guarantee, write a deny rule.
Anthropic’s own warning is worth taking at face value: auto mode “reduces permission prompts but does not guarantee safety.” If auto mode isn’t available to a session (an unsupported model, or an organisation that switched it off), the session starts in Manual instead.
Allow, ask and deny rules
Rules live under permissions in a settings.json file, written as Tool or Tool(specifier). Claude Code checks deny first, then ask, then allow; the first match wins, however specific the others are.
{
"permissions": {
"allow": [
"Bash(npm run *)",
"Bash(git commit *)"
],
"ask": [
"Bash(git push *)"
],
"deny": [
"Read(**/.env)",
"WebFetch(domain:pastebin.com)"
]
}
}| Rule | Matches |
|---|---|
Bash | Every shell command (as a deny rule, it removes the tool entirely) |
Bash(npm run build) | Exactly npm run build, not npm run build --watch |
Bash(npm run *) | npm run build, npm run test --watch and a bare npm run |
Bash(ls *) / Bash(ls*) | ls -la but not lsof / both: the space is part of the rule |
Read(**/.env) | Any .env at or below the current directory |
Edit(/src/**) | Files under the project’s src/ when the rule is in project settings: one leading slash anchors at the settings source, not the filesystem root |
Read(//Users/me/secrets/**) | An absolute path: two slashes |
WebFetch(domain:example.com) | Fetches to example.com (add *.example.com for subdomains) |
mcp__github__* | Every tool from the MCP server named github |
The rules that matter most in practice:
- Put the star after the subcommand.
Bash(git log *)allows onlygit log;Bash(git *)allows every git command, includinggit -c, which can run a program you name. - Compound commands are split. An allow rule must match every part, so
Bash(npm test *)doesn’t approvenpm test && curl …. A deny or ask rule fires if any part matches, even inside$(…). - A Bash rule matches text, not programs. A deny on
Bash(rm *)stopsrm -rf build/but not/bin/rm -rf build/orbash -c 'rm -rf build/'. The docs say plainly that these rules aren’t a security boundary; the sandbox is. - Read denies reach further than Read. A Read deny also blocks Edit and Write on that path, and file commands Claude Code recognises in Bash such as
catandhead. It doesn’t stop a Python or Node script that opens the file itself.
/permissions lists every rule and the file it came from, and you can edit them there mid-session. Choosing “Yes, and don’t ask again” on a prompt saves an allow rule to .claude/settings.local.json at the repository root; a file-edit approval lasts only until the session ends.
Which settings file wins
Five places can hold permissions. For a single value, such as the starting mode, the highest one wins; rule lists from all of them are merged, and a deny anywhere beats an allow anywhere.
- Managed settings, deployed by your organisation. Nothing below can override them.
--settingson the command line, for that one session..claude/settings.local.json: you, in this project, kept out of git..claude/settings.json: the team’s, checked into the repository.~/.claude/settings.json: you, in every project.
Because deny rules are evaluated before allow rules from every scope, a project-level deny blocks your personal allow, and your personal deny blocks the project’s allow. The same goes for ask: an allow you saved with “don’t ask again” can’t outrank an ask rule from the project or your organisation, which is a common reason a prompt keeps coming back.
Allow rules in a project’s .claude/settings.json grant power, so Claude Code applies them only after you accept the workspace trust dialog for that folder. Deny and ask rules apply straight away, since they only restrict.
The sandbox: /sandbox, Seatbelt and bubblewrap
The sandbox is a boundary the operating system enforces around the shell commands Claude runs: it limits where they can write and which hosts they can reach. It is off by default; turn it on with /sandbox or "sandbox": { "enabled": true } in a settings file.
On macOS it uses Seatbelt, which is built in. On Linux and WSL2 it needs bubblewrap and socat; the /sandbox panel says if either is missing. On native Windows, commands run unsandboxed.
| Access | Default |
|---|---|
| Writes | The working directory, a per-user temp directory and directories you added |
| Reads | Most of the machine, including ~/.ssh and ~/.aws/credentials |
| Network | Only through a local proxy that checks each host; the allowed list starts empty |
| Environment | Inherited from Claude Code, secrets included |
Three things to understand before relying on it:
- It covers shell commands only. Claude’s own Read, Edit and WebFetch tools follow your permission rules instead, and hooks, MCP servers and your status line run with your full access.
- It has two modes. Auto-allow runs sandboxed commands without a prompt, even in Manual mode; deny rules, content-specific ask rules such as
Bash(git push *)and critical-path removals still apply. Regular permissions keeps every prompt. - There is an escape hatch. When a command fails inside the sandbox, Claude can retry it unsandboxed. In Manual mode you are asked; in auto mode the classifier decides. Set
"allowUnsandboxedCommands": false(Strict sandbox mode in the panel) to remove the option.
There is no built-in credential deny list, so name the files and variables you want hidden:
{
"sandbox": {
"enabled": true,
"credentials": {
"files": [
{ "path": "~/.ssh", "mode": "deny" },
{ "path": "~/.aws/credentials", "mode": "deny" }
],
"envVars": [
{ "name": "GITHUB_TOKEN", "mode": "deny" }
]
}
}
}What --dangerously-skip-permissions does
--dangerously-skip-permissions starts Claude Code in bypassPermissions mode: no permission prompts, including for writes to .git and .claude. It is meant for containers and VMs where nothing Claude does can hurt you.
It is the same as claude --permission-mode bypassPermissions, and is often called YOLO mode; Codex’s equivalent flag even has --yolo as its alias. A few things survive it:
- deny rules still block, and explicit ask rules still prompt;
rmorrmdiraimed at a critical path (the filesystem root, your home directory, the working directory and its parents) still asks, with a two-minute countdown that denies the command if nobody answers;- a
PreToolUsehook that returnsdenystill blocks the call; - Claude Code refuses to start in this mode as root or under sudo, outside a recognised sandbox.
The first time you use it interactively, Claude Code shows a warning you have to accept, then records that in ~/.claude/settings.json. You can’t switch into bypass mid-session unless you started with it, or with --allow-dangerously-skip-permissions, which adds it to the Shift+Tab cycle without turning it on.
When it is reasonable
Inside something you can throw away: a container or VM, running as a non-root user, holding no credentials you would mind losing and with limited network access. Anthropic’s dev container configuration exists for exactly this, and its docs give this pattern for unattended runs:
# inside the container, never on your own machine
claude -p "Upgrade the test dependencies and fix what breaks" --dangerously-skip-permissionsOn your own Mac it is hard to justify. Anthropic’s docs say the mode “offers no protection against prompt injection or unintended actions”: a README, an issue or a web page that tells Claude to run something gets run. If the prompts are the problem, auto mode, the sandbox in auto-allow mode, or a short allowlist removes most of them without that exposure. To make sure you never reach for the flag by habit, lock it out in your own settings:
{
"permissions": {
"disableBypassPermissionsMode": "disable"
}
}A sensible starting policy
Pre-approve the commands you run all day, make pushes ask, deny reads of secrets, and turn the sandbox on. That removes most prompts without widening what Claude can reach.
{
"permissions": {
"allow": [
"Bash(npm test)",
"Bash(npm run lint)",
"Bash(npm run build)",
"Bash(git commit *)"
],
"ask": [
"Bash(git push *)"
],
"deny": [
"Read(**/.env)",
"Read(**/.env.*)",
"Read(**/secrets/**)"
],
"disableBypassPermissionsMode": "disable"
},
"sandbox": {
"enabled": true,
"credentials": {
"files": [
{ "path": "~/.ssh", "mode": "deny" },
{ "path": "~/.aws/credentials", "mode": "deny" }
]
}
}
}- Narrow allow rules keep working in auto mode, where broad ones are set aside. Swap in your own test, lint and build commands.
- An ask rule on push prompts in every mode, auto and bypass included, so a push always comes back to you.
- The deny rules keep Claude’s file tools out of secrets at any depth.
Read(**/.env.*)also hides.env.example; drop it if you want Claude to read that. - The sandbox covers what the rules can’t: a script that opens a file itself, or a command written in a form your rules don’t match.
Put it in ~/.claude/settings.json to apply it everywhere, or in a project’s .claude/settings.json to share it with your team. Then leave sessions in auto, and press Shift+Tab for Manual when the work is sensitive. If you also want an alert when an agent is waiting on you, that is a hook: see Claude Code hooks, explained.
Headless runs: dontAsk and an exact allowlist
In claude -p nobody can answer a prompt, so anything that would ask is refused. Say so explicitly with --permission-mode dontAsk, and list exactly what the run may do with --allowedTools.
claude -p "Run the test suite and summarise the failures" \
--permission-mode dontAsk \
--allowedTools "Bash(npm test)" "Read"- Always pass a mode. A run with none takes the built-in starting mode, which can be auto.
--disallowedToolsadds restrictions on top of your settings, and--permission-prompts nonetells Claude that nobody can approve a request, so it doesn’t keep retrying.- Watch what the repository brings. A
-prun shows no trust dialog, so it runs the hooks in a project’s.claude/settings.jsonand connects the servers in its.mcp.json, even in a folder you never trusted. In a repository you didn’t write, start with--bare, or pass--setting-sources user.
Seen first-hand
In our own headless runs, a deny always beat an allow that matched the same call, whichever flag or settings file each came from. That matches the documented order, and it shapes how you write a CI allowlist: you can’t open a hole in a deny with a narrower allow, so keep the deny list short and specific.
How Claude Code, Codex, Grok Build and OpenCode compare
Codex is the only one of the four with an operating-system sandbox on by default. Claude Code starts in classifier-reviewed auto mode, Grok Build asks first, and OpenCode allows most things until you configure it.
| Claude Code | Codex CLI | Grok Build | OpenCode | |
|---|---|---|---|---|
| Starts in | Auto: a classifier reviews risky actions | Workspace writes allowed; asks to leave the workspace or use the network | Ask: prompts for anything not already allowed | Permissive: most tools allowed; asks for outside paths and repeated identical calls; denies .env reads |
| OS sandbox | Off; /sandbox (Seatbelt, bubblewrap), shell commands only | On, network off | Off; --sandbox workspace (Seatbelt, Landlock) | None documented |
| Rules | Allow, ask, deny; deny wins whatever the order | Sandbox mode plus approval policy | Allow, deny; deny wins | Allow, ask, deny; the last matching rule wins |
| Switch in a session | Shift+Tab | /permissions | Shift+Tab | Command palette |
| Skip every prompt | --dangerously-skip-permissions (deny rules still apply) | --dangerously-bypass-approvals-and-sandbox, alias --yolo (no sandbox either) | --always-approve (deny rules and PreToolUse hooks still apply) | --auto (explicit denies still apply) |
The rule order is the difference to watch if you carry a policy from one tool to another. In Claude Code and Grok Build a deny wins wherever it sits; in OpenCode the last matching rule wins, so its catch-all "*" goes first and the exceptions after it. On macOS, Grok Build’s sandbox doesn’t enforce its network limits; its docs say child-network blocking works on Linux only.
One first-hand note on headless use: in our testing, Grok Build’s grok -p ran every tool without asking and honoured only explicit --deny rules, so treat it like a bypass mode in scripts. For the wider picture, see Codex vs Claude Code and OpenCode vs Claude Code; if you run several sessions side by side, running Claude Code sessions in parallel covers keeping track of which one is waiting.
Questions
How do I bypass permissions in Claude Code?
Start it with claude --dangerously-skip-permissions, or claude --permission-mode bypassPermissions. Deny rules, explicit ask rules and checks on deleting critical paths still apply. Use it only in a disposable container or VM; on your own machine, auto mode removes most prompts with a classifier still checking risky actions.
Why is Claude Code always asking for permission?
You are probably in Manual mode, set by a settings file, a flag or your organisation; press Shift+Tab to switch. Other causes: an ask rule that matches, auto mode pausing after three blocks in a row, or file-edit approvals, which last only until the session ends. Pre-approve the commands you run often with allow rules.
Is Claude Code dangerous?
It runs commands with your user’s access, so the risk depends on the mode. Auto mode reviews risky actions but, in Anthropic’s words, does not guarantee safety; bypass mode offers no protection against prompt injection. Deny rules and the opt-in sandbox are the hard limits.
What permissions should I give Claude Code?
Allow the exact test, lint and build commands you run all day, put git push behind an ask rule, deny reads of .env files and secrets, and turn on the sandbox with your credential files denied. Keep allow rules narrow: broad ones are set aside in auto mode anyway.
How do I limit Claude Code’s permissions?
Add deny rules under permissions in ~/.claude/settings.json or the project’s .claude/settings.json, enable the sandbox, and set disableBypassPermissionsMode to "disable". For scripts, use --permission-mode dontAsk with an explicit --allowedTools list.
What is the difference between auto mode and --dangerously-skip-permissions?
Auto mode still checks each risky action with a classifier and blocks things like force pushes and curl | bash. --dangerously-skip-permissions checks nothing beyond your deny and ask rules and a few built-in guards.
Sources
Checked on 12 October 2026. These tools change often; where a source and this page disagree, the source is right, and we would like to hear about it at hello@aibridge.sh.
- Claude Code: choose a permission mode · code.claude.com · checked 12 Oct 2026
- Claude Code: configure permissions · code.claude.com · checked 12 Oct 2026
- Claude Code: settings files and precedence · code.claude.com · checked 12 Oct 2026
- Claude Code: sandboxed Bash tool · code.claude.com · checked 12 Oct 2026
- Claude Code: run programmatically (headless) · code.claude.com · checked 12 Oct 2026
- Claude Code: hooks guide (hooks and permission modes) · code.claude.com · checked 12 Oct 2026
- Claude Code changelog · code.claude.com · 2.1.284, 28 Sep 2026
- Codex approvals and security · learn.chatgpt.com · checked 12 Oct 2026
- Codex sandboxing · learn.chatgpt.com · checked 12 Oct 2026
- Grok Build permissions · docs.x.ai · checked 12 Oct 2026
- Grok Build sandbox · docs.x.ai · checked 12 Oct 2026
- OpenCode permissions · opencode.ai · checked 12 Oct 2026
Change log
- : First published.
Keep reading
- How-toHow to run several Claude Code sessions at once: worktrees, tmux and appsHow to run several Claude Code sessions at once without collisions: git worktrees, claude --worktree, agent view, tmux, notifications and quota costs.
- ComparisonsCodex vs Claude CodeCodex vs Claude Code as they ship in October 2026: price and limits, default models, sandboxing, instruction files, sessions and CI, and when to use both.
- ConceptsClaude Code hooks, explained (with examples)Claude Code hooks in October 2026: the 33 events, settings JSON, stdin payload, matchers and exit codes, with notification and command-blocking examples.
- ComparisonsCursor vs Claude CodeCursor is an AI editor, Claude Code a terminal agent, and they work together. Price, models, approvals, privacy and the SpaceX deal, checked October 2026.