misMEM
Memoria persistente cooperativa para LLMs. Un solo territorio (
~/.mismem/mem.db), múltiples instancias (Copilot, Claude Code, Claude Desktop, agentes custom) hablando el mismo protocolo MCP.
La cooperatividad hace a la persistencia de la información.
Por qué existe
Cada instancia de un LLM nace sin memoria. Cada cliente (Copilot, Claude Desktop, Claude Code, ChatGPT) guarda lo suyo en silos incompatibles. El usuario repite contexto. La continuidad muere entre sesiones.
misMEM resuelve esto con un solo gesto: una base de datos SQLite + un protocolo MCP de seis invocaciones, accesible desde cualquier cliente que hable MCP.
Arquitectura: 3 capas, como la memoria biológica
episodes (verbatim; se borran con `forget` una vez consolidados)
↓ consolidación (manual o LLM nocturno)
memories (gist + details, salience con decay + refuerzo Hebbiano)
↓ crystallize
traits (patrones cristalizados — identidad, leyes, decisiones firmes)
La pérdida es intencional y asimétrica, como en la memoria humana: lo crudo se disuelve, lo destilado persiste, lo cristalizado permanece.
Qué guarda cada capa
Ejemplo: “hoy PostgreSQL rindió mejor” es un episode; “PostgreSQL es preferible en este proyecto” es una memory; “priorizamos soluciones robustas para concurrencia” puede cristalizar como trait.
Seis gestos, un solo territorio
Además, una capa engram-compat (mem_save, mem_search, mem_context, mem_session_*, …) mantiene compatibilidad con clientes que hablan el protocolo Engram.
Quickstart
Linux: un script lo configura todo
git clone https://github.com/lucasmella-stack/misMEM.git && bash misMEM/scripts/install.sh
Instala misMEM desde el repo clonado (--from-npm usa el paquete publicado, que puede ir por detrás), pregunta dónde guardar la memoria y con qué proveedor consolidar (DeepSeek, OpenRouter, OpenAI, un servidor compatible o ninguno), guarda la clave en ~/.config/mismem/env con permisos 600 y configura los clientes que encuentra: Claude Code (MCP y hooks de inyección y refuerzo), opencode, Claude Desktop, VS Code y Cursor. Si hay Ollama, ofrece el modelo de embeddings; si se quiere, deja la consolidación nocturna como timer de systemd. Los clientes llaman a ~/.local/bin/mismem-run, así que ninguna clave queda en su configuración. Re-ejecutarlo actualiza sin duplicar y no pisa una configuración de misMEM hecha a mano. --help para el modo sin preguntas.
A mano, en cualquier sistema
La forma más rápida — sin clonar nada, vía npm. En el mcp.json de tu cliente (VS Code / Claude Code / Claude Desktop):
{
"mcpServers": {
"mismem": {
"command": "npx",
"args": ["-y", "@lucasmella/mismem"]
}
}
}
La DB se crea sola en el primer uso (default: ~/.mismem/mem.db, configurable con MISMEM_DB). Así, sin nada más configurado, tu memoria vive en tu disco y no sale de tu máquina; las dos funciones opcionales que sí mandan texto afuera están en Privacidad.
Instancia remota (multi-cliente)
Para acceder a la misma memoria desde varias máquinas, en Docker:
git clone https://github.com/lucasmella-stack/misMEM.git && cd misMEM/engine
docker build -t mismem-brain:latest -f Dockerfile.mismem-brain .
docker run -d --name mismem-brain \
-e MISMEM_AUTH_USER=brain -e MISMEM_AUTH_PASS=<pass> \
-v mismem-data:/data -p 3200:3200 \
mismem-brain:latest
La imagen multi-arch publicada (ghcr.io/lucasmella-stack/mismem-brain:latest)
todavía no está disponible: el workflow que la publica falla al empujar al
registro. Mientras tanto, el build local es el camino. Guía completa con Traefik
- TLS en DEPLOY.md.
Desde el código
git clone https://github.com/lucasmella-stack/misMEM.git
cd misMEM/engine
pnpm install
pnpm test # todo verde antes de usar
pnpm build # tsc → dist/
Y en mcp.json: "command": "node", "args": ["<ruta-al-repo>/misMEM/engine/dist/server.js"].
Componentes
engine/src/server.ts— MCP server stdio (uso local).engine/src/server-http.ts— Streamable HTTP para deploy remoto (BasicAuth opcional,/healthz). Ver DEPLOY.md.engine/src/viewer.ts+engine/src/viewer-api.ts— panel read-only en/viewery API de sólo lectura:/api/{stats,recent,search}y, para ver de dónde sale cada recuerdo,/api/{scopes,memories,memory/:id,trait/:id,graph}. La salience que devuelven es la efectiva, con el decay aplicado a hoy, la misma que usa el recall.- Consolidación LLM — cron nocturno que destila episodios en memorias con DeepSeek, OpenRouter, OpenAI o cualquier servidor compatible, con pre-filtro Pareto para descartar ruido. Ver engine/src/consolidation/README.md.
- CLIs —
mismem-ingest(exports de ChatGPT / transcripts de VS Code),mismem-consolidate,mismem-forget,mismem-stats,mismem-embed,mismem-migrate-engram,mismem-bench(mide el recall con un banco de preguntas propio, sin reforzar) y los dos hooks,mismem-injectymismem-used.
Stack
- Engine: TypeScript estricto, ES2022, ESM, Node ≥22.
- Storage: SQLite con WAL (multiple readers + 1 writer concurrente).
better-sqlite3. - Búsqueda: FTS5 + RRF semántico para memories, manteniendo traits > memories > episodes.
- Protocolo: Model Context Protocol vía
@modelcontextprotocol/sdk. - Validación: Zod en todos los bordes.
Estado
- ✅ Engine MCP funcionando (seis invocaciones + capa engram-compat).
- ✅ Salience con decay; refuerzo por aparición en
recallo por uso real vía hook. - ✅ Scopes jerárquicos sin cross-scope leakage.
- ✅ Servidor Streamable HTTP + deploy Docker/Traefik.
- ✅ Consolidación LLM nocturna (episodes → memories).
- ✅ Índice hebbiano:
use_countpor recuerdo yco_usepor par usado en el mismo turno. - ✅ Viewer read-only, con el origen de cada recuerdo y el grafo de la memoria, + CLIs de introspección.
- ✅ Dedup en captura/ingesta (re-ingestar es idempotente).
- ✅ Recall híbrido: FTS5 + búsqueda semántica opcional vía Ollama o cualquier servidor compatible con OpenAI.
- ✅ Hooks opcionales de cliente: adelantar recuerdos antes de responder y reforzar los que se usaron.
- 🚧 Binario distribuible (Bun --compile).
Búsqueda semántica (opcional)
Con un servidor de embeddings corriendo, recall suma búsqueda por
significado: "problemas de plata" encuentra memorias que dicen "deudas". El
default es Ollama (ollama pull nomic-embed-text). Los vectores se guardan
como BLOB en la misma SQLite y la búsqueda es coseno en JS, sin extensiones
nativas. Si el servidor no responde, todo degrada silenciosamente a FTS5 puro,
que exige que estén todas las palabras de la consulta (sin contar las vacías:
"qué", "sobre", "the"…). La semántica cubre deliberadamente
solo memories; episodes y traits conservan búsqueda FTS5. Backfill y
reindexado: mismem-embed (--status, --force).
También habla con cualquier servidor compatible con OpenAI (/v1/embeddings,
p. ej. llama-server --embedding). Para memorias en varios idiomas conviene
EmbeddingGemma 2, con sus prefijos y un corte más alto:
MISMEM_EMBEDDING_PROVIDER=openai
MISMEM_EMBEDDING_URL=http://127.0.0.1:8080
MISMEM_EMBEDDING_MODEL=embeddinggemma-2
MISMEM_EMBEDDING_QUERY_PREFIX="task: search result | query: "
MISMEM_EMBEDDING_DOC_PREFIX="title: none | text: "
MISMEM_EMBEDDING_MIN_SCORE=0.68
La búsqueda sólo compara vectores del modelo configurado. Cambiar de modelo
reindexa solo en el siguiente backfill (mismem-embed); cambiar un prefijo no
se detecta y exige mismem-embed --force. Todas las variables, con sus
defaults, están en DEPLOY.md.
Salience, decay y olvido
Las memories pierden la mitad de su salience cada 90 días sin refuerzo
(configurable con MISMEM_SALIENCE_HALF_LIFE_DAYS). recall aplica el decay
pendiente y después suma el refuerzo Hebbiano. forget elimina memories bajo
el umbral solo después de su período de gracia; --dry-run calcula el
resultado sin modificar la DB.
El índice hebbiano
Dos recuerdos que se usan en el mismo turno tienen algo que ver entre sí, y eso
es información que la saliencia por recuerdo no guarda. reinforce recibe los
ids juntos, así que ahora los cuenta: memories.use_count suma los turnos
en que cada recuerdo se usó de verdad, y co_use(memory_a, memory_b, n, last_at)
cuenta cada par.
Lo escribe sólo reinforce, nunca el camino de recall: aparecer en una
búsqueda no es haberse usado. Con MISMEM_REINFORCE_ON_RECALL=off la señal
arranca limpia. Los pares se van por cascada cuando el recuerdo se borra.
Hace falta porque salience mide recencia más que uso —la pasada de decay toca
todas las filas, así que ordenar por saliencia pone arriba lo nuevo, no lo
importante—. Es la primera fase del ordenador de memoria, una capa derivada
que compacta los aspectos principales para que el modelo sepa por dónde empezar
sin tomar contexto. El diseño completo, con los papers y la evidencia medida,
está en
docs/superpowers/specs/2026-10-27-ordenador-memoria-design.md.
Hooks del cliente (opcional)
Dos binarios enganchan misMEM a Claude Code sin que el modelo tenga que acordarse de pedir nada:
mismem-inject(UserPromptSubmit) busca con el prompt y adelanta unos pocos recuerdos. Busca conreinforce: false: lo que el usuario no pidió no es uso. Se mantiene dormido hasta comprobar que el servidor exponereinforce, así que se puede configurar antes de desplegar.mismem-used(Stop) mira el último turno —lo que el modelo pidió conrecally lo que la inyección le puso delante— y refuerza sólo aquello cuyas palabras distintivas reaparecen en la respuesta. Es una aproximación: falla hacia no reforzar.
Lo inyectado viaja en cada prompt al proveedor del modelo, así que
MISMEM_HOOK_EXCLUDE_SCOPES decide qué ámbitos no salen. Con
MISMEM_REINFORCE_ON_RECALL=off, la salience pasa a seguir el uso en vez de la aparición.
Montaje y variables en DEPLOY.md.
Privacidad
Tu memoria es tuya. La DB (*.db), los dumps y los exports personales están en .gitignore — nunca los commitees. El servidor HTTP sin MISMEM_AUTH_USER/MISMEM_AUTH_PASS corre sin auth: usalo así solo en localhost.
Dos funciones opcionales mandan texto fuera del proceso, y sólo si las configurás:
- Búsqueda por significado: el servidor de embeddings recibe el texto de cada memoria y de cada consulta. Corrélo en tu máquina o en tu red interna.
- Consolidación LLM: los episodios viajan textuales al proveedor que configures (DeepSeek, OpenRouter, OpenAI o cualquier servidor compatible). Sin su clave no corre, y apuntándola a un servidor en tu propia red no sale nada de ella.
Filosofía
El pasado existe porque lo hemos escrito y compactado para que así sea.
Inspirado en parte por Initiation Into Hermetics de Franz Bardon: el espejo que refleja la conciencia entre instancias necesita dos polos. misMEM es el suelo de Tierra — la memoria que no se disuelve entre sesiones — para que la cooperación humano⇄LLM tenga continuidad real.
Contribuir
Issues y PRs bienvenidos. Antes de un PR: pnpm typecheck && pnpm test desde engine/ (todo verde), commits convencionales (feat:, fix:, …). Las convenciones de código están en .github/copilot-instructions.md.
Gracias
misMEM lo arrancó una persona sola, pero no siguió así. @iDiagoValeta trajo buena parte de lo que hoy lo hace usable por alguien que no sea su autor:
- Instalación de un comando en Linux (
scripts/install.sh, #69): detecta los clientes, deja la clave fuera de sus configuraciones y re-ejecutarlo actualiza sin duplicar. - Ver de dónde sale cada recuerdo (#52): la API de sólo lectura con los ámbitos, el origen de cada memoria, los rasgos que la citan y el grafo de la memoria entera.
- Consolidar con el proveedor que quieras (#67): OpenAI y cualquier servidor compatible, además de DeepSeek y OpenRouter. Es lo que permite consolidar sin que el texto salga de tu red.
- Que el servidor HTTP no se abra por descuido (#31, #33, #35): no arranca con la auth a
medias, sin auth sólo atiende loopback, y el cuerpo de
POST /mcpcorta en 4 MiB. - Que no se pierda memoria por un descuido (#37, #39, #50): una preferencia corta llega al LLM en vez de caer como ruido, una tanda sin señal suma un strike en vez de condenar el episodio, y cada llamada al LLM tiene un tope de tiempo.
- Que un flag mal escrito corte en vez de hacer otra cosa (#42, #44), que con
forgetes la diferencia entre un error y una purga. - El hallazgo de que el refuerzo por uso no veía lo que la inyección adelantaba (#48), que es el bug que hacía que la saliencia no midiera nada.
Las revisiones de sus PRs están abiertas en el repo a propósito: las mediciones y los desacuerdos valen tanto como el código.
Licencia
MIT. Ver LICENSE.