Quick start · How it works · Setup · Options · Import history · MCP & knowledge graph · Troubleshooting
Long-term memory for MiMoCode, backed by MemPalace.
MiMoCode ships a solid file-based project memory (MEMORY.md, checkpoints, FTS5 search). This plugin adds the other half: a semantic memory that spans all your sessions and projects. Every completed turn is saved into a MemPalace "palace", and on each new request the most relevant past exchanges are retrieved by meaning, not just keywords, and placed into the system prompt. The model doesn't have to remember to search; the plugin does it for it.
| 🧠 Passive recall Memories arrive in the system prompt on their own — no model discipline required. How it works |
🗂️ Project wings Exchanges are scoped per project; flip one option for palace-wide recall. Options |
🕸️ Active memory MCP tools let the model search deeper and write facts to a knowledge graph. MCP & KG |
The same round trip is pinned by test/e2e.test.ts against a real palace: captured in one session, mined, and recalled through the system prompt in the next.
Tip
Don't install anything by hand. Paste this line into MiMoCode itself:
Set up https://github.com/mvalentsev/mimocode-mempalace for me, with "log": true
It reads this page and walks every step of Setup on its own — install MemPalace, create the palace, write the config — then tells you when to restart. That is exactly how this plugin's field installs have happened.
Prefer full control over the process? Setup below is four manual steps.
Write side:
session.postfires when a top-level turn finishes (it fires for completed and failed turns alike; only completed ones are saved).- The plugin writes the user question and the final answer as a small transcript file.
- A debounced, serialized
mempalace minerun files it into the palace. Runs never overlap, so the palace index stays healthy. - Exchanges are scoped into a wing named after your project directory, so search results stay project-relevant by default.
Read side:
chat.messageremembers the text you typed.experimental.chat.system.transformrunsmempalace searchwith that text and appends a# Long-term memory (MemPalace)section to the system prompt: your identity file (optional) plus the top matching memories.- Results are cached per query for two minutes, so the multi-step tool loop of a single turn costs one search, not five.
Subagent slices (checkpoint writers, reviewers, title generators) are not captured, only the main loop. If mempalace is missing or the palace is unreachable, the plugin logs what happened and stays out of the way; your session works as if it were not installed.
- Install MemPalace (the plugin needs MiMoCode 0.1.6 or later):
uv tool install "mempalace>=3.6.0"- Create a palace — the folder your memories live in:
mkdir -p ~/mimo-memory && mempalace init ~/mimo-memory --yesinit offers to mine the folder right away — skip that: it's empty, and the plugin runs mempalace mine itself as you work.
- Add both keys to
~/.config/mimocode/mimocode.json, replacingYOUwith your username (whoamiprints it) in the twocommandpaths:
{
"plugin": [
["mimocode-mempalace", { "palace": "~/mimo-memory", "log": true }]
],
"mcp": {
"mempalace": {
"type": "local",
"command": ["/home/YOU/.local/bin/mempalace-mcp", "--palace", "/home/YOU/mimo-memory"],
"enabled": true
}
}
}- Restart MiMoCode. The first start downloads the plugin and can take a minute; every start after that is seconds. Then check:
tail ~/.local/share/mimocode-mempalace/plugin.logready: MemPalace X.Y.Z, palace=..., wing=... — memory is on. That's the whole install.
What the two keys do, and the fine print
pluginis the memory loop itself — capture and recall into the system prompt.mcphands the model MemPalace tools it can call on its own (details); the plugin works fine without it, so drop that block if you only want the passive loop.- Both
commandpaths must be absolute: the array is spawned without a shell, so~is not expanded there (plugin options likepalacedo expand it). If your binary is not under/home/YOU/.local/bin,which mempalace-mcpprints where it is. - MiMoCode reads
mimocode.jsonandmimocode.jsoncfrom that directory and merges both, so if you already keep amimocode.jsonc, put the keys there rather than starting a second file. - There is nothing to
npm installyourself — MiMoCode installs the npm package on the next start. Options live right next to the plugin name, in the same file; a project's.mimocode/mimocode.jsonworks too. No side-channel config files. - On mempalace older than 3.6.0 the plugin logs
plugin disabledand neither reads nor writes. - No log file after the restart? The plugin never ran — see Troubleshooting. The MCP
mempalace_mempalace_searchansweringNo palace foundon a fresh palace is normal; it turns into real hits after your first completed turn. - Have sessions from before the plugin? Switch on
backfillnow, it works best right after install (see Import your past sessions).
Hacking on a checkout instead
Use the absolute repo path as the plugin name:
{
"plugin": [
["/home/YOU/src/mimocode-mempalace", { "palace": "~/mimo-memory" }]
]
}Setup used two of these — palace and log; everything else tunes a default.
| Option | Default | Meaning |
|---|---|---|
palace |
~/.local/share/mimocode-mempalace/palace |
Palace directory (create it with mempalace init) |
bin |
mempalace |
mempalace executable, if not on PATH |
wing |
"auto" |
"auto" scopes memories per project directory name; a string pins one wing for everything; false drops per-project scoping — exchanges land in a shared unsorted wing and search is palace-wide |
searchScope |
"wing" |
"wing" keeps recall inside the current project; "palace" searches across all projects ("how did I solve this in that other repo?") |
captureMode |
"exchange" |
"exchange" saves question + final answer; "turn" also keeps the intermediate assistant replies of the turn (tool-loop reasoning) |
cleanupAfterMine |
false |
Delete exchange transcripts once they are mined; by default they stay as a plain-text journal |
capture |
true |
Save completed turns; false also keeps the startup sweep from mining leftovers, so the plugin never writes to the palace |
inject |
true |
Retrieve and inject memories |
identityFile |
~/.local/share/mimocode-mempalace/identity.md |
Markdown prepended to every injected block; missing file means no identity section; false disables. It is one global file injected in every project, so keep it about you, not about the project of the day |
injectResults |
5 |
Search results per injection |
injectMaxChars |
6000 |
Cap on the injected block size |
searchTimeoutMs |
10000 |
Search budget per query; on timeout the turn simply runs without memories |
mineDebounceMs |
3000 |
Quiet window before captured exchanges are mined in one batch |
mineTimeoutMs |
120000 |
Mine run budget |
mineAgent |
"mimocode" |
Agent name mempalace records on every mined drawer |
backfill |
false |
Import past MiMoCode sessions once: true for all, a number for the N most recent (see below) |
mimoDb |
~/.local/share/mimocode/mimocode.db |
MiMoCode's SQLite database, read by backfill |
exportsDir |
~/.local/share/mimocode-mempalace/exchanges |
Where exchange transcripts are kept |
agents |
["main"] |
Agent slices to capture |
log |
false |
true logs to ~/.local/share/mimocode-mempalace/plugin.log, a string sets a custom path |
Everything above only covers turns completed while the plugin is running. MiMoCode also keeps your whole history in a SQLite database, and the plugin can file it into the palace once:
{
"plugin": [
["mimocode-mempalace", { "palace": "~/mimo-memory", "backfill": 50 }]
]
}On the next start the plugin reads the database (read-only; a live MiMoCode is fine, the db is in WAL mode), exports your past top-level sessions as transcripts — each scoped to the wing of the project it belonged to — and mines them. Subagent slices and hook-injected turns are filtered out, and sessions the plugin has already captured are skipped. true imports everything; a number imports the N most recent sessions.
Backfill runs once: it drops a .backfill-done.json marker next to the exchange transcripts and skips itself afterwards. Delete the marker to run it again. Best switched on right when you install the plugin.
The plugin covers the passive loop: capture and inject, no model discipline required. The mcp block you added in Setup step 3 wires in the active half: the MemPalace MCP server, tools the model calls on its own. Both halves share the same palace.
MiMoCode prefixes every tool with the server name from the config, so with the mempalace entry from Setup the model sees mempalace_mempalace_search, mempalace_mempalace_kg_query, mempalace_mempalace_kg_add and friends. The injected block answers most questions by itself; MCP lets the model follow up when the injected excerpt is not enough, and record durable facts into the knowledge graph.
Part of the graph also builds itself. Since MemPalace 3.6.0 the mine --mode convos run behind every captured turn records the paths, symbols and identifiers an exchange mentions, and links a pair of them into a hallway once it recurs across two exchanges — mempalace hallways --wing <project> lists them, mempalace_mempalace_list_hallways hands the same thing to the model. Those come from what you actually worked on; the kg_add facts below stay the deliberate half.
To make the model actually use the graph, add a rules file (AGENTS.md in ~/.config/mimocode/ or your project):
## Memory protocol
Relevant memories already arrive in the system prompt under "Long-term memory
(MemPalace)"; you don't need to search for what's already there.
- When an injected memory is truncated or you need more context around it,
call `mempalace_mempalace_search` with a focused query.
- After a decision, a fixed bug, or a stated preference, record one fact with
`mempalace_mempalace_kg_add` (subject "user" or the project name, object
under 128 chars). Prefer quality over quantity; skip facts you are not
sure about.
- Query `mempalace_mempalace_kg_query` for entity "user" when personalization
matters.- Everything is local: exchanges, the palace, the search. Nothing leaves your machine beyond what your model provider already sees in the prompt.
- Exchange transcripts stay in
exportsDirafter mining.mempalace mineis incremental and skips already-filed files; the leftovers double as a plain-text journal of your sessions. Turn oncleanupAfterMineif you prefer them gone. - A session that exits quickly can outrun the debounced mine. The next plugin start notices transcripts written since that directory was last mined and files them, so nothing is lost — and a start that has nothing new to file runs no
mempalace mineat all. The bookkeeping lives in.mine-state.jsonat the root ofexportsDir; delete it and the next start re-mines every wing, which is safe but slow. - The injected block tells the model to trust current code over old memories when they conflict.
- The plugin's palace is for conversations. If you also mine a whole codebase with the mempalace CLI, give that its own palace directory: tens of thousands of code drawers crowd conversation hits out of palace-wide searches, and CLI maintenance (
mempalace repair) takes far longer on a big palace. - Vanilla OpenCode isn't a target right now: the capture path is built on MiMoCode's
session.posthook. For OpenCode, look at opencode-mempalace-persistence.
Set "log": true in the plugin options and read ~/.local/share/mimocode-mempalace/plugin.log.
ready: MemPalace X.Y.Z, palace=..., wing=...means the plugin found everything.- The log file does not exist at all: the plugin never ran.
- Check that MiMoCode is 0.1.6 or later, and give the very first start time to finish downloading the package.
- Make sure the
pluginentry sits in a config MiMoCode actually reads (~/.config/mimocode/mimocode.json, or.mimocode/mimocode.jsonof the project you launched it in). - A broken or empty
mimocode-mempalace@latestfolder under~/.cache/mimocode/packages/blocks the install from being retried — delete that folder and restart. - When in doubt, read MiMoCode's own log — the newest file in
~/.local/share/mimocode/log/.service=pluginlines show the plugin being picked up (loading plugin) or the exact install error (failed to install plugin, usually the road to registry.npmjs.org). Noservice=pluginlines at all means MiMoCode never picked the plugin up from that config — runenv | grep -iE 'mimocode|xdg'and look forMIMOCODE_HOME(relocates every path, config included) orMIMOCODE_PURE(turns off external plugins).
mempalace unavailablemeans the binary isn't on the PATH MiMoCode runs with; setbinto an absolute path.palace is empty until the first exchange is minedis normal on a fresh palace; it goes away after your first completed turn. In the same state the MCPmempalace_mempalace_searchanswersNo palace foundwith a hint to runmempalace mineyourself — don't: the plugin mines for you, and a bare CLImineis how palaces get split (see The palace and the CLI).skip <session>: agent "..." not in [main]shows the subagent filter doing its job.search failed (code=143 timedOut=true)under load: on a small machine a mine running in parallel can push a search pastsearchTimeoutMs; that turn just runs without memories. RaisesearchTimeoutMsif it keeps happening.backfill: exported N session(s) ...reports the one-time history import;backfill skipped: ...names the reason (missing or unreadable database, unexpected schema).
- No
mempalace_mempalace_*tools in the session: themcpblock is missing from the config MiMoCode actually read, or was added without a restart — servers are picked up at startup. Also check that the firstcommandentry is a real file (which mempalace-mcpprints it) and that both paths are absolute;~is not expanded insidecommand. Theservice=mcplines in MiMoCode's own log tell the story:foundmeans the config entry was read,local mcp startup failedmeans thecommanddoesn't start. - MiMoCode's log shows
MCP error -32601: Unknown method: resources/list(andprompts/list) formempalaceright aftertoolCount=36 create() successfully created client: harmless noise. The server implements tools only, and MiMoCode probes the optional resources and prompts APIs anyway; the client is already connected by that point. - MCP tools worked earlier in the session but now every call fails with
Not connected: the server process died or was killed, and MiMoCode does not reconnect it within a running session. Restart MiMoCode.
Search error: Error executing plan: Internal error: Error finding idmeans the palace directory references vector segment folders it does not contain. The palace is the whole directory, not just the database file: ChromaDB keeps vectors in<uuid>/folders next tochroma.sqlite3. This is what symlinkingchroma.sqlite3into a second directory produces — and one search from the wrong root is enough to break search from the real one too (the plugin logspalace warning: chroma.sqlite3 ... is a symlinkwhen it spots this). Keep one real palace directory, point every consumer at it, and runmempalace repair --yes --palace <dir>to rebuild the index.- Maintaining the palace from the CLI: a bare
mempalacecommand without--palacetargets the default palace (from~/.mempalace/config.json, else~/.mempalace/palace) — not the plugin's. Mining or repairing there quietly splits your data across two palaces; always pass--palacematching the plugin'spalaceoption.
bun install
bun test # unit suite; the e2e file auto-skips without mempalace on PATH
bun run typecheckSee CONTRIBUTING.md for the ground rules and CHANGELOG.md for release history.
MIT