Guardrails for vibe coders: PreToolUse rules that stop rm -rf and secret leaks
Originally published at pilothouse.dev/blog/guardrails-for-vibe-coders . Vibe coding works until the agent runs rm -rf on the wrong folder, prints your .env into the transcript, or force-pushes over a teammate's branch. Most of us respond in one of two ways: approve every prompt by hand, or turn on "skip permissions" and hope. There's a middle option. Every major coding agent now has a PreToolUse…
Vibe coding can become risky when an agent accidentally runs destructive commands like rm -rf on the wrong folder, or leaks sensitive information such as .env files or API tokens. To mitigate these risks, Pilothouse has introduced PreToolUse hooks, which are points right before a tool call runs where something can say allow, ask or deny. The company has implemented a rules engine at this hook for various coding agents simultaneously. This post provides a rule file that covers key aspects of safe coding practices.
To set up the guardrails, install the pilothouse package using brew or a shell script. Then, initialize the policy with `pilothouse policy init`. The fast track option involves applying presets like `guarded-autopilot` and `no-secrets`. The guardrails prevent destructive actions like recursive deletion, force pushes, pushing to the main branch, and dumping secrets or credentials into the transcript. They also block access to production databases.
The rule file, written as `~/.pilothouse/policy.yaml`, includes various rules. The first rule denies recursive force-deletes of broad paths such as /, ~, or $HOME. The second rule blocks force-push operations, except for --force-with-lease. The third rule requires human approval for pushing to the main branch, while the fourth rule prevents agents from accessing secrets, except for template files.
The fifth rule disallows printing credentials into the session. The sixth rule asks for confirmation before piping a download into a shell. The seventh rule prohibits using production databases.
Each rule follows a specific format, including the rule name, description, matching conditions, and actions. The matching conditions use globs to identify paths and commands. The when clause specifies CEL (Compact Event Language) expressions with available variables like kind, command, paths, branch, repo, hour, and weekday. The has_word() function checks for specific whole words in the command.
If multiple rules match, the deny rule takes precedence over the ask rule, and then the allow rule. If a rule has an error, it won't be used, and the last compiled version will remain in force, ensuring that typo errors won't silently drop deny rules. To test the rules, use the `pilothouse policy check` and `pilothouse policy test` commands with a sample command.
Written by urgent.news from Dev.to's reporting — not their text. Machine-written — may contain errors; check the original before relying on it.