Skip to main content

memware

Memory for AI agents that only remembers the latest truth.

memware is one SQLite file with two stores:

  • turns — immutable evidence. Every prompt and answer from past sessions, split into ~400-token passages and indexed with FTS5. Recall ranks passages and quotes only the matching ones; reading a session back returns whole turns. BM25 × recency × use, no model in the loop.
  • beliefs — a bi-temporal ledger of facts. A new value for the same (subject, relation) supersedes the old one. Recall only ever returns the currently valid belief; history is kept for audit and never reaches a prompt.

No daemon, no vector database, no LLM call at capture or read time. A 30-day corpus of a busy coding agent — 18k turns, 40k passages — indexes in about fourteen seconds into ~120 MB.

$ memware sync ~/.claude/projects --harness claude-code
{"added": 14348, "files": 1475}

$ memware assert "api" "listens on port" "8443" --source "session 3f2a, turn 41"
{"outcome": "superseded", "belief_id": 2, "incumbent_id": 1}

$ memware recall "which port does the api use" --what beliefs
api listens on port 8443            # 8080 is in the ledger, retired, and never surfaces

Why

Agent memory systems that rewrite what they remember degrade: continuous LLM consolidation can push utility below having no memory at all (Useful Memories Become Faulty When Continuously Updated by LLMs). And embeddings cannot tell a contradicted fact from a rephrased one — AUROC 0.59 — so vector stores serve stale facts 15–40% of the time on evolving knowledge (Temporal Validity in Retrieval Memory).

memware borrows four mechanisms from human memory research and keeps them deliberately small:

mechanism in the brain in memware
evidence ≠ belief hippocampus vs neocortex (complementary learning systems) turn table is append-only; belief table is separate
update on surprise reconsolidation driven by prediction error memware assert at the moment an agent notices a conflict
only the latest understanding reconsolidated traces overwrite in place deterministic supersession keyed on (subject, relation), ordered by event time
need-probability recall Anderson & Schooler 1991 / ACT-R activation bm25 × (1+age)^-d × (1 + w·ln(1+uses))

Full rationale and citations: docs/design.md.

Install

The Claude Code plugin's hooks call memware as a bare command, so the CLI must be on the PATH your shell uses — install it as a tool, not into a project virtualenv:

uv tool install "memware[mcp]"     # recommended
# or
pipx install "memware[mcp]"

Then confirm the shim resolves (if this prints nothing, the hooks will silently do nothing):

memware --version
which memware
Plain pip install

pip install "memware[mcp]" works for library and CLI use, but a plain pip install into a project or conda environment usually leaves memware off the PATH that Claude Code's hooks run under — use uv tool or pipx (above) for the plugin, or install into an environment that is always active. memware (core) omits the MCP server; drop [mcp] only if you do not want the MCP tools.

Use it from Claude Code

claude plugin marketplace add ericwalisko/memware
claude plugin install memware@memware
claude mcp add -s user memware -- memware-mcp   # optional tools; -s user = every project, not just this dir

Backfill your existing sessions (optional, once). The plugin only captures new sessions; index the transcripts already on disk so recall works over past work from day one:

memware backfill                 # indexes ~/.claude/projects (idempotent; ~5 s for a month)

Prefer a guided first run? memware setup walks through the backfill and backups together, asks whether derive may run automatically, and prints the operating guidance. Run it on a fresh install or after an upgrade. memware setup --yes accepts the defaults non-interactively and never switches derive on.

The belief ledger starts empty and is not backfilled — beliefs are derived, not stored in transcripts. It fills as you work (via the remember tool) and through memware derive, which mines the indexed transcripts for durable facts — see Deriving beliefs. Transcript recall is what backfill gives you immediately, and it is where most of the value is.

Requires the memware CLI on your PATH (see Install). Hooks: a SessionStart hook catches up any session whose SessionEnd was skipped (some environments force-kill Claude Code — a worktree manager may SIGKILL it — and a kill cannot run SessionEnd); a second one injects memware digest, a short block with this project's recent sessions and beliefs and a line pointing at recall; SessionEnd/PreCompact sync the transcript into the index; an optional UserPromptSubmit hook injects the handful of beliefs whose subject the prompt names, each with the date it was recorded (beliefs only — transcript search is on demand through the MCP tools). Neither block injects a derived measurement, moving version or status, or a version the project's manifest overrules; memware beliefs --stale lists what they leave out. Set MEMWARE_DB to move the store. Start a session with MEMWARE_NO_CAPTURE=1 to keep it out of the index and the backup mirror: the hooks list its transcript, and every sync and backup skips what is listed. A session that runs no memware hook cannot be recognised that way. See docs/integrations.md and docs/keeping-memory-clean.md.

Deriving beliefs

memware derive --plan     # no network: every excerpt a run would send, and where
memware derive            # dry run: sends the excerpts to the model, prints the facts, files nothing
memware derive --apply    # files them; runs again later from where it stopped

derive reads every turn from an interactive session indexed since its last run, has a model turn the sentences that look like facts into (subject, relation, value) triples, and files only the triples that pass a deterministic check: every word of the value must appear in the excerpt, so a model cannot introduce a fact the evidence does not contain. Derived beliefs carry reliability 0.5, below anything you stated yourself, so a contradiction lands in memware review rather than on top of your belief.

The default provider is the Claude Code CLI on your own subscription (claude -p, Haiku), so there is nothing to configure. --provider openai sends the extraction to any OpenAI-compatible endpoint instead (OPENAI_BASE_URL / OPENAI_MODEL / OPENAI_API_KEY).

Interactive sessions only, by default. Claude Code records what started each session (entrypoint: cli interactive, sdk-cli for claude -p), and derive skips the turns of claude -p and Agent SDK runs. On a machine that runs agent lanes those are most of the transcripts, and the eval scaffolding among them reads like fact. They stay indexed and recallable; they just never become beliefs. If your headless runs hold decisions you want in the ledger, opt them back in with memware config derive.sources all. A turn with no recorded entrypoint (a transcript from before Claude Code wrote the field, or another harness) is read as interactive, so nothing the filter cannot label is dropped. memware derive --plan prints the setting and how many new turns each setting would read, and memware stats counts sessions, turns and beliefs by entrypoint and names the project directories holding the most sessions.

A dry run is not offline: it sends the excerpts to that provider and skips only the write. --plan is the view that sends nothing. It lists every excerpt a run would send with its source pointer, then the session, excerpt, character and model-call counts and the destination, and it works before claude or OPENAI_* is set up. Read it before you turn derive on for transcripts that must not leave the machine.

You do not need an always-on machine. The plugin can run it for you on session start, at most once a day. memware setup is where you switch that on: it shows where the excerpts go before it asks. memware config derive.auto true sets the same switch directly. Other options — a macOS LaunchAgent that catches up after sleep, a systemd timer with Persistent=true, plain cron — are in docs/scheduling.md.

Use it from Hermes Agent

integrations/hermes/memware/ is a memory-provider plugin built on Hermes's MemoryProvider ABC — prompt-time belief prefetch, non-blocking turn capture, and memware_recall / memware_remember tools — sharing one store with Claude Code.

The supersession rule

same key, same value   → reinforce (reliability rises, use is counted)
same key, newer value  → supersede: incumbent gets valid_to = new.valid_from
same key, older value  → filed as history; the timeline stays consistent
weaker challenger      → parked as a candidate and sent to review

Ordering is decided by valid_from (when the evidence says it became true), never by insertion order — so a backfill converges to the same state in any order, twice, or in batches. Three policies: auto (last writer by event time), gate_conflicts (default: a less reliable challenger goes to review), await_confirmation.

Recall is keyword search; the agent supplies the meaning

The index is FTS5/BM25 — fast, model-free, and literal. The recall tool therefore takes several phrasings and fuses them by reciprocal rank, so a tool-calling agent puts its own reasoning into retrieval at call time (synonyms, related concepts, the literal value it expects), the same way it would issue a few grep or web-search queries:

recall(queries=["which port does the api listen on", "api port", "8443", "gateway listen port"])

Byte-identical hits collapse to a single slot, so a prompt captured on many days — a scheduled job's own preamble, say — never crowds out distinct evidence; the turns stay in the store and a session still reads back whole.

Prompt-time injection (the hooks) stays deterministic and only injects beliefs whose subject the prompt names.

Backups and the wipe trap

Transcripts are deleted by the OS after ~30 days, so an aged session lives only in the store — back it up, and never wipe-and-re-backfill (backfill only re-indexes transcripts still on disk). memware guards this: migrations snapshot first, and backfill warns if a backup is larger than the store. Once a destination is set, backups happen automatically at session boundaries — the SessionStart hook takes a throttled snapshot (at most once every ~20h), and a clean SessionEnd does too. No cron; immune to a laptop sleeping through a scheduled time, and — because the start hook always runs — also to a session being force-killed (a worktree/pane manager that SIGKILLs Claude Code never runs SessionEnd).

memware setup                              # guided: index sessions, pick a folder, take a first backup
memware backup                             # tiered snapshot (1/3/7/14-day) + transcript mirror
memware restore --latest                   # after a wipe, restore — do not re-backfill
memware nuke                               # delete everything, typed-confirmation guarded

Full guide: docs/backup.md.

Keeping evaluations out of the evidence

Full guide: docs/keeping-memory-clean.md.

Headless runs write transcripts too, unless you pass --no-session-persistence to claude -p. Set MEMWARE_NO_CAPTURE=1 in any run you do not want indexed: the plugin's hooks list its transcript so no sync indexes it and no backup mirrors it, and the Hermes provider captures nothing. That needs a memware hook to run in the session, so also put [memware-eval] in evaluation prompts, and use memware-eval --corpus ROOT --db scratch.db --beliefs-from ~/.memware/memware.db to judge retrieval against a store that excludes them. memware prune --containing TEXT shows the runs that already slipped in and the beliefs derived from them, and --apply un-indexes the runs and retracts those beliefs; copies already mirrored to a backup folder have to be deleted there by hand. For a pasted secret, run memware prune --turns-containing --apply from a plain terminal: it asks for the value without echoing it and removes it from the store file too, and memware scan --backups counts every place it is left, the transcripts memware does not index included (removal runbook). For a durable filter that every sync and backup honours — including runs that predate a marker — list content signatures in ~/.memware/ignore-markers.txt (or MEMWARE_IGNORE_MARKERS); any transcript whose head contains one is never indexed or mirrored.

A generator that runs from its own working directory can be excluded by path, whatever its environment: memware exclude --add '*/<project-dir>/*' previews a capture.exclude glob and --apply writes it (docs/keeping-memory-clean.md).

Reviewing contested supersessions

memware does not ship a UI. It ships a contract — ReviewBackend with publish() and collect() — plus two implementations: JSONL outbox/inbox files and a plain HTTP endpoint. Wire it to whatever you already use to make decisions.

memware review sync                       # outbox ~/.memware/review-outbox.jsonl
echo '{"review_id": 7, "decision": "approve"}' >> ~/.memware/review-inbox.jsonl
memware review sync                       # applied

Evaluation

memware-eval scores retrieval against a question set: does the right evidence surface, and does the stale value stay hidden? It needs no model, so results are reproducible. The protocol for end-to-end comparisons — agent alone vs agent + memware — is in docs/eval.md.

Editor and shell integration

memware ships no editor plugins — --plain (tab-separated, id-first) and --json are the integration surface, and everything is a copy-paste recipe on top of them. Shell completions come from memware completions zsh|bash|fish (needs the [shell] extra: uv tool install "memware[mcp,shell]"). --plain pipes cleanly to fzf/awk/cut:

memware recall "which port does the api use" --plain | fzf --delimiter='\t' --with-nth=10

Emacs, Vim, Neovim, an $EDITOR bulk-edit round-trip, and completion install steps are in docs/editor-integration.md.

Accessibility

memware emits no colour at all (so NO_COLOR is honoured by construction), and no information is ever carried by colour. Default output is screen-reader-friendly — labeled, one field per line, blank line between records; --plain and --json are the stable machine formats; and --ascii (auto-on in a non-UTF-8 locale) avoids glyphs a screen reader or terminal might mangle. Full statement: docs/accessibility.md.

Status

Alpha. The schema may change before 1.0; the ledger semantics will not.

License

MIT. See LICENSE.

Release files for memware 0.7.0

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for memware 0.7.0
File Size Uploaded
memware-0.7.0.tar.gz 290.0 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for memware 0.7.0
File Interpreter ABI Platform
memware-0.7.0-py3-none-any.whl Python 3 none any Details

Total release size: 424.1 kB

Release files / memware-0.7.0.tar.gz

Download URL memware-0.7.0.tar.gz
Size 290.0 kB
Tags Source
SHA-256 checksum
How to use checksums
45be3b12d8c5ab6c2e0f5c13c9f649fc68e344a772d54f8eaa98f0313df8987a
BLAKE2b-256 checksum
How to use checksums
8773f890abdeb0f08a7ebd700d7adcbcfa5c08da5d1793b782380cfd1eac5ba6
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Sep 17, 2026.

Transparency log

Release files / memware-0.7.0-py3-none-any.whl

Download URL memware-0.7.0-py3-none-any.whl
Size 134.1 kB
Tags Python 3
SHA-256 checksum
How to use checksums
7a3b10d5bfac1a0ed9eb68f725552e8eb86ff3a6c85b986dd6ef60641e6fd20c
BLAKE2b-256 checksum
How to use checksums
4204e01d9d37be824dc5a883c55437e625df100247f4792e611ace43fcf50e4e
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Sep 17, 2026.

Transparency log

Release history Release notifications | RSS feed

0.9.0

2 release files

0.8.0

2 release files

0.7.1

2 release files

This release

0.7.0 This release

2 release files

0.6.1

2 release files

0.6.0

2 release files

0.5.0

2 release files

0.4.0

2 release files

0.3.0

2 release files

0.2.5

2 release files

0.2.4

2 release files

0.2.3

2 release files

0.2.2

2 release files

0.2.1

2 release files

0.2.0

2 release files

0.1.3

2 release files

0.1.2

2 release files

0.1.1

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page