All thoughts

Hard Rules Inside Claude Code

AI agents are good but never fully predictable. Claude Code mods let me put hard rules around one, and the simple ones cost nothing to run.

How it works

How a mod runs, step by stepFive blocks in a row joined by arrows. Only the fourth block, the mod, is gold.1. You ask: a prompt or a task. 2. Claude acts: starts a step, like a tool. 3. Event fires: Claude Code announces it. 4. Mod runs: your code, no model call by default (highlighted). 5. Result: passed on, changed or stopped. 01You aska prompt or atask02Claude actsstarts a step,like a tool03Event firesClaude Codeannounces it04Mod runsyour code, nomodel call bydefault05Resultpassed on,changed orstopped
Select a step to see what it does.
One trip through Claude Code. The mod is the only gold step: plain code that runs every time its event fires, then lets the step through, changes it, or stops it.

Anthropic added mods to Claude Code. As it works, Claude Code fires events: a prompt is submitted, a tool is about to run, a request is about to go to the model, a subagent is about to start, the conversation is about to be compacted. A mod is a TypeScript or JavaScript handler for those events. It can read the event, pass it on, change it, or stop it.

In LEGO terms, the events are the touches, and a mod is the piece that lights up every time its touch comes.

The details that matter to me:

  • Mods live in plugins. You install them with /plugin, and they run in the CLI and the desktop app.
  • Claude Code has a built-in skill for writing them, so I can describe a rule and have it drafted, installed and reloaded in the same session.
  • /diff is a mod now. Anthropic moved some of its own features onto the same system.
  • Mods have your permissions and no sandbox. claude plugin validate shows what a plugin hooks into before you trust it.

Advice and rules

I sort the ways to steer Claude Code by one question: who makes sure it happens?

KindWhere it livesWho makes sure it happensModel call?
PromptThe message I sendThe model, if it reads it the way I meantYes
SkillA markdown file Claude can loadThe model, when it judges the skill relevantYes
HookA settings file: a command, HTTP call, MCP tool or promptClaude Code, on every matching eventOnly prompt and agent hooks
ModTypeScript or JavaScript in a pluginClaude Code, on every matching eventOnly if the mod asks for one

The top two are advice. The model weighs them, and most of the time it follows them. The bottom two are rules. Claude Code runs them whether the model agrees or not.

Hooks and mods share a lot. Anthropic's docs call a mod's handlers hooks, and call the settings-file kind "settings hooks." Settings hooks can allow, block or log an event. A mod can do that and also rewrite the event, add commands, draw its own panel, and replace pieces of the interface. Settings hooks are a simpler form of the same idea.

What it costs

A plain mod costs nothing in tokens. It's code reacting to an event, so it can run on every tool call and every turn.

Two costs to keep in mind. A mod can call a model on purpose, and that spends usage. And a mod that changes the system prompt between requests breaks the prompt cache, so every request after it costs more.

My take

In my factory, the agent is the one part I can't fully predict. Everything around it should be predictable: the logs, the checks, the gate before anything ships, and a person who says GO. Most of that layer usually sits outside the coding agent: CI, scripts, review. Mods let part of it run inside Claude Code itself, on every step.

Agents are probabilistic. A better prompt makes the right move more likely, never certain. What I can control is the layer around them. Lauren Tan's line from How I Use pstack applies here too: if you keep leaving the same comment, make it a rule the mistake can't get past. Because a plain mod is free to run, I can put the boring checks on every step, which is exactly where I want them.

Three jobs I'd give mods first

These are my picks, named for what they do in my setup. The pieces they need are all in Anthropic's docs. I haven't built them yet.

Claude Code with three mods addedA large block, Claude Code as it ships, sits on a deck in plain ink. Three small mods are attached to it and lit in amber: a run log high on its right side with a glowing tape, a model picker lower down wired to three model chips on the deck with the chosen chip lit, and a clean-slate cap on top with a dashed line passing a long run to a fresh session block at the front of the deck.Run logtraces each turnModel pickerper subagentClean slatehands off long runsFresh sessionclean contextClaude Codeas it ships

Key

  • Claude Codeas it ships
  • Gold box: a modruns on events; no model call unless it asks
  • Gold chipthe model picked; plain chips are the others
  • Dashed linea handoff to a fresh session
  • Plain blocka fresh session
Claude Code is the base plate as it ships, in plain ink. The gold parts are the pieces I'd snap on: a run log and a model picker on the side, and a clean-slate switch on top that passes a long run to a fresh session.

A run log. In Part 2 of the Agent OS series the step before shipping is "trace it, eval it." Mods can see that trace from inside. Each request to the model fires an event that reports the model that answered and the tokens it used. Each tool call fires an event, subagents included. Write both to a file and I have a record of every run to evaluate later. That's tracing with no extra model calls.

A model picker. I want the cheap model on searching and reading, and the strong one on the change itself. Claude Code already lets a subagent set its own model, in its definition or for all subagents with CLAUDE_CODE_SUBAGENT_MODEL. A mod can decide at the moment a subagent starts, or for a single request. Paired with the run log, I can check later whether the cheap model was good enough. Model choice becomes something I can measure.

A clean slate. Long sessions drift. Old context crowds out the task. Claude Code compacts on its own, and you can set when with /autocompact. A mod can read how full the context is at any point, read the transcript, ask for a compact, and send a message to another of my sessions. My plan: past a line I pick, write the open task and the decisions so far to a file, then hand that to a fresh session. One gap: I haven't found a documented way for a mod to start a new session by itself. It can message one that already exists.

Where my factory rules would go

The rules from my factory map onto mods almost directly. Still ideas:

  1. The eval gate. If Claude is about to call a task done and no test ran in that turn, send it back. Claude Code can already keep Claude working when a stop check fails, so the mod mostly has to remember which commands ran.
  2. The NDA guard. Anthropic lists redacting secrets from tool output as something a mod can do. I'd add a private list of names, and refuse any write that would put one of them in a public file.
  3. The human GO. Hold every git push until I say yes. Anthropic's docs include a mod that pauses a risky command and asks the user first. Mine would ask about every push.

None of this replaces evals or a real review. It makes the cheap checks happen every single time, so the expensive ones can spend their attention on judgment.

Try this

  1. Run /plugin to see what you already have installed. Before you add a plugin with mods, run claude plugin validate on it and read what it hooks into.
  2. Pick one comment you keep repeating to your agent. For example: "run the tests before you say it's done." Ask Claude Code to draft it as a mod with its built-in skill, and read the code before you install it.

Sources