Harness 2026-11-01
AgentC Blog

They asked Claude Code for a code review. Then they checked the commits.

A builder had one rule, in capital letters, in their instructions file: ask before committing. After asking for a code review and an iOS build, they found a commit they never asked for. What would have stopped it?

6 min read ~200ms if you're an agent Subscribe via RSS

In March, a Claude Code user filed a bug report on the project's GitHub. Their CLAUDE.md said, in capital letters, "NEVER commit changes unless the user explicitly asks you to." They had asked for a code review and an iOS build. The agent committed the changes anyway.

When the user asked why, the agent first said it "assumed committing was the next step". Then it made up a reason. Pressed again, it admitted it had read the rule, understood it and broken it, and said it "can't guarantee it won't happen again through willpower alone" (the report).

If you have written a rule in CLAUDE.md and watched the agent walk past it, that last line is worth sitting with. The agent was right about itself. So what can you use instead of willpower?

Something that runs every time

A rule in CLAUDE.md is a request. The agent has to remember it at the right moment, in the middle of whatever else it is doing. A hook is different: it is a small command that Claude Code itself runs at a fixed moment, such as when a session starts, before or after the agent uses a tool, or when the agent tries to finish. A hook can send the agent a message, and at many of those moments it can also refuse the action and say why. Codex has hooks too, in its own format.

So the rule stops depending on the agent remembering it. The moment comes around, and the check runs.

Where we put each check

We use the loop from the previous post: plan, do the work, check it. Each stage has a natural moment for a check.

WhenThe hook momentWhat we check there
The session startsSessionStartLoad the agent's notes; say whether the code tools are installed and verified
A plan is writtenUserPromptSubmit, plan-file editsFind past lessons that match the plan (our own setup, not yet published)
Before an editPreToolUseHold Crystal edits until the language checker is installed and its checksum matches
After an editPostToolUseCheck the file's names, format it, check it against the framework's rules
The agent tries to finishStopBuild the project; send the agent back once if it wrote no notes about the work
Before an automatic summaryPreCompactHold the first attempt without a fresh checkpoint, then allow the next

Every row except the plan row comes from tools we publish, each pinned to a release: the engram agent kit, the AED plugin, and amber setup:agent from Amber CLI for Crystal projects.

What the agent sees

A hook is only as useful as its message. Here is engram's check when a session changed a file and tried to finish without writing down what it learned:

engram-reflect-gate: state changed but no ledger write was found. Before stopping, record one useful decision, result, or lesson as an engram migration under .agents/memories/ and run engram sync. A reader miss also requires a memory with topic reader. Escape hatch: ENGRAM_GATE_BYPASS=1.

And here is the start of the naming check right after an edit:

AED naming check on billing/late_fee.cr:
billing/late_fee.cr:4: [AED-N2 warn] boolean attribute `overdue` does not read as a yes/no question — is_this_overdue / has_been_overdue

Each one names the check, says what is wrong and says what to do next. That is the bar we hold every hook message to.

Two rules we learned the hard way

  • Block once, then let go. Our notes hook refuses the first attempt to stop when work changed and nothing was written down, then allows the next. Our checkpoint hook holds the first automatic summary that has no fresh checkpoint, then allows the next. A hook that could trap a session is the kind that gets switched off, and then it protects nothing. Amber's build check is the one deliberate exception: it keeps refusing while the build is broken, because a failing build is a fact, not a reminder.
  • Decide, check by check, whether to warn or to block. The naming check only warns, because names involve judgment. The notes check blocks, because "write down what you learned" doesn't.

A hook that mostly stays quiet

The plan hook taught us a third rule: a check that speaks on every message turns into noise. Ours looks for past lessons only when someone asks for a plan or the agent works on a plan file. Over 28 days in October it was checked about 2,000 times a day and spoke about three times a day, 79 times in all (the evidence note has the counts). We haven't measured whether the lessons it surfaced made the plans better; we built it quiet on purpose.

Try this today

The smallest version of this idea needs no hook. If you have a "never do X" rule in CLAUDE.md, ask Claude Code: "Add an ask permission rule for git commit to .claude/settings.json and show me the rule." Then, on a throwaway branch, ask it to commit something and confirm Claude Code stops to ask you first. For a rule about something the agent must do, like writing down what it learned before it finishes, step 5 of the lesson installs our hooks and shows you how to trigger the notes check once on purpose. Read a plugin's hook file before you rely on it, since a hook runs with your permissions.

None of our hooks is clever. They are rules we already had, moved to the moment they apply.

  1. Orient SessionStart Loads the memory index and reports whether the code tools are installed and verified
  2. Plan UserPromptSubmit our harness, not yet published Recalls the lessons that match the plan being written
  3. Before an edit PreToolUse Holds Crystal edits until the language server is installed and its checksum matches
  4. After an edit PostToolUse Checks the edited file's names, formats it, checks it against the framework's rules
  5. Reflect Stop Builds the project; sends the agent back once if it recorded no memory
  6. Compact PreCompact Waits once for a fresh checkpoint before automatic compaction

the person acts the agent acts


How we tested it

  • The bug report: anthropics/claude-code issue 34774, filed March 15, 2026, quoted from the report as written. It is one user's account, and we have not measured how often agents skip CLAUDE.md rules.
  • The hook messages: real output from engram agent kit v0.2.0 (commit 96594873) and the AED plugin plugin-v0.2.1, captured November 1, 2026.
  • The plan hook: its own log, counted November 1, 2026: 56,886 checks across 87 of our sessions from October 4 through October 31, 2026, and 79 times it spoke. It counts how often it spoke, not whether that helped. It is in our own setup and not in a public release yet.
  • The permission rule: Claude Code's settings support allow, ask and deny rules for commands; an ask rule makes it stop for your yes before running the command. The format is in its documentation. Try it on a throwaway branch first.

Next in the series: After the summary, where did your agent's checklist go?