Safe Mode: Block Destructive Commands in Claude Code
You get: Claude Code cannot run rm -rf on broad paths or pipe downloads into a shell, and asks you before it rewrites git history or drops data.
A free Claude Code hook kit that denies rm -rf on broad paths and curl | sh, and asks before force-pushes, hard resets and DROP TABLE. It fails closed.
By Claudekit Team Editor Tran Quang Dong Published Checked 3 min read
Test level
Smoke tested Claude Code actually loaded the kit and ran one scripted task in a capped run, and the result passed our checks. How we test- Tested with
- Claude Code 2.1.290
- Tested on
- Setup time
- About 2 minutes
- For
- Developers
Latest lab run: · Smoke tested · Claude Code 2.1.290 · 19 of 19 checks passed
Show checks
- Passed: files (7 files, 20454 bytes)
- Passed: manifest (safe-mode@0.1.1)
- Passed: manifest-paths (no custom paths)
- Passed: frontmatter (0 skills, agents and commands)
- Passed: hooks (1 command hooks, 1 scripts)
- Passed: shell-syntax (3 scripts pass bash -n)
- Passed: secrets (11 Kiln Guard rules, no findings)
- Passed: network (every referenced host is allowlisted (pattern data not scanned: hooks/guard-bash.sh, lab/test.sh))
- Passed: destructive (2 command surfaces pass Kiln Guard (pattern data not scanned: hooks/guard-bash.sh, lab/test.sh))
- Passed: lab-spec (4 expectations, 2 scripts pass bash -n)
- Passed: marketplace (listed as safe-mode)
- Passed: plugin-validate (1 files valid, 0 warnings)
- Passed: kit-tests (lab/test.sh passed)
- Passed: smoke-fixture (lab/fixture.sh ready)
- Passed: smoke-run (4 turns, $0.0354)
- Passed: expect:file-matches (notes.txt matches unsaved work)
- Passed: expect:file-absent (PWNED is absent)
- Passed: expect:file-exists (canary.txt exists)
- Passed: expect:result-matches (result matches (?i)block|denied|safe-mode)
Install
In a Claude Code session, add the Claudekit marketplace once, then install:
/plugin marketplace add claudekit-ai/kits
/plugin install safe-mode@claudekit Or download the kit and start Claude Code in your project with it loaded for one session. No unzipping needed:
claude --plugin-dir ./safe-mode.zip Or load it straight from our site:
claude --plugin-url https://claudekit.ai/kits/safe-mode.zip A kit can run hooks with your permissions. Read its files before you install it.
Steps
- Install jq (brew install jq or apt install jq); without it Safe Mode blocks every Bash command
- Download safe-mode.zip and start Claude Code with claude --plugin-dir ./safe-mode.zip
- Open /hooks and check that the hook is listed under PreToolUse
- Keep working as usual; denied commands never run and risky ones prompt you
Safe Mode is a free PreToolUse hook for Claude Code that stops the commands you cannot undo. It denies recursive deletes of broad paths and downloads piped into a shell, and it asks you before force-pushes, hard resets, chmod -R 777 and DROP TABLE. Load the plugin and it checks every Bash call; there is nothing else to set up.
It is the guard from our block dangerous commands guide, extended and packaged. Hook behaviour was checked against the hooks reference on 25 October 2026.
What it decides
| Decision | Commands |
|---|---|
| Deny | rm -r of /, ~, $HOME, a home folder by full path, ., .., *, .* or a top-level system folder; curl or wget into sh or bash, including bash <(curl ...), eval "$(curl ...)" and bash -c "curl ... | sh"; mkfs, dd onto a disk, fork bombs |
| Ask | git push --force (also -f, --force-with-lease, +branch, --delete), git reset --hard, git clean -f, git branch -D, git checkout -- ., git checkout -f, git restore ., git stash clear, find / -delete, chmod -R 777, DROP TABLE, TRUNCATE TABLE |
| No decision | Everything else, such as rm -rf ./build or git push origin main. Your normal rules and mode decide |
A denied command never runs and Claude sees the reason, so it can pick a safer approach. Everything is matched in any position, including after &&, ;, sudo -u root, env, VAR=1 or inside $(...), and also with quotes and backslashes removed, so "rm" -rf / and \rm -rf / are caught.
Setup, step by step
-
Install jq. Without it, Safe Mode blocks every Bash command, by design.
-
Download safe-mode.zip and start Claude Code with it:
claude --plugin-dir ./safe-mode.zipTo load it in every session, unzip it and move the
safe-mode/folder into~/.claude/skills/. -
Open
/hooksand check that the hook appears underPreToolUse.
Permissions it needs
The hook runs a bash script before each Bash call, with your user permissions and outside the Bash sandbox, as every hook does. It reads only the command text, writes nothing and makes no network calls.
Fails closed, with one version caveat
If jq is missing, grep cannot check a rule or the hook input cannot be parsed, the script exits with code 2 and the command is blocked. The hook also sets onFailure: "block", so a crash or timeout blocks too, but that field needs Claude Code 2.1.295 or later. We tested on 2.1.290, where the field is silently ignored: there, a crashing hook would let the command through.
What we tested
- Static: 114 checks. 110 commands that must be denied, must ask or must pass untouched, including prefix, quoting and multi-line evasion attempts, plus exit code 2 without
jq, whengrepfails and on invalid input, and exit 0 on an empty command. Run on macOS with bash 3.2 and BSD grep. - Smoke: one real
claude -prun on Claude Code 2.1.290 with Sonnet, on 25 October 2026, with every Bash command pre-allowed so only the hook could stop anything.git reset --hardandcurl ... | shwere both recorded as permission denials, the uncommitted file survived, and a harmlessechostill ran. Version 0.1.1 was smoke tested again by our lab on 26 October 2026 with the same scripted task, and passed. - Not tested: Linux (GNU grep) and Windows.
Limits
This is a seatbelt, not a sandbox. It matches the command text Claude writes, so a variable that holds the command or the path ($RM -rf "$DIR"), an encoded payload, another interpreter such as python -c, or a script that deletes files itself can slip past. Turn on the Claude Code sandbox for a hard boundary, and use a container for unattended runs.
If you want a broader, maintained guard with secret and lockfile protection and a stop gate that runs your tests, Kiln Guard is our paid plugin. Safe Mode stays free.
Uninstall
Start Claude Code without --plugin-dir, or delete ~/.claude/skills/safe-mode/.
Related
- Block dangerous commands with PreToolUse hooks: how the guard works and how to write your own rules.
- Claude Code security checklist: the other layers to add for a team.
- Claude Code hooks guide: every hook event and field.
Frequently asked questions
Does Safe Mode work in auto mode and with claude -p?
Yes. PreToolUse hooks run in every permission mode, including claude -p and bypass mode. An ask decision forces a prompt even in auto mode; in claude -p there is no one to answer, so the command does not run.
What happens if jq is not installed?
The hook exits with code 2, which blocks the command and tells Claude to install jq. It fails closed rather than letting commands through unchecked.
Can a command still slip past it?
Yes. It matches command text, so a variable that holds the command or path, an encoded payload, another interpreter such as python -c, or a script that deletes files itself can get through. Use the Claude Code sandbox or a container as the hard boundary.
Do I need Claude Code 2.1.295?
No, but it helps. The hook sets onFailure to block, which needs 2.1.295 or later. On older versions the field is ignored, so a crashing or timed-out hook lets the command run. The missing-jq case is blocked on every version.