Por qué desaparecieron 90GB de tu disco: el estado de dependencias que dejan atrás los worktrees eliminados

Tu portátil dice que el disco está casi lleno. Vacías la carpeta de descargas, eliminas unas cuantas imágenes de Docker, reinicias, y dos semanas después te dice lo mismo. El verdadero culpable es un directorio que probablemente nunca has abierto: ~/.hermes/installs. Nunca aparece como un proceso grande ni sale en du -sh ~/Downloads — simplemente crece en silencio.
El motivo es simple y no es un bug. Cada vez que arrancas el agente en un worktree de hermes -w, un árbol de revisión o un clon temporal, Hermes prepara un entorno de dependencias dedicado para ese checkout — un entorno de Python, un entorno de test, el runtime de PM, unos 200MB por árbol. Cuando el árbol desaparece, ese entorno no. El PR #133808, fusionado el 7 de octubre de 2026, tapa ese hueco.
El estado está indexado por ruta
Primero, qué es exactamente la cosa. El estado de dependencias vive bajo <hermes home>/installs/<install_key>/, donde install_key no es un nombre de proyecto sino un hash de la ruta:
# pm/environments.py
def install_key(project_root: Path) -> str:
canonical = str(Path(project_root).resolve())
return hashlib.sha256(canonical.encode("utf-8")).hexdigest()[:16]
Así que dos worktrees del mismo repositorio obtienen claves distintas y entornos distintos, porque sus rutas difieren. Eso es deliberado: el sentido entero de un worktree es el aislamiento, y compartir un solo entorno de dependencias entre árboles lo consumiría.
El coste es que el aislamiento tiene una vida útil. git worktree remove, el pruner de arranque, hermes worktree prune, e incluso un rm -rf manual sobre el árbol dejan installs/<key>/ intacto. El estado de dependencias existe por ruta de checkout; el checkout se ha ido, el estado no, y ya nada lo referencia.
Las cifras del PR hacen concreto el problema. En un host de desarrollador, tras quince días de campañas de worktrees, ~/.hermes/installs contenía 499 entradas que sumaban 92GB, de las cuales 402 entradas (80GB) registraban un checkout que ya no existe — 360 de ellas bajo .worktrees/ — con una antigüedad mediana de cuatro días. Solo 76 entradas pertenecían a checkouts vivos. Más de cuatro quintos del espacio era estado fantasma.
El arreglo: un único registro decide qué es huérfano
El nuevo pm/install_states.py hace algo deliberadamente sencillo. Todo directorio de estado que se ha sincronizado correctamente contiene inputs/.project-root, escrito por record_activation_inputs, que nombra el checkout al que pertenece. La comprobación consiste simplemente en si esa ruta sigue existiendo.
La parte sutil es que “no está” no significa “borrado”. Un data root compartido con un contenedor (-v ~/.hermes:/opt/data) o un volumen no montado también registrará rutas que el proceso actual no puede ver. Así que el veredicto se restringe a probadamente borrado: el checkout debe haber estado en algún sitio que este proceso pueda observar — bajo el data root que posee installs/, o directamente dentro de un directorio .worktrees/ que todavía existe. Los directorios de estado sin registro alguno nunca se tocan.
La recuperación es igual de conservadora. Todo lo que sigue retenido se conserva:
- el
.install.lockno se puede tomar (un proceso lo está usando); - cualquier generación bajo
environments/aún tiene un lease vivo (algo la está leyendo); - un lock que ni siquiera se puede abrir cuenta como retenido.
Esa inclinación es la correcta. Borrar un entorno de dependencias que está en uso rompe la sesión en marcha; conservar uno que debería haberse ido solo cuesta disco.
Cómo recuperarlo ahora
No hay ninguna migración que hacer. Dos rutas hacen el trabajo automáticamente:
hermes pm gc # la salida gana una entrada final: N install state dir(s) of deleted checkouts
hermes worktree prune # recupera el estado tras la pasada de ramas, para árboles que ya no existen
El pruner que se ejecuta en cada arranque de Hermes también lo hace, así que en uso normal el estado de un worktree borrado desaparece en el siguiente arranque de hermes o en el siguiente pm gc. La recuperación al arrancar es fail-soft — un fallo se registra a nivel de debug y nunca bloquea el arranque.
Para ver primero qué estás cargando:
du -sh ~/.hermes/installs # total
ls ~/.hermes/installs | wc -l # número de entradas
hermes worktree list # antigüedad, tamaño, veredicto y motivo de cada árbol en .worktrees/
hermes worktree list es el pre-vuelo seguro: imprime un veredicto y el motivo de cada árbol antes de que hagas prune. Nunca borra cambios rastreados sin commitear, commits únicos sin pushear, ni árboles en uso, y los árboles temporales solo con archivos sin rastrear se archivan en ~/.hermes/archive/worktree-prune/ antes de eliminarlos.
En qué se diferencia de las otras historias de disco
Aquí hemos cubierto varios problemas relacionados con el disco, y los mecanismos son lo bastante distintos como para no confundirlos:
- una actualización que hace explotar el disco trata de artefactos temporales durante
hermes update; - la pérdida de datos del worktree sucio trata de un pruner que borró árboles que debería haber conservado;
- este va en la dirección opuesta: algo que debería haberse borrado no se borró. La limpieza llegó al árbol, pero no al estado de dependencias que el árbol dejó atrás.
Los dos primeros son bugs de barandilla; este es un hueco de cobertura. Juntos forman la imagen del lado de las dependencias, y recortar el almacenamiento al 78% de su tamaño anterior cubre el lado de los datos — sesiones y cachés — si quieres las dos mitades.
La versión corta
~/.hermes/installs/guarda el estado de dependencias indexado por el hash de la ruta de checkout, un entorno de ~200MB por worktree o clon temporal;- borrar el árbol nunca borraba ese estado — ni
pm gc, ni worktree prune, nirm -rf; - ahora
hermes pm gc,hermes worktree pruney el pruner de arranque recuperan el estado cuyo checkout está probadamente borrado, y dejan en paz cualquier cosa que esté detrás de un lock o un lease retenido; - medido en un host: 499 entradas con 92GB, 402 de ellas huérfanas (80GB), de 92GB a 18GB tras la recuperación.
Si abres worktrees o levantas clones desechables con regularidad, ejecuta hoy un du -sh ~/.hermes/installs. Si el número es más grande de lo que esperabas, hermes pm gc es toda la respuesta.