Ein Befehl für alle Plugins: hermes plugins update zeigt dir jetzt erst die Liste


Zurück aus einer Woche Urlaub tippst du hermes plugins list und findest zwölf installierte Plugins, sieben davon mit Update-Flag. Zwei davon, weißt du noch, brachten Bugfixes. Also fängst du an, Namen zu tippen – hermes plugins update foo, dann bar – und irgendwo beim vierten verlierst du den Überblick, welche noch übrig sind, gibst auf und versprichst dir, dich später darum zu kümmern.

Das ist die Sorte Hausarbeit, die nie etwas kaputt macht, aber ständig kostet. Eine am 19. Oktober gemergte Änderung räumt damit auf: hermes plugins update funktioniert jetzt ohne Plugin-Namen – erst prüfen, dann einmal aktualisieren.

Warum früher ein Name verlangt war

Das update-Subcommand tat genau eine Sache: einen Namen nehmen, nachschauen, wie dieses Plugin installiert wurde, und die neuere Version ziehen. Es wusste nicht, was sonst installiert war, also konnte es ohne Namen nur einen Usage-Fehler ausgeben:

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

Massen-Updates bedeuteten, sich selbst eine Schleife zu schreiben, und die Schleife schreibt man leicht schlecht. Ist der Verzeichnisname wirklich der Plugin-Name? Catalog-Installationen und Git-Installationen aktualisieren sich unterschiedlich – verzweigst du danach? Wenn eines scheitert, machst du weiter? All diese Entscheidungen lagen früher in deinem Kopf.

Jetzt: kein Name heißt „alle prüfen“

hermes plugins update

In einem Terminal läuft eine Read-only-Sonde check-updates und gibt eine Tabelle aus:

# Plugin Aktuell Neueste Update
1 hermes-dreaming 2.9.3 2.9.5 catalog re-pin
2 obsidian-sync a1b2c3d4 9f8e7d6c git pull

Unter der Tabelle nennt es jedes übersprungene Plugin und den Grund – zum Beispiel skipped foo (pip): pip distribution; Hermes does not upgrade it. Dann fragt es einmal:

Update all 2? [Y/n]:

Enter oder y, und es aktualisiert jedes einzelne. Jedes Plugin läuft weiterhin durch den vollen Einzel-Plugin-Pfad – das ist kein Force-Push. Wenn eine neue Version neue Capabilities anfragt (ein neues Tool, neuer Dateisystemzugriff), erscheint dieser Prompt weiterhin pro Plugin; wenn der Catalog einen Release-Commit neu festnagelt, wird auch das weiterhin gefragt. Der Sinn des Batchings ist, wiederholtes Tippen zu entfernen, nicht die informierte Zustimmung.

Ein Fehler stoppt den Rest nicht

Das schlechteste Batch-Verhalten ist „das dritte Plugin ist gescheitert, also liefen die letzten vier nie“. Hier ist jedes Plugin unabhängig:

  • Ein Fehler gibt die eigene Fehlerzeile des Plugins aus und macht weiter;
  • Der Lauf endet mit einer Zusammenfassung, aufgeteilt in ✓ updated, = already current und ✗ failed (mit der ersten Zeile des Fehlergrunds);
  • Der Exit-Code ist 1, wenn etwas gescheitert ist, 0, wenn alles geklappt hat;
  • Gibt es nichts zu tun, sagt es No plugin updates to apply. und beendet mit 0.

Damit ist es sicher, es hinter ein Shell-Conditional oder in einen geplanten Job zu hängen:

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

In Skripten, Cron und Pipes

Ohne Terminal (Cron, CI, eine Pipe nach tee) ist der Default nichts tun: Es gibt die Liste aus, beendet mit 1 und sagt dir, du sollst mit --yes erneut laufen. Diese Vorsicht ist Absicht – Massen-Upgrades sollten in einer unbeaufsichtigten Umgebung nie still etwas verändern.

Mit --yes laufen die Updates tatsächlich, aber die Zustimmung fällt fail-closed aus:

  • Neue Capabilities, die eine neue Version anfragt, werden nicht erteilt; das Plugin bleibt eingeschränkt;
  • Ein neu festgenagelter Catalog-Commit wird nicht angewendet;
  • Alles, was keine zusätzliche Zustimmung braucht, aktualisiert sich normal.

--yes ist außerdem nur ohne Namen gültig. hermes plugins update foo --yes wird abgelehnt, damit es niemand als „dieses eine upgraden und alles durchwinken, was es fragt“ liest.

Wenn du wirklich unbeaufsichtigte Updates für manche Plugins willst, ist das ein separater, expliziter Schalter:

plugins:
  auto_apply: true    # tracked Git installs only; default false

auto_apply deckt nur getrackte Git-Plugins ab. Gepinnte, manuell platzierte, provenance-drifted oder pip-distribution-Zeilen bleiben unberührt. Beide Wege laufen durch denselben Security-Scan vor dem Update.

Welche Plugins übersprungen werden, und warum

Das Massen-Update handelt nur bei den zwei Sorten, die update tatsächlich bewegen kann: Catalog-Installationen (neu festgenagelt auf den geprüften Catalog-Commit) und getrackte Git-Installationen (gepullt). Alles andere wird namentlich übersprungen, statt still „aktualisiert“ zu werden:

Fall Skip-Grund
pip distribution Hermes upgradet keine PyPI-Pakete – das ist Job von pip
pinned (Version oder Commit) Gepinnt heißt: Du willst, dass es da bleibt
needs fixing Repariere erst den Installationszustand
status unknown Das Remote ist nicht erreichbar, also wird nicht geraten

Wenn du ein Plugin direkt per git clone ins Plugin-Verzeichnis gelegt hast, ist es keine getrackte Installation – lauf zuerst hermes plugins adopt <name>, damit Hermes weiß, woher es kommt. Das ist Absicht: Es pullt kein Verzeichnis, dessen Herkunft es nicht versteht.

Noch ein Sicherheitsdetail: Wenn eine neue Version ihr Manifest ändert oder eine update_url einführt bzw. ersetzt, lehnt Hermes die neue Adresse ab, bis du sie freigibst:

hermes plugins trust-update-url my-plugin

Das ist eine Prüfung der Feed-Herkunft, keine Sandbox. Es verteidigt gegen „der Update-Kanal wurde gegen den Server von jemand anderem getauscht“; es verteidigt nicht dagegen, dass Code, dem du bereits vertraust, etwas Böses tut.

Wann geprüft wird, und wie du prüfen kannst

hermes plugins update führt dieselbe Sonde aus wie hermes plugins check-updates, die read-only ist und Plugin-Dateien unangetastet lässt – gut fürs Monitoring:

hermes plugins check-updates   # report only, changes nothing

Das Gateway führt außerdem eine geplante Prüfung aus, getaktet über plugins.auto_update_check_hours (Standard 24 Stunden, 0 deaktiviert sie). Ihr Receipt ist über hermes pm status und die Sync-Status-Ansicht im Desktop sichtbar. Das steuert nur, wie oft Hermes nachschaut – standardmäßig wird nichts aktualisiert, außer du läufst update oder entscheidest dich für auto_apply.

Praktische Hinweise

  • Erst schauen, dann springen. Wenn du unsicher bist, wie weit du zurückliegst, lauf zuerst hermes plugins check-updates; es fasst nichts an.
  • Danach hermes plugins list laufen lassen. Das Massen-Update fragt weiterhin pro Plugin. Wenn du dich durch einen Autorisierungs-Prompt durchgehämmert hast, endet das Plugin eingeschränkt statt kaputt, und nichts schreit dich an – ein Blick lohnt sich.
  • Verlass dich in CI nicht auf Defaults. Ohne Terminal verweigert es das Update und beendet mit 1; wenn deine Pipeline Non-Zero als Fehler wertet, gib --yes explizit mit oder halt Upgrades aus der CI heraus.
  • „Neue Version“ heißt je nach Installationsart etwas anderes. Eine Catalog-Installation bewegt sich auf einen Commit, den der Catalog geprüft hat; eine Git-Installation folgt dem HEAD des Upstream-Branches. Letztere hat einen deutlich größeren Blast-Radius.

Zwei frühere Artikel liefern den Hintergrund: wie der Plugin-Catalog funktioniert und das CI-Supply-Chain-Gate dahinter. Wenn du portable Plugins pflegst, deckt das MCP-Trust-Gate für portable Plugins die andere Hälfte der Vertrauensgeschichte ab. Die vollständige Subcommand-Liste steht in der Plugins-Command-Referenz.

Kurz gefasst

Massen-Upgrades sind nicht der schwierige Teil – „Masse“ und „informierte Zustimmung“ zusammenzuhalten ist es. Diese Änderung zieht die Linie klar: Das wiederholte Tippen fällt weg, und jede Entscheidung, die zählt (neue Capabilities, ein neu festgenagelter Catalog-Commit, eine geänderte Update-Quelle), landet weiterhin einzeln vor dir. Für alle, die ein Dutzend Plugins betreiben, ist das der Unterschied zwischen „das mach ich irgendwann“ und einem Einzeiler pro Woche.