My agents run without permission prompts, so the brake moved into the hook
The permission prompt was the last brake on my fleet, and it was in the wrong place. A prompt fires when a human is sitting there to read it. My agents do most of their work when nobody is: the nightly drain, the noon pass, the headless jobs that read the open web. Those run with prompts skipped, by design, because a prompt nobody answers is a stalled job. So the protection was strongest exactly…
My agents operate without permission prompts, prompting the brake to be moved into a hook. The permission prompt was the last safeguard in my fleet, only present in the correct location. My agents carry out most of their tasks unattended, such as nightly and noon passes, and headless jobs that read the open web. These tasks bypass prompts, as a prompt without a response results in a stalled job.
Consequently, the protection was strongest where I was actively monitoring and absent during unattended operations. Now, a hook has taken its place instead of the prompt. The hook runs a small shell script before each tool call, regardless of the session or permission mode. This script reads the call as JSON and either permits it or exits, providing feedback to the model.
Initially, the hook focused on a specific class of actions, like injecting instructions, accessing credential files, dumping the keychain, and piping downloads into a shell. However, it has since expanded to cover additional classes, including force pushes, hard resets, branch swaps, recursive deletes, and package releases. The hook exists due to the location where the old rules were situated.
A rule restricted to a single directory would not be triggered if the violation originated elsewhere. Therefore, a hook that applies to every session is necessary. To enforce rules universally, the hook is loaded everywhere. The rule for adding a rule is a throughput rule rather than a caution rule. A rule should only be implemented if it is rarely triggered or if it prevents destructive cross-session activities.
Rules that are frequent and easily recoverable, such as plain pushes, new branches, dry-run cleans, or deleting build output, are excluded. The test suite has an equal number of passing and blocking cases, with the passing cases being more important since they occur dozens of times daily, and a false block on any of them is more costly.
The hook applies two types of refusals: a block that requires human intervention, or a redirect that refuses the action while providing a sanctioned alternative, allowing the session to correct itself without human involvement. The majority of refusals in the destructive class are redirects. The guard, responsible for enforcing these rules, has a doctor that validates its decisions by feeding synthetic tool calls through itself and checking the outcomes.
If a field the guard reads changes name, the known-bad cases will no longer block, and the doctor will fail loudly instead of silently permitting everything. The guard is parsed before every tool call in every session, so any syntax errors in the hook would block all tools, including the one that would fix the issue. Therefore, a stray quote caused a two-day block before the new rules were implemented.
The guard is now written to scratch, syntax-checked, reviewed by the doctor, and only then copied over. With the brake now in the hook, the prompt has become optional. It has been disabled in interactive sessions, and the headless jobs explicitly declare the bypass mode instead of inheriting the ambient setting. The decision to remove the prompt was made earlier that day, after realizing that the brake it provided had no replacement.
The order of implementation matters: cover the class first, then eliminate the prompt. There is only one way to bypass the hook, and it is not by granting permission. The escape is typing the command in your own terminal, where the hook does not run. A spoken approval in the conversation does not unblock the tool call and should never be considered a reason to retry or rephrase the command.
Any signal that could grant a session passage would turn the refusal back into a reminder, which has occurred twice before the hook's implementation. The original prompt asked for confirmation. The hook does not ask; it already understands which actions I have never been uncertain about.
Written by urgent.news from Dev.to's reporting — not their text. Machine-written — may contain errors; check the original before relying on it.