A Written Rule Isn't Enough
Here are the rules my AI can't break, and how I lock them.
My harness rests on rules written in plain text. The AI reads them every session and follows them almost always. Almost. For most rules, an occasional miss is fine: I fix it and add a line. For a few, one miss is one too many. Those I back with code that blocks the action.
Why a written rule isn't enough
A written rule is one instruction among thousands of words. Over a long session, the context fills up and gets summarised, and an instruction can slip into the background. An email or a web page the AI reads can contain instructions that pull it off course. And a model can be wrong with great confidence.
I learned this from a real mistake. My rule already said to show me emails before sending them. One day I rejected a command that sent follow-ups, and later found it had already run: 56 emails were out. The rule was written down. It stopped nothing.

My red lines, and how they're locked
Never contact an excluded company
The rule is written in the rules files of both my tools, Claude Code and Codex. It's backed by a hook: a small script that runs before any action that sends or drafts an email. If the text names a company on my exclusion list, or an address linked to it, the action is blocked. The same script runs in both tools.
The script has limits, and its own comments say so: it compares text, so it can't know that a person works for that company. The written rule is still needed: it tells the AI to check known links before writing. The code catches the obvious, and the rule covers judgement. When a link is confirmed, it becomes one more line in the list.
Never publish without my approval
In some projects, a publish or deploy command is simply refused by the tool's permissions. The AI can prepare, test and check everything. Going live goes through me.
Secrets don't go through the conversation
My API keys live in my Mac's keychain. Scripts read them directly, and they never appear in a file or in the exchange with the AI. It can't print what it has never seen.
A verdict can only get more cautious
In MesAmendes, my app that checks traffic fines, the model proposes a verdict. Code then checks it against public data, and that code can only make the verdict more cautious, never more favourable. Even when the model is wrong, it can't promise someone their fine will be cancelled.
How to sort your rules
For each rule, ask one question: if the AI breaks it once, is that serious and irreversible?
- No: the rule stays in text. Style, format, the order of steps, the choice of model. A miss can be fixed.
- Yes: the rule gets locked by code. A message sent, a payment, a deletion, a release, a secret printed.
In my setup, the second list fits on one hand. That's on purpose: every lock adds friction, so only lock what deserves it.
Four ways to lock a rule
- The tool's permissions: forbid certain commands, like publishing or deleting. It's the simplest option, a few lines of settings.
- Hooks: a script that runs before an action and blocks it if it breaks the rule.
- Don't give access: if the AI doesn't have the key, it can't use it. A draft that waits for your click instead of a direct send.
- Checks in the code: tests that must pass, a check that can only add caution.
One catch: each tool has its own settings. Claude Code's permissions don't apply to Codex, and the other way round. A red line has to be locked in every tool that could cross it.
Text and code work together
I keep the written rule even when code locks it. It explains why the limit exists, and it covers the cases the code can't see. It also says what to do when a lock fires: tell me, and don't rephrase the request to get around it. Text guides the AI in almost every case, and code holds the line in the ones that matter.
