Quickstart | Concepts | API | Verify | Coverage | Teams | Anchors | Recovery | Human approval in CI | Verifiable audit log | Unattended runs | Approval when unattended | Hooks vs deny | Skip permissions | PreToolUse hook | Deny not working | Headless permissions | MCP human-in-the-loop
Claude Code --dangerously-skip-permissions: what it skips, and a safer way to run unattended
--dangerously-skip-permissions starts Claude Code in bypassPermissions mode: tool calls run without a permission prompt, including writes to .git and .claude. It does not turn off everything: deny rules, ask rules, a PreToolUse hook that answers deny and the guard on critical-path rm still apply. It gives no protection against prompt injection, so the official advice is to use it only in a container or VM. For most unattended jobs, --permission-mode dontAsk with an allow list, plus the sandbox, does the job with far less risk. Checked against Claude Code 2.1.312 and the official Permission modes, Permissions, Hooks guide and Sandboxing pages.
What the flag turns off
The CLI reference: the flag is "Equivalent to --permission-mode bypassPermissions". The Permission modes page: this mode "disables permission prompts and safety checks so tool calls execute immediately, including writes to protected paths". In practice:
- No prompt for Bash, Edit, Write, WebFetch or MCP calls.
- Allow rules stop mattering: "Allow rules have no effect in
bypassPermissions", because everything is already allowed. - Writes to protected paths (
.git,.claudeand a few others) go through without a prompt. Claude can edit its own settings and hooks. - With the sandbox on, a command that fails in the sandbox may be retried outside it, and in an interactive session "In
bypassPermissionsmode: the retry runs without a prompt". A sandboxed command that connects to a host outside your allowed domains is also "Allowed without a prompt", unlessnetwork.strictAllowlistis set.
What still blocks
- Deny rules. "Deny rules block in every mode, including
bypassPermissions." - Ask rules. Tools matched by an explicit
askrule still prompt. In a-prun, where nobody can answer, those calls are denied. - PreToolUse hooks. The Hooks guide: a hook that returns
permissionDecision: "deny""blocks the tool even inbypassPermissionsmode or with--dangerously-skip-permissions.PreToolUsehooks fire before any permission-mode check, in every permission mode." - Critical-path removals. Recognized
rmandrmdirof critical paths still get a prompt or a denial (you can switch this off separately). - Root. On Linux and macOS Claude Code refuses to start:
--dangerously-skip-permissions cannot be used with root/sudo privileges for security reasons(skipped inside a recognized sandbox).
What it does not do: think for you. The page's own warning: "bypassPermissions offers no protection against prompt injection or unintended actions." A README, an issue or a web page that tells the agent to run curl ... | sh gets the same treatment as your own request.
Why people use it, and what to use instead
The usual reasons are a cron job, a GitHub Actions step, or a long task where you do not want to answer 200 prompts. Each has a narrower tool.
CI and cron: deny what is not on a list. dontAsk "denies every call that would otherwise prompt"; listed tools still run.
claude -p "Run the tests and fix the failing one" \
--permission-mode dontAsk \
--allowedTools "Read,Edit,Bash(npm test),Bash(git diff *)" \
--permission-prompts none \
--output-format json
--permission-prompts none tells Claude Code nobody is there to answer, so tools that need a person are removed. Refused calls are listed under permission_denials in the JSON; count them and fail the job if needed. More on -p runs: Claude Code headless mode: permissions, approvals and CI.
Long interactive tasks: auto mode. The official alternative for "far fewer permission prompts": claude --permission-mode auto. A classifier reviews each action instead of you. It needs a supported model, and your organization can turn it off.
A real boundary: the sandbox. Rules read the text of a command; the sandbox limits the process. Turn it on and close the retry:
{"sandbox": {"enabled": true, "allowUnsandboxedCommands": false,
"failIfUnavailable": true, "network": {"strictAllowlist": true}}}
It covers shell commands. The built-in Read, Edit and Write tools follow permission rules instead, so keep deny rules for secrets and for .claude/**.
If you really need bypass mode, do what the docs say: a container or VM, a non-root user, no secrets you would not hand to a stranger, and an egress allowlist on the runner. Add deny rules anyway, because they still apply:
{"permissions": {"deny": ["Bash(curl *)", "Bash(ssh *)", "Read(.env)", "Read(.env.*)",
"Edit(.claude/**)", "Edit(.mcp.json)"]}}
A Bash rule matches the command text and "isn't a security boundary around the program" (Permissions page): sh -c 'curl ...' slips past. Use them as a fence, not a wall.
Locking the flag out for a team. Set permissions.disableBypassPermissionsMode to "disable" in managed settings. A checked-in .claude/settings.json cannot start a session in bypass mode either: defaultMode: "bypassPermissions" there "doesn't take effect".
Side by side
--dangerously-skip-permissions | dontAsk + --allowedTools | PreToolUse hook | Sandbox | |
|---|---|---|---|---|
| Prompts | none | none, unlisted calls denied | can ask, allow or deny | unchanged |
| Deny rules | still apply | apply | apply | apply |
| Decides by | nothing | name and pattern of the call | any code you write | what the process touches |
| Protects against prompt injection | no | partly: only listed tools run | as good as your logic | limits the damage |
| Breaks how | runs everything | blocks too much | fails open unless made fail-closed | blocks tools that need the network |
Where a person is still needed
Some actions should not run without a person at the moment of the call, in any mode: push or merge, deploy, send mail, delete outside the checkout, spend money. In dontAsk they are simply refused, and you review the job's output afterwards. If the job must do them, the call has to wait until someone approves it from somewhere other than the terminal. Claude Code's built-in tools do not do that on their own; a PreToolUse hook can, within its timeout. How to write one, and how to stop it failing open: Claude Code PreToolUse hook: examples, exit code 2 and the "hook error".
Deus Witness is one such hook. deus-witness-hook sends each matched call to the witness, compares it with a mandate you signed with a passkey, and holds a call the mandate does not cover until you approve it on your phone. The hook checks the signed receipt before it prints allow; if you do not answer in time, or the service is unreachable, the call is denied. Because hooks fire in every permission mode, this holds in bypass mode too, but the hook decides only Claude Code's tool calls: it does not see what a script does once it runs, so keep the sandbox or container under it. Setup for unattended runs: Safe way to run Claude Code unattended and Require approval before Claude Code runs a command unattended.