Skip to content
Back to blog
6 min read

One File to Govern Them All: A Policy Layer for Every AI Agent

One File to Govern Them All: A Policy Layer for Every AI Agent

A rule a project can’t see is a rule a project can’t talk itself out of.

Every project I own has its own CLAUDE.md: the house style, the deploy gotchas, the specific way that repo likes its work done. That’s fine, right up until you ask the question underneath it. What happens the day I forget to write one? Or worse, what happens the day an agent, trying to be helpful, quietly reasons its way into a project file that says it’s fine to skip the part that matters, just this once?

A pile of per-project instruction files is only as safe as the least careful one. So I stopped treating “how an agent behaves” as something each repo gets to decide for itself, and split it into layers instead. One of them a project can’t touch, on purpose.

The three-file stack

An AI coding agent working on my machine reads instructions from three places, in a fixed order, and each layer only gets to add detail, never take it away.

The managed policy lives at /etc/claude-code/CLAUDE.md, machine-wide, loaded into every agent session regardless of which project it’s in. This is the floor: the chain of command (branch, open a pull request, a human merges, no exceptions), the safety rules (never commit secrets, never destroy unpushed work, propose before anything irreversible), the positioning rules for public-facing work. Nothing below it may relax anything it says.

The estate policy sits at the root of my whole GitHub estate, and auto-loads for any agent working inside it, the same way a .gitignore in a parent directory quietly applies to everything under it. This is where the cross-cutting specifics live: the naming conventions, the shared tooling, the estate-wide gotchas that apply to more than one project but aren’t universal enough for the floor.

The project policy is each repo’s own CLAUDE.md: this site’s tech stack, its house style, the exact node version its deploy pipeline needs. Local detail, and only local detail.

Each layer can add. None of them can subtract. A project file can tell an agent what font to use or how sparing to be with em dashes. It cannot tell an agent that it’s fine to commit straight to main, because that was already settled two layers up, and a project was never in the room when that decision got made.

What actually belongs at the floor

The test for “does this belong in the managed policy” is simple: would I be upset if any project quietly opted out of it? If yes, it doesn’t get to live in a project file where it could drift, get forgotten, or get talked around by a well-meaning agent trying to satisfy a task. It goes in the one place every session reads no matter what it’s working on.

That’s the chain of command. That’s “never commit a secret.” That’s “propose, don’t presume, on anything hard to undo.” None of that is specific to this blog, or to any single repo. It’s specific to me trusting the work at all.

Governance you can point to, not just promise

Here’s the part that makes this more than tidy file organization: the managed policy has a section that maps directly onto the NIST AI Risk Management Framework, the same framework I use with clients. Govern, Map, Measure, Manage, written into the floor itself rather than left as an idea I claim to follow.

Govern is the chain of command: a human is accountable for every change, full stop. Map is the instruction to establish context and flag risk before acting, rather than assuming a task is safe because it sounds routine. Measure is the demand for observable correctness: tests, checks, and an honest report when something didn’t work, not a cheerful “done” that papers over a skipped step. Manage is the proportionate response to risk: dry-runs, staged rollout, a human gate on the dangerous parts.

I’ve written elsewhere about applying that same framework to client work. This is that framework turned inward first, onto my own practice, before I ever hand it to somebody else’s.

The part that isn’t just a convention

Here’s the detail that turns this from a nice policy into an actual boundary: the managed policy file is owned by root. I write and run these agent sessions as an ordinary user, and an ordinary user can’t edit a root-owned file just because a project asked nicely, or because a prompt seemed to grant permission. The floor isn’t enforced by an agent choosing to respect it. It’s enforced by not being able to reach it in the first place.

That distinction matters more than it sounds like it should. A rule an agent merely agrees to follow is a rule that can, in principle, get reasoned around: a clever-enough prompt, an edge case nobody anticipated, a task framed just persuasively enough. A rule sitting outside the filesystem permissions an agent has isn’t something to reason around at all. It’s just not there to edit.

The same shape, one level up

I’ve written before about the same instinct at the scale of a single guardrail config: separate the control plane, the rules that define what’s allowed, from the data plane, where the actual work happens, and never let the thing being governed rewrite its own rulebook alone. That piece was about one repo’s CI check. This is the identical shape at the scale of an entire machine: the managed policy is the control plane no project ever gets write access to, and every project’s own CLAUDE.md is the data plane, free to add local color but never to touch the floor underneath it.

Different altitude, same answer to the same recursive question: can it change what it’s allowed to do without anyone looking? At the machine level, the honest answer isn’t “I trust it not to.” It’s “it structurally can’t.”

Where it landed

Every project I own still has its own CLAUDE.md. It still tells an agent what font this site uses, what Node version its deploy pipeline needs, how sparing to be with em dashes. What no project file can tell an agent is that this one repo gets to skip the parts that matter. That decision was never the project’s to make, and it still isn’t. Every change that lands here, however small, goes through the same floor: a branch, a pull request, and a human who actually has to look before anything reaches main.

That’s not a rule I’m trusting anyone to remember out of habit. It’s a rule nobody gets to reach around.