>_

Claude Code Saves Corrections but Does Not Enforce Them

Robin||5 min
Last updated: August 17, 2026
claude-codehooksautomationself-correction
Claude Code Saves Corrections but Does Not Enforce Them

I wrote this in February 2026, when a correction really did die with the session. I had corrected Claude Code on the same preference four times in a week, and each time the adjustment went out with the context window.

That part is largely fixed, and not by me. Claude Code now ships auto memory, on by default, described in Anthropic's own docs as "notes Claude writes itself based on your corrections and preferences". If you correct Claude today, there is a good chance it writes that down without being asked. Not a certainty - the docs are clear that Claude decides - but the default is no longer zero.

So the interesting question moved. Survival is no longer the whole question - it is narrower now. A correction may survive, if Claude judged it worth writing, and if the index it lands in has not outgrown what loads. What is left over is what a surviving correction is actually worth, and there the docs are blunt: memory files and CLAUDE.md alike are "context, not enforced configuration". If something has to happen regardless of what Claude decides, the documented answer is a PreToolUse hook that blocks the action.

Be clear about what follows, because the honest version is less than the title promises. What I built catches corrections; it does not turn them into rules on its own, and that was a deliberate design decision I still think was right. Where auto memory saves what Claude judged worth a note, my hook saves what matched a pattern I defined - a different filter, not a better one, and the confidence threshold below means it misses things too. Everything downstream of that catch is gated on me saying yes.

The rest of this post is that mechanism, the reason for the gate, and the part I designed and never finished building.

Want the foundational patterns first? The free 3-pattern guide covers memory, delegation, and knowledge graphs at concept level.

The Problem: A Saved Note Is Not an Enforced Rule

Here's a concrete example. I prefer snake_case for Python variables. In February, every session where Python came up, I corrected it, and the next session started from the same default.

Today auto memory may well save that preference. What it saves is a note, and the note is loaded as context alongside everything else competing for Claude's attention. Anthropic's docs are explicit that this is not enforcement: "Claude treats them as context, not enforced configuration. To block an action regardless of what Claude decides, use a PreToolUse hook instead."

Three further limits are worth knowing, all documented. Claude "doesn't save something every session. It decides what's worth remembering", so a given correction may simply not be written. Only the first 200 lines or 25KB of MEMORY.md load at session start, and anything past that is not loaded then. And detail gets moved into topic files that are not loaded at startup at all - Claude reads them on demand. One more if you work on two machines: the auto memory store is machine-local and scoped to a single repository. The rule files further down behave differently - project rules in .claude/rules/ are committed and travel with the repo, and personal ones in ~/.claude/rules/ apply to every project on that machine.

So the pattern that remains is narrower than the one I described in February, and more specific: a preference can be saved, loaded, and still not acted on. Typing it as a rule does not change that - a rule file is context too. What typing buys you is that the preference is written down in a form specific enough to act on, and the docs do say specific instructions are followed more consistently than vague ones. That is the whole claim.

Auto memory alone
  • -Claude decides what is worth saving
  • -Saved as a note, loaded as context, not enforced
  • -Index capped at 200 lines / 25KB per session
  • -No type, no staging, no second look
With the correction-to-rule hook
  • +Correction detected automatically (8 patterns)
  • +Caught on a fixed rule, not on Claude's judgement
  • +Logged as an experience and queued for the graph
  • +A rule is offered, never written without my yes

The Hook: Catching a Correction Before It Evaporates

I built a UserPromptSubmit hook - it fires on every message I send to Claude. Its job is to detect whether my message is correcting Claude's behavior, and if so, capture it before it evaporates.

The detection works across eight correction patterns. Some are explicit: "no, not like that" or "stop doing X". Some are implicit: "instead, try Y" or "can you do this differently". Some are evaluative: "that's too verbose" or "you're overcomplicating this" - and if you find yourself giving that first one repeatedly, the reason style rules stop working is a separate problem a rule will not fix. A separate pattern catches repeated mistakes that surface across turns. Each pattern has a confidence weight based on how reliably it signals a genuine correction versus frustration or clarification.

When a correction scores 75 or above, the hook does four things, and none of them is "write a rule": it logs the correction to a history file, creates an experience record, queues an entry for my knowledge graph, and returns a message I have to acknowledge before the session continues. The experience and the queue entry have a second gate of their own - a single weak pattern in a short message logs the correction but does not become an experience.

Then it stops. The message ends with the words "consider whether a Rule should come from the pattern", and that nudge is the entire rule step. Nothing is generated, nothing is staged. Turning it into an actual rule is a separate, manual path that asks me first.

And I should apply my own standard here rather than only to Anthropic: that message is injected as context. It does not block anything. When I said above that memory files are "context, not enforced configuration", my hook is the same class of object - it is a very insistent note. The only thing on this page that actually stops an action is a PreToolUse hook, and this is not one.

What Actually Runs
User corrects Claude's behavior
v
Hook detects correction pattern (8 types)
v
Confidence score calculated (fires at 75)
v
Experience logged + knowledge-graph entry queued
v
Acknowledgment forced before the session continues
v
A one-line nudge to consider a rule. No draft is written
Self-Learning Architecture
Rule LayerA nudge in the message. Nothing is generated
Capture LayerExperience record + knowledge-graph entry + forced acknowledgment
Scoring LayerComposite confidence, fires at 75
Detection Layer8 correction patterns with confidence weights (0.65-0.95)

The Gate, and Why It Is There

Immediately promoting a correction to a permanent rule would be a mistake. A single frustrated "no" shouldn't reshape behavior forever. Context matters. Tone matters. Sometimes a correction is task-specific, not general.

So the rule step asks. The hook detects and captures; generating an actual rule file is triggered only when I confirm it, and what it would write is a draft - a candidate. My own rule for this says it in one line: candidate rules are not automatically active, they are not loaded at session start, and they have to be reviewed and promoted explicitly.

That is the whole safety property, and it is worth more than the automation it replaced. A hook that writes its own rules is a system that edits its own instructions between sessions, unsupervised, based on a regex hitting the word "no". I did not want that, and I still do not.

There is a second reason the gate is right, which I only appreciated later: my hook fires on my messages. It sees what I type. It cannot see what Claude did, so it can never tell whether a rule it wrote was followed. Anything that promoted rules on "no further complaints" would be reading silence as success.

What I Never Finished

Here is the part I owe you, because the original version of this post described it as if it were running.

The promotion layer - candidate to trial to stable, confidence scores, auto-archival - is designed but not built. The design is real: there is a staging directory, a template, a schema with confidence thresholds and a promotion counter. The /rules-review command that is supposed to list and promote candidates has a documentation file and no implementation; the script it names was never added to the repository, in the entire history.

The counters say the rest. Rules generated, ever: zero. Promoted: zero. Currently staged: zero.

The capture half, meanwhile, has been running the whole time: 142 of my 464 stored experiences are correction-tagged (counted 2026-08-17; it is a live file and still growing). So the honest scorecard is that the detector works and has worked for months, and the thing it was supposed to feed never got written.

I left it that way on purpose once I understood the gate argument, and then never went back to make the design match. If you clone the detector, you are cloning the half that works.

A Concrete Example, and What It Taught Me

The example I originally used here was this. I was running a code review session, Claude picked Haiku, and I typed:

no, use Sonnet for this, not Haiku.

I wrote that the hook fired, classified it as an override, and pushed the confidence well above threshold. Before republishing this post I ran the real functions against that exact string:

code
detect_patterns("no, use Sonnet for this, not Haiku.")  ->  []
calculate_confidence(...)                               ->  (0, None)

Zero patterns. Nothing fires. The reason is embarrassing and instructive: the negation keyword list contains nein and not no. I built this hook while working in German and never noticed that the single most common English correction word is missing from it.

It gets better. The German version does match - and still does not fire:

code
detect_patterns("nein, nimm Sonnet dafuer, nicht Haiku")
  ->  [explicit_negation, weight 0.90]
calculate_confidence(...)  ->  73

Seventy-three, against a threshold of seventy-five. A clean, unambiguous, correctly-worded correction lands two points short.

So the honest worked example is that my worked example does not work. The detector fires on longer, more emphatic corrections - repeated mistakes, multi-pattern messages, the ones where I am visibly annoyed - and quietly misses the short precise ones. That is a real bias in what my 142 captures represent, and I did not know it until I checked my own post.

The negation keyword list contains "nein" and not "no". I never noticed.

Where This Actually Differs from Auto Memory

Auto memory stores what Claude judged worth remembering - build commands, debugging insights, preferences it observed. That is genuinely useful, and since it is on by default you get it for free. What it produces is a note, and Anthropic's docs are clear that notes are loaded as context rather than enforced.

What my hook adds is not a rule. It is determinism about the catch. Auto memory saves a correction if Claude judges it worth saving; my hook saves it if it matches a pattern above a threshold I set. Neither of those is better in the abstract - but mine is inspectable, and I can point at the captures and the patterns that produced them.

The rule step is where the two would genuinely diverge, because a rule is a different object from a note: "Robin prefers Sonnet" is a fact, "Prefer Sonnet for code review tasks" is a directive. But neither guarantees behaviour - a rule file is the same class of object as CLAUDE.md, and the docs say plainly that these "shape Claude's behavior but are not a hard enforcement layer". What a rule buys is specificity, and the docs agree specific instructions are followed more consistently than vague ones. That is the whole prize, and it is smaller than it sounds.

I built something similar for context drift in long sessions - a hook that injects relevant context mid-session when Claude's attention drifts. That hook reads the AI's reasoning. This hook reads my corrections. Both are feedback loops, but they operate on different signals: one monitors the AI, the other monitors me.

I looked for prior work while building this. Reflexion (2023) and Google's RL self-correction research both address in-session correction - the model corrects itself within a single context window. Neither generates persistent rules that survive session boundaries.

The gated rule step is the piece I haven't seen elsewhere - and, per the section above, the piece I never finished. Take it as a design worth copying rather than a system worth cloning.

The Before and After

In February, before both this hook and auto memory: five sessions, five corrections, five resets. Every preference I had that deviated from defaults was a tax I paid repeatedly.

Auto memory made that tax smaller and less predictable rather than gone. Some corrections stick because Claude wrote them down. Some do not, because it judged them not worth remembering. From the outside you cannot tell which.

With the hook: I correct something once and it is definitely written down, in a form I can grep, with the pattern and score that caught it. That is a smaller claim than "fixed forever" and it is the one I can back.

What that buys over months is a corpus rather than a rule set - roughly 140 captured corrections that any session can read as context, and that I can go through when I want to see what I actually keep correcting. This pairs with the broader hook automation system that handles everything from context management to delegation.

The detection hook lives in Evolving Lite as correction-detector.py. Free and open source - but be precise about what ported, because I was not when I first wrote this. The eight patterns and their weights are byte-identical. The scoring is not: the Lite fork fires at 50 instead of 75, only activates from your third session onward, and is missing two things the full version has - a bonus for repeat corrections, and a step that strips quoted text before matching. That second one exists because quoting somebody else's "no, that's wrong" used to trip the detector. Lite will do that.

The rule-generation and promotion layer above it is designed, gated on explicit confirmation, and unimplemented. Treat the schema as a blueprint, not a download.

This lives in primeline-ai/evolving-lite - the self-evolving Claude Code plugin. Free, MIT, no build step.

FAQ

What types of corrections does the hook detect?+
Eight pattern types: explicit negation, alternative suggestions, wrong assumption corrections, override commands, too-much feedback, clarifications, preference corrections, and repeated-mistake detection. Each pattern carries a confidence weight between 0.65 and 0.95 based on how reliably it signals a genuine behavioral correction.
Why does the hook ask before writing a rule?+
Because a hook that writes its own rules is a system editing its own instructions between sessions, unsupervised, on the strength of a pattern match. A single frustrated correction during a difficult debug session shouldn't earn a permanent place in every future context window. The rule step is therefore gated on explicit confirmation, and anything it writes is a candidate: not loaded at session start, and promoted only by explicit review.
Does this work across different Claude Code sessions?+
Yes, but through the experience log rather than through rule files. A detected correction is written to disk and read back as context in later sessions. Cross-session persistence is no longer the differentiator it was in February 2026 - Claude Code auto memory is on by default and persists too. What differs is that the catch is deterministic: it fires on a pattern above a threshold I set, rather than on Claude judging the correction worth remembering. Being in context is still not the same as being obeyed; only a PreToolUse hook blocks an action outright, and this hook is not that.
How is this different from Claude Code's built-in auto memory?+
Less than the original version of this post claimed. Auto memory writes notes about what Claude judged worth remembering; this hook writes an experience record whenever a message matches one of eight correction patterns above a confidence threshold. The difference is who decides and whether you can inspect the decision - not enforcement, since Anthropic's docs describe memory files as context rather than enforced configuration and only a PreToolUse hook blocks an action. The rule-generation layer that would have been a real difference is designed, deliberately gated on confirmation, and never implemented: zero rules generated to date.

>_ Get the free Claude Code guide

>_ No spam. Unsubscribe anytime.

>_ Related