Memmy: memoria local compartida para agentes en un VPS
Aprende a compilar Memmy 1.0.4 en Ubuntu, ejecutar el servicio en el puerto 18960 y mantener en una base SQLite local la memoria compartida de tus agentes.
Qué es Memmy y qué almacena
Memmy es un concentrador de memoria local para agentes de IA que se ejecuta en su propio VPS (servidor privado virtual). Mantiene una base de datos SQLite con lo que han aprendido sus agentes, y todos los agentes del servidor leen y escriben en ese mismo almacén. El proyecto es memmy-agent de MemTensor, cuenta con licencia MIT y está en la versión 1.0.4 desde julio de 2026.
En un servidor sólo son relevantes algunos componentes. Memmy incluye un servicio de memoria que escucha en http://127.0.0.1:18960, una interfaz de línea de comandos (CLI) memmy-memory que se comunica con ese servicio y un entorno de trabajo de escritorio. El entorno de trabajo sólo está empaquetado para macOS y Windows, por lo que en un VPS Linux debe ejecutar el servicio y la CLI. Esto basta para proporcionar una memoria compartida a Claude Code, Codex y Cursor.
Memmy clasifica lo que almacena en cuatro capas. L1 Trace es el turno sin procesar: la solicitud, la respuesta y las llamadas a herramientas. L2 Policy es un procedimiento inducido a partir de trazas que demostraron ser útiles. L3 World Model es conocimiento estable sobre un proyecto o un entorno. Skill es un procedimiento invocable que se ha concretado a partir de una política. El servicio asigna una capa al ingerir un turno, por lo que no debe crearlas manualmente. Si estas distinciones parecen abstractas, la memoria es una de las etapas posteriores de un recorrido por etapas para aprender a crear agentes, y las capas se entienden mejor después de escribir un bucle de agente sencillo y observar cómo olvida todo entre ejecuciones.
Qué cambia con un hub de memoria compartida frente a la memoria independiente de cada herramienta
Actualmente, cada agente incorpora su propia memoria. Claude Code guarda los archivos de instrucciones en el repositorio. Cursor guarda las reglas en la base de datos de su espacio de trabajo. Codex guarda los registros de sesión en ~/.codex. Cada almacén pertenece a una sola herramienta, por lo que un dato que enseñó el lunes en una herramienta no está disponible el martes en otra. Esto tiene dos costes: los tokens que se gastan en volver a explicar el mismo proyecto y el trabajo incorrecto que un agente realiza basándose en una suposición que ya corrigió en otro lugar.
Un hub saca el almacén de la herramienta. Memmy también lee los almacenes existentes, por lo que no empieza con una base de datos vacía. Su escáner conoce seis fuentes: Claude Code en ~/.claude/projects/**/*.jsonl, Codex en ~/.codex/sessions/<YYYY>/<MM>/<DD>/rollout-*.jsonl, OpenCode en ~/.local/share/opencode/opencode.db, los archivos state.vscdb de Cursor, las bases de datos SQLite de OpenClaw en ~/.openclaw y Hermes en ~/.hermes. Puede añadir una fuente manualmente con un nombre y una ruta local.
Los contadores de importación no coincidirán, y es normal. El escáner agrupa los mensajes por fuente y conversación, y después escribe una memoria L1 por cada turno completo. Un turno se considera completo cuando tiene contenido de usuario no vacío y termina con un mensaje del asistente no vacío, por lo que una sesión interrumpida no aporta nada. Los mensajes se deduplican mediante puntos de control de conversación e identificadores de turno estables. El número de elementos escaneados, el número de mensajes importados y el número de memorias nuevas también serán distintos en la misma ejecución.
Esta es la pieza que complementa cómo Claude Code gestiona el contexto dentro de una sesión. La gestión del contexto determina qué cabe en una sola ventana. Un hub de memoria determina qué permanece después de cerrar esa ventana.
Qué necesita en el VPS
- Node.js 22 o posterior. La documentación de Memmy lo requiere y Ubuntu 24.04 incluye Node 18.
gity una cadena de herramientas de compilación, porquebetter-sqlite3es un módulo nativo que puede compilarse durante la instalación.- Aproximadamente 2 GB de RAM. La instalación en root descarga un workspace grande y una cadena de herramientas para compilar el frontend.
- Varios GB de espacio libre en disco para
node_modulesy la base de datos.
sudo apt update
sudo apt install -y git build-essential python3 curl ca-certificates sqlite3
curl -fsSL https://deb.nodesource.com/setup_22.x | sudo -E bash -
sudo apt install -y nodejs
node --versionnode --version debería mostrar v22 o una versión posterior. Un v18 aquí indica que el paso de NodeSource no se aplicó y que la instalación fallará después al comprobar el motor requerido por el proyecto.
Instalar Memmy desde el código fuente en Ubuntu 24.04
git clone https://github.com/MemTensor/memmy-agent.git
cd memmy-agent
cp .env.example .env
npm install
npm run memory:buildnpm run memory:build compila el espacio de trabajo de @memmy/memory en Memory/dist. En un servidor sin interfaz gráfica no es necesario compilar nada más del árbol. Compruebe que el módulo nativo se haya cargado:
node -e "require('better-sqlite3'); console.log('better-sqlite3 loads')"Si esa línea genera un error en lugar de mostrar la salida, el módulo nativo no coincide con la versión de Node. Ejecute npm rebuild better-sqlite3, que es exactamente lo que hace el script de inicio del proyecto antes de iniciar cualquier componente.
El README documenta bash scripts/dev-start.sh como un comando de inicio único. No lo ejecute en un VPS sin interfaz gráfica. Inicia el shell de escritorio de Electron y un servidor de desarrollo de Vite en el puerto 19000 junto al servicio de memoria. Electron necesita una pantalla, por lo que, en un servidor sin sesión gráfica, el script se bloquea o termina.
Inicie el servicio de memoria y compruebe que responde
npm run memory:serve:devEsa es la forma documentada de ejecutar el servicio de memoria desde el código fuente. Se enlaza a 127.0.0.1:18960, mantiene la base de datos en ~/.memmy/memory-service/memory.sqlite y lee la configuración desde ~/.memmy/config.yaml. El README muestra los mismos valores de forma explícita:
npm run memory:serve:dev -- \
--host 127.0.0.1 --port 18960 \
--db ~/.memmy/memory-service/memory.sqlite \
--config ~/.memmy/config.yamlDesde un segundo shell, pregunte al servicio si está activo:
curl -sS http://127.0.0.1:18960/api/v1/healthHealth es el único endpoint que nunca solicita un token, por lo que es la comprobación adecuada. Si curl termina con el código 7 y un mensaje Failed to connect to 127.0.0.1 port 18960, no hay ningún proceso escuchando. Revise el terminal donde se ejecuta el servicio, porque los errores durante el arranque se muestran allí. La causa habitual es que el módulo nativo de SQLite no se pueda cargar. ss -lntp | grep 18960 confirma el socket cuando el servicio ya está activo.
El resto de la API HTTP (interfaz de programación de aplicaciones) se encuentra bajo /api/v1.
POST /api/v1/memory/addescribe una memoria yPOST /api/v1/memory/searchconsulta.GET /api/v1/memory/:idyDELETE /api/v1/memory/:idleen y eliminan una entrada.POST /api/v1/sessions/openyPOST /api/v1/sessions/:sessionId/closedelimitan una sesión del agente.POST /api/v1/turns/startyPOST /api/v1/turns/:turnId/completeregistran un turno.GET /api/v1/panel/overview,/api/v1/panel/analysisy/api/v1/panel/itemsalimentan el panel.
Memmy reserva un bloque de puertos. En modo sin interfaz gráfica sólo se usa el primero: 18960 para la memoria, 18970 para el estado del gateway, 18980 para la interfaz web y la administración HTTP, 18990 para la API compatible con OpenAI que inicia memmy serve, y después 19000 y 19010 para el servidor de desarrollo del frontend de escritorio. Si algo en el equipo ya utiliza uno de esos puertos, consulte esa lista.
De dónde procede realmente el comando memmy-memory
Aquí es donde suele fallar la primera instalación, así que léalo en el paquete en lugar de hacer suposiciones. El nombre del comando no tiene ninguna relación con el nombre del repositorio. Procede del campo bin del workspace que lo define:
node -p "JSON.stringify(require('./Memory/package.json').bin)"Esto muestra {"memmy-memory":"./dist/src/cli/index.js"}. Por tanto, el punto de entrada compilado es Memory/dist/src/cli/index.js y sólo existe después de npm run memory:build, porque la compilación crea dist y marca el archivo como ejecutable. Ejecútelo directamente:
node Memory/dist/src/cli/index.js healthSi quiere usar el nombre corto desde su PATH, cree un enlace al mismo archivo:
sudo ln -s "$PWD/Memory/dist/src/cli/index.js" /usr/local/bin/memmy-memory
memmy-memory healthLa CLI usa http://127.0.0.1:18960 de forma predeterminada y acepta --url, --token, --config, --source y --user-id. Sus subcomandos son init, health, search, add, get y delete, además de las llamadas de sesión y de turno que usan los agentes en lugar de las personas. memmy-memory search "deploy steps" y memmy-memory add "staging migrates on deploy" son los dos que ejecuta un agente con más frecuencia.
¿Cómo se conecta Claude Code con Memmy?
Claude Code no tiene una interfaz de complementos de memoria, por lo que Memmy no se integra directamente con él. La integración es más sencilla. Claude Code ejecuta memmy-memory como un comando de shell normal, y un archivo de instrucciones le indica cuándo hacerlo. El instalador documentado de Memmy crea ese archivo automáticamente: memmy-memory init --agent coloca un archivo de instrucciones de memoria en el directorio de reglas del agente de destino.
Escriba la instrucción manualmente una vez. Así sabrá exactamente qué se indicó al agente. Claude Code lee CLAUDE.md desde la raíz del proyecto al inicio de cada sesión, por lo que una sección como esta constituye toda la integración:
## Memory
Before starting a task, run `memmy-memory search "<topic>"` and read what comes back.
When a task is done, run `memmy-memory add "<what you learned>"` for anything that will matter next session.Tenga claro qué obtiene con esto. Es una integración basada en instrucciones. Funciona cuando el modelo decide ejecutar el comando, y no en otros casos. Nada obliga a realizar la llamada. Si una sesión termina sin ejecutar add, no se guarda nada. La única señal es un resultado vacío la próxima vez que busque. Es la misma limitación que los propios archivos de memoria de Claude Code, con una diferencia: el almacén es compartido, por lo que la nota también llega a Codex y Cursor en la misma máquina. Un entorno de ejecución que expone una interfaz de complementos real elimina esta limitación en lugar de depender de una instrucción. Por eso la memoria persistente aparece junto a los límites de presupuesto y las reglas de permisos entre los complementos de DeepSeek Harness que conviene instalar.
La dirección inversa no requiere ninguna configuración. El escáner de Memmy ya lee ~/.claude/projects/**/*.jsonl, que es donde Claude Code escribe las transcripciones de sus sesiones. Ejecute Memmy en el mismo servidor donde ejecuta Claude Code dentro de una sesión de tmux y el trabajo del día anterior se convertirá en memoria sin configurar nada.
¿Memmy funciona como servidor MCP para Claude Code?
No, y conocer esta limitación ahorra una tarde de trabajo. MCP (model context protocol) tiene clientes y servidores. Memmy es un cliente. Se conecta a servidores MCP y ofrece sus herramientas a su propio entorno de ejecución de agentes. No publica un endpoint MCP al que claude mcp add pueda conectarse. El único puente MCP del repositorio pertenece a la integración de Composio dentro de la API local de escritorio, y esa API escucha en un puerto aleatorio en 127.0.0.1, protegido por su propia cabecera x-memmy-mcp-token.
El lado cliente se configura en ~/.memmy/config.yaml, el archivo al que apunta MEMMY_CONFIG, en tools.mcpServers:
tools:
mcpServers:
example:
type: stdio
command: npx
args:
- "-y"
- "your-mcp-server"
toolTimeout: 30
enabledTools:
- "*"type acepta stdio, sse y streamableHttp. Un servidor stdio se ejecuta como proceso hijo de Memmy, por lo que su comando debe existir en el mismo equipo y ejecutarse con el mismo usuario. Si ya mantiene servidores MCP en ejecución en un VPS, esos son los que debe enumerar aquí.
Mantener privado el almacén de memoria
Todo lo que gestiona Memmy se encuentra en ~/.memmy: config.yaml, el espacio de trabajo, memory-service/memory.sqlite y los archivos de ejecución. El análisis y la ingesta se realizan localmente, y las memorias se escriben en ese archivo SQLite local. Por tanto, la configuración predeterminada es realmente local.
Hay dos rutas que acceden a la red. MEMMY_CLOUD_SERVICE usa https://memmy-api.memtensor.cn de forma predeterminada y habilita el modo de cuenta con sus tokens de prueba, por lo que el modo de clave API nunca lo utiliza. El programa de mejora de memoria es un ajuste independiente de la configuración de privacidad y permanece desactivado hasta que lo habilita.
Hay una tercera ruta que es más fácil de pasar por alto. Si configura un proveedor de embeddings alojado, el texto de cada memoria se envía a ese proveedor para convertirlo en un vector. El almacenamiento local no evita ese envío. Un endpoint de embeddings alojado por usted es la única forma de evitarlo.
Mantenga el puerto 18960 en la dirección de loopback. No necesita una regla de firewall, porque un servicio enlazado a 127.0.0.1 no es accesible desde fuera del equipo. Acceda a él desde su portátil mediante SSH:
ssh -N -L 18960:127.0.0.1:18960 you@your-vpsSi alguna vez lo enlaza a una dirección más amplia, establezca primero un token. Definir storage.token en la configuración, o la variable de entorno MEMMY_MEMORY_TOKEN o MEMORY_SERVICE_TOKEN, hace que todos los endpoints, excepto el de health, requieran un bearer token. Los valores de configuración admiten referencias a ${ENV_NAME}, por lo que el token y las claves API de sus modelos permanecen fuera del propio archivo. Es la misma práctica que mantener los secretos fuera de los agentes de IA en el resto del sistema, y una política predeterminada de denegación en ufw es su protección adicional si una versión futura cambia la dirección de enlace predeterminada.
Haz una copia de seguridad de ~/.memmy antes de confiar en él
memory.sqlite es todo el almacén. Los vectores se guardan en ese mismo archivo mediante la extensión sqlite-vec, por lo que un solo archivo es suficiente para la copia de seguridad. Copiarlo con cp mientras el servicio escribe puede generar una base de datos inconsistente. Use el comando de copia de seguridad propio de SQLite:
mkdir -p ~/memmy-backup
sqlite3 ~/.memmy/memory-service/memory.sqlite ".backup '$HOME/memmy-backup/memory.sqlite'"Esto crea una copia coherente mientras el servicio sigue ejecutándose. Transfiérala fuera del servidor según una programación, que es para lo que sirve restic para almacenamiento externo. Perder config.yaml implica volver a introducir la configuración del proveedor. Perder memory.sqlite implica perder todos los recuerdos, y ningún otro elemento del sistema contiene una segunda copia.
Ejecutar el servicio de memoria con systemd
npm run memory:serve:dev en un shell termina junto con el shell. Un archivo de unidad mantiene el servicio activo después de los reinicios.
[Unit]
Description=Memmy memory service
After=network-online.target
[Service]
Type=simple
User=memmy
WorkingDirectory=/opt/memmy/memmy-agent
EnvironmentFile=/etc/memmy/memory.env
ExecStart=/usr/bin/npm run memory:serve:dev
Restart=on-failure
RestartSec=5
[Install]
WantedBy=multi-user.targetNo incluya el token en la unidad. Guárdelo en /etc/memmy/memory.env, con root como propietario y con permisos 600:
MEMMY_CONFIG=/home/memmy/.memmy/config.yaml
MEMMY_MEMORY_TOKEN=replace-this-with-a-long-random-stringsudo systemctl daemon-reload
sudo systemctl enable --now memmy-memory
systemctl status memmy-memory --no-pager
curl -sS http://127.0.0.1:18960/api/v1/healthstatus=203/EXEC en la salida de estado indica que systemd no pudo ejecutar ExecStart en absoluto. Por tanto, compruebe which npm: en una instalación de NodeSource es /usr/bin/npm, mientras que con nvm se encuentra en una ruta bajo el directorio personal del usuario, que systemd no localizará. Una unidad que se inicia y termina de inmediato ha fallado dentro de npm. journalctl -u memmy-memory -n 50 muestra el motivo. El procedimiento es el mismo que para cualquier otro servicio de systemd en un VPS.
Lo que Memmy todavía no hace
- No existe una compilación de escritorio para Linux. Los scripts de empaquetado cubren macOS y Windows, por lo que el workbench, su asistente de configuración inicial y el panel de memoria no están disponibles en el propio servidor.
memory:serve:devejecuta el punto de entrada de TypeScript mediantetsx, una ruta de desarrollo. El repositorio también incluyememory:servepara la salida compilada. Ejecutenpm runsin argumentos para ver qué scripts existen realmente en su copia de trabajo.- La recuperación crea su ventana de búsqueda a partir de las 2,000 filas vectoriales más recientes y después aplica la selección Top-K dentro de esa ventana. En un almacén muy grande, una memoria antigua puede quedar fuera de ella.
- La generación de embeddings se realiza después de la captura y los errores se envían a una cola de reintentos, en lugar de bloquear el turno del agente. Es posible que una memoria añadida hace un momento todavía no se pueda encontrar mediante la búsqueda vectorial.
- Un único archivo SQLite equivale a un único nodo. No existe clustering, por lo que un segundo servidor constituye una memoria separada.
La versión 1.0.4 y aproximadamente 329 estrellas en julio de 2026 describen un proyecto reciente. Las opciones, las rutas y los nombres de los scripts cambian entre versiones. Consulte el campo bin y la salida de npm run en su propia copia de trabajo, en lugar de confiar en un comando copiado de cualquier sitio, incluido este documento.
FAQ
¿Por qué la comprobación de estado devuelve «conexión rechazada»?
No hay ningún proceso escuchando en el puerto 18960. Un código de salida 7 de curl con Failed to connect to 127.0.0.1 port 18960 significa que el servicio de memoria no está en ejecución o terminó durante el arranque. Por tanto, lea la salida del terminal o el journal donde se inició. Las dos causas habituales son un módulo nativo better-sqlite3 que no coincide con su versión de Node, lo que se corrige con npm rebuild better-sqlite3, y una versión de Node inferior a 22. Confirme el socket con ss -lntp | grep 18960 cuando el servicio esté activo.
¿De dónde procede el comando memmy-memory después de compilar desde el código fuente?
Procede del campo bin del paquete de workspace @memmy/memory, no del nombre del repositorio. Ejecute node -p "JSON.stringify(require('./Memory/package.json').bin)" dentro del checkout; el comando muestra {"memmy-memory":"./dist/src/cli/index.js"}. Ese archivo sólo existe después de npm run memory:build, porque la compilación crea dist y marca el archivo como ejecutable. Ejecútelo como node Memory/dist/src/cli/index.js health o cree un enlace simbólico en /usr/local/bin para usar el nombre corto.
¿Puedo añadir Memmy a Claude Code con claude mcp add?
No. Memmy es un cliente MCP, no un servidor MCP. Se conecta a los servidores incluidos en tools.mcpServers dentro de ~/.memmy/config.yaml y ofrece sus herramientas a su propio runtime. Claude Code accede a Memmy en sentido inverso: ejecuta la CLI memmy-memory como un comando de shell, siguiendo un archivo de instrucciones que memmy-memory init --agent escribe en el directorio de reglas del agente.
¿Ejecutar Memmy envía mis memorias a un servicio en la nube?
El escaneo y la ingesta se ejecutan localmente, y las memorias se escriben en ~/.memmy/memory-service/memory.sqlite en su propio disco. MEMMY_CLOUD_SERVICE apunta a https://memmy-api.memtensor.cn para el modo de cuenta y los tokens de prueba, y el programa de mejora de memoria permanece desactivado hasta que lo habilite. La ruta que debe supervisar es el proveedor de embeddings: un modelo de embeddings alojado recibe el texto de cada memoria que convierte en un vector. Si esto es importante, use un endpoint que administre usted mismo.