Hermes estrena su propio gestor de paquetes: qué arreglan de verdad pm doctor, repair y gc


Una mañana hermes no arranca: un único ModuleNotFoundError, y lo único que hiciste ayer fue instalar un plugin. O lo contrario: la misma config funciona en tu portátil y en el escritorio afirma que una herramienta no existe. Abres pip list para averiguar por qué y descubres tres entornos de Python, ninguno de los cuales sabe de los otros.

Por eso Hermes lleva su propio gestor de paquetes. hermes pm no gestiona la aplicación Hermes (para eso está hermes update); gestiona la capa de abajo: binarios de herramientas y entornos de dependencias de Python. En cuanto esa línea queda clara, cada subcomando tiene un sitio evidente.

Qué posee

La documentación lo resume en tres tareas: instalar binarios de herramientas fijados y ponerlos en el PATH, preparar entornos de Python gestionados para Hermes, y explicar la diferencia entre lo declarado y lo que está realmente instalado.

Cada archivo implicado juega un papel, y confundirlos es la mala lectura más habitual:

Archivo Papel
pm/lock.json Versiones exactas de herramientas gestionadas, URLs por target, hashes SHA-256
pm/pyproject.toml + pm/uv.lock Los requisitos y el lock de Python del propio gestor de dependencias
pyproject.toml + uv.lock Los requisitos del proyecto principal, extras, marcadores de plataforma
facts.json del tool-store Entradas de herramientas instaladas, identidades, exportaciones de entorno, digests de archivos realizados
facts.json por instalación El entorno de Python seleccionado, su sello de entrada, extras habilitados

Una entrada en el lockfile no demuestra que un paquete esté instalado. Esa sola frase explica hermes pm doctor: compara el estado instalado con el lock y comprueba los bytes realizados.

Los cuatro comandos del día a día

hermes pm status     # el último recibo de sync/update como JSON, o un simple "sin recibo"
hermes pm doctor     # ¿coinciden identidades, archivos y digests de las herramientas con el lock?
hermes pm install    # herramientas requeridas + Python, y luego sincroniza el extra all
hermes pm repair     # reconstruye y valida el entorno de dependencias de Python

status es el punto de partida más barato. Imprime el recibo más reciente — esta es salida real de esta máquina, recortada:

{
  "exit_code": 0,
  "feature_list": null,
  "finished_at": "2026-10-21T16:57:52.054592+00:00",
  "kind": "plugin-check",
  "outcome": "ok",
  "plugin_checks": [],
  "refusal": null,
  "schema": 1,
  "steps": [],
  "update_id": null,
  "venv_rebuild": null,
  "warnings": []
}

outcome, refusal, warnings y steps suelen bastar para distinguir un éxito de una ejecución parcial o de un rechazo.

install merece su propio párrafo. Un pm install a secas instala las herramientas requeridas más Python, pone las herramientas en el PATH, sincroniza el extra all y además instala las herramientas opcionales por defecto — agent-browser con Chromium, y cua-driver. Si falla la descarga de esas herramientas opcionales, se imprime un aviso y no se rompe la instalación, porque la mayoría solo quiere la CLI, no un navegador ni control de escritorio.

Si las omitiste en el momento de instalar con --skip-browser o --skip-computer-use, esa elección queda registrada: las instalaciones posteriores sin flags y hermes update siguen dejándolas fuera. Para revertirlo, nombra el paquete una vez — hermes pm install agent-browser.

Reparar una cadena de dependencias rota

repair y gc resuelven problemas distintos; mezclarlos hace perder tiempo.

pm repair reproduce en una generación nueva el conjunto de dependencias registrado de la generación seleccionada, lo valida y luego lo selecciona. Lo crucial: no parsea la configuración de plugins, así que la config del plugin que rompió tus dependencias no se vuelve a leer. Tampoco cambia pins, extras ni config de plugins. Si el registro es ilegible o falta el lock guardado, falla en lugar de entregarte un entorno reducido.

Al arrancar, Hermes solicita la misma reparación cuando encuentra dependencias incompletas, pero los intentos automáticos están acotados; ejecutar pm repair de forma explícita no lo está.

pm gc elimina lo que nada referencia: entradas huérfanas del tool-store, descargas parciales elegibles, entornos de Python gestionados por lease que no se usan y el estado installs/INSTALL_KEY/ de checkouts que ya no existen. Es deliberadamente conservador — conserva los checkouts que este proceso no puede ver (una instalación de host vista desde un contenedor que comparte la raíz de datos, por ejemplo) y cualquier estado cuyo lock de instalación o lease de entorno siga tomado.

Regla mnemotécnica de una línea: roto significa repair, inflado significa gc.

Pins, la regla de los tres días y los mirrors

Todo paquete de Python del que depende Hermes debe tener al menos tres días de antigüedad cuando Hermes lo fija — el exclude-newer de uv, aplicado por el chequeo de lock en CI. La intención es simple: un paquete publicado hace minutos, quizá comprometido, no puede llegar a uv.lock.

La consecuencia práctica: hermes pm lock es el paso que aplica la comprobación, y contra un mirror que no publica horas de subida se detiene con has no publish time. Cuando veas eso, apunta ese paso a https://pypi.org/simple; las instalaciones del día a día pueden seguir pasando por el mirror.

Los mirrors se configuran con index-url en pip.conf, que Hermes pasa a uv, o con UV_INDEX_URL.

Las descargas reintentan, los hashes malos no

La política de reintentos merece recordarse:

  • Como máximo cuatro intentos por sondeo o transferencia, con backoff de 1, 2 y 4 segundos; una cabecera Retry-After puede alargar la espera hasta 30 segundos.
  • Se reintentan: 408, 429, 500, 502, 503, 504, además de resets de conexión, timeouts, fallos temporales de DNS y cuerpos de respuesta interrumpidos.
  • Las descargas por rangos conservan los bytes ya recibidos; los servidores sin soporte de rangos necesitan un stream nuevo.
  • No se reintentan: hashes que no coinciden, fallos de certificado, errores del filesystem local — fallos permanentes.

Así que si una descarga falla tres veces, lee la causa en el log antes de culpar a la red.

Comandos de mantenedor, y el flag nuevo

Son herramientas de desarrollo y empaquetado; la mayoría de usuarios nunca las necesita.

Comando Efecto
pm lock Vuelve a generar uv.lock desde pyproject.toml; no escribe nada si el lock está al día
pm lock --bump NAME VERSION Resuelve y hashea los artefactos objetivo y escribe el pin de la herramienta en pm/lock.json
pm update [names...] Consulta versiones aguas arriba, cambia pins, instala las herramientas modificadas
pm update --check Consulta sin escribir; un exit 1 puede significar que hay actualizaciones — lee la salida
pm update --target TARGET Resuelve versiones para un target concreto
pm update --uv / --npm Refresca también la resolución de Python o de npm
pm update --termux [--check] Vuelve a fijar archivos del pool de termux que el pool rodante ha retirado
pm bundle --out DIR Prepara un payload portable (snapshot del código, herramientas, dependencias) — no un instalador firmado

El nuevo pm update --skip-target TARGET resuelve una molestia concreta: cuando aguas arriba va con retraso, no quieres que se refresquen los pins de un target determinado. Digamos que el pool de termux aún se está poniendo al día y quieres que una ronda de actualización deje linux-arm64-bionic en paz — pasa el flag (repetible) y esos pins se quedan, mientras las ejecuciones posteriores siguen reportando el paquete como actual.

Solución de problemas por síntoma

  • Falta una herramienta o está en la versión equivocada → lee pm doctor y luego instala ese paquete de forma explícita con pm install en una instalación escribible.
  • Conflicto de dependencias → lee pm status, corrige los requisitos declarados del plugin, reintenta.
  • Dependencias de Python dañadas → pm repair, y reinicia Hermes.
  • Un entorno nuevo no surtió efecto → reinicia el proceso de Hermes afectado. No añadas un segundo árbol de site-packages a un import path en caliente.
  • El disco se lo comieron entornos viejos → pm gc; si el disco ya está lleno, nuestra guía de autoprune con poco disco cubre el lado del runtime.
  • Paquete o extra desconocido → pm install acepta nombres de paquete, no nombres de extras de Python ni especificaciones name==version de pip.

El sesgo de diseño

hermes pm está hecho para fallar en voz alta en lugar de entregarte en silencio un entorno degradado. Una tabla de costes mal formada impide que un servidor cargue, un registro ilegible hace fallar repair, un pool de termux retirado hace que una actualización dé error — todo para que el problema salga ahora y no como un fallo extraño la semana que viene.

Si lo único que quieres es actualizar Hermes en sí, nunca necesitas pm; la guía de actualización sin sustos cubre ese otro camino.