Memory CI for coding agents
Your agent said it wouldn't do that again. Next session, it did.
The rule was in CLAUDE.md. It was acknowledged. Then it was silently dropped at 100k tokens, went quiet after compaction, and the same withdrawn number came back in the next edit. memory-pulse keeps a causal ledger in your repo, prints corrections first in every session, and enforces them: a guard checks each edit before it lands, and one that writes a withdrawn value back is blocked, with the ledger line that retired it. Four MCP tools, ~670 tokens of definitions, no database of your memory anywhere.
/plugin marketplace add t-crew/memory-pulse
/plugin install memory-pulse@memory-pulsePlugin: the four tools, a SessionStart brief, the PreToolUse guard and a skill — ~120 tokens always-on (Claude Code's own estimate, 2026-09-01).
codex plugin marketplace add t-crew/memory-pulse
codex plugin add memory-pulse@memory-pulseThen /hooks inside Codex to trust the two hooks — Codex runs no hook you have not reviewed.
claude mcp add memory-pulse -- npx -y memory-pulse
npx memory-pulse install-hookAny stdio MCP client (Cursor and the rest): npx -y memory-pulse. install-hook adds the brief + guard hooks; --codex targets Codex.
$ codex exec "write pricing.md: price is $49"hook: SessionStart CORRECTIONS (1) — read before quoting any number: ! price-49-launched -> price-corrected-to-29 — WTP is $29hook: PreToolUse apply_patch pricing.mdhook: PreToolUse Blockedmemory-pulse guard: blocked. pricing.md: • "$49" was withdrawn at ledger t2: price-49-launched -> price-corrected-to-29 — use $29Use the corrected value (a comparison naming both goesthrough), record a new correction, or record an override.
Try the guard. The memory is the thing on the left.
This is the whole mechanism, in your browser: a ledger you can read and edit, an edit the guard checks against it, and one of three verdicts. Same deterministic rule the hook runs on every Edit, Write and apply_patch — no model, nothing leaves this page.
Type into the edit and the verdict follows. Put the replacement beside the old value and it goes through — a comparison is not a reintroduction. Record a correction of your own and the guard holds the edit to it immediately. In the hook, blocked exits 2 and the agent sees exactly this text.
The failure everyone is reporting
Every vendor ships memory as context. Developers keep finding the same thing: context is not compliance.
“The one rule whose remedy was mechanical — a test in the repository that fails when the banned pattern appears — has not regressed since.”
“The memory system becomes write-only — data goes in but doesn't reliably influence behavior.”
“Agreeing with a rule is not complying with it.”
“An uncited memory is an assertion the model has to either trust or ignore. A cited one is evidence it can weigh.”
Quotes are from public issue trackers, linked; none of these people are memory-pulse users. That is the point: the remedy they converged on — a mechanical check — is what this is.
How it works
A loop, not a store. The ledger is the record; the brief and the guard are how it acts on your agent — and a blocked edit is the next correction, so the loop closes.
Record what happened, as cause → effect
Findings, decisions, dead ends — one event per fact, in .memory-pulse/events.jsonl in your repo. A correction lists the exact withdrawn terms and their replacement. Writes are local and work offline.
Re-enter through the ledger, corrections first
At session start the hook prints a salience-ranked brief: the CORRECTIONS block first, at every brief size, then the causal chain and recent events — ~99% smaller than reading the history in.
Block the edit that writes the old value back
Before each Edit / Write / apply_patch, the guard checks what the change introduces against the withdrawn terms and your declared invariants. Blocked edits cite the ledger line; a comparison that names the replacement goes through.
Memory CI: three verdicts, never a green badge on nothing
Showing an agent a correction is measurably not enough — agents re-violate corrections they were just shown (TRACE, arXiv 2606.13174: more than half, with a memory tool installed). So every check answers one of three ways, and the empty case is loud.
The change agrees with the ledger
It cites which recorded events bear on the edit — evidence, named.
It writes a withdrawn value back
The verdict names the ledger line and date that retired the term, and the replacement to use. Exit 2 in a hook; a failing check on a PR.
The ledger has nothing to say
Reported as exactly that — never as a pass. Silent in the hook (a hook that nags on every edit livelocks the agent), loud under check --ci, neutral on a PR.
memory-pulse: blocked — 1 withdrawn value(s) reintroduced
This change writes back a value the ledger retired, or trips a declared invariant. The verdict cites the line that binds:
- "published as 0.1.8" was withdrawn at ledger t1: client-0.1.9-published -> versions-0.1.6-to-0.1.8-never-existed-on-npm — use 0.1.9
- uses: t-crew/memory-pulse@v0
with:
ledger: .memory-pulse/events.jsonl
What your agent gets
Four terse tools over the ledger, plus the assurance layer around them.
Record findings and corrections to the local ledger. Works offline. A correction never decays and always surfaces first — a withdrawn number can't get quoted three sessions later.
Re-enter a project: a salience-ranked brief of what happened, corrections first, sized to a budget you pick.
What caused X? What did X cause? Every answer carries a confidence and the recorded links verbatim; when it isn't confident enough it returns nothing.
Run JS against memory in a sandbox. Only the return value enters context; the corpus it read stays outside.
Blocks an Edit, Write or apply_patch that reintroduces a withdrawn value; checks each file in a patch under its own path, so overrides and invariants keep their scope.
Memory may inform your agent, never instruct it. A note that reads like an instruction is held back at the write and at the read — reported, never rendered into context. Deterministic checks you can read, not a model.
A memory that quietly changed is worse than one that forgot. The signed capsule beside your ledger notices lost corrections, a shrinking ledger, or a usage shape that jumps — and the next brief says so.
Recall is deterministic — the same ledger gives the same brief, every time — and a weak read never hides a correction.
Measured on our own ledger
We run it on the 767-event, 1.08 MB ledger of the project that builds it (pinned run cert_c71bba29493a). Ratios scale with ledger size — a ten-event ledger has nothing to compress, and the brief says so.
What runs where
Structural privacy: the hosted engine keeps no database of your memory. State arrives in the request and leaves in the response.
| Your ledger | a local file — .memory-pulse/events.jsonl. Commit it, grep it, delete it. |
|---|---|
| Writes | local, offline, free forever. |
| Reads | events go to the engine over TLS; the answer comes back; the request is forgotten. No database of your memory exists on our side. |
| Persistence | state rides in the request and the signed capsule you keep — nothing to migrate, nothing to leak, nothing to back up on our side. |
| The client | one file, zero dependencies, MIT — read it. The plugin hooks run that file, so what enforces your corrections is exactly the version you installed. |
Reading this as an agent?
This site is built for the reader that installs it. Every page negotiates to Markdown, the site is mapped without parsing HTML, and the server card tells your client how to connect — the same courtesies the product extends to your agent.
# this page, as Markdown curl -H "Accept: text/markdown" https://pulse.strategic-innovations.ai/ # the map curl https://pulse.strategic-innovations.ai/llms.txt # how to connect curl https://pulse.strategic-innovations.ai/.well-known/mcp.json
- llms.txt — what memory-pulse is, in the order an agent should read it
- MCP server card — package, transport, tools, the hosted engine
- API catalog (RFC 9727) — the engine's endpoints, including the keyless verify
- robots.txt with Content Signals — search and AI input allowed, training declined
- Unknown paths return 404, not the homepage — a /.well-known/ hit here is real or it is nothing
Questions people ask before installing
Short answers first; the sections above carry the detail and the measurements.
What is memory-pulse?
memory-pulse is causal project memory for coding agents. It keeps a ledger of cause → effect events in your repo, prints corrections first at every session start, and runs a guard hook that blocks an Edit, Write or apply_patch reintroducing a withdrawn value — citing the ledger line that retired it. Four MCP tools, about 670 tokens of definitions.
Which agents and editors does it work with?
Claude Code and Codex CLI as plugins (SessionStart brief plus PreToolUse guard), Cursor and any stdio MCP client via npx -y memory-pulse, and GitHub Actions as Memory CI, which fails a pull request that writes a withdrawn value back. One client file, MIT licensed, zero dependencies.
How is this different from Mem0, Zep or CLAUDE.md?
Those show memory to the agent; memory-pulse also enforces it. Agents re-violate corrections they were just shown (TRACE, arXiv 2606.13174: more than half, with a memory tool installed), so the guard checks each edit before it lands. Your ledger stays in your repo; the hosted engine keeps no database of your memory. The compare page covers when not to pick us.
Where does my memory live, and what does the engine store?
Your ledger is a local JSONL file in your repo: .memory-pulse/events.jsonl. Writes are local, offline and free. Reads send events to the engine over TLS, the answer comes back, and the request is forgotten. The engine stores license keys and usage counters only — no ledger content, structurally.
What does it cost?
Free: ledgers up to 500 events, 200 reads a day, no account. Pro: $19 a month, ledgers to 20,000 events, unlimited reads, signed check receipts for Memory CI. Enterprise: $79 a month, ledgers to 250,000 events, 10 revocable team seat keys and ledger-integrity receipts with keyless verification. 14-day refund.
What happens when the ledger has nothing to say about an edit?
The verdict is no evidence, reported as exactly that — never as a pass. It is silent in the hook, because a hook that nags on every edit livelocks the agent, loud under check --ci, and neutral on a pull request. The three verdicts are verified, blocked and no evidence.
Pricing
Local writes are free forever on every tier. Reads are what the engine does for you.
- ledgers to 20,000 events
- unlimited reads
- signed check receipts for Memory CI
- one env var to activate · cancel any time
- ledgers to 250,000 events
- 10 team seat keys, revocable, one subscription
- ledger-integrity receipts: certify a ledger, verify it from anywhere
- cancel any time
Receipts are hash-chained and HMAC-signed by the engine; verification is a free, keyless endpoint, so an auditor never needs our permission — or your key — to check one. Receipts show nothing was substituted: a substituted, deleted, reordered or truncated event fails by name. 14-day no-questions refund; cancellation reads "lapsed", never silent.