← failproof.ai
guide·may 10, 2026·6 min read

how to block rm -rf in claude code

install failproof ai, run failproofai policies --install, and the block-rm-rf policy catches recursive deletion at the PreToolUse hook before bash runs it. safe paths like /tmp stay deletable. no prompts, no praying - the agent simply cannot execute the call.

“the ai agent ran rm -rf and it took my repo with it”

The shape of the story is almost identical every time. A developer leaves a coding agent unattended for an hour. The agent decides rm -rf node_modules is the cleanup it needs - except three tool calls earlier the working directory shifted to ~and the model never re-read its prompt. The agent comes back “done.” The home directory is gone. The laptop boots into a recovery screen.

Variants of this clip go viral every month. “the ai agent deleted my database.” “claude code deleted production.” the cursor session that wiped two years of infra. the overnight run that erased a feature branch mid-rebase. the coding agent that destroyed months of work. the cause is the same: the harness happily ran a recursive delete on a path the model misjudged. the fix is also the same - one PreToolUse hook that reads the literal command and refuses it before bash sees it.

Why this is the single most common agent disaster

Every viral “the agent deleted my repo” story has the same shape. The model decides rm -rf node_modules would help, the cwd is something different than it thought, and the harness happily runs the call. By the time the operator notices, the working tree is gone. Sometimes the home directory is gone. Sometimes the disk is gone.

Adding “don't use rm -rf” to CLAUDE.mddoes not stop this. The model isn't disobedient - it's confused about what directory it's in. The fix is a process that reads the literal command, decides the destination would be unsafe, and refuses to run it. That is what hooks are for.

Install the block-rm-rf hook

block-rm-rf ships in the default policy set. Two commands enable it:

The second command writes hook entries into ~/.claude/settings.json. From this point forward, every bash tool call Claude Code is about to make passes through failproof first.

What block-rm-rf matches

  • rm -rf, rm -fr, rm -Rf, rm -fR - any order of the flags
  • Separated flags: rm -r -f, rm -f -r
  • Long-form: rm --recursive --force
  • Wrapped in shell substitution: $(rm -rf …), `rm -rf …`
  • Hidden in bash -c "…" and sh -c "…" wrappers

The match runs on the literal command string Claude Code is about to invoke, not the prompt. The model can phrase the request however it likes - what hits failproof is the actual bash string.

Safe paths and allowlists

Outright blocking every rm -rf is too aggressive for real work. block-rm-rf ships with a path allowlist that keeps common sandbox directories deletable:

  • /tmp and /var/tmp
  • node_modules, .next, dist, and other build artifacts inside the project root
  • Any path you add yourself in the dashboard

From http://localhost:8020 open the policies tab, click block-rm-rf, and add the paths you want allowed. The change reloads instantly - no agent restart required.

What Claude Code sees when it fires

When block-rm-rf denies a call, failproof returns a structured message that the harness surfaces back to the model. The agent gets:

  • the policy id (block-rm-rf),
  • the literal command that was refused,
  • the reason and a suggested alternative - e.g. “path is outside the allowlist; if you intended to clean build artifacts, run the project's clean script.”

This means the next reasoning step is informed rather than blind. The agent does not get stuck in a loop trying the same delete twice; repair beats retry.

Get started

book a demo →