Hermes bringt einen eigenen Paketmanager mit: was pm doctor, repair und gc wirklich reparieren


Eines Morgens startet hermes nicht mehr: ein einziger ModuleNotFoundError, und alles, was du gestern getan hast, war ein Plugin zu installieren. Oder das Gegenteil — dieselbe Config funktioniert auf dem Laptop, und auf dem Desktop behauptet sie, ein Tool existiere nicht. Du öffnest pip list, um zu verstehen warum, und findest drei Python-Umgebungen, von denen keine von der anderen weiß.

Deshalb bringt Hermes einen eigenen Paketmanager mit. hermes pm verwaltet nicht die Hermes-Anwendung (das ist hermes update), sondern die Ebene darunter: Tool-Binaries und Python-Dependency-Umgebungen. Ist diese Grenze einmal klar, hat jedes Subkommando seinen offensichtlichen Platz.

Was in seiner Zuständigkeit liegt

Die Docs fassen es in drei Aufgaben: gepinnte Tool-Binaries installieren und auf den PATH legen, verwaltete Python-Umgebungen für Hermes vorbereiten und den Unterschied zwischen dem erklären, was deklariert ist und was tatsächlich installiert wurde.

Die beteiligten Dateien haben jeweils eine Rolle, und sie zu verwechseln ist das häufigste Missverständnis:

Datei Rolle
pm/lock.json Exakte Versionen der verwalteten Tools, URLs pro Target, SHA-256-Hashes
pm/pyproject.toml + pm/uv.lock Python-Anforderungen und Lock des Dependency-Managers selbst
pyproject.toml + uv.lock Anforderungen, Extras und Plattform-Marker des Hauptprojekts
facts.json im Tool-Store Installierte Tool-Einträge, Identitäten, Umgebungs-Exporte, Digests realisierter Dateien
facts.json pro Installation Die gewählte Python-Umgebung, ihr Input-Stamp, aktivierte Extras

Ein Eintrag im Lockfile beweist nicht, dass ein Paket installiert ist. Dieser eine Satz erklärt hermes pm doctor: Es vergleicht den installierten Zustand mit dem Lock und prüft die realisierten Bytes.

Die vier Alltagsbefehle

hermes pm status     # der letzte Sync-/Update-Beleg als JSON, oder ein schlichtes "no receipt"
hermes pm doctor     # stimmen Tool-Identitäten, Dateien und Digests mit dem Lock überein?
hermes pm install    # benötigte Tools + Python, dann das Extra "all" synchronisieren
hermes pm repair     # die Python-Dependency-Umgebung neu bauen und validieren

status ist der billigste Einstieg. Es gibt den jüngsten Beleg aus — hier echte Ausgabe von dieser Maschine, gekürzt:

{
  "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 und steps reichen meist, um Erfolg von einem Teillauf oder einer Verweigerung zu unterscheiden.

install verdient einen eigenen Absatz. Ein blankes pm install installiert die benötigten Tools plus Python, legt die Tools auf den PATH, synchronisiert das Extra all und installiert dazu die optionalen Standard-Tools — agent-browser mit Chromium und cua-driver. Ein fehlgeschlagener Download dieser optionalen Tools gibt eine Warnung aus und lässt die Installation nicht scheitern, weil die meisten nur die CLI wollen, keinen Browser und keine Desktop-Steuerung.

Wenn du sie bei der Installation mit --skip-browser oder --skip-computer-use ausgelassen hast, wird diese Wahl festgehalten: Spätere blanke Installationen und hermes update lassen sie weiterhin weg. Um das umzudrehen, nenne das Paket einmal explizit — hermes pm install agent-browser.

Eine kaputte Dependency-Kette reparieren

repair und gc lösen verschiedene Probleme; sie zu verwechseln kostet Zeit.

pm repair spielt den aufgezeichneten Dependency-Satz der gewählten Generation in einer neuen Generation nach, validiert sie und wählt sie dann aus. Entscheidend: Es liest die Plugin-Konfiguration nicht, die deine Dependencies kaputt gemacht hat, wird also nicht erneut gelesen. Pins, Extras und Plugin-Config ändert es ebenfalls nicht. Ist der Datensatz unlesbar oder fehlt das gespeicherte Lock, scheitert es, statt dir eine reduzierte Umgebung hinzustellen.

Beim Start fordert Hermes dieselbe Reparatur an, wenn es unvollständige Dependencies findet, aber automatische Versuche sind begrenzt; ein explizit ausgeführtes pm repair ist es nicht.

pm gc entfernt, worauf nichts mehr verweist: verwaiste Tool-Store-Einträge, geeignete Download-Partials, ungenutzte lease-verwaltete Python-Umgebungen und den Zustand installs/INSTALL_KEY/ von Checkouts, die es nicht mehr gibt. Es ist bewusst konservativ — es behält Checkouts, die dieser Prozess nicht sehen kann (etwa eine Host-Installation, betrachtet aus einem Container, der sich das Daten-Root teilt), und jeden Zustand, dessen Install-Lock oder Environment-Lease noch gehalten wird.

Merkregel in einer Zeile: kaputt heißt repair, aufgebläht heißt gc.

Pins, die Drei-Tage-Regel und Mirrors

Jedes Python-Paket, von dem Hermes selbst abhängt, muss mindestens drei Tage alt sein, wenn Hermes es lockt — exclude-newer von uv, durchgesetzt vom CI-Lock-Check. Die Absicht ist einfach: Ein Paket, das vor Minuten veröffentlicht wurde und möglicherweise kompromittiert ist, darf nicht in uv.lock landen.

Die praktische Folge: hermes pm lock ist der Schritt, der die Prüfung anwendet, und gegen einen Mirror, der keine Upload-Zeiten veröffentlicht, stoppt er mit has no publish time. Wenn du das siehst, richte genau diesen einen Schritt auf https://pypi.org/simple aus; Alltagsinstallationen können weiter über den Mirror laufen.

Mirrors konfigurierst du über index-url in pip.conf, die Hermes an uv durchreicht, oder über UV_INDEX_URL.

Downloads werden wiederholt, falsche Hashes nicht

Die Retry-Policy sollte man sich merken:

  • Höchstens vier Versuche pro Probe oder Transfer, mit 1, 2 und 4 Sekunden Back-off; ein Retry-After-Header kann eine Wartezeit auf bis zu 30 Sekunden verlängern.
  • Wiederholt werden: 408, 429, 500, 502, 503, 504 sowie Verbindungsresets, Timeouts, temporäre DNS-Fehler und abgebrochene Response-Bodies.
  • Ranged Downloads behalten die bereits empfangenen Bytes; Server ohne Range-Unterstützung brauchen einen neuen Stream.
  • Nicht wiederholt werden: Hash-Mismatches, Zertifikatsfehler, lokale Dateisystemfehler — dauerhafte Fehlschläge.

Wenn ein Download also dreimal scheitert, lies die Ursache im Log, bevor du das Netzwerk beschuldigst.

Maintainer-Befehle und das neue Flag

Das sind Entwicklungs- und Packaging-Werkzeuge; die meisten Nutzer brauchen sie nie.

Befehl Wirkung
pm lock uv.lock aus pyproject.toml neu locken; schreibt nichts, wenn das Lock aktuell ist
pm lock --bump NAME VERSION Zielartefakte auflösen und hashen, dann den Tool-Pin in pm/lock.json schreiben
pm update [names...] Upstream-Versionen abfragen, Pins ändern, geänderte Tools installieren
pm update --check Abfragen ohne Schreiben; Exit 1 kann bedeuten, dass Updates existieren — lies die Ausgabe
pm update --target TARGET Versionen für ein bestimmtes Target auflösen
pm update --uv / --npm Zusätzlich die Python- oder npm-Auflösung auffrischen
pm update --termux [--check] Termux-Pool-Archive neu pinnen, die der Rolling-Pool ausgemustert hat
pm bundle --out DIR Eine portable Payload bereitstellen (Source-Snapshot, Tools, Dependencies) — kein signierter Installer

Das neue pm update --skip-target TARGET löst ein ganz konkretes Ärgernis: Wenn Upstream hinterherhängt, willst du die Pins eines bestimmten Targets nicht aufgefrischt haben. Angenommen, der Termux-Pool holt noch auf und du willst, dass eine Update-Runde linux-arm64-bionic in Ruhe lässt — übergib das Flag (wiederholbar), dann bleiben diese Pins stehen, während spätere Läufe das Paket trotzdem als aktuell melden.

Fehlersuche nach Symptom

  • Ein Tool fehlt oder hat die falsche Version → pm doctor lesen, dann dieses Paket auf einer beschreibbaren Installation explizit per pm install nachziehen.
  • Dependency-Konflikt → pm status lesen, die deklarierten Anforderungen des Plugins korrigieren, erneut versuchen.
  • Beschädigte Python-Dependencies → pm repair, dann Hermes neu starten.
  • Eine neue Umgebung wurde nicht wirksam → den betroffenen Hermes-Prozess neu starten. Hänge keinen zweiten site-packages-Baum an einen laufenden Import-Pfad.
  • Datenträger von alten Umgebungen gefressen → pm gc; wenn die Platte schon voll ist, deckt unser Leitfaden zum automatischen Prune bei knapper Platte die Laufzeitseite ab.
  • Unbekanntes Paket oder Extra → pm install nimmt Paketnamen, keine Python-Extra-Namen und keine pip-Spezifikationen wie name==version.

Die Design-Haltung

hermes pm ist darauf gebaut, laut zu scheitern, statt dir still eine degradierte Umgebung hinzustellen. Eine fehlerhafte Kostentabelle verhindert, dass ein Server lädt; ein unlesbarer Datensatz lässt repair scheitern; ein ausgemusterter Termux-Pool lässt ein Update in einen Fehler laufen — alles, damit das Problem jetzt auftaucht und nicht nächste Woche als seltsamer Fehlschlag.

Wenn du nur Hermes selbst aktualisieren willst, brauchst du pm nie; der Leitfaden zum sauberen Upgrade beschreibt diesen anderen Weg.