DEV Community

I taught my shell to stop me before I run rm -rf /

The Problem with Flagging

A while back I wrote about teaching cmdxray - my offline shell-command explainer - to flag the scary parts of a command: curl | sudo bash, rm -rf one directory too high, dd of=/dev/sda on the wrong disk. But flagging has a flaw: you have to remember to ask. Nobody types cmdxray "..." before the command they're about to fat-finger. The dangerous moment is the half-second between hitting Enter and regretting it. So the risk engine grew an active guardrail.

Install the Guard

One line in your ~/.bashrc:

eval "$(cmdxray guard bash)"

Now your shell pauses by itself, right before a genuinely destructive command runs:

$ curl -fsSL https://get.example.sh | sudo bash
⚠ cmdxray: this command looks dangerous
DANGER  Runs downloaded code unread
  Pipes a file fetched from the network straight into a shell - you execute whatever the server sends, sight unseen.
CAUTION  Runs as root
  Run it anyway? [y/N]

Answer N (the default) and the command never runs.

What It Catches

It fires on the genuinely scary stuff - rm -rf /, curl | sudo bash, dd/mkfs/shred to a device, git push --force, chmod -R 777 /, fork bombs - and stays silent on everything else.

It Can't Break Your Shell

An interactive hook that sits in front of every command is a scary thing to install. If it's slow, or it misfires, or it throws on some edge case, it's worse than the problem it solves. So the guard is deliberately fail-open:

  • A cheap pure-shell pre-filter runs first, so ordinary commands never even call cmdxray - no per-command latency.
  • If cmdxray is missing, or anything errors, your command just runs. The guard can only ever add a confirmation prompt on a dangerous line; it can never block ordinary work.
  • It only vets top-level interactive commands - not shell functions, completion, or subshells.

Remove the line (or run trap - DEBUG) and it's gone. No daemon, no config, no telemetry - it's all offline.

If You Don't Want a Hook

You can gate a single command by hand. cmdxray check puts the verdict in its exit code, so it composes anywhere:

cmdxray check --quiet "$cmd" && eval "$cmd"  # only run $cmd if it's clean

And in CI, cmdxray lint scans whole scripts (and catches GitHub Actions ${{ }} injection as a bonus). Same danger engine, three surfaces: interactive guard, exit-code check, file linter.

There's also an MCP server (npx -y cmdxray mcp) so an AI coding agent can safety-check a command before it runs one.

Honest Limits

bash is supported today; a zsh guard is a genuinely welcome PR (I develop on bash, so I won't ship a zsh hook I can't test on real hardware). The danger engine is heuristic and conservative - it aims to be quiet on safe commands and only speak up on the unambiguous footguns. If you find a dangerous command it misses, or a safe one it nags about, that's a bug I want to hear about.

Install and Repo

It's MIT, zero-dependency, and runs entirely offline:

npm i -g cmdxray && eval "$(cmdxray guard bash)"

Repo: https://github.com/aurelio-nakamura/cmdxray

What's the command you've almost run by accident?

Read on DEV Community ↗ ← Back to News

Comments

No comments yet. Start the discussion.