Skip to content
Agentic Control Plane

How to Run Claude Code in YOLO Mode Safely (2026)

David Crowe David Crowe · · 14 min read
claude-code permissions hooks policy security coding-agents
Share X HN LinkedIn

Running Claude Code? See, control, and price every tool call it makes — allow/ask/deny policy, a per-session bill at API rates, and a full audit log, in one command:

curl -sf https://agenticcontrolplane.com/install.sh | bash

Full Claude Code guide →  ·  see your first governed call →  ·  free up to 5 agents

“Yolo mode” is the mode people actually run. The prompts get annoying, the work is real, and --dangerously-skip-permissions makes the agent stop asking. The question worth answering isn’t whether people will use it — they already do — it’s what you should have written down before they did.

Here’s the honest answer, and it’s better news than the flag’s name suggests.

What the flag actually turns off

--dangerously-skip-permissions (equivalently, --permission-mode bypassPermissions) auto-allows every call through Claude Code’s permission system. That’s the subsystem that produces “Allow this tool call? (y/n)”. It is not the only subsystem between the model and your filesystem.

Still enforced with the flag on, per Claude Code’s own control model:

Still holds Gone
deny rules at every settings scope — deny beats allow everywhere, and a managed (org-deployed) deny can’t be overridden even by a CLI flag Every interactive permission prompt
Explicit ask rules, and MCP tools flagged as requiring interaction Any control whose mechanism was “a human reads the command and decides”
PreToolUse hook blocks — hooks fire in every permission mode, and exit 2 / permissionDecision: "deny" is unconditional The acceptEdits / auto classifier screen, which bypass replaces rather than stacks with
The rm -rf circuit breaker, which catches rm -rf / and rm -rf ~ even inside $(…)
The refusal to run bypass mode as root

So bypass mode is not “no controls.” It is exactly your denies and your hooks, and nothing else. That’s a precise statement, and it’s also the whole design brief: the flag doesn’t make a session dangerous, it makes a session exactly as safe as the rules you wrote in advance. The December home-directory wipe ran under this flag; the circuit breaker that would catch it today was widened afterwards.

The corrected long-form version of this — including our own published error about it — is Is --dangerously-skip-permissions safe?

The hardening checklist, in order

Order matters here: each step covers a class the one above it doesn’t, and the cheap ones come first.

1. Write the deny rules before you need them

Deny is the only rule tier that survives the flag, so it’s where anything non-negotiable belongs. In ~/.claude/settings.json (user scope) or .claude/settings.json (project):

{
  "permissions": {
    "deny": [
      "Bash(curl:*)",
      "Bash(rm:*)",
      "Read(./.env)",
      "Read(~/.aws/credentials)",
      "Read(~/.ssh/id_*)",
      "WebFetch"
    ]
  }
}

Two things the docs are unusually candid about, and both change how you write these:

  • Deny the command family, not the arguments. Anthropic’s own docs call argument-constrained Bash patterns fragile — Bash(curl http://github.com/ *) misses the -X GET spelling, the https:// spelling, and env-var indirection. Bash(curl:*) is a rule; Bash(curl http://… *) is a wish.
  • Write() rules are silently never consulted. Edit() rules govern Write and NotebookEdit. A warning was added in v2.1.210 because enough people had rules that did nothing.

And know the ceiling on this step: a deny list is a string match evaluated inside the client, so a compound command, an interpreter, or a three-line script the agent writes and runs all route around it. That’s not a bug you can patch out — it’s the documented bypass class, and it’s why step 2 exists.

2. Put anything that must hold in a PreToolUse hook

Hooks are the strongest mechanism inside the harness. PreToolUse fires on every tool call in every permission mode — the hook receives permission_mode: "bypassPermissions" in its input, which it couldn’t if it never ran — and a hook that exits 2 or returns permissionDecision: "deny" blocks the call unconditionally. A hook allow, correctly, cannot loosen a deny or ask rule.

The caveat: Claude Code hooks are fail-open on timeout. The docs say it plainly. A hook that stalls doesn’t block, so if your enforcement lives in a hook, that hook’s availability is now part of your security posture, and a crashed control layer silently stops controlling. Design for that before you depend on it.

3. Turn the sandbox on

/sandbox — Seatbelt on macOS, bubblewrap on Linux. It’s off by default, which is the single most common gap in a yolo setup. Once on: writes confined to the workspace and $TMPDIR, network through a proxy with no domains pre-allowed, and a set of paths write-protected with no exemption possible (settings files, hook and skill directories, .mcp.json, credentials, shell rc files, .git/hooks).

The two limits to hold in your head: reads are unconfined by default — the docs explicitly warn that ~/.ssh and ~/.aws/credentials are readable unless you add deny-read rules, which is why they’re in the step-1 snippet above — and the model can request dangerouslyDisableSandbox through the normal permission flow, which in bypass mode is a flow that no longer asks anyone. A sandbox bounds the blast radius; it decides nothing. Sandboxes and control planes is the longer version of that trade.

4. Don’t run it as root, and don’t inherit a hostile repo’s settings

Bypass mode refuses to run as root — take the hint rather than working around it. The other sharp edge is headless: -p counts as having accepted workspace trust, so a scripted invocation in a repo you didn’t write inherits that repo’s project settings. --setting-sources user strips them. Worth wiring into any cron or CI invocation, because that’s exactly where nobody is watching.

5. Flip the org-level switch if the answer is “never”

If a class of machine should never have this mode available at all, managed (org-deployed) settings carry two kill switches: permissions.disableBypassPermissionsMode removes the mode, and allowManagedHooksOnly pins your hooks so a user or project setting can’t override them. Managed denies can’t be overridden by a CLI flag either.

This is the strongest purely-native answer, and its limit is honest: managed settings are files on the endpoint. They assume the endpoint is managed.

6. Add a layer the flag can’t reach

Everything above lives on the machine running the agent, which means everything above can be edited by whoever owns that machine. disableAllHooks is a documented one-line switch that stops all hooks; deleting the hook entry does the same. For a developer on their own laptop that’s fine — you’re not defending against yourself. For anything where the endpoint isn’t the trust boundary, the control that holds has to sit somewhere the endpoint can’t edit.

That’s the layer we build. Two paths, and they’re genuinely different:

# Connected: policy and the record live off the machine
curl -sf https://agenticcontrolplane.com/install.sh | bash

# Fully on-device: no account, nothing leaves your box
curl -sf https://agenticcontrolplane.com/install.sh | bash -s -- --local

What each gets you in a bypass session:

  • A safety floor. Recursive force-delete of a root or home path, mkfs, dd to a block device, fork bombs, force-push to main/master — denied regardless of policy, token-matched so flag order and spelling don’t help (rm -r -f ~, rm -rf ~/), and recursed one level into bash -c "…" and eval. In the connected path this floor is evaluated server-side, where no tenant setting, no standing approval, and no client flag can reach it.
  • allow / ask / deny policy applied to every call, in one dialect, across every harness you run — not re-derived per settings file.
  • An audit line either way. One row per call — tool, decision, reason, timestamp — written whether the call was allowed, denied, or waved through by a human. tail -f ~/.acp/audit.jsonl in local mode; a queryable ledger in the connected one. A record of what a bypass session did is the thing every native model is missing, across every harness we’ve measured.

What the installer writes to your machine, file by file, if you’d rather read before you pipe.

7. Re-run the installer if you installed before August 27, 2026

One honest correction, because it affects the local path specifically. The on-device decision engine (~/.acp/decide.mjs) had a wrapper-and-compound bypass: timeout 5 rm -rf ~ classified as a timeout command rather than an rm, because the wrapper parser skipped flags but not the positional operands a wrapper like timeout consumes before the real command. It’s fixed — the engine now carries an explicit wrapper table with per-wrapper flag and operand arity, and scans each segment of a compound command separately.

The fix is live in the canonical installer. Verify it yourself in one line:

curl -s https://agenticcontrolplane.com/install.sh | grep 'const WRAPPERS'

You should see const WRAPPERS = new Map([. If you installed before August 27, 2026, your ~/.acp/decide.mjs predates the fix and re-running the installer replaces it:

curl -sf https://agenticcontrolplane.com/install.sh | bash -s -- --local

Your ~/.acp/policy.json is left alone — the installer only writes it when it doesn’t already exist. The connected path was never affected; its classifier runs server-side.

What still isn’t covered

The list this site always carries, because a hardening checklist that ends on a win is a sales page.

A deny list can’t constrain a Turing-complete tool. Step 1’s rules are a first line, not a boundary. python3 -c "import shutil; shutil.rmtree(...)" is not a trick — it’s what a coding agent does all day. Every layer above the sandbox reasons about command text; only the kernel reasons about effects.

The hook is fail-open, by design and by ours. Claude Code proceeds if a hook times out, and ACP’s dispatcher also fails open by default — your tool runs, loudly flagged as unchecked, rather than your session bricking when a network hop is slow. That’s the right default for a developer laptop and the wrong one for a machine touching production, which is why the ~/.acp/failmode opt-in exists. Either way, it’s a choice you should make deliberately rather than discover.

Local mode is removable by whoever owns the machine. --local puts the engine, the policy, and the log on your disk. That’s the point — no account, nothing leaves the box — and it also means it enforces against accidents, not against the person holding the keyboard. Only the off-machine path changes that property.

Nothing here covers what the agent reads. Bypass mode plus unconfined sandbox reads is a credential-exposure shape, not a destructive-command shape, and no permission prompt was ever going to catch it. Deny-read rules and the sandbox are the controls; the flag doesn’t touch either, which is the good news and the reason step 1 includes them.

Yolo is a per-harness word. These seven steps are Claude Code’s. Codex’s --yolo drops the sandbox and the approvals; Antigravity’s --dangerously-skip-permissions is total — verified, hooks are not invoked at all under it; Cursor’s Run Everything mode has no sandbox, no classifier, no prompts. If you run more than one agent, the equivalent table for all of them is Bypass Permissions Safely, and the mechanism view — which of the eight control patterns survive an escape hatch at all — is harness control patterns.

The short version

Yolo mode isn’t the risk. An unprepared yolo mode is. The flag removes the one control that was never going to scale anyway — a human reading every command — and leaves standing exactly the two that do: rules written in advance, and a check that runs outside the prompt. Write those, turn the sandbox on, put one layer somewhere the flag can’t reach, and the mode is what it should have been called: the mode where your policy does the work instead of your attention.

Every Claude Code behavior above is from Anthropic’s docs and our own control-model page, current to v2.1.233; the ACP behavior is from the installer, which is plain text you can read top to bottom. Harnesses move — we correct these pages when they do, in public.

Can you run Claude Code in yolo mode safely?

Safely enough for ordinary work, if you do three things first: write deny rules for the command families you never want run (deny beats allow at every scope and survives bypassPermissions), put anything that must hold in a PreToolUse hook (hooks fire in every permission mode and a hook deny is unconditional), and turn on the sandbox with /sandbox. Without those, bypass mode is genuinely what its name says — the prompts were the only thing standing between the agent and the command, and you removed them.

What does --dangerously-skip-permissions actually turn off?

Only the interactive permission prompts. It sets the session to bypassPermissions, which auto-allows every call through Claude Code’s permission system. Deny rules at every scope, explicit ask rules, PreToolUse hook blocks, MCP tools flagged as requiring interaction, and an rm -rf circuit breaker that fires even inside command substitution all still apply, and the mode refuses to run as root.

How do I disable yolo mode for my whole team?

permissions.disableBypassPermissionsMode in managed (org-deployed) settings removes the mode entirely, and allowManagedHooksOnly pins your hooks so a user or project setting cannot override them. Both are files on the endpoint, so both assume the endpoint is managed — if it is not, the control that holds has to live somewhere the endpoint cannot edit.

Do hooks still run with --dangerously-skip-permissions?

Yes. PreToolUse fires on every tool call in every permission mode, and exit code 2 or permissionDecision deny blocks the call unconditionally. The caveat worth knowing is the other direction: Claude Code hooks are fail-open on timeout, so a hook that stalls does not block. If your enforcement lives in a hook, that hook’s availability is part of your security posture.

Share X HN LinkedIn
Get the next data drop
What agents actually cost, new tool-surface captures, and the occasional incident post-mortem — sent when we publish something worth your inbox, not on a schedule. Unsubscribe anytime.
Share: Twitter LinkedIn
Related posts

← back to blog