Desarrolladores
Instalación avanzada e infraestructura
Para cuando el servidor sale de tu portátil. Cada tema trae un diagrama o una tabla, la configuración correcta más corta y un enlace al documento completo en GitHub.
Cuatro sitios donde puede correr
El binario es el mismo en los cuatro. Cambia la dirección de escucha, y con ella cuánta autenticación y cuánto cifrado te toca poner.

| Topología | Escucha | Autenticación | TLS | Se ejecuta como |
|---|---|---|---|---|
| Solo portátil | 127.0.0.1:49374 | No hace falta | No | unidad de usuario de systemd, agente de launchd o un contenedor |
| Equipo de homelab | 0.0.0.0:49374 | Bearer token y lista de hosts permitidos, ambos obligatorios | Recomendado | Docker con healthcheck, o el servicio de sistema del AUR |
| LAN con TLS | 0.0.0.0:49374 detrás de un proxy | Token root, más un usuario y una clave de API por persona | Sí. Caddy con su CA interna funciona sin dominio | Docker Compose con Caddy como sidecar |
| Túnel | Ningún puerto en el host | Igual que el servidor en la LAN | Sí, en el edge de Cloudflare | Docker Compose con cloudflared como sidecar |
Un portátil puede prescindir de HTTP con ai-memory serve --transport stdio. Para un homelab, el repositorio trae un script bin/deploy con plantillas de compose y de env. Sigue el paso a paso de despliegue en homelab.
TLS con un proxy inverso
ai-memory no termina TLS por sí mismo, por diseño. Un bearer token autentica una petición. No la cifra.
Puedes prescindir de TLS cuando
- el agente habla con él por stdio
- el servidor solo escucha en loopback, para un usuario, y nadie abre
/webdesde otra máquina - es desarrollo local o un experimento puntual
Necesitas TLS cuando
- existen cuentas, porque entonces las claves
aim_viajan por la red - el servidor escucha más allá de loopback
- abres
/webdesde otra máquina - se puede llegar al servidor desde fuera de la LAN

Para un dominio público con los puertos 80 y 443 accesibles. Caddy emite y renueva solo el certificado de Let’s Encrypt. El repositorio tiene el archivo compose completo en docker/compose.tls.caddy.yml.
memory.example.com {
reverse_proxy ai-memory:49374
}
Sin dominio y sin exponer nada. La CA interna de Caddy firma el certificado, y tú instalas su certificado raíz una vez en cada máquina cliente. Si te saltas ese paso, los clientes rechazan la conexión o se acostumbran a ignorar las advertencias.
{
local_certs # le dice a Caddy que use la CA interna en vez de LE
}
homelab.local, 192.168.1.50 {
reverse_proxy ai-memory:49374
}
docker compose exec caddy cat /data/caddy/pki/authorities/local/root.crt > caddy-root.crt
Para cuando ya usas nginx y tienes los archivos del certificado. HTTP/1.1 y la cabecera Connection vacía son obligatorios para el transporte HTTP streamable de MCP.
server {
listen 443 ssl http2;
server_name memory.example.com;
ssl_certificate /etc/nginx/certs/memory.crt;
ssl_certificate_key /etc/nginx/certs/memory.key;
location / {
proxy_pass http://ai-memory:49374;
proxy_set_header Host $host;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_http_version 1.1;
proxy_set_header Connection "";
}
}
Un túnel solo saliente, así que no abres puertos en el router. Necesita un dominio en Cloudflare, y el plan gratuito sirve. En el panel, apunta el hostname público a http://ai-memory:49374. El archivo compose completo es docker/compose.tls.cloudflared.yml.
cloudflared:
image: cloudflare/cloudflared:latest
container_name: ai-memory-tunnel
restart: unless-stopped
command: tunnel --no-autoupdate run
environment:
- TUNNEL_TOKEN=${CLOUDFLARE_TUNNEL_TOKEN}
Después, avisa al servidor
La lista de hosts permitidos debe incluir el hostname público, o la protección contra DNS rebinding rechaza las peticiones del proxy. La opción de cookie segura es obligatoria en cuanto la gente inicia sesión por un listener que va más allá de loopback.
AI_MEMORY_AUTH_TOKEN=...long-random-token-from-generate-auth-token...
AI_MEMORY_AUTH__SECURE_COOKIE=true
AI_MEMORY_ALLOWED_HOSTS=memory.example.com,localhost,127.0.0.1
AI_MEMORY_BIND=0.0.0.0:49374
Y reapunta los clientes
La URL de MCP termina en /mcp. La URL de los hooks es el origen sin ruta.
ai-memory install-mcp --client claude-code --apply \
--server-url "https://memory.example.com/mcp" --auth-token "$AI_MEMORY_AUTH_TOKEN"
ai-memory install-hooks --agent claude-code --apply \
--server-url "https://memory.example.com" --auth-token "$AI_MEMORY_AUTH_TOKEN"
Mantén el servidor en marcha
ai-memory no se reinicia solo. De eso se encarga el gestor de servicios de cada sistema operativo.
Para una estación de trabajo de un solo usuario. Los paquetes del AUR instalan la unidad. No necesita sudo y guarda el estado en ~/.local/share/ai-memory. Una unidad de usuario se detiene al cerrar sesión, salvo que actives lingering.
systemctl --user daemon-reload
systemctl --user enable --now ai-memory.service
systemctl --user status ai-memory.service
journalctl --user -u ai-memory.service -f
# que siga corriendo después de cerrar sesión
loginctl enable-linger "$USER"
Para una estación de trabajo compartida o un equipo en la LAN. Los datos viven en /var/lib/ai-memory, la configuración en /etc/ai-memory/config.toml y los secretos en /etc/ai-memory/env. No ejecutes las dos unidades en la misma dirección de escucha.
sudo systemd-sysusers /usr/lib/sysusers.d/ai-memory.conf
sudo systemd-tmpfiles --create /usr/lib/tmpfiles.d/ai-memory.conf
sudo -u ai-memory ai-memory \
--data-dir /var/lib/ai-memory \
--config /etc/ai-memory/config.toml \
init
sudo systemctl daemon-reload
sudo systemctl enable --now ai-memory.service
journalctl -u ai-memory.service -f
Los tarballs de macOS incluyen un plist de LaunchAgent con dos marcadores por rellenar. Ejecuta esto desde el tarball extraído. Un LaunchAgent se detiene al cerrar sesión, y macOS no tiene nada equivalente a lingering. Nadie rota sus dos archivos de log.
mkdir -p ~/Library/Logs/ai-memory
AI_MEMORY_BIN=~/Applications/ai-memory/ai-memory
sed -e "s|__AI_MEMORY_BIN__|$AI_MEMORY_BIN|" \
-e "s|__HOME__|$HOME|" \
packaging/launchd/com.github.akitaonrails.ai-memory.plist \
> ~/Library/LaunchAgents/com.github.akitaonrails.ai-memory.plist
launchctl bootstrap gui/$(id -u) \
~/Library/LaunchAgents/com.github.akitaonrails.ai-memory.plist
ai-memory no tiene dispatcher de servicios de Windows, así que sc create apuntando al exe no funciona, y una tarea programada con Start-Process muere en el siguiente reinicio. WinSW lo envuelve. Usa rutas absolutas: un servicio corre como LocalSystem, y %LOCALAPPDATA% se expandiría al perfil equivocado.
<service>
<id>ai-memory</id>
<name>ai-memory MCP server</name>
<description>Long-term memory server for AI coding agents.</description>
<executable>C:\Users\you\AppData\Local\ai-memory\ai-memory.exe</executable>
<arguments>--data-dir "C:\Users\you\AppData\Local\ai-memory" serve --transport http --bind 127.0.0.1:49374</arguments>
<startmode>Automatic</startmode>
<onfailure action="restart" delay="5 sec"/>
<log mode="roll"/>
</service>
& "$Dest\ai-memory-service.exe" install
& "$Dest\ai-memory-service.exe" start
& "$Dest\ai-memory-service.exe" status
Unidades de systemd en la guía de instalaciónlaunchd en la guía de macOSWinSW en la guía de Windows
El directorio de datos y las copias de seguridad
La wiki es la verdad. Es markdown plano en un repositorio git, y el índice de búsqueda se construye a partir de ella.
Reindex reconstruye las páginas, los enlaces y la búsqueda de texto completo a partir de la wiki. No recupera sesiones, observaciones, traspasos, usuarios, claves, filas de auditoría ni embeddings, así que la base de datos también va en tu copia de seguridad.
| Directorio | Contiene | Tipo | ¿Hay que copiarlo? |
|---|---|---|---|
wiki/ | Todas las páginas en markdown, en un solo repositorio git | Verdad | Sí. Va en el tarball de la copia de seguridad, y también puedes hacerle rsync o git push |
raw/ | Segmentos de transcripción inmutables y saneados de los lanzamientos gestionados | Verdad | Sí, si usas ai-memory run. Cópialo aparte |
db/ | memory.sqlite: índice de texto completo, entidades, embeddings, sesiones, usuarios, filas de auditoría | Derivado en su mayoría | Sí. Las páginas, los enlaces y la búsqueda se reconstruyen desde la wiki. Las sesiones, los traspasos, los usuarios y las claves solo viven aquí |
models/ | El modelo local de embeddings, unos 87 MB | Reconstruible | No. Se vuelve a descargar, o colocas los archivos tú mismo |
logs/ | Salida de trazas con rotación | Desechable | No |
Por defecto: ~/.local/share/ai-memory en Linux, ~/Library/Application Support/ai-memory en macOS, %LOCALAPPDATA%\ai-memory en Windows y /data en el contenedor. Cámbialo con AI_MEMORY_DATA_DIR.
Copia de seguridad y restauración

Copiar
Usa la API de backup en línea de SQLite, así que las escrituras que ocurren durante la instantánea quedan coherentes. El tarball contiene el árbol de la wiki, la instantánea de la base de datos y config.toml.
# seguro con el servidor en marcha
ai-memory backup --to /tmp/ai-memory-backup.tar.gz
Restaurar
--data-dir es la ruta del volumen en el host. Las rutas de aquí son las de la guía de despliegue. Usa las tuyas.
# Primero detén el servidor.
docker compose -f ~/deploy/ai-memory/docker-compose.yml down
# Restaura (sysinfo se niega si el contenedor sigue corriendo).
ai-memory restore --from /tmp/ai-memory-backup.tar.gz --data-dir /var/opt/docker/utils/ai-memory/data --force
# Vuelve a arrancar.
docker compose -f ~/deploy/ai-memory/docker-compose.yml up -d
Lee las operaciones de ciclo de vida: purgar, renombrar, mover, restaurar una página, resetear
Enrutamiento e identidad
Un servidor compartido tiene que responder dos preguntas: a qué proyecto pertenece esta sesión y quién pregunta.
El archivo marcador
Por defecto, el proyecto es el nombre del directorio actual, en un workspace llamado default. Deja un .ai-memory.toml en cualquier directorio superior para cambiarlo. Los hooks suben desde el directorio de trabajo y usan el primer marcador que encuentran.
Trabajo y personal
Un marcador por directorio padre. Todos los repositorios que cuelgan de él caen en ese workspace, con el nombre del directorio como proyecto.
# ~/projects/movvia/.ai-memory.toml
workspace = "movvia"
# ~/personal/.ai-memory.toml
workspace = "personal"
Monorepo
Un marcador con un proyecto fija todos los subdirectorios a ese proyecto. Gana el marcador más cercano.
# ~/projects/movvia/pe-portais/.ai-memory.toml
workspace = "movvia"
project = "pe-portais"
Worktrees de git
Los worktrees enlazados y los subdirectorios se resuelven al repositorio principal, aunque el worktree viva fuera de él.
# ~/projects/.ai-memory.toml
workspace = "oss"
project_strategy = "repo-root"
El mismo archivo contiene las reglas de [capture] con ignore_paths, y ai-memory install-hooks --apply --capture-mode allowlist convierte el marcador en un opt-in: un repositorio sin marcador no emite eventos. Los hooks nativos aplican ambas cosas. Los hooks de shell del wrapper de Docker no. Lee la referencia del archivo marcador.
Modos de auto-scope
Una llamada MCP sin proyecto explícito se resuelve con un puntero de “proyecto actual”. El modo decide quién comparte ese puntero. El servidor registra el modo activo al arrancar.
| Modo | Cuándo usarlo |
|---|---|
per_actor | El modo por defecto. Aísla harness en paralelo y personas distintas en un mismo servidor. |
per_session | Para clientes con sesión que reenvían el id de sesión del hook en cada petición MCP. |
single | El comportamiento anterior a la v1.39. Un solo slot para todo el proceso, gana la última escritura. Inseguro en un servidor compartido. |
[auto_scope]
mode = "per_actor" # "per_actor" (por defecto desde v1.39) | "per_session" | "single"
session_ttl_secs = 3600 # TTL de las entradas por clave (por defecto 1 h)
max_entries = 4096 # límite duro; se expulsan primero las inserciones más antiguas
Lee cómo funciona el aislamiento de auto-scope
SSO y OIDC
Cada desarrollador inicia sesión una vez con un device flow de OIDC contra cualquier emisor que cumpla el estándar, como Keycloak, Okta o Entra ID. Ese token autentica después los hooks nativos de ciclo de vida y los comandos de la CLI cuando no hay un bearer token estático configurado.
ai-memory auth login oidc-device \
--issuer "https://issuer.example.com/realms/team" \
--client-id "ai-memory-cli"
Sin red, límites y actualizaciones
Lo que necesitan saber una revisión de seguridad, un plan de capacidad y una ventana de mantenimiento.
Instalación air-gapped (sin red)
Binarios
Cada archivo de una versión tiene su .sha256. Descárgalo en una máquina con red, verifícalo y llévalo dentro. Las versiones solo traen checksums, sin procedencia SLSA ni atestación de artefactos.
Compilar desde el código
SQLite va incluido y libgit2 va vendorizado, así que la compilación necesita un toolchain de C y tu mirror de crates. cargo vendor funciona.
El modelo de embeddings
Una instalación por defecto descarga el modelo de Hugging Face en el primer arranque. Para que no salga ninguna petición, coloca antes model.safetensors, tokenizer.json y config.json en <data_dir>/models/all-MiniLM-L6-v2/. Los checksums están fijados en el código.
El binario no tiene telemetría. El wrapper de Docker consulta Docker Hub en busca de una imagen más nueva como mucho una vez cada 24 horas, y AI_MEMORY_NO_VERSION_CHECK=1 lo desactiva. En un entorno air-gapped las actualizaciones son manuales, igual que la instalación. Lee la página de instalación sin red.
Capacidad
Todas las escrituras pasan por un solo escritor. El proyecto midió dónde está su tope, con cargo test -p ai-memory-store --test writer_throughput -- --ignored --nocapture.
| Escritores concurrentes | Throughput | Latencia media |
|---|---|---|
| 1 | 42/s | 23,9 ms |
| 8 | 295/s | 3,4 ms |
| 32 | 698/s | 1,43 ms |
| 128 | 700/s | 1,43 ms |
- El techo ronda las 700 escrituras por segundo y se alcanza cerca de los 32 escritores.
- La cola de escritura está limitada a 1024. Pasado ese punto, los productores se frenan y todas las escrituras acaban llegando.
- Los hooks de shell dejan de esperar al servidor a los 200 ms y guardan el evento en una cola local, así que un servidor lento no bloquea a tu agente.
AI_MEMORY_HOOK_RATE_PER_SECyAI_MEMORY_HOOK_RATE_BURSTañaden un rate limit opcional por actor y sesión. Viene desactivado.
Actualización
ai-memory upgrade
- Con el wrapper de Docker, esto verifica y reemplaza el wrapper, descarga la imagen y vuelve a preparar los scripts de hooks. Un servidor en otro host se actualiza aparte.
- Las migraciones del esquema y de la wiki corren al arrancar. Solo van hacia delante: un binario más antiguo se niega a abrir un directorio migrado, así que ejecuta antes
ai-memory backupsi cabe la posibilidad de volver atrás.
Lee la guía de migración a la 2.0, con el camino de vuelta incluido
Preguntas y respuestas
¿ai-memory necesita TLS?
No en un portátil de un solo usuario escuchando en 127.0.0.1, ni por stdio. Añade un proxy TLS cuando existan cuentas, cuando el servidor escuche más allá de loopback, cuando abras la interfaz web desde otra máquina o cuando se pueda llegar a él desde fuera de la LAN. ai-memory no termina TLS por sí mismo.
¿De qué tengo que hacer copia de seguridad?
Ejecuta ai-memory backup, que es seguro con el servidor en marcha. El tarball contiene el árbol de la wiki, una instantánea consistente de SQLite y config.toml. La wiki es la fuente de verdad. Las páginas, los enlaces y la búsqueda se pueden reconstruir desde ella con ai-memory reindex, pero las sesiones, los traspasos, los usuarios y las claves solo existen en la base de datos.
¿ai-memory es compatible con SSO?
Admite autenticación por dispositivo con OIDC para los hooks de ciclo de vida y los comandos de la CLI, contra cualquier emisor que cumpla el estándar. El servidor no valida tokens OIDC por sí mismo, así que poner la API del servidor detrás de tu proveedor de identidad requiere un gateway compatible con OIDC delante.
¿Pueden dos servidores compartir un directorio de datos?
No. Ejecuta un servidor por directorio de datos. Desde la 2.0 el servidor toma un bloqueo exclusivo sobre .serve.lock y un segundo servidor se niega a arrancar.
¿Lo ejecutas en un sitio poco habitual?
Abre un issue y describe tu entorno. El código, la documentación y el tracker son públicos.