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

--dangerously-skip-permissions removes the prompts, not your deny rules or your PreToolUse hooks. A seven-step hardening order for a bypassPermissions session — what to write before you flip the flag, and an honest list of what none of it covers.

"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](/controls/claude-code):

| 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?](/blog/claude-code-dangerously-skip-permissions)

## 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):

```json
{
  "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](/blog/claude-code-deny-list-bypass),
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](/blog/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:

```bash
# 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](/controls#where-every-native-model-ends).

[What the installer writes to your machine](/install-explained), 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:

```bash
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:

```bash
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](/integrations/claude-code) — 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](/blog/bypass-permissions-safely), and the mechanism
view — which of the eight control patterns survive an escape hatch at all — is
[harness control patterns](/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](/controls/claude-code), current to v2.1.233; the ACP
behavior is from the [installer](/install-explained), which is plain text you can
read top to bottom. Harnesses move — we correct these pages when they do, [in
public](/blog/claude-code-dangerously-skip-permissions).*


