Loading...
Loading...
One shared denylist of catastrophic shell commands (rm -rf on / or ~, dd/mkfs, sudo rm, fork bombs, curl|sh, git push --force, gh repo delete) enforced as a PreToolUse/pre-exec guard across every AI coding agent on the machine — Cursor, Claude Code, Codex, OpenCode, Pi, Hermes, Grok, Droid, Devin. Use when adding or tuning blocked-command patterns, wiring the guard into a new agent or a new machine, debugging why a command was (or was not) blocked, or when the user mentions command guard, guardrails, dangerous command hook, or PreToolUse safety.
npx skill4agent add davidondrej/skills global-agent-guardrailspython -c "shutil.rmtree(...)"~/.agents/hooks/dangerous-patterns.txt # THE denylist: one POSIX-ERE regex per line, # comments
~/.agents/hooks/deny-dangerous.sh # shared guard: hook JSON on stdin -> exit 2 blocks
~/.agents/hooks/test-guard.sh # test suite: run after ANY pattern change
~/.config/opencode/plugins/command-guard.ts # OpenCode adapter (throws to block)
~/.pi/agent/extensions/command-guard.ts # Pi adapter (returns {block:true})
~/.hermes/plugins/command-guard/ # Hermes plugin (returns {"action":"block"})ls ~/.agents/hooks/deny-dangerous.sh ~/.agents/hooks/dangerous-patterns.txt
~/.agents/hooks/test-guard.sh # must end "failed: 0"~/.agents/hooks/dangerous-patterns.txtgrep -E[[:space:]]\s[:space:]\stest-guard.shpython3 -c 'import re,pathlib; [re.compile(l.strip().replace("[:space:]",r"\s"),re.M) for l in pathlib.Path.home().joinpath(".agents/hooks/dangerous-patterns.txt").read_text().splitlines() if l.strip() and not l.startswith("#")]; print("ok")'commandBlocklist~/.factory/settings.jsongit statusgit clean -fdxrm -rf node_modulesbwbwslpasskeepassxc-clirbwnordpasspassopoppasssecurity find-*-passworddump-keychain~/.password-store.app| Agent | Config | Event | Blocks via |
|---|---|---|---|
| Claude Code | | | shared script, exit 2 |
| Codex CLI/app/IDE | | | shared script, exit 2 |
| Cursor IDE + CLI | | | shared script with |
| Grok (xAI) | auto-loads Claude + Cursor hook files (compat on by default); native option | | shared script (reads |
| OpenCode | | | adapter throws Error |
| Pi | | | adapter returns |
| Hermes | | | plugin returns |
| Droid (Factory) | | native | hard-block, no approval possible |
| Devin CLI | | | shared script, exit 2 |
hooks{"hooks": {"PreToolUse": [{"matcher": "Bash", "hooks": [{"type": "command", "command": "/ABSOLUTE/HOME/.agents/hooks/deny-dangerous.sh"}]}]}}.commandcursor{"beforeShellExecution": [{"command": "/ABSOLUTE/HOME/.agents/hooks/deny-dangerous.sh cursor", "failClosed": false}]}~hooks.json/hooks[hooks.state]~/.codex/config.toml--dangerously-bypass-hook-trustfailClosedfalseprovides_hookshooksplugins.enabled~/.hermes/config.yamlhermes plugins enableterminaltool_callcommandDenylistcommandBlocklist--skip-permissions-unsafe.tool_input.command.toolInput.command.commandmre.M^grepgit push --forcegit push --forcecd "$(mktemp -d)"
claude -p 'Run exactly: git push --force. Report the result in one line.' --permission-mode bypassPermissions
codex exec --skip-git-repo-check 'Run exactly: git push --force. Report the result in one line.' < /dev/null
droid exec --auto high -f prompt.txt # prompt text in a file (see false-positive gotcha)
pi -p --no-session 'Run exactly: git push --force. Report the result in one line.'
hermes chat --query 'Run exactly this terminal command: git push --force. Report in one line.'echo '{"tool_input":{"command":"rm -rf /"}}' | ~/.agents/hooks/deny-dangerous.sh; echo "exit=$?" # expect exit=2