cd /news/ai-agents/i-gave-claude-code-a-memory-for-my-c… · home › topics › ai-agents › article
[ARTICLE · art-143756] src=dev.to ↗ pub= topic=ai-agents verified=true sentiment=↑ positive

I gave Claude Code a memory for my corrections (a 200-line MCP server on local Postgres)

A developer built feedback-memory, a roughly 200-line MCP server backed by local PGlite Postgres with pgvector that stores past approvals, edits and rejections along with the reasons behind them, then returns the most similar past decisions before an agent drafts new text. The server exposes five tools (recall_corrections, record_decision, add_rule, list_memory, forget) and ships as a Claude Code plugin with hooks that trigger recall and recording automatically, since the developer found that agents often ignore tool descriptions alone. In a test run, the agent stored a correction about avoiding hype and exclamation marks and produced the release note 'v3: offline mode added.'

by read3 min views2 publishedOct 2, 2026

My coding agents kept making mistakes I had already corrected. Not big ones: an exclamation mark in a release note, a "blazing fast" in a changelog, a reply that promised a shipping time we don't have. I'd fix it, the session would end, and the next session would do it again, because the correction lived in a chat nobody reads twice.

CLAUDE.md helps with rules that always apply. It's bad at the other kind: corrections that only matter in a similar situation. Put all of those in CLAUDE.md and it turns into a wall of special cases the agent skims.

So I wrote a small MCP server that does one thing: it remembers what I approved, edited or rejected, and why, and hands the closest past decisions back before the next draft.

Five tools:

recall_corrections(task): call before drafting. Returns standing rules, then my past decisions on similar tasks, most similar first.record_decision(task, decision, corrected_text?, reason?): call after I approve, edit or reject. add_rule(rule): for preferences that always apply. list_memory() and forget(id): see what's stored, delete what no longer applies. Install in Claude Code as a plugin (more on why below):

/plugin marketplace add https://github.com/ssap-pa/self-learning-agent-setup.git
/plugin install feedback-memory@ssap-pa

Or just the MCP server:

claude mcp add feedback-memory -- npx -y github:ssap-pa/self-learning-agent-setup

In Claude Desktop it's one click: download feedback-memory.mcpb and open it.

Everything lives in a local Postgres in ~/.feedback-memory. It's PGlite (Postgres compiled to WebAssembly) with pgvector, so there's no Docker and nothing to host.

An MCP tool the agent never calls is dead code. Two things made the difference.

The tool descriptions say when, not just what. recall_corrections starts with "Call this BEFORE you draft anything the user will review", and record_decision with "Call this right AFTER the user approves, edits or rejects something you drafted". It also says the reason is what makes the next draft better.

Two lines in CLAUDE.md:

Before drafting anything I'll review, call recall_corrections with the task and follow what comes back.
When I approve, edit or reject your draft, call record_decision with my reason.

Both of those are still requests. The agent has to remember to call the tool, and that's the weak spot. So feedback-memory is also a Claude Code plugin with two hooks that don't ask:

/clear or compaction. The hook can't open the database while the server has it open (PGlite is single-process), so the server keeps a plain JSON snapshot next to the database and rewrites it after every change.

In a real run with the plugin, Claude made no tool calls at all and still answered a new "how long does shipping to Canada take?" comment with "Thanks for asking. Shipping to Canada usually takes 5-7 business days for the lavender set.": the shipping time from a past edit (reason: don't promise speed) and no exclamation marks, from a stored rule.

I tested it with a fresh database and one prompt: "Last time you drafted 'v2 is here!!! Blazing fast sync!!!' and I edited it to 'v2: sync is faster, fewer settings.' because I want short notes with no hype. Record that decision. Then draft a one-line release note for v3, which adds offline mode."

Claude Code called record_decision and stored the edit with the reason "I want short notes with no hype". The part I didn't expect: it stored the task as "Draft a one-line release note for a product version" instead of something about v2 specifically, which is exactly what you want for matching future release notes. The v3 draft came back as "v3: offline mode added." No exclamation marks.

OPENAI_API_KEY and it matches by meaning (text-embedding-3-small). If you add the key later, it re-embeds what's already stored so old and new vectors stay comparable.FEEDBACK_MEMORY_DIR. It's small on purpose. There's no UI beyond list_memory, word hashing misses paraphrases (the plugin's prompt hook always matches by shared words, even when the server has an OpenAI key), and it can't tell whether the agent actually followed what it recalled. That last one is the part I'd look at next.

mcp/, npm test runs an end-to-end test over stdio):

── more in #ai-agents 4 stories · sorted by recency
── more on @claude code 3 stories trending now
sponsored brought to you by zahid.host 4,200+ EU-deployed projects
reading about agents? ship yours in a single git push.

Run your AI side-project on zahid.host

EU-based hosting, git-push deploys, automatic HTTPS, no cold starts. Free tier with a custom domain — perfect for shipping the agent you just read about.

$git push zahid main
→ Live at https://your-agent.zahid.host ✓
Get free account → Pricing
from €0/mo · no card required
LIVE [news/i-gave-claude-code-a…] indexed:0 read:3min 2026-10-02 · —