This is my first open source project, and it started with an uncomfortable realization about my own setup.
I was building it with a coding agent, which writes far more code than I can honestly review. I have a day job. I'd look at the diffs in the evening and know I hadn't really read them. And I had "guardrails": rules files, instructions, a config that said what the agent should never do. My setup looked governed.
Then I checked what was actually enforced. The honest answer was: almost nothing. The rules were prose in a file the agent reads and weighs against everything else in its context. Nothing blocked anything. Every green checkmark in my mental dashboard was a suggestion wearing a control's clothing.
That gap has a general shape, and once you see it you see it everywhere in the AI tooling space: compiling a policy is not enforcing it, and writing a rule is not even compiling it. A rule that never gets consulted isn't passing. It's just unenforced, invisibly.
What I built instead
Chock is governance-as-code for AI coding agents, built around making that gap impossible to hide — including from me.
You write a policy once, as plain reviewable files committed to your repo. A compiler turns it into whatever enforcement each agent actually supports:
Pre-tool-use hooks for Claude Code and Cursor: the command is blocked before it runs, on the machine where the agent is working, with your policy's message explaining why.
Git hooks: block at commit time, before a PR exists.
A CI gate: the floor that holds no matter what the contributor's setup is.
Instruction files for every agent that supports nothing stronger.
Because policies are committed content, they travel with every clone and fork. Someone forks your repo, opens their agent, and your rules are already in its context and its hooks. They installed nothing.
The part I actually care about
The feature I'd defend in a fire is the coverage report. Chock refuses to say a policy is "enforced" unless it can verify the mechanism is actually installed for that specific agent. Otherwise the report says "advisory" or "enforced-at-commit" — per agent, per policy.
Here's what that looks like in practice, from my own repo's published coverage right now: 4 policies enforced (real pre-execution hooks), 4 enforced-at-commit (git hooks plus the CI gate), 11 advisory (rule text the agent reads). Most of my own policies are just prompts, and the report says so, because for eleven of the thirteen supported agents there is no hook API to do better with — yet. When an agent gains one, the same policy moves up a tier without being rewritten. The honest levels are the product. The prompts are just the fallback.
I wanted lying to be structurally hard: the claim is computed from a witness of the installed mechanism, not from whether a config file exists. There's an install witness per agent, a lockfile that hashes the compiled artifacts (not just the source — a deleted gate should not report "all packs match"), and every published policy ships with an eval suite that replays the actual compiled gate against throwaway git repos and reads exit codes.
It kept catching its own author, which is why I trust it
The agent that built most of this was working under the framework's own policies the whole time. Some of what got caught:
My release contract is a test: compiled artifacts must be byte-identical across a patch release. A re-run of our own init command quietly rewrote a config default, and CI failed the commit. Annoying. Correct.
A hook fix baked one machine's Python path into a committed settings file. On any other machine, the same checkout computed a different enforcement verdict — exactly the kind of quiet coverage lie the report exists to catch. Found while rehearsing the upgrade path.
The policy catalog is itself a repo that adopts the framework, and its very first commit after adoption was rejected by its own protect-main-branch policy.
Property-based tests, added last week, found within seconds that the id validator accepted a trailing newline (Python's $ matches before one) on an identifier that gets spliced into generated bash. Fixed the same hour.
A governance tool whose own gates keep catching its own maintainer is either broken or working. The test suite says working: ~680 tests, replayed policy evals, Hypothesis properties, coverage-guided fuzzing in CI.
What it doesn't do
It can't stop someone editing code in vim, and it doesn't try — that's what the CI gate is for. Pre-tool-use blocking covers two agents today; the other eleven get committed rules plus the git/CI layers, and the report tells you which is which instead of pretending. It's repo-local: no org-wide distribution layer yet, no runtime platform, deliberately no policy language to learn — declarative manifests and reviewable shell, because the honesty guarantee has to stay tractable.
Try it
pip install chock
chock init .
chock add protect-main-branch
chock sync --repo .
Then try committing straight to main and watch it exit non-zero, no matter which agent — or which human — typed it.
The catalog has installable policies (hash-pinned, each with replayed evals), with mappings to the OWASP Agentic Top 10, MITRE ATLAS, NIST AI RMF, and the EU AI Act. There's also a weekly threat-intel digest where every published agent-threat framework is compiled with citations and mapped — honestly — to what's actually covered.
All of it is open source. If you run AI agents against a repo you care about, I'd genuinely like to hear where this breaks for you — and if your own setup's "guardrails" are prose, go check what's actually enforced. Mine weren't.
Top comments (0)