Memoria persistente para Claude Code: cómo funciona realmente el contexto entre sesiones
Cierra su portátil el viernes después de una sesión de tres horas en la que Claude Code refactorizó su módulo de autenticación, aprendió que su equipo usa un contenedor personalizado Result<T> en lugar de lanzar excepciones y por fin comprendió por qué UserService no puede importar desde billing/. El lunes abre una nueva sesión y Claude, con total seguridad, envuelve una nueva función en un bloque try/catch e importa el módulo prohibido. Todo lo que aprendió ha desaparecido.
Este es el problema de ergonomía que define a las herramientas de programación con agentes: el modelo no tiene memoria episódica. Cada sesión empieza desde cero, más lo que usted haya anotado manualmente. Busquemos una solución de ingeniería con honestidad, incluidas las partes que no funcionan.
El problema central: las sesiones no conservan estado por diseño
Una sesión de Claude Code es una conversación. Cuando termina, la transcripción se archiva y el contexto de trabajo —la comprensión acumulada a lo largo de decenas de llamadas a herramientas— se evapora. La siguiente sesión reconstruye el contexto a partir de tres fuentes:
- Su
CLAUDE.mdfiles (project and user scope) - Los archivos que Claude lea durante la sesión
- Lo que usted escriba
Ninguna de estas fuentes recoge el conocimiento derivado : los callejones sin salida que ya exploró, la razón por la que existe una solución alternativa extraña o el hecho de que probó el enfoque A y este rompió la integración continua. Volver a deducir ese conocimiento consume tokens y tiempo real en cada sesión.
El impulso natural es crear una capa de memoria: capturar lo que ocurrió, comprimirlo e inyectar de nuevo la parte relevante al inicio. El proyecto de código abierto claude-mem es una implementación de referencia clara de este mismo patrón, y merece la pena estudiarlo tanto si lo adopta como si no.
El patrón arquitectónico detrás de la memoria persistente de Claude Code
Todo enfoque serio de la memoria persistente en Claude Code sigue el mismo ciclo de tres etapas. Entender cada etapa por separado te permite implementarla, comprar una solución u omitirla.
Etapa 1: Capturar
Necesitas observar lo que ocurrió en una sesión. Claude Code ofrece, como parte de su ciclo de vida, hooks — comandos de shell que se ejecutan ante determinados eventos. Los relevantes son:
| Hook | Se ejecuta cuando | Uso |
|---|---|---|
SessionStart | Comienza una sesión | Inyectar memoria |
SessionEnd | Termina una sesión | Activar la captura |
PostToolUse | Después de cualquier llamada a una herramienta | Transmitir actividad detallada |
Stop | El agente termina de responder | Punto de control |
Un hook mínimo de captura en .claude/settings.json:
{
"hooks": {
"SessionEnd": [
{
"matcher": "*",
"hooks": [
{
"type": "command",
"command": "$CLAUDE_PROJECT_DIR/.claude/mem/capture.sh"
}
]
}
]
}
}
El hook recibe JSON por stdin con la descripción del evento. Para SessionEnd recibes el ID de la sesión y la ruta de la transcripción, de modo que capture.sh puede leer el registro completo de la conversación:
#!/usr/bin/env bash
INPUT=$(cat)
TRANSCRIPT=$(echo "$INPUT" | jq -r '.transcript_path')
SESSION_ID=$(echo "$INPUT" | jq -r '.session_id')
# Hand the raw transcript to the compression stage
python3 "$CLAUDE_PROJECT_DIR/.claude/mem/compress.py" \
--transcript "$TRANSCRIPT" \
--session "$SESSION_ID"
Una trampa habitual: los hooks tienen un tiempo límite de ejecución, y enviar una transcripción extensa de forma síncrona a un LLM hará que se supere. En la práctica, conviene que la captura se lance sin esperar a que termine: escribe la ruta de la transcripción en una cola y procésala con un proceso de trabajo en segundo plano, no dentro del propio hook.
Etapa 2: Comprimir
Las transcripciones sin procesar no sirven como memoria: son enormes y están llenas de ruido (volcados de archivos, un exceso de mensajes de herramientas y tus errores de escritura). La etapa de compresión utiliza un LLM para destilar la sesión en hechos duraderos. Aquí conviene gastar una llamada a Haiku 4.5, no a Opus: resumir es precisamente el tipo de tarea de gran volumen y bajo riesgo para el que están pensadas las tarifas de Haiku.
import anthropic
client = anthropic.Anthropic()
PROMPT = """You are a memory compressor. From this coding session
transcript, extract ONLY durable facts worth remembering next session:
- Architectural decisions and their rationale
- Conventions discovered (naming, error handling, imports)
- Dead ends already explored (so we don't repeat them)
- Unresolved TODOs
Output JSON: a list of {fact, category, files[], confidence}.
Omit anything transient. If nothing durable happened, output []."""
resp = client.messages.create(
model="claude-haiku-4-5",
max_tokens=1500,
system=PROMPT,
messages=[{"role": "user", "content": transcript_text}],
)
memories = resp.content[0].text
Fíjate en el campo confidence y en la instrucción explícita de generar []. Ambos sirven para limitar los daños del tipo de fallo que veremos más adelante. Guarda la salida en algún lugar que permita consultas: SQLite con una columna de embeddings, o un almacén vectorial cuyas claves sean el proyecto y las rutas de los archivos.
Etapa 3: Inyectar
Al comenzar la sesión, recuperas los recuerdos relevantes y los inyectas. El hook SessionStart puede escribir en stdout, y esa salida se añade al contexto de Claude:
{
"hooks": {
"SessionStart": [
{
"matcher": "*",
"hooks": [
{ "type": "command", "command": "$CLAUDE_PROJECT_DIR/.claude/mem/inject.sh" }
]
}
]
}
}
La decisión de ingeniería crucial es el filtrado por relevancia. Inyectar toda la memoria es la opción ingenua y es un error: infla el contexto y ahoga los hechos útiles. Es mejor recuperar información según el tema probable de la sesión. Si aún no puedes determinarlo, inyecta solo hechos de alta confianza aplicables a todo el proyecto y ofrece acceso al resto mediante un servidor MCP para que Claude pueda consultar la memoria bajo demanda:
# A tiny MCP tool the agent calls when it wants history
@mcp.tool()
def recall(query: str, files: list[str] = []) -> list[dict]:
"""Retrieve relevant memories about this codebase."""
return memory_store.search(query, files=files, min_confidence=0.6)
Este modelo de consulta bajo demanda supera en la práctica al de envío anticipado. En lugar de adivinar qué es relevante al iniciar, dejas que el agente pregunte «¿hemos trabajado antes en este código de facturación?» justo cuando importa. El hook aporta un pequeño resumen siempre disponible; el servidor MCP se encarga de recuperar información específica.
Dónde falla esto — y sí, falla
Llevo suficiente tiempo utilizando capas de memoria como para ser escéptico. Los tipos de fallo son reales y se acumulan.
La memoria comprimida por IA alucina. El compresor es, a su vez, un modelo de lenguaje. A veces registrará como «decisión» lo que en realidad era una idea descartada, o invertirá el razonamiento que motivó una elección. Ahora tienes un recuerdo falso con apariencia de autoridad que se inyecta al iniciar, y el agente confía en él más de lo que debería. Esto es peor que no tener memoria, porque presenta información errónea con seguridad. El campo confidence y la revisión humana del almacén de memoria son las únicas medidas de mitigación reales.
El contexto obsoleto es un enemigo silencioso. Refactorizas UserService el martes. Tu memoria del lunes sigue diciendo «la autenticación está en UserService». Nada la invalida. Los recuerdos pierden precisión en cuanto cambia el código, y no existe una señal clara para hacerlos caducar. Vincula los recuerdos a hashes de archivos o a los SHA de los commits y considérarlos dudosos cuando se mueva el archivo subyacente.
Los costes de tokens aumentan en cada sesión. La memoria inyectada es contexto que pagas en cada turno, se utilice o no. Una capa de memoria que inyecta 4K tokens al iniciar añade esa cantidad al coste de entrada durante toda la sesión. El modelo MCP basado en consultas bajo demanda ayuda, pero la captura y la compresión también generan gastos recurrentes.
Esta es la comparación honesta:
| Enfoque | Coste de configuración | Tokens recurrentes | Riesgo de obsolescencia | Ideal para |
|---|---|---|---|---|
CLAUDE.md únicamente | Minutos | Bajo y determinista | Tú lo controlas | La mayoría de los proyectos |
| Herramientas MCP de alcance limitado | Horas | Solo bajo demanda | Baja | Estado actual del sistema |
| Capa de memoria completa | Días | Mayor, por sesión | Alto | Trabajo largo y exploratorio |
La verdad incómoda: probablemente no lo necesitas
Antes de implementar nada de esto, escribe un buen CLAUDE.md. Un archivo elaborado manualmente que diga «usamos Result<T>, nunca lances excepciones; UserService no debe importar billing/; la autenticación se trasladó a auth/ en el segundo trimestre» resuelve el 80% del problema de memoria sin riesgo de alucinaciones y con un coste determinista. Está escrito por una persona, así que es fiable por su propia elaboración.
Las capas de memoria justifican su coste en un ámbito más reducido de lo que sugiere la publicidad: trabajo prolongado y exploratorio en el que el conocimiento derivado (callejones sin salida, investigaciones a medio terminar) realmente no puede escribirse de antemano porque aún no lo conoces. Para el trabajo habitual de desarrollo de funcionalidades, CLAUDE.md junto con un par de servidores MCP de alcance limitado cubre más necesidades que un flujo automatizado de memoria, y nunca te miente.
Si decides implementar el flujo, la etapa de compresión es donde más importa prestar atención a los costes: generar resúmenes frecuentes con Haiku es barato, pero solo si el precio por token es razonable desde el principio, una de las razones por las que los equipos canalizan este tipo de trabajo de gran volumen en segundo plano a través de proveedores como AI Prime Tech.
Recomendaciones prácticas
- Las sesiones no conservan estado. El conocimiento derivado —callejones sin salida, razonamientos, convenciones— es lo que realmente se pierde, y volver a obtenerlo resulta costoso.
- El patrón es capturar → comprimir → inyectar. Conecta la captura y la inyección mediante hooks de
SessionEnd/SessionStart; realiza la captura de forma asíncrona para evitar que se agote el tiempo de ejecución de los hooks. - Prioriza las consultas bajo demanda frente al envío anticipado. Aporta un resumen muy breve al iniciar y después ofrece una herramienta MCP
recallpara que el agente recupere la memoria solo cuando sea relevante. - Comprime con Haiku 4.5, etiqueta cada recuerdo con su nivel de confianza y los hashes de los archivos de origen, y considera la memoria dudosa cuando cambien los archivos.
- La memoria automatizada puede mentir. El contexto inventado y obsoleto es peor que no tener ninguno porque parece autoritativo. Mantén la supervisión humana del almacén de memoria.
- Prueba
CLAUDE.mdprimero. Para la mayoría de los proyectos, un archivo de contexto escrito manualmente junto con herramientas de alcance limitado supera a una capa de memoria completa en coste, confianza y mantenimiento: recurre a la persistencia solo cuando tu trabajo sea realmente largo y exploratorio.
Una sola clave de API para Claude Opus 5.5, Sonnet 5, Haiku 4.5 y Fable 5.1, además de GPT-6 modelos. Pago por uso, sin suscripción.
Obtén tu clave de API →