Claude Checkpoint MCP
Guarda el estado de la sesión de Claude Code (objetivo, tareas, decisiones, archivos modificados, comandos recientes) en un archivo local y lo restaura como un resumen compacto de reanudación tras un fallo, /clear o límite de contexto. Solo local, secretos redactados.
Documentación
claude-checkpoint-mcp
Guarda el estado de tu sesión de Claude Code localmente, para que un fallo, /clear, o el límite de contexto no obliguen a Claude a reconstruir el contexto desde cero.
claude-checkpoint-mcp es un servidor local de Model Context Protocol con dos herramientas:
save_session_checkpointescribe el estado de trabajo de tu sesión en un pequeño archivo JSON en el proyecto.load_session_checkpointconvierte ese archivo de nuevo en un resumen compacto para reanudar.
Se ejecuta completamente en tu máquina. Nada se envía a ningún lugar.
Contenido
- Por qué: deja de pagar dos veces por el mismo contexto
- Cómo funciona
- Instalación
- Configuración
- Uso
- Referencia de herramientas y ejemplos
- El archivo
.claude-checkpoint - Seguridad y privacidad
- Solución de problemas
- Desarrollo
Por qué: deja de pagar dos veces por el mismo contexto
Una sesión larga de Claude Code acumula mucho contexto:
- lo que estás tratando de hacer;
- qué enfoques ya fallaron;
- qué archivos importan;
- qué prueba sigue en rojo.
Varias cosas pueden borrar todo eso a mitad de tarea:
- un fallo de terminal, caída de SSH o suspensión del portátil;
- quedarse sin ventana de contexto;
- un
/clearpara obtener una ventana nueva.
La siguiente sesión comienza en frío. Para volver a donde estabas, Claude tiene que reconstruir ese contexto:
- Releyendo archivos para averiguar qué cambió y por qué. Cada lectura de archivo son tokens de entrada.
- Reejecutando exploración:
grep,git diff,ls, ejecuciones de pruebas, todo solo para redescubrir el estado. - Reexplicando. Vuelves a escribir el objetivo, las restricciones y los callejones sin salida, o Claude redescubre los callejones sin salida de la manera difícil.
Cada una de esas acciones reenvía la conversación creciente como entrada, por lo que el costo se acumula.
claude-checkpoint-mcp reemplaza esa reconstrucción por una lectura pequeña y estructurada:
| Sin checkpoint | Con load_session_checkpoint | |
|---|---|---|
| Restaurar el objetivo y las restricciones | Los vuelves a escribir, o Claude los infiere | Una sección del resumen |
| Saber qué está hecho vs. pendiente | Re-derivado del código y git | Lista de tareas con estados |
| Saber qué archivos importan | Relectura amplia | Lista exacta de archivos tocados, con notas |
| Saber qué cambió desde entonces | Releer todo para estar seguro | Solo los archivos cuyo contenido realmente cambió se marcan |
| Recordar intentos fallidos | A menudo repetidos | Registrados en Decisiones y trampas |
El resumen de reanudación para una sesión típica es de aproximadamente 1.2 KB de markdown, unos pocos cientos de tokens. El ejemplo a continuación es salida real de ese tamaño.
El mayor ahorro proviene de la detección de deriva. Al guardar, el servidor registra un hash de contenido para cada archivo con cambios sin confirmar. Al cargar, compara esos hashes con el árbol de trabajo y le dice a Claude exactamente qué archivos cambiaron después del checkpoint. Todo lo demás en el resumen se puede confiar tal cual, por lo que Claude relee solo lo que tiene que releer.
Cómo funciona
Session 1 Session 2 (after crash / /clear)
───────── ────────────────────────────────
Claude ──save_session_checkpoint──┐ ┌──load_session_checkpoint── Claude
goal, tasks, summary, │ │ compact markdown brief
next steps, decisions, ▼ │ + "changed since checkpoint"
files, commands ┌─────────────────────┐
│ <project>/ │
server adds: │ .claude-checkpoint │◀── git: branch, HEAD,
git branch/HEAD, │ .claude-checkpoint │ dirty files + hashes
dirty files + hashes, │ .prev (backup) │
redacts secrets └─────────────────────┘
- Claude aporta el significado: el objetivo, el progreso, las decisiones, los siguientes pasos y qué comandos importaron.
- El servidor aporta los hechos: rama git y HEAD, cada archivo sin confirmar o sin rastrear con su hash de contenido, y marcas de tiempo.
- Las instrucciones del servidor enseñan a Claude cuándo actuar. Se le dice a Claude que cargue al inicio de una sesión y que guarde después de hitos, antes de operaciones arriesgadas y cuando la conversación se vuelve larga. No necesita que se le pida cada vez.
Instalación
Requisitos: Node.js 20+ y git. Git es opcional, pero sin él pierdes la detección de deriva.
git clone https://github.com/tenlean/claude-checkpoint-mcp.git
cd claude-checkpoint-mcp
npm install
npm run build
El punto de entrada del servidor ahora está en dist/index.js.
Configuración
Claude Code
Como plugin (lo más fácil). Este repositorio también es un marketplace de plugins de Claude Code. No necesitas clonar ni compilar nada:
claude plugin marketplace add tenlean/claude-checkpoint-mcp
claude plugin install claude-checkpoint-mcp@tenlean
Reinicia Claude Code, luego /mcp debería mostrar plugin:claude-checkpoint-mcp:claude-checkpoint como conectado.
Configuración manual. Si clonaste el repositorio, registra el servidor una vez para tu cuenta de usuario, para que esté disponible en todos los proyectos:
# Run from the claude-checkpoint-mcp directory
claude mcp add --scope user checkpoint -- node "$PWD/dist/index.js"
Usa una ruta absoluta. Un servidor a nivel de usuario se lanza desde cualquier proyecto en el que abras Claude Code. Una ruta relativa como
./dist/index.jsse resolvería contra ese proyecto, no contra este repositorio."$PWD/dist/index.js"se expande a la ruta absoluta cuando ejecutas el comando, que es lo que se guarda.
Verifica que esté registrado:
claude mcp list
Dentro de una sesión, /mcp debería mostrar checkpoint como conectado.
Alternativa a nivel de proyecto. Para compartir el servidor con un equipo a través del control de versiones, agrégalo al .mcp.json del proyecto:
{
"mcpServers": {
"checkpoint": {
"command": "node",
"args": ["/absolute/path/to/claude-checkpoint-mcp/dist/index.js"]
}
}
}
De cualquier manera, agrega los archivos de checkpoint al .gitignore del proyecto, o a tu gitignore global:
.claude-checkpoint*
Claude Desktop (claude_desktop_config.json)
Abre el archivo de configuración:
| SO | Ruta |
|---|---|
| macOS | ~/Library/Application Support/Claude/claude_desktop_config.json |
| Windows | %APPDATA%\Claude\claude_desktop_config.json |
Agrega el servidor bajo mcpServers, usando la ruta absoluta a tu compilación local:
{
"mcpServers": {
"checkpoint": {
"command": "node",
"args": ["/absolute/path/to/claude-checkpoint-mcp/dist/index.js"],
"env": {
"CHECKPOINT_PROJECT_ROOT": "/absolute/path/to/your/project"
}
}
}
}
Reinicia Claude Desktop después de guardar el archivo.
Claude Desktop no tiene noción de "proyecto actual". Usa
CHECKPOINT_PROJECT_ROOTpara establecer el proyecto predeterminado, o haz que Claude paseprojectRooten cada llamada ("guarda un checkpoint para /home/me/code/my-app"). Consulta resolución de raíz de proyecto.
Otros clientes MCP
Cualquier cliente MCP que admita el transporte stdio puede ejecutar el servidor:
node /absolute/path/to/claude-checkpoint-mcp/dist/index.js
Uso
Las instrucciones integradas del servidor cubren los casos comunes automáticamente. También puedes pedirle a Claude directamente.
Guardar:
- "Registra nuestro progreso."
- "Guarda un checkpoint antes de ejecutar la migración."
- "Actualiza el checkpoint. Fusiona lo que acabamos de hacer."
Reanudar (en una sesión nueva):
- "Reanuda donde lo dejamos."
- "Carga el checkpoint y continúa."
Ejemplo de resumen de reanudación
Esta es salida real de load_session_checkpoint. En el escenario, un archivo se confirmó sin cambios después del guardado, y un compañero luego editó session.ts:
# Resuming: my-app (checkpoint saved 2m ago, 2026-10-08 02:23:55 UTC)
Branch `feat/github-oauth` @ b2ef1b591 (uncommitted changes)
## Goal
Add GitHub OAuth login with persistent sessions
## Tasks
- [x] OAuth callback route
- [~] Session cookie persistence
- [ ] Logout endpoint
## Where things stand
Callback exchanges the code and creates a session, but the cookie is dropped on reload. Suspect SameSite/secure flags in dev.
## Next steps
1. Set sameSite: 'lax' and secure only in production in src/auth/session.ts
2. Re-run npm test -- auth
3. Start the logout endpoint
## Decisions & gotchas
- Use iron-session, not express-session (needs edge runtime support)
- Don't mock the GitHub API in e2e tests; use the recorded fixtures in test/fixtures
## Files touched (3)
- src/auth/session.ts (M) — cookie options
- src/auth/callback.ts (M)
- src/auth/session.spec.ts (??)
## Recent commands (last 2, oldest first)
- ✓ `GITHUB_CLIENT_SECRET=«redacted» npm run dev`
- ✗ exit 1 `npm test -- auth` — 2 failing in session.spec.ts: cookie missing after reload
## Since this checkpoint
- 1 new commit(s) on HEAD
- ⚠ Changed after the checkpoint, re-read before editing: `src/auth/session.ts`
callback.ts se confirmó después del guardado, pero su contenido no cambió, por lo que no se marca. Solo session.ts necesita ser releído.
Marcadores de tareas: [x] hecho · [~] en progreso · [ ] pendiente · [!] bloqueado.
Referencia de herramientas y ejemplos
save_session_checkpoint
Escribe <projectRoot>/.claude-checkpoint.
| Parámetro | Tipo | Requerido | Descripción |
|---|---|---|---|
goal | string (≤ 500) | ✅ | Objetivo principal de la sesión |
tasks | { description, status }[] (≤ 30) | status: pending · in_progress · done · blocked | |
summary | string (≤ 4000) | Dónde están las cosas: qué funciona, qué está roto, en qué estabas en medio | |
nextSteps | string[] (≤ 20) | Próximas acciones ordenadas para quien reanude | |
decisions | string[] (≤ 20) | Decisiones clave, restricciones, callejones sin salida a evitar | |
modifiedFiles | { path, note? }[] (≤ 100) | Archivos para anotar, o archivos confirmados para incluir. Los cambios git sin confirmar se detectan automáticamente. Las rutas absolutas dentro del proyecto se almacenan como relativas. | |
recentCommands | { command, exitCode?, note? }[] (≤ 50) | Comandos significativos, del más antiguo al más reciente. Los secretos se redactan. | |
mode | "replace" | "merge" | Predeterminado replace. Ver abajo. | |
projectRoot | string (absoluta) | Anula la resolución de raíz |
Guardado completo:
{
"goal": "Add GitHub OAuth login with persistent sessions",
"tasks": [
{ "description": "OAuth callback route", "status": "done" },
{ "description": "Session cookie persistence", "status": "in_progress" },
{ "description": "Logout endpoint", "status": "pending" }
],
"summary": "Callback exchanges the code and creates a session, but the cookie is dropped on reload. Suspect SameSite/secure flags in dev.",
"nextSteps": [
"Set sameSite: 'lax' and secure only in production in src/auth/session.ts",
"Re-run npm test -- auth"
],
"decisions": ["Use iron-session, not express-session (needs edge runtime support)"],
"modifiedFiles": [{ "path": "src/auth/session.ts", "note": "cookie options" }],
"recentCommands": [
{ "command": "GITHUB_CLIENT_SECRET=gh_live_8f2a91 npm run dev", "exitCode": 0 },
{ "command": "npm test -- auth", "exitCode": 1, "note": "2 failing in session.spec.ts" }
]
}
Respuesta (texto mostrado al modelo):
Checkpoint saved to /home/me/code/my-app/.claude-checkpoint (2202 bytes, replace).
3 task(s), 3 file(s), 2 command(s) on feat/github-oauth@b2ef1b591.
⚠ Redacted 1 secret-looking value(s).
Actualización incremental con merge:
{
"goal": "Add GitHub OAuth login with persistent sessions",
"mode": "merge",
"tasks": [
{ "description": "Session cookie persistence", "status": "done" },
{ "description": "Logout endpoint", "status": "in_progress" }
],
"recentCommands": [{ "command": "npm test -- auth", "exitCode": 0, "note": "all green" }]
}
| Campo | replace | merge |
|---|---|---|
goal | establecido | establecido |
tasks | establecido | actualizado al hacer coincidir description; las nuevas tareas se agregan |
summary, nextSteps | establecido | reemplazados si se proporcionan, de lo contrario se conservan |
decisions | establecido | agregado (deduplicado) |
recentCommands | establecido | agregado; los más antiguos se eliminan más allá de 50 |
modifiedFiles | escaneo git fresco + proporcionado | escaneo git fresco + proporcionado + registrado previamente |
id, createdAt | nuevo | conservado |
Salida estructurada (structuredContent):
{
"path": "/home/me/code/my-app/.claude-checkpoint",
"bytes": 2202,
"mode": "replace",
"counts": { "tasks": 3, "modifiedFiles": 3, "recentCommands": 2, "redactions": 1 },
"warnings": ["Redacted 1 secret-looking value(s)."]
}
load_session_checkpoint
Solo lectura. Lee el checkpoint, verifica la deriva y devuelve el resumen.
| Parámetro | Tipo | Requerido | Descripción |
|---|---|---|---|
format | "brief" | "full" | Predeterminado brief (markdown, como arriba). full devuelve el JSON completo del checkpoint más la deriva. | |
projectRoot | string (absoluta) | Anula la resolución de raíz |
Ejemplos:
{}
{ "format": "full", "projectRoot": "/home/me/code/my-app" }
Salida estructurada (structuredContent):
{
"found": true,
"path": "/home/me/code/my-app/.claude-checkpoint",
"fromBackup": false,
"updatedAt": "2026-10-08T02:23:55.477Z",
"drift": {
"branchChanged": false,
"currentBranch": "feat/github-oauth",
"commitsSince": 1,
"changedSince": ["src/auth/session.ts"]
},
"warnings": []
}
Si no existe un checkpoint, la herramienta devuelve found: false con un mensaje de "nada que reanudar". Eso no se trata como un error.
Cómo se elige la raíz del proyecto
- El argumento
projectRoot - La variable de entorno
CHECKPOINT_PROJECT_ROOT - La primera raíz
file://del cliente, si el cliente admite raíces MCP - El directorio de trabajo del proceso del servidor
La ruta debe ser absoluta y debe ser un directorio existente. Los enlaces simbólicos se resuelven. El archivo siempre se escribe exactamente en <root>/.claude-checkpoint.
El archivo .claude-checkpoint
Esto es JSON simple y versionado, por lo que es fácil de leer, comparar o editar a mano. Ejemplo real:
{
"version": 1,
"id": "ee5507c0-855e-44a5-85c1-d97b767537c9",
"createdAt": "2026-10-08T02:23:55.477Z",
"updatedAt": "2026-10-08T02:23:55.477Z",
"generator": { "name": "claude-checkpoint-mcp", "version": "0.1.0" },
"project": { "name": "my-app" },
"git": {
"branch": "feat/github-oauth",
"head": "b2ef1b5919ee5d456ea146c9362a7abc92b1e556",
"dirty": true
},
"goal": {
"primary": "Add GitHub OAuth login with persistent sessions",
"tasks": [
{ "description": "OAuth callback route", "status": "done" },
{ "description": "Session cookie persistence", "status": "in_progress" },
{ "description": "Logout endpoint", "status": "pending" }
]
},
"summary": "Callback exchanges the code and creates a session, but the cookie is dropped on reload. Suspect SameSite/secure flags in dev.",
"nextSteps": [
"Set sameSite: 'lax' and secure only in production in src/auth/session.ts",
"Re-run npm test -- auth",
"Start the logout endpoint"
],
"decisions": [
"Use iron-session, not express-session (needs edge runtime support)",
"Don't mock the GitHub API in e2e tests; use the recorded fixtures in test/fixtures"
],
"modifiedFiles": [
{ "path": "src/auth/session.ts", "status": "M", "source": "git", "note": "cookie options", "hash": "9ec893ef673dac860e7e2b6fcaad602983eeb0b1" },
{ "path": "src/auth/callback.ts", "status": "M", "source": "git", "hash": "f3ecc849c3875d4f11bb42ae0e5ab6c71931d7f1" },
{ "path": "src/auth/session.spec.ts", "status": "??", "source": "git", "hash": "9daeafb9864cf43055ae93beb0afd6c7d144bfa4" }
],
"recentCommands": [
{ "command": "GITHUB_CLIENT_SECRET=«redacted» npm run dev", "exitCode": 0, "at": "2026-10-08T02:23:55.477Z" },
{ "command": "npm test -- auth", "exitCode": 1, "note": "2 failing in session.spec.ts: cookie missing after reload", "at": "2026-10-08T02:23:55.477Z" }
],
"meta": { "redactions": 1, "truncated": false }
}
| Campo | Notas |
|---|---|
version | Versión del esquema. Las versiones anteriores se migran al cargar; las versiones desconocidas se rechazan. |
id / createdAt | Estables entre guardados de merge; nuevos en replace |
git | null fuera de un repositorio git, o antes del primer commit del repositorio |
modifiedFiles[].status | Código porcelain de git (M, A, D, R, ??), o M para archivos reportados solo por Claude |
modifiedFiles[].source | git (detectado) o agent (reportado por Claude, o arrastrado de una fusión anterior) |
modifiedFiles[].hash | Hash de blob git del contenido del árbol de trabajo al guardar; impulsa la detección de deriva |
meta.truncated | true si se eliminó algo para ajustarse a los límites de lista o tamaño |
Las rutas siempre son relativas a la raíz del proyecto. El archivo nunca almacena rutas absolutas.
Seguridad y privacidad
- Solo local. No hay llamadas de red. El servidor lee metadatos de git y un archivo, y escribe un archivo.
- Redacción de secretos. Lo siguiente se reemplaza con
«redacted»en comandos, notas, resúmenes, tareas y decisiones antes de que cualquier cosa toque el disco:- asignaciones de
*_KEY=,*_TOKEN=,*_SECRET=,*PASSWORD=, incluidas las formasHeader: valuey JSON - encabezados
Authorization: Bearer … - credenciales en URLs (
postgres://user:pass@…) - banderas
--password/--token/--api-key/--secret - tokens simples de
sk-…,ghp_…,github_pat_…,AKIA…yxox?-…La redacción es una red de seguridad, no una garantía, así que mantén el archivo fuera del control de versiones.
- asignaciones de
- Escrituras seguras ante fallos, solo para el propietario. Los archivos se escriben con el modo
0600. Cada guardado escribe un archivo temporal, lo sincroniza (fsync) y lo renombra en su lugar, de modo que un fallo a mitad del guardado no puede dejar un punto de control a medias. - Copia de seguridad automática. El punto de control válido anterior se conserva como
.claude-checkpoint.prev. Si el archivo principal está corrupto, la carga recurre a la copia de seguridad y lo indica. Un archivo corrupto nunca sobrescribe una copia de seguridad buena. - Tamaño limitado. Cada campo tiene un límite de longitud, y el archivo está limitado a 64 KB (los comandos más antiguos se eliminan primero), de modo que un punto de control no puede convertirse en un sumidero de tokens.
- Sin shell. Git se ejecuta mediante
execFilecon un tiempo de espera de 3 segundos yGIT_OPTIONAL_LOCKS=0, por lo que nunca compite con tus propios comandos de git. - No toca tu configuración. Si el punto de control no está ignorado por git, la respuesta de guardado te lo advierte. Nunca edita
.gitignorepor ti. - Seguro con llamadas a herramientas en paralelo. Las llamadas a herramientas se serializan dentro del servidor, de modo que los guardados concurrentes de
mergeno pueden perder actualizaciones.
Solución de problemas
| Síntoma | Solución |
|---|---|
checkpoint no aparece en /mcp | Ejecuta claude mcp list y comprueba que la ruta sea absoluta y que dist/index.js exista (npm run build). |
| El punto de control se escribe en el directorio incorrecto | El servidor recurrió a su directorio de trabajo. Pasa projectRoot, o establece CHECKPOINT_PROJECT_ROOT. |
projectRoot must be an absolute path | Usa una ruta completa como /home/me/code/app, no ./app. |
| El resumen dice "Saved commit … is no longer reachable" | La rama se reescribió o se reinició después del guardado. La deriva no se puede calcular contra el historial, así que trata los archivos marcados como que necesitan una relectura. |
| Advertencia: "not git-ignored" | Añade .claude-checkpoint* a .gitignore. |
| Sin sección "Since this checkpoint" | El proyecto no es un repositorio git, o no tenía confirmaciones en el momento del guardado. |
Los registros del servidor van a stderr. Stdout está reservado para el protocolo MCP.
Desarrollo
npm run typecheck # strict TypeScript, src + tests
npm test # unit tests + in-memory MCP end-to-end tests (vitest)
npm run build # compile to dist/
npm run inspect # open the MCP Inspector against dist/index.js
src/
├── index.ts # entry point: stdio transport, signals, stderr logging
├── server.ts # McpServer construction + server instructions
├── tools.ts # save/load tool schemas and handlers
├── schema.ts # zod schema for the checkpoint file (v1) + migrations
├── store.ts # project root resolution, atomic I/O, backup/fallback
├── git.ts # branch/HEAD/status snapshot, blob hashing, drift detection
├── redact.ts # secret scrubbing
└── render.ts # checkpoint → markdown resume brief
Construido con el oficial @modelcontextprotocol/sdk y zod.