# Show HN: A pre-execution guard that stops AI agents running destructive commands

> Source: <https://github.com/vandith1/agent-guard>
> Published: 2026-08-16 12:53:51+00:00

Your coding agent will eventually run `git reset --hard`

, force-push to main, or
drop a table. Not because it's careless — because it's confident, and the loop
drifted three steps ago.

** Try it in your browser →** — paste any command, see whether it would be blocked and by which rule. Nothing is sent anywhere; the rules run locally.

This is a ~60-line shell hook that stops the commands you can't undo. It runs before every shell command the agent proposes, exits 2 to deny, and writes the reason to stderr — which agent CLIs feed back into the loop, so the agent stops retrying and surfaces the command to you instead.

```
BLOCKED by guard [discard all local changes (git reset --hard)]
  command: git reset --hard HEAD~3
  This one is gated to the human. Do not retry, do not reword.
  Surface the exact command and let the human run it.
bash install.sh          # merges a PreToolUse hook into .claude/settings.json
bash test-guard.sh       # 6 assertions, should be 6 passed / 0 failed
```

Works with Claude Code's `PreToolUse`

hook, and with any agent CLI that runs a
shell hook before a tool call and respects its exit code. Requires `bash`

,
`grep -E`

, and `python3`

.

`git reset --hard`

· `rm -rf`

· `git clean -f/-x`

· `git checkout .`

·
`git filter-branch`

· force-push to main/master/production · `DROP TABLE`

·
`TRUNCATE`

· `FLUSHALL`

· `aws delete-*`

/`terminate-*`

· `kubectl delete`

·
`terraform destroy`

· `docker … prune`

· `chmod 777`

· `curl … | sh`

·
raw writes to `/dev/sd*`

.

Rules live in one array at the top of the script as `label@@regex`

pairs. Edit
them. Add a test case when you do — including a benign command the new pattern
must *not* catch. That's how you find an over-greedy regex before it finds you.

**It stops:** a confident agent proposing an irreversible command in plain text, which is the
failure mode I actually hit — the loop drifted three steps ago and the next command discards a
day's work.

**It does not stop:** anything deliberately evading it. `g""it reset --hard`

, a base64 payload
through `eval`

, a shell script, an alias. The matcher is a regex over the proposed command string,
and a regex loses to an adversary every time.

That distinction is the whole threat model, and it is worth being blunt about: if your agent is obfuscating commands to get around a hook you installed, a pattern list is not your problem. This assumes a well-intentioned model having a bad moment, not a hostile one.

It also does not replace the things that are strictly more reliable because they sit outside your machine: server-side branch protection, least-privilege credentials, and backups. Nothing here is a substitute for any of those. Use them, and use this for the irreversible operations they do not cover — a hard reset on uncommitted work, a recursive delete, a dropped table, a destroyed stack.

A seatbelt, not a rollcage.

**It matches the whole command string, arguments included.** So a commit message
that quotes a gated phrase gets blocked. That's deliberate: the alternative is
parsing shell quoting, expansion and `eval`

, and every parser is a new way to
slip a command past the guard. Fail-safe beats clever. The habit that fixes it:
`git commit -F .commit-msg`

instead of `-m "…"`

, never a heredoc.

**It fails closed.** If it can't read the command out of the hook payload, it
blocks. A guard that silently degrades to "allow everything" is worse than no
guard, because you'd stop watching.

Destructive commands and *external-effect* commands are different problems.

**Tier 1**—`rm -rf`

,`reset --hard`

,`DROP TABLE`

. Unrecoverable. Never negotiable, no unlock, not even for you-in-a-hurry. This repo is tier 1.**Tier 2**—`git push`

,`npm publish`

, deploys, migrations. Real effects, but reviewable and reversible. These shouldn't be*banned*— they should be gated, unlockable by a human for a short window that auto-relocks.

Tier 2 is where the design gets interesting: the unlock has to be something the agent can't touch, including refreshing its timestamp to extend the window or deleting it to hide that it was used.

The full kit adds tier 2 with the time-boxed unlock, a config file, a git
pre-push hook, an isolation workflow, a merge gate that catches prompt
regressions with a deterministic grader, and the incident write-ups behind each
rule: [https://andevan.gumroad.com/l/agent-control-kit](https://andevan.gumroad.com/l/agent-control-kit)

MIT licensed. Take it, fork it, ship it in your own tooling.
