Un solo comando para actualizar todos los plugins: hermes plugins update ahora te enseña la lista primero


Vuelves de una semana de vacaciones, ejecutas hermes plugins list y te encuentras doce plugins instalados, siete marcados con actualización disponible. Te acuerdas de que dos de ellos traían correcciones de errores. Así que empiezas a escribir nombres —hermes plugins update foo, luego bar— y en algún punto alrededor del cuarto pierdes la cuenta de cuáles quedan, lo dejas estar y te dices que ya lo resolverás otro día.

Es el tipo de tarea que nunca rompe nada pero te va cobrando por partes. Un cambio fusionado el 19 de octubre lo arregla: hermes plugins update ahora funciona sin nombre de plugin — primero audita, luego actualiza de una vez.

Por qué antes exigía un nombre

El subcomando update hacía exactamente una cosa: recibir un nombre, averiguar cómo se había instalado ese plugin y traer la versión más nueva. No tenía ni idea de qué más había instalado, así que sin nombre solo podía imprimir un error de uso:

$ hermes plugins update
usage: hermes plugins update [-h] name
hermes plugins update: error: the following arguments are required: name

Actualizar en bloque significaba escribirse tu propio bucle, y el bucle es fácil de escribir mal. ¿El nombre del directorio es de verdad el nombre del plugin? Las instalaciones de catálogo y las de Git se actualizan de forma distinta: ¿haces una bifurcación según el caso? Si una falla, ¿sigues adelante? Todo ese criterio vivía en tu cabeza.

Ahora: sin nombre significa «audítalos todos»

hermes plugins update

En una terminal lanza una sonda de check-updates en modo solo lectura y muestra una tabla:

# Plugin Actual Última Actualización
1 hermes-dreaming 2.9.3 2.9.5 re-pin del catálogo
2 obsidian-sync a1b2c3d4 9f8e7d6c git pull

Debajo de la tabla nombra cada plugin que se salta y por qué, por ejemplo skipped foo (pip): pip distribution; Hermes does not upgrade it. Luego pregunta una vez:

Update all 2? [Y/n]:

Pulsas Intro o y y actualiza cada uno. Cada plugin sigue pasando por la ruta completa de un solo plugin — esto no es un push forzado. Si una versión nueva pide nuevas capacidades (una herramienta nueva, acceso nuevo al sistema de archivos), ese aviso sigue apareciendo plugin por plugin; si el catálogo vuelve a apuntar a otro commit de release, eso también se pregunta. El sentido de agrupar es quitar tecleo repetido, no quitar consentimiento informado.

Un fallo no detiene al resto

El peor comportamiento en lote es «falló el tercer plugin, así que los cuatro últimos nunca se ejecutaron». Aquí cada plugin es independiente:

  • Un fallo imprime la línea de error de ese plugin concreto y sigue adelante;
  • La ejecución termina con un resumen dividido en ✓ actualizado, = ya al día y ✗ falló (con la primera línea del motivo del fallo);
  • El código de salida es 1 si falló algo, 0 si todo salió bien;
  • Sin nada que hacer, dice No plugin updates to apply. y sale con 0.

Eso lo hace seguro para meterlo detrás de un condicional de shell o en una tarea programada:

hermes plugins update --yes || echo "some plugin failed to update"

Ejecutarlo en scripts, cron y pipes

Sin terminal (cron, CI, un pipe hacia tee) el comportamiento por defecto es no hacer nada: imprime la lista, sale con 1 y te dice que lo vuelvas a lanzar con --yes. Esa prudencia es deliberada: las actualizaciones en bloque nunca deberían cambiar cosas en silencio dentro de un entorno desatendido.

Con --yes las actualizaciones sí se ejecutan, pero el consentimiento falla cerrado:

  • Las capacidades nuevas que pide una versión nueva no se conceden; el plugin queda restringido;
  • Un commit del catálogo vuelto a fijar no se aplica;
  • Todo lo que no necesita consentimiento extra se actualiza con normalidad.

Además, --yes solo es válido sin nombre. hermes plugins update foo --yes se rechaza, para que nadie lo lea como «actualiza este y aprueba automáticamente lo que pida».

Si de verdad quieres actualizaciones desatendidas para algunos plugins, eso es un interruptor aparte y explícito:

plugins:
  auto_apply: true    # solo instalaciones Git rastreadas; por defecto false

auto_apply cubre únicamente plugins Git rastreados. No toca filas fijadas (pinned), colocadas a mano, con procedencia desviada ni distribuciones pip. Ambas rutas ejecutan el mismo escaneo de seguridad previo a la actualización.

Qué plugins se omiten y por qué

La actualización en bloque solo actúa sobre los dos tipos que update puede mover de verdad: instalaciones de catálogo (vueltas a fijar al commit del catálogo revisado) e instalaciones Git rastreadas (con pull). Todo lo demás se omite por su nombre en lugar de «actualizarse» en silencio:

Caso Motivo de la omisión
distribución pip Hermes no actualiza paquetes de PyPI, eso le toca a pip
fijado (versión o commit) Fijado significa que quieres que se quede donde está
necesita arreglo Arregla primero el estado de la instalación
estado desconocido No puede alcanzar el remoto, así que no va a adivinar

Si hiciste git clone de un plugin directamente dentro del directorio de plugins, eso no es una instalación rastreada: ejecuta antes hermes plugins adopt <name> para que Hermes sepa de dónde vino. Es intencional: no va a hacer pull de un directorio cuya procedencia no entiende.

Un detalle de seguridad más: si una versión nueva cambia su manifiesto, o introduce o reemplaza un update_url, Hermes rechaza la dirección nueva hasta que la apruebes:

hermes plugins trust-update-url my-plugin

Eso es una comprobación de procedencia del feed, no un sandbox. Te defiende de «alguien cambió el canal de actualizaciones por el servidor de otra persona»; no te defiende de que código en el que ya confías haga algo malo.

Cuándo se comprueba y cómo comprobarlo

hermes plugins update ejecuta la misma sonda que hermes plugins check-updates, que es de solo lectura y no toca los archivos de los plugins — ideal para monitorizar:

hermes plugins check-updates   # solo informa, no cambia nada

El gateway también ejecuta una comprobación programada, espaciada según plugins.auto_update_check_hours (24 horas por defecto, 0 la desactiva). Su recibo se ve con hermes pm status y en la vista de estado de sincronización de Desktop. Eso solo controla cada cuánto mira Hermes: nada se actualiza por defecto salvo que ejecutes update o te apuntes a auto_apply.

Consejos prácticos

  • Mira antes de saltar. Si no sabes cuánto te queda por detrás, lanza primero hermes plugins check-updates; no toca nada.
  • Ejecuta hermes plugins list después. La actualización en bloque sigue preguntando por cada plugin. Si pasaste a base de Intro por un aviso de autorización, ese plugin acaba restringido en vez de roto, y nada te avisa a gritos: vale la pena echar un ojo.
  • No confíes en los valores por defecto dentro de CI. Sin terminal se niega a actualizar y sale con 1; si tu pipeline trata un código distinto de cero como fallo, pasa --yes de forma explícita o deja las actualizaciones fuera de CI.
  • «Versión nueva» significa cosas distintas según el tipo de instalación. Una instalación de catálogo pasa a un commit que el catálogo revisó; una instalación Git sigue el HEAD de la rama upstream. La segunda tiene un radio de impacto mucho mayor.

Dos artículos anteriores dan el contexto: cómo funciona el catálogo de plugins y la puerta de cadena de suministro en CI que hay detrás. Si mantienes plugins portables, la puerta de confianza MCP para plugins portables cubre la otra mitad de la historia de confianza. La lista completa de subcomandos está en la referencia de comandos de plugins.

La versión corta

Actualizar en bloque no es la parte difícil: lo difícil es mantener juntos «bloque» y «consentimiento informado». Este cambio traza la línea con claridad: el tecleo repetido desaparece, y cada decisión que importa (capacidades nuevas, un commit de catálogo vuelto a fijar, un origen de actualización cambiado) sigue poniéndose delante de ti, de una en una. Para quien lleva una docena de plugins, esa es la diferencia entre «ya lo haré» y un one-liner semanal.