El agujero negro de recursos de Claude Code: de un paquete de 11,3 MB a 1,2 TB devorando disco
Categories:
Claude Code es una aplicación cliente de Node.js de un solo archivo sin gestión del ciclo de vida de recursos: al iniciarse analiza un paquete de 11,3 MB, escribe en disco sin límites durante la ejecución y, al cerrar la terminal, el proceso sigue vivo consumiendo memoria hasta que el sistema se bloquea. Basado en informes reales de usuarios en GitHub Issues y análisis inverso de la comunidad, este artículo revisa sistemáticamente sus defectos de gestión de recursos en memoria, CPU y disco, revelando problemas estructurales en la arquitectura de empaquetado, diseño de almacenamiento y gestión del ciclo de vida del proceso. Estos no son casos marginales, sino fallos de arquitectura reportados continuamente desde agosto de 2025 hasta abril de 2026, y que fueron cerrados en masa por robots de “stale”.
Arquitectura del empaquetado: el coste de un archivo de 11,3 MB
El núcleo de Claude Code es un único archivo empaquetado llamado cli.js, de aproximadamente 11,3 MB. El usuario de la comunidad paultendo realizó un análisis estático exhaustivo en Issue #29481, revelando varios problemas graves de arquitectura.
Tiempo de arranque de V8: 32 % del tiempo dedicado al análisis
El perfilado de CPU muestra que compileSourceTextModule consumió el 31,7 % del tiempo de muestreo durante la fase de arranque. El motor V8 necesita unos 300 ms para analizar este archivo de 11,3 MB, mientras que un script Node.js sin empaquetar tarda solo 23 ms. Un 7,3 % adicional se gasta en llamadas a spawnSync y un 3,5 % en recolección de basura. Esto significa que, antes de que el usuario introduzca cualquier comando, más del 40 % del tiempo de arranque se pierde en puro análisis.
Carga total: solo 20 importaciones dinámicas
Todo el paquete se analiza y ejecuta completamente al iniciar, con solo 20 expresiones import(). Cada usuario paga el coste de todas las funcionalidades, haya o no uso. A continuación se muestra lo que debería cargarse bajo demanda pero se empaqueta por completo:
pie title Composición del paquete (≈ 13,5 MB)
"Lógica central de la aplicación" : 7540
"SDK de AWS Bedrock" : 1100
"highlight.js (182 lenguajes)" : 1000
"OpenTelemetry" : 900
"Google Vertex + gRPC + Protobuf" : 800
"RxJS" : 300
"Otros (Ink, Zod, Ajv, Axios, etc.)" : 1807Un asistente de codificación necesita resaltar Brainfuck, ensamblador MIPS, Flix, Zephir, Inform7, Lasso y otros 182 lenguajes, lo que ya indica la crudeza de la estrategia de empaquetado. Mantener solo unas 40 lenguas comunes ahorraría alrededor de 786 KB de análisis.
Redundancia de dependencias: cuatro clientes HTTP, tres bibliotecas de validación
Cada SDK introduce dependencias independientes, lo que genera cuatro clientes HTTP (Axios, Undici, Got, fetch nativo) y tres bibliotecas de validación (Zod, Ajv, JSON Schema) en el mismo paquete. En entornos Node 18+, fetch ya está totalmente disponible, por lo que los demás clientes son innecesarios.
413 llamadas síncronas al sistema de archivos
El paquete contiene 196 existsSync, 109 statSync, 108 readFileSync, 58 mkdirSync, etc., sumando 413 llamadas síncronas al sistema de archivos. Cada una bloquea el bucle de eventos. Muchas siguen el patrón existsSync(path) && readFileSync(path), que podría reemplazarse por un único try { await readFile(path) } catch {}.
1087 envoltorios de interoperabilidad CJS/ESM
Cada módulo CommonJS empaquetado dentro de ESM genera un parche de compatibilidad __toESM/__commonJS/__require, totalizando 1087. Estos parches aumentan el peso del análisis y añaden una pequeña sobrecarga en tiempo de ejecución por módulo.
Polyfills innecesarios de Node 20
El paquete incluye 62 polyfills de Promise (nativo desde Node 0.12), 57 de Symbol (nativo desde Node 4), 57 funciones auxiliares async (nativo desde Node 8) y 3 polyfills de AbortController (nativo desde Node 15). Son dependencias transitivas compiladas para versiones antiguas de Node o navegadores, totalmente redundantes en el entorno objetivo.
ripgrep empaqueta los binarios de 6 plataformas: 61 MB
Los binarios de ripgrep para 6 plataformas se empaquetan completos, sumando 61 MB. En contraste, sharp usa dependencias opcionales e instala solo el binario de la plataforma actual. Esto implica un desperdicio de aproximadamente 51 MB de espacio en disco por instalación.
Degradación del rendimiento de Ink con la longitud del diálogo
La UI de terminal usa Ink (React for Terminal). El análisis muestra 6457 llamadas a createElement, 578 hooks useState, pero solo 11 envoltorios React.memo(), lo que representa un 1,9 %. En Ink, cada actualización de estado dispara una reconciliación completa del DOM virtual. Durante la respuesta en streaming, cada token recibido dispara una actualización, provocando renderizados innecesarios de componentes no memoizados. A medida que el diálogo crece, la salida renderizada se expande y cada re‑render requiere más diffs de contenido terminal. Esto coincide con el fenómeno descrito en Issue #22265 de “la sesión se vuelve cada vez más lenta”.
Consumo de disco: crecimiento ilimitado de GB a TB
Los problemas de disco son la falla de gestión de recursos más grave de Claude Code, con el mayor alcance y consecuencias.
Fuga del módulo nativo .node en Windows: 20 GB por semana
Issue #23095 documenta un problema no resuelto durante meses: el binario nativo de Windows (claude.exe) extrae plugins Node.js al directorio temporal en cada sesión, pero nunca los elimina. Cada archivo ocupa ~6,6 MB; el usuario SlothKing16 acumuló 2813 archivos en 4 días, totalizando 18 GB. Otro usuario, kolkov, reportó ~20 GB/semana, llegando a 100 GB/semana en usuarios intensivos. El problema se reportó a principios de 2025 y ha sido marcado repetidamente como duplicado y cerrado por robots.
Directorio ~/.claude: más de 3 GB sin gestión
El usuario kolkov auditó una máquina con 8 meses de uso diario en Issue #5024:
pie title Uso del directorio ~/.claude (≈ 3,1 GB)
"projects/ (historial de sesiones)" : 2500
"debug/ (registros de depuración)" : 303
"file-history/ (instantáneas de archivos)" : 232
"history.jsonl (historial global)" : 10
"Otros" : 55Datos clave: archivo JSONL de sesión único de 203 MB, archivo JSONL de sub‑agente de 72 MB, history.jsonl con más de 37 000 entradas. No hay rotación, compresión ni limpieza. Las instantáneas en file-history/ no se deduplican; el mismo archivo editado 10 veces genera 10 copias completas. Los registros en debug/ nunca se eliminan.
Salida de tareas en segundo plano: bucle de retroalimentación de 1,2 TB
Issue #32282 expone un defecto de diseño increíble. Cuando Claude Code lanza varios agentes en segundo plano y ejecuta automáticamente un comando bash que verifica el progreso, la salida del comando se escribe en el mismo directorio que coincide con el patrón glob, creando un bucle de retroalimentación infinito:
flowchart LR
A["bash: for f in tasks/*.output; tail -5 $f"] --> B["Salida escrita en tasks/task-A.output"]
B --> C["glob coincide con task-A.output mismo"]
C --> D["tail -5 lee su propia salida"]
D --> E["Se añade más contenido a sí mismo"]
E --> CVarios usuarios reportaron el mismo problema: 1,2 TB, 460 GB, 303 GB, 235 GB, 480 GB, 36 GB. Los comentarios del issue contabilizan 70 issues relacionados, agrupados en 15 conjuntos; solo los dos primeros grupos suman ~9,5 TB de consumo. La velocidad de escritura alcanza 425 MB/s durante 18 minutos, hasta que el disco se agota.
Falla en cascada: colapso irreversible tras llenar el disco
Issue #24207 describe la reacción en cadena desastrosa al agotarse el espacio:
flowchart TD
A["Espacio en disco = 0"] --> B["Fallo al escribir .claude.json"]
B --> C["Se genera un archivo de longitud cero"]
C --> D["Se lee como JSON inválido"]
D --> E["Sobrescribe toda la configuración del proyecto"]
E --> F["Tokens OAuth/API dañados"]
F --> G["Se requiere re‑autenticación"]
G --> H["Todos los agentes/sesiones en ejecución se detienen"]
H --> I["Incluso liberando espacio, no se recupera"]Sin advertencias, sin degradación elegante, sin ruta de recuperación. El usuario debe terminar manualmente todos los procesos, liberar espacio, restaurar configuraciones, volver a autenticarse y reconfigurar todo.
Escritura concurrente: sin bloqueos, sin transacciones, sin coordinación
En el directorio ~/.claude/ el único archivo de bloqueo es .update.lock (5 bytes). Todos los demás archivos se escriben sin protección. Cuando varios procesos de Claude Code se ejecutan simultáneamente (agentes + sub‑agentes son uso normal), no hay coordinación alguna:
| Archivo | Escritor | Mecanismo de bloqueo | Consecuencias conocidas |
|---|---|---|---|
sessions-index.json | Cada sesión del proyecto | Ninguno | Condiciones de carrera |
{uuid}.jsonl | Sesión principal + compresión | Ninguno | Pérdida de entradas |
.claude.json | Cada proceso | Ninguno | Configuración corrupta (8 reportes) |
file-history/* | Cada edición/escritura | Ninguno | Crecimiento ilimitado |
En Windows la situación empeora: los trucos de escritura atómica (escribir a .tmp y luego rename()) fallan porque rename() devuelve EPERM si el archivo está abierto por otro proceso, destruyendo la atomicidad.
Memoria y CPU: de 13 GB RSS a pánico del kernel
Consumo extremo de memoria en Windows
Issue #24840 registra un caso extremo en Windows: RSS de 13,21 GB, compromiso de memoria virtual de 47,17 GB, mientras la máquina tiene solo 42,56 GB de RAM. Se produjeron 3,75 M de fallos de página, indicando I/O continuo en disco. En 347 s de ejecución, solo 35 s fueron CPU en modo usuario, ~90 % del tiempo esperando I/O y swap. Otras aplicaciones (por ejemplo, el navegador Opera) dejaron de responder por completo.
Pánico del kernel en macOS
Issue #39253 informó consecuencias más graves: en un MacBook Pro M3 Pro (18 GB RAM), ejecutar múltiples instancias de Claude Code provocó pánicos del kernel. Se observaron dos tipos de pánico: OOM kill de Jetsam (presión de memoria que mata al proceso watchdogd) y timeout del watchdog (watchdogd no se registra durante > 90 s por falta de recursos). El sistema se reinicia sin advertencia, sin diálogos de error y sin oportunidad de guardar el trabajo.
Procesos huérfanos: continúan tras cerrar la terminal
Issue #44507 (abril 2026, hace pocos días) reportó una falla básica de gestión del ciclo de vida: al cerrar la ventana de la terminal, el proceso de Claude Code sigue vivo. Un proceso aislado consumió 35,4 GB RSS y 95,5 % de CPU durante 21 días. La causa raíz es la ausencia de un manejador process.stdin.on("end") en el punto de entrada CLI, mientras más de 55 temporizadores setInterval (para sondeo, telemetría, refresco de barra de estado, etc.) mantienen el bucle de eventos de Node.js activo indefinidamente. El heap de V8 crece sin límite, sin presión de GC, sin --max-old-space-size y sin watchdog de auto‑terminación.
Congelación al 100 % de CPU
Issue #27415 reportó una congelación al 100 % de CPU desencadenada por TaskStop, causada por un bucle descontrolado de posix_spawn en el runtime de Bun. Issue #26224 describió bloqueos de 5‑20 min al procesar grandes prompts.
Fracaso sistémico de la arquitectura de archivos planos
Asignar sin limpiar: patrón arquitectónico presente en todos los issues
El miembro de la comunidad kolkov señaló repetidamente en varios issues que la causa raíz es la misma:
Esta fuga de
.nodeno es un bug aislado; es un síntoma de un patrón arquitectónico recurrente donde Claude Code asigna recursos sin limpiarlos.
Desde 2025 hasta 2026, el problema evolucionó de un único archivo .claude.json a una proliferación de archivos JSONL, pero la arquitectura subyacente no cambió: archivos planos, sin bloqueos, sin transacciones, sin limpieza, sin compresión.
SQLite y un daemon local: propuestas de la comunidad
La comunidad ha sugerido varias veces reemplazar el almacenamiento plano por SQLite. Una base de datos SQLite puede resolver todos los problemas: modo WAL para lecturas concurrentes + escritura única atómica, transacciones que garantizan “todo o nada” en cada sesión, compresión integrada, limpieza TTL, deduplicación de contenido y consistencia multiplataforma.
Otra propuesta es introducir un daemon local (similar a un servidor LSP o la arquitectura de Docker), donde todos los procesos de Claude Code se comuniquen vía IPC, proporcionando coordinación sin cambiar el backend de almacenamiento.
Ingeniería inversa de la comunidad vs robot “stale”
El comentario de gebeer resume la situación:
Gracias por tu análisis exhaustivo. Esto debería haberse solucionado hace tiempo por los mantenedores.
kolkov añadió:
Lo irónico es que la comunidad está haciendo la depuración por ellos: ingeniería inversa del código, rastreo de rutas de error, propuestas de parches con fragmentos de código; y la respuesta es un robot que cierra todo después de 60 días.
Comparación de gestión de recursos con herramientas similares
GitHub Copilot, como extensión de VS Code, está limitado por la gestión de memoria y ciclo de vida del host de extensiones; Cursor, un fork de VS Code, hereda el mismo marco de gestión de recursos; ambos almacenan datos en SQLite o bases similares, soportando concurrencia y transacciones de forma nativa. Claude Code optó por procesos independientes + archivos planos, pero no implementó la gestión de recursos esperada: sin límite de memoria, sin cuota de disco, sin watchdog de proceso, sin salida elegante. Su comportamiento se asemeja más a una demostración de prototipo que a una herramienta lista para producción.
Paradoja entre capacidad del modelo y calidad de ingeniería
Un archivo empaquetado de 11,3 MB, 413 llamadas síncronas al sistema de archivos, 1087 envoltorios CJS/ESM, ausencia de limpieza de recursos, falta de control de concurrencia y sin monitor de espacio en disco—estos no son casos marginales, sino defectos estructurales del sistema. Desde el Issue #5024 de agosto 2025 hasta el Issue #44507 de abril 2026, la comunidad ha reportado continuamente la misma clase de problemas, ofreciendo análisis detallados y propuestas de solución, mientras muchos issues fueron marcados como “not planned” o cerrados automáticamente por el robot de “stale”. Una herramienta de codificación AI cuya propia calidad de código depende de auditorías y correcciones comunitarias constituye una paradoja digna de reflexión.
Si utilizas Claude Code, se recomienda revisar periódicamente el tamaño del directorio ~/.claude, limpiar los archivos .node temporales y asegurarte de salir correctamente con Ctrl + C antes de cerrar la terminal. Si el espacio en disco desaparece repentinamente, ahora sabes dónde buscar la causa.