muninn

agent
Security Audit
Fail
Health Warn
  • License — License: AGPL-3.0
  • Description — Repository has a description
  • Active repo — Last push 0 days ago
  • Low visibility — Only 6 GitHub stars
Code Fail
  • rm -rf — Recursive force deletion command in .github/workflows/release.yml
  • process.env — Environment variable access in assets/motion/source/export.mjs
Permissions Pass
  • Permissions — No dangerous permissions requested

No AI report is available for this listing yet.

SUMMARY

Persistent memory for Claude Code and Codex CLI that never serves a replaced decision, and turns CLAUDE.md / AGENTS.md rules into permission rules and deny hooks. Local-first: one Rust binary, SQLite + FTS5, no cloud, no API key, no LLM in the read path. Cue-anchored recall under a 700-token budget.

README.md

The Muninn raven and its ring. One sentence at a time appears under the tagline, turns into a spark and enters the ring. When the plan changes to zstd, the old gzip decision comes back out, struck through, as the old plan.

CI Works with Claude Code and Codex Runs on Windows, macOS and Linux No cloud service License: AGPL-3.0-only

Muninn: persistent memory for Claude Code and Codex

A memory for Claude Code and Codex that keeps up when you change your mind.

Every time you open a new session, Claude Code or Codex starts from zero, with no idea that last
week you picked a database, agreed on a folder structure, or told it never to touch a certain
file. So you explain it all again, or it guesses.

Memory tools fix the forgetting, but most of them bring a new problem. They remember
everything, including the decisions you have since changed. Ask about the database and the
assistant gets the old choice and the new one side by side, and has to guess which is current.
Sometimes it guesses wrong, and you find the old choice back in your code.

Muninn remembers what you decided, and when you change your mind, it puts the old decision away.
The assistant only sees what is true now. The old one is still in your history if you ever want
to look.

It also turns the rules in your CLAUDE.md or AGENTS.md into settings that block the action,
so "never edit the migrations folder" holds even when the assistant has forgotten it. It runs on
your computer, with no cloud service and no API key.

Install · How it works · Rules · Compare · Questions · Technical overview

A quick example

On Monday you tell the assistant:

Let's use gzip to compress the files we send.

On Thursday you change your mind:

Change of plan, let's use zstd instead.

Two weeks later, in a brand-new session, you ask it to write up how the project compresses
files. The assistant remembers neither conversation, so it checks its memory. A typical memory
tool hands it both messages. Muninn hands it only Thursday's, and the assistant writes zstd.

Monday: gzip is saved as decision 1. Thursday: zstd becomes decision 2 and decision 1 is stamped retired. Two weeks later, a typical memory tool hands the assistant both cards and it guesses gzip; Muninn hands it only zstd.

Test results

We tested it against two popular memory tools, claude-mem and agentmemory. Every tool got the
same conversations, and the assistant was then given tasks that depended on a decision that had
later been changed.

Bar chart. Changed in conversation: Muninn 252 of 270, claude-mem 208 of 268. Change also in the code: Muninn 54 of 54, claude-mem 25 of 54, agentmemory 1 of 54. Old value written back: Muninn 0 of 54, claude-mem 10 of 54.

  • When you change your mind in conversation, the assistant used the up-to-date decision in
    252 of 270 tasks (93%) with Muninn, against 208 of 268 (78%) with claude-mem. We tried
    five different ways of phrasing the change, and Muninn was never behind.
  • When the change also shows up in your code, the assistant got it right in 54 of 54
    tasks with Muninn, 25 of 54 with claude-mem and 1 of 54 with agentmemory.
  • An old decision never sneaks back in. With Muninn the assistant wrote a replaced value into
    its work 0 times out of 54. With claude-mem it did 10 times.

An early measurement also points to lower costs: on those same tasks the assistant took about
half as many steps with Muninn, and each task cost about 40% less. That figure has not been
confirmed by a test of its own yet, so read it as a first sign.

Each test had its rules written down before it ran, and all the raw results are in this
repository, so anyone can check them. The full comparison, including the tools we have not
tested yet, is in docs/why-muninn.md.

What happens in the background

You never call Muninn. It rides along on the hooks Claude Code and Codex already fire, reads from
a small database in your project, and writes to it only when a session ends.

Diagram of hooks, a read path, a write path and the store. A packet travels step by step: the session catalog, a message matched against active cards, the match returned as evidence, an edit denied by a rule, the transcript turned into a new card, and a commit that moves an old card to retired.

  1. A session starts. The assistant gets a short catalog of what is on record, so it knows
    what it can ask for.
  2. You write a message. Muninn takes your words and the files in play and looks for them among
    the decisions that still stand. Retired ones are not in the list it searches.
  3. The matches go back as evidence, capped at 700 tokens, each with where it came from and how
    much to trust it. No AI model runs in this step, so the same question gets the same answer.
  4. The assistant reaches for something a rule forbids. If you turned that rule into a setting,
    the tool refuses before anything changes.
  5. The session ends. Muninn reads the conversation and keeps the decisions, rules, corrections
    and dead ends, in your words.
  6. A commit changes a value. When the code stops using something a decision named, that
    decision is retired, and the new value is recorded along with the commit.

What else it does

Once it is set up it works in the background, and you keep talking to your assistant as usual.
It keeps what you actually said rather than a summary of it, so nothing gets rewritten into
something you never meant. Everything stays on your computer: Muninn has no account and no cloud
service, and it never sends your conversations anywhere. It adds a few thousandths of a second
to each message.

SessionStart prints the catalog of what is on record, newest first. A new session starts. The assistant knows what is on record before you ask anything. Last week a redis cache lost writes and became dead end 4. Today the assistant plans redis again; Muninn brings back card 4, marked tried before, and the plan changes. It is about to repeat a mistake. What failed last time comes back before it is tried again.
A rule in CLAUDE.md becomes a proposed deny setting; after the user types y, an edit to migrations is denied. A written rule becomes a lock. You see the proposed setting first, and it applies only after you say yes. A long conversation is compacted into a summary that loses a rule and a correction; both come back from the store. The conversation gets compacted. Rules come back from the store, not from the summary: 100 of 100 times.
A commit diff replaces gzip with zstd; the gzip card is retired and a zstd card citing the commit takes its place. A commit changes a value. The decision that named the old value is retired on its own. The store cracks, the hook still exits 0, and the conversation carries on while the error goes to a log. Muninn breaks. Your session does not. Every hook exits cleanly, and the error goes to a log.

Rules that block instead of rules that get ignored

Claude Code reads CLAUDE.md as context, and a rule in it can be lost when a long conversation
is compacted or simply not followed. Muninn turns a rule such as "never edit the migrations
folder" from CLAUDE.md, AGENTS.md or .claude/rules into Claude Code permission rules and a
deny hook, so the edit is refused before it happens. It shows you the proposed settings first
and changes nothing until you say yes:

muninn compile && muninn apply

In Claude Code, /muninn:apply does the same.

Four steps inside a box labelled your computer: a message is written, the same words are saved verbatim in the .muninn folder, a packet trying to reach the cloud bounces off the edge, and later the card comes back in a few milliseconds with no model.

Muninn compared with claude-mem and agentmemory

Every row below comes from the same test harness: the same live sessions filled each tool's
memory through its own hooks, and a fixed check graded what the assistant wrote. No AI judge
graded anything.

Muninn claude-mem agentmemory
Uses the current decision after you changed it in conversation 252 / 270 208 / 268 not in this run
…when the change also reached the code 54 / 54 25 / 54 1 / 54
Writes a replaced value into its work anyway 0 / 54 10 / 54 —
Same conversations give the same memory yes, 3 runs of 20 sessions stored the same records stored text did not overlap between two runs not measured
Room it takes in the assistant's context about 2.4 times claude-mem's baseline not measured

Every row above measures the same case: a decision that changed while the project went on.
If you need one memory for a whole team, use an assistant other than Claude Code or Codex, or
already run short on context, read the limits below before you install. Mem0, Zep, Letta and
Claude Code's built-in memory have not been run on the same harness, so there is no figure to
compare. docs/why-muninn.md says why for each one.

Limits

  • Muninn uses a bit more of the assistant's attention. Assistants can only keep so much text in
    mind at once. Muninn's reminders take about 2.4 to 2.6 times the room claude-mem's do. You can
    switch the per-message reminders off, at the cost of a few more wrong answers.
  • It notices a change best when you write a sentence. "Let's switch to zstd" is easy to catch,
    while a reply that is just the word "zstd" is harder, though Muninn now wins that case too.
  • Languages don't mix well. If you ask in English about something you decided in Spanish,
    Muninn may not find it.
  • It is a personal memory. On a team, each person gets their own, built from their own
    conversations, and a git push does not share it with anyone. Muninn keeps its folder out of
    your repository, so your conversations are not published along with your code.
  • It works with Claude Code and Codex only, for now. Other assistants are planned for later.

Install

You need Claude Code or Codex. You do not need to know how to program. Installing is done once
per computer; after that, you turn Muninn on in each project where you want memory.

It works on Windows, macOS (Apple silicon and Intel) and Linux. On Windows, Claude Code needs
Git for Windows installed, the same thing Claude Code
itself asks for; Codex needs nothing extra.

Claude Code

Type these two lines in Claude Code, one at a time:

/plugin marketplace add ilien-dev/muninn
/plugin install muninn@muninn

Restart Claude Code. The first session downloads Muninn itself, about 13 MB, and checks the
download before using it.

Codex

Run these in a terminal:

codex plugin marketplace add ilien-dev/muninn
codex plugin add muninn@muninn

Open Codex, type /hooks and approve Muninn's hooks. Codex runs no plugin hook until you do.
The first session after that downloads Muninn, the same way as in Claude Code.

Setting up a new project

Muninn stays silent in a project until you turn it on there. Do it once per project, on each
computer you work from: the memory lives on your machine, not in the repository, so a fresh
clone starts without it.

In Claude Code, open the project and type:

/muninn:init

In Codex there is no command for this, so you ask Codex to do it. Open Codex in the project
folder, paste this message and send it:

Run `muninn init` in this project, then `muninn status`. If `muninn` is not found, use `~/.local/bin/muninn` instead (on Windows, `~/.local/bin/muninn.exe`). Show me what both commands print.

Codex may ask your permission before running them; say yes. When it's done, the last line it
shows starts with MUNINN and says GREEN.

If you prefer the terminal, run this inside the project folder instead:

~/.local/bin/muninn init

On Windows, in PowerShell: ~\.local\bin\muninn.exe init.

That file appears after your first Codex session with the plugin installed. If it isn't there
yet, open Codex once, close it, and try again.

To check it in Claude Code, type /muninn:status: it prints a line starting with MUNINN that
says GREEN. Memory starts filling from that conversation on. If you use both assistants on the
same project, one init covers both.

A Claude Code terminal types the install commands, then /muninn:init and /muninn:status, and ends on MUNINN GREEN.

What init changes in the project:

  • It creates the .muninn/ folder, where the memory is kept, and adds it to .gitignore, so
    your conversations never end up in a commit.
  • It turns off Claude Code's own memory for the project. muninn init --keep-native leaves it
    on.
  • It lets the assistant run muninn why, muninn status and muninn show without asking you
    each time.

Running it twice is harmless. To remove Muninn from a project, run muninn clean --yes: it
undoes exactly what init changed.

Updating

  • Claude Code: open /plugin, choose the muninn marketplace and update it, or turn on
    auto-update there once.
  • Codex: run codex plugin marketplace upgrade.

Restart the assistant afterwards. You don't run muninn init again: the first session after an
update fetches the new version, and the memory you already have stays.

Using it

You don't need to do anything. Muninn listens while you work. If you are curious, you can ask it
what it knows:

muninn why "why did we pick zstd"   # what stands now, and what it replaced
muninn status                        # is everything healthy

Questions

Why does Claude Code forget everything between sessions?

Each session starts with an empty context: the assistant only knows what is in CLAUDE.md and
what you tell it again. Muninn keeps the decisions, rules, corrections and dead ends from earlier
sessions and hands the ones that matter back to the assistant when you write a message, capped at
700 tokens. Codex works the same way, and Muninn covers it with the same memory.

Why does Claude ignore my CLAUDE.md, and can Muninn stop it?

CLAUDE.md is read as context, not as a setting, so a rule can be dropped when the conversation
is compacted or skipped during a long task. Muninn helps in two ways. Rules come back from its
store after a compaction, not from the summary (100 of 100 times in our test). And a rule you
turn into a setting with muninn compile && muninn apply blocks the action whether or not the
assistant remembers it.

Does it send my conversations anywhere?

No. There is no account, no server and no cloud service. The memory is a folder called
.muninn/ inside your project, and init adds it to .gitignore so it never reaches a commit.
On the first session the plugin downloads Muninn itself and checks it against its checksum
before it runs.

Will it slow my assistant down?

Not noticeably. The hooks are held to hard limits in CI with a full store of 20 000 records:
2.8 ms for a session start and 4.0 ms for a message (95th percentile). No AI model runs while it
answers the assistant.

What happens if Muninn itself breaks?

Your session carries on. Every hook exits cleanly even when something inside it fails, and the
error goes to a log in .muninn/log/. A test drives the real hooks 200 times per run, including
with the database corrupted, and fails if a hook blocks or a retired decision leaks out.
muninn status tells you what is wrong.

Do I need an API key, or does it cost anything to run?

No key and no running cost. Muninn is a single program on your computer, and it does not call
a paid model.

Does it clash with Claude Code's own memory?

init turns Claude Code's built-in memory off for that project. If you want to keep both, run
muninn init --keep-native.

Is it an alternative to claude-mem, Mem0 or engram?

It does the same job as claude-mem: memory across sessions, through hooks, for coding assistants.
The difference is what happens when a decision changes. We tested Muninn against claude-mem and
agentmemory on that case, and the results are above.
Mem0 and engram have not been run on the same test, so there is no figure to compare yet.

Can my team share one memory?

Not yet. Each person's memory is built from their own conversations and stays on their machine.
A git push does not share it.

How do I see what it remembers, or take it out?

muninn why "your question" shows what stands now and what it replaced, and
muninn why --all "topic" includes the retired ones. To remove Muninn from a project, run
muninn clean --yes, which undoes exactly what init changed.

For the technically curious

About the name

In Norse myth, the god Odin keeps two ravens. Every morning they fly out over the world, and every
evening they come back to tell him what they saw. Huginn is thought; Muninn is memory. In one of
the old poems, Odin says he worries that Huginn may not come back, and that he worries more for
Muninn.

That always struck me as the right way round: a thought can be had again, and a memory that does
not come back is gone.

Your AI assistant is Huginn. It thinks fast, it covers a lot of ground, and every morning it
starts from nothing. Muninn is the one that comes back carrying what you decided.

License

Muninn is © 2026 ilien and free to use under the
GNU Affero General Public License, version 3 only, with the extra terms in
NOTICE. In short:

  • Anyone may use, change, host and sell Muninn, including as a cloud service.
  • Anyone who shares a changed version, or offers one to people over a network, must publish its
    full source code under the same license.
  • Every copy must keep the notice "Based on Muninn by ilien - https://github.com/ilien-dev/muninn",
    and a changed version must say it was changed.

Want to contribute? There is a one-time Contributor License Agreement; see
CONTRIBUTING.md.

The animations in this README are drawn from assets/motion/source/
and can be rebuilt with node export.mjs there.

Reviews (0)

No results found