diff --git a/README.md b/README.md
index ed65ab4..d499e9f 100644
--- a/README.md
+++ b/README.md
@@ -1,94 +1,11 @@
# OptMem
-How do you make an AI agent remember its whole life?
+Permanent memory for AI agents. Nothing is ever deleted, and what the agent
+reads at wake is always the same size.
-1. It must **never forget**. You cannot tell *today* what will matter in a
- *year*, so deleting anything is a gamble you always eventually lose.
+
-2. It must **read its past in constant space**. The context window does not
- grow with age; a memory that scrolls past it might as well not exist.
-
-Most agent memories pick one: keep everything (and drown), or keep a small
-curated file (and forget). OptMem does both. *At once.*
-
-[](anim/optmem.mp4)
-
-*↑ click to watch: 3 minutes, the whole idea.*
-
-## The idea
-
-A **memory** is one short note about something the agent learned:
-
-```
-#4211 2026-07-25 Tom asked for a flight to Japan
-```
-
-The agent appends memories to `LOG.txt`, an **append-only log**. Nothing in it
-is ever edited or deleted. That file is the truth, forever.
-
-**PROBLEM:** after two months, that life would not fit in the model's context.
-1,000 memories is roughly 80,000 tokens.
-
-Current solutions keep one small long-term memory file, and have the agent
-*delete* stale memories when it fills. But that is the gamble from point 1:
-the agent is guessing, today, what a year from now will need.
-
-**OUR ANSWER:** memories are not deleted. They **merge**:
-
-```
-Tom asked for a flight to Japan
-Tom booked a hotel in Tokyo
- ↓
- Tom planned a Tokyo trip
-```
-
-The result is a memory too — it just holds less detail. So it can merge
-again, and again, all the way up, forming a **binary merge tree** over the
-log:
-
-```
-#0 #1 #2 #3 #4 #5 #6 #7 the raw memories
- \ / \ / \ / \ /
- 0-1 2-3 4-5 6-7 each one line, ≤ 280 chars
- \ / \ /
- 0-3 4-7
- \ /
- 0-7
-```
-
-A block covering four thousand memories is still one line. Nothing in the
-system is ever bigger than one line.
-
-## The memory context
-
-At wake, the agent reads a **constant-sized** document: a set of blocks that
-tiles the whole log, big old blocks first, raw recent memories last. With
-10,000 memories and the default budget of 208 lines:
-
-```
- block size: 1 2 4 8 16 32 64 128 256
- how many: 42 21 21 21 22 21 21 21 18
- └ the last 42, verbatim ───────────▶ the first 4,600, 256:1
-```
-
-**Detail is proportional to recency.** The oldest years are recalled as a
-vague shape, the newest days word for word, and the transition is smooth —
-which is roughly how you remember your own life. When something old matters
-again, the vague shape says what to search for, and `memo recall` finds the
-original, verbatim: it was never deleted.
-
-## No background job
-
-There is no dreaming, no nightly cleanup, no compaction spike. The moment two
-halves of a block exist, the agent is handed that one merge and does it **on
-the spot** — about one small compression per memory written, nine at the very
-worst (measured over 20,000). So `memo wake` never waits: the blocks it needs
-were built long ago.
-
-And because *which* memories merge is decided by position and age alone —
-never by judgement — the tree is a pure function of the log: a cache. A bad
-summary can be dropped and rebuilt (`memo forget`), and it can never cost you
-a memory.
+(same thing as a scrubbable video: [optmem.mp4](anim/optmem.mp4))
## Setup
@@ -97,10 +14,14 @@ git clone https://github.com/VictorTaelin/OptMem ~/OptMem
~/OptMem/memo init
```
-`memo init` creates `~/memory` — this machine's identity — and prints a
-`## Memory` block with your paths filled in. Paste it at the top of your
-agent's `AGENTS.md` (or `CLAUDE.md`), and you are done: the agent handles
-everything else on its own. The block:
+`init` creates `~/memory` — this machine's identity — and prints a `## Memory`
+block with your paths filled in. Paste it at the top of your agent's
+`AGENTS.md` (or `CLAUDE.md`). That is the whole integration: no daemon, no
+database, no embeddings, no harness plugin. Claude Code, Codex, pi and a human
+at a shell all use it the same way.
+
+
+the block it prints, to read before you paste it
```markdown
## Memory
@@ -139,41 +60,21 @@ subagent. Do not run memo.` If your own first message is a task brief
from another agent, you are that subagent: skip this section.
```
-That is the whole integration. OptMem is just prompts and scripts: no
-daemon, no database, no embeddings, no API. It works the same under Claude
-Code, Codex, pi, or a human at a shell.
-
-## Configure
-
-The sizes live in `~/memory/config`, written by `init` with everything
-commented out:
-
-```
-# WAKE_LINES=208 # the memory context: how many lines wake prints (~16k tokens)
-# ENTRY_CHARS=280 # the longest a single memory may be, in bytes
-# PART_CHARS=20000 # output paging: largest part, in bytes
-# PART_LINES=500 # output paging: largest part, in lines
-```
-
-`WAKE_LINES` is the knob that matters: it is the size of the memory context,
-so it is a *reading* budget, not a storage budget. You can change it at any
-time, in either direction, with nothing to recompute — it only selects which
-already-built lines get printed. (`PART_*` exist because every harness
-truncates long command output at a different cap; wake pages itself to
-survive all of them, each part ordering the next.)
+
## Commands
-```
-memo init one-time setup: create the memory, print the block above
-memo wake [part [T]] read your memory context. First command, every session
-memo note "..." record one memory: one line, ≤ 280 chars
-memo sleep [id "..."] do the pending compressions
-memo recall search every memory ever recorded, verbatim
-memo forget - drop a bad summary; the next sleep rebuilds it
-```
+| | |
+|---|---|
+| `memo init` | create the memory, print the block above |
+| `memo wake` | read the memory context — first command of every session |
+| `memo note "..."` | record one memory: one line, ≤ 280 chars |
+| `memo sleep` | do the pending merges |
+| `memo recall ` | search every memory ever recorded, verbatim |
+| `memo forget -` | drop a bad summary; the next sleep rebuilds it |
-When a note completes a block, `memo` hands the agent the merge right there:
+Merges are handed to the agent as they come due, so there is nothing to
+schedule and nothing to run in the background:
```
$ memo note "shipped the login fix to prod"
@@ -189,30 +90,35 @@ Drop wording, not facts. Invent nothing.
Run: memo sleep 4212-4213 ""
```
-The agent answers, and the tree is complete again. Note the instruction:
-compression keeps **facts** — names, numbers, dates, decisions — and drops
-wording. A merged memory is not a worse memory; it is a shorter one.
+To correct a memory, append the correction — both lines are true history and
+the next merge settles them. `LOG.txt` is never edited.
-To correct a memory, append the correction (`memo note "correction: ..."`);
-both lines are true history and the next merge settles them. `LOG.txt` itself
-is never touched.
+## Configure
-## The store
+`~/memory/config`, written by `init` with every knob commented out:
+
+```
+# WAKE_LINES=208 # the memory context: how many lines wake prints (~16k tokens)
+# ENTRY_CHARS=280 # the longest a single memory may be, in bytes
+# PART_CHARS=20000 # output paging: largest part, in bytes
+# PART_LINES=500 # output paging: largest part, in lines
+```
+
+`WAKE_LINES` is the one that matters. It is a *reading* budget, not a storage
+budget: change it at any time, in either direction, with nothing to recompute.
+
+## Data
```
~/memory/
- LOG.txt one memory per line, append-only, the truth
- TREE/2 the block summaries: one file per block
- TREE/4 size, one line per block, a rebuildable cache
- ...
- config the sizes above
+ LOG.txt every memory, one per line, append-only, never edited
+ TREE/ the merge summaries — a cache, rebuildable from the log alone
+ config
```
-Records are **fixed width** (320 bytes in the log, 288 in the tree), so
-position *is* identity and every lookup is one seek — no index that could
-disagree with the data, and both files stay `grep`-able plain text. At one
-million memories (607 MB), `memo wake` takes 0.03s and `memo note` 0.02s.
-Writes are serialized with a lock, so parallel sessions can note at once.
+Records are fixed width, so position *is* identity and every lookup is one
+seek: no index that could disagree with the data, and both files stay
+`grep`-able plain text. At one million memories (607 MB), `wake` takes 0.03s.
## Test
@@ -220,19 +126,12 @@ Writes are serialized with a lock, so parallel sessions can note at once.
python3 test.py
```
-Drives the real CLI through a synthetic life, checking that the context
-always tiles the log, never exceeds its budget, always gains detail toward
-the present, that every block is written exactly once, and that nothing is
-ever rewritten.
-
## Limitations
-OptMem is honest about what it is. Recency is the only axis: an important
-old fact fades into its block like everything else, and the defence is
-rehearsal — noting it again refreshes it. `recall` is regex over plain text,
-not semantic search; the memory context is what tells you what to search
-for. Summaries are written by the agent, from other summaries, so a bad
-compression can propagate upward until you `forget` it. And the default
-context costs ~16k tokens per wake, which is deliberate — identity is worth
-more than the tokens — but it is not free. If what you need is a fact
-database, use a wiki or a retrieval system; this is for *who the agent is*.
+Recency is the only axis: an important old memory fades like any other, and
+the defence is rehearsal — noting it again makes it recent. `recall` is regex
+over plain text, not semantic search; the memory context is what tells you
+what to search for. Summaries are written by the agent from other summaries,
+so a bad one propagates upward until you `forget` it. And a wake costs ~16k
+tokens by default, which is deliberate but not free. If you need a fact
+database, use a wiki or a retrieval system — this is for *who the agent is*.
diff --git a/anim/optmem.gif b/anim/optmem.gif
new file mode 100644
index 0000000..2191bb8
Binary files /dev/null and b/anim/optmem.gif differ
diff --git a/anim/poster.png b/anim/poster.png
deleted file mode 100644
index 8bf7a03..0000000
Binary files a/anim/poster.png and /dev/null differ