mimocode-mempalace
v0.1.3
Published
MemPalace long-term memory for MiMoCode: captures every completed turn into a semantic memory palace and injects relevant memories back into the system prompt
Maintainers
Readme
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.
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.
Quick start
[!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": trueIt 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.
How it works
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.
Setup
- Install MemPalace (needs MiMoCode 0.1.5 or later):
uv tool install "mempalace>=3.3.5"- 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.
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. - 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.3.5 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).
Use the absolute repo path as the plugin name:
{
"plugin": [
["/home/YOU/src/mimocode-mempalace", { "palace": "~/mimo-memory" }]
]
}Options
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 |
| 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 |
Import your past sessions
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.
Active memory: MCP and the knowledge graph
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.
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.Notes
- 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 pending exchange files and mines them, so nothing is lost.
- 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.
Troubleshooting
Set "log": true in the plugin options and read ~/.local/share/mimocode-mempalace/plugin.log.
The plugin
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.5 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).
The MCP server
- 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=35 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.
The palace and the CLI
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.
Development
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.
License
MIT
