Most people I know who use Claude Code run it with auto-approve on, me included. You give it a task, look at something else for a few minutes, and review the diff when it’s done. Anthropic’s own numbers back this up: people approve about 93% of permission prompts, and in their testing, auto mode still let through about 17% of the risky actions in a small set of 52 (Anthropic Engineering).
The diff only shows what the agent shipped. It doesn’t show what it read, what it ran, or what it tried and backed out of along the way. That gap is what I’ve been working on for the last several months with Guard.
How Guard works
Claude Code has hooks: scripts that run at fixed points in a session. Guard registers four of them: before a tool call, after a tool call, when a prompt is submitted, and when a turn ends.
The one that matters most is the first. Before Claude runs a shell command, reads or writes a file, fetches a URL or calls an MCP tool, the hook sends the tool name and its input to a policy engine. The engine checks it against a set of rules and returns one of three answers:
- allow: nothing happens
- warn: the action runs, and the developer sees a warning
- block: the action is denied, and Claude is told why
The rules are written in YAML, versioned, and deterministic. There’s no model in the decision. That was a deliberate choice: I didn’t want a second LLM deciding whether the first LLM’s action was okay, because then you have two systems you can’t fully predict instead of one. Every verdict records the exact rule version that produced it, and the evaluation log is hash-chained, so editing a single record breaks the chain. It isn’t anchored anywhere outside the database yet, so it won’t catch someone rewriting the whole chain.
Every rule I ship defaults to warn or log. Blocking is something a team opts into, one rule at a time.
The first blind spot was mine
A few weeks in, I realized Guard wasn’t capturing file reads. Writes and shell commands were coming through fine, so everything looked busy and healthy. But one of the main things I built it for was noticing when an agent opens files that hold secrets, and for at least a week it had seen none of that.
Nothing alerted me. A monitor that silently misses a whole category of actions looks exactly like a monitor with nothing to report.
The fix for the bug was simple. The bigger change was in how rules report: when a rule can’t see the evidence it needs, Guard now records “evidence missing” instead of quietly passing.
Warnings people ignore are worse than none
The next problem was the opposite. My secret-detection rules fired on ordinary file reads, constantly. When everything warns, people learn to skim past warnings, and then the one that matters gets skimmed too. I’ve removed false warnings from five rules so far. It’s slow work: measure what fires, narrow the rule, ship it, measure again.
Two problems I haven’t solved
These are the two I think about most, especially if you look at Guard as a control on an AI agent rather than a dev tool.
The agent could, in principle, turn it off. Guard has no rule today that flags the agent editing its own Claude Code settings or the hook script, so it leans on Claude Code’s own permission handling for those files. A monitor that the monitored system can reconfigure is only as strong as whatever stops that edit.
Pattern matching on shell commands is fragile. Several rules match on command text. Even against an agent that’s just being sloppy, that’s easy to get wrong: my own rm -rf rule only fires when / or ~ is the first thing being deleted, so rm -rf build/ ~/ gets through. Against an agent that’s trying to get around it, pattern matching is a weak defense.
What does hold up: when a team sets a rule to block, Claude Code still enforces that block with --dangerously-skip-permissions on, and in headless claude -p. I tested both with a hook that returns the same deny response Guard does.
How well does it catch real incidents?
This is the question I care about most, and I don’t have a measured answer yet. I’m building a harness that replays documented coding-agent incidents through Guard’s rules, and I’ll publish the results, misses included. If I’m asking people to trust a monitor, they should be able to see where it fails.
What I want to understand next
- How often agents read secrets they don’t need during normal work, versus only in edge cases.
- Whether agents change course after a warning. When Guard warns on one command, does the agent find another way to the same result?
- Whether a deterministic rule set stays useful as agents get more capable, or only ever catches the clumsy cases.
If you’re running coding agents on a team and have seen something go wrong, or almost go wrong, I’d like to hear about it: [email protected].