- Python 72.6%
- TypeScript 24.5%
- JavaScript 0.7%
- Shell 0.4%
- TeX 0.4%
- Other 1.2%
|
Some checks failed
ci.yaml / docs: Fork-Migration ist fertig — Doku nachgezogen, echter Offene-Punkte-Stand ergänzt (push) Failing after 0s
Docker Build, Test, and Publish / Detect affected areas (push) Has been cancelled
Docker Build, Test, and Publish / build (amd64, type=gha,scope=docker-amd64, type=gha,mode=max,scope=docker-amd64, linux/amd64, ubuntu-latest-32-core) (push) Has been cancelled
Docker Build, Test, and Publish / build (arm64, type=gha,scope=docker-arm64, type=gha,mode=max,scope=docker-arm64, linux/arm64, ubuntu-latest-32-arm-core) (push) Has been cancelled
Docker Build, Test, and Publish / publish (amd64, type=gha,scope=docker-amd64, type=gha,mode=max,scope=docker-amd64, linux/amd64, ubuntu-latest-32-core) (push) Has been cancelled
Docker Build, Test, and Publish / publish (arm64, type=gha,scope=docker-arm64, type=gha,mode=max,scope=docker-arm64, linux/arm64, ubuntu-latest-32-arm-core) (push) Has been cancelled
Docker Build, Test, and Publish / merge (push) Has been cancelled
Nix flake check / Detect affected areas (push) Has been cancelled
Nix flake check / nix flake check (push) Has been cancelled
CLAUDE.md/README.md beschrieben die Mac-/Linux-Umstellung noch als offen, obwohl sie am selben Tag (2026-09-07) tatsächlich abgeschlossen wurde: install_hermes.sh und hermes/Dockerfile repointen origin bereits automatisch, patch_hermes.py ist entfernt, beide Produktivinstanzen wurden manuell nachsynchronisiert. Ersetzt durch den tatsächlichen Stand + einen neuen, echten Offene-Punkte-Abschnitt: der Fork liegt 189 Commits hinter dem echten Upstream zurück, kein automatischer Re-Sync bisher. |
||
|---|---|---|
| .github | ||
| acp_adapter | ||
| agent | ||
| apps | ||
| assets | ||
| contributors | ||
| cron | ||
| datagen-config-examples | ||
| docker | ||
| docs | ||
| evals | ||
| gateway | ||
| hermes_cli | ||
| locales | ||
| mcp-research-data | ||
| native/fts5_cjk | ||
| nix | ||
| optional-mcps | ||
| optional-skills | ||
| plugins | ||
| providers | ||
| scripts | ||
| skills | ||
| tests | ||
| tests-js | ||
| tools | ||
| tui_gateway | ||
| ui-tui | ||
| web | ||
| website | ||
| .coderabbit.yaml | ||
| .dockerignore | ||
| .env.example | ||
| .envrc | ||
| .fork-upstream-base | ||
| .gitattributes | ||
| .gitignore | ||
| .hadolint.yaml | ||
| .mailmap | ||
| .npmrc | ||
| .nvmrc | ||
| .prettierignore | ||
| .prettierrc | ||
| .python-version | ||
| AGENTS.md | ||
| batch_runner.py | ||
| CLAUDE.md | ||
| cli-config.yaml.example | ||
| cli.py | ||
| compat_manifest.json | ||
| COMPAT_MANIFEST.md | ||
| constraints-termux.txt | ||
| CONTRIBUTING.es.md | ||
| CONTRIBUTING.md | ||
| docker-compose.windows.yml | ||
| docker-compose.yml | ||
| Dockerfile | ||
| eslint.config.shared.mjs | ||
| flake.lock | ||
| flake.nix | ||
| hermes | ||
| hermes_bootstrap.py | ||
| hermes_constants.py | ||
| hermes_logging.py | ||
| hermes_startup_watchdog.py | ||
| hermes_state.py | ||
| hermes_state_common.py | ||
| hermes_state_compression.py | ||
| hermes_state_dbfile.py | ||
| hermes_state_errors.py | ||
| hermes_state_fts.py | ||
| hermes_state_gateway.py | ||
| hermes_state_guard.py | ||
| hermes_state_holders.py | ||
| hermes_state_maintenance.py | ||
| hermes_state_messages.py | ||
| hermes_state_portability.py | ||
| hermes_state_readpool.py | ||
| hermes_state_registry.py | ||
| hermes_state_repair.py | ||
| hermes_state_schema.py | ||
| hermes_state_search.py | ||
| hermes_state_sessions.py | ||
| hermes_state_telegram.py | ||
| hermes_state_titles.py | ||
| hermes_state_usage.py | ||
| hermes_state_wal.py | ||
| hermes_time.py | ||
| LICENSE | ||
| mcp_serve.py | ||
| mini_swe_runner.py | ||
| model_tools.py | ||
| package-lock.json | ||
| package.json | ||
| PORTING-NOTES.md | ||
| pyproject.toml | ||
| README.es.md | ||
| README.md | ||
| README.ur-pk.md | ||
| README.zh-CN.md | ||
| registration_lifecycle.py | ||
| run_agent.py | ||
| SECURITY.es.md | ||
| SECURITY.md | ||
| setup-hermes.sh | ||
| setup.py | ||
| SOUL.md | ||
| toolset_distributions.py | ||
| toolsets.py | ||
| trajectory_compressor.py | ||
| UPSTREAM-README.md | ||
| utils.py | ||
| uv.lock | ||
Hermes-Agent-Fork
Eigener, dauerhaft gepflegter Fork von NousResearch/hermes-agent für Iris. Dieses Dokument erklärt das Update-Konzept, den Ablauf und wie du selbst — auch nach Monaten Pause — wieder sicher ein Update durchführen kannst.
Warum dieser Fork existiert
Iris bettet hermes-agent als Kern-Agent-Runtime ein, sowohl auf dem Mac (~/.hermes/hermes-agent)
als auch auf dem Linux-Server (Docker-Container iris-hermes/iris-hermes-scheduled). Iris
braucht dabei einige eigene Anpassungen am hermes-agent-Quellcode — Bugfixes für Probleme, die
Iris kritisch treffen, und Iris-eigene Integrationsfeatures (z. B. target: server|client für
Terminal-/Datei-Tools, Docker-outside-of-Docker-Pfadübersetzung).
Bisher liefen diese Anpassungen als 18 textuelle Laufzeit-Patches
(linux-server/iris-server/hermes/patch_hermes.py), die bei JEDEM Container-Boot bzw. jeder
Mac-Installation frisch auf einen neuen GitHub-Klon angewendet wurden. Das war fragil: ein
git pull auf eine neuere hermes-agent-Version konnte einen Patch unbemerkt brechen — nur eine
✗-Zeile im Log, kein harter Fehler. Am 2026-09-05 führte genau das zu einem Totalausfall: der
Patch, der verhindert, dass jeder Hermes-Job für immer auf "running" hängt, griff nach einem
Upstream-Update nicht mehr, unbemerkt bis zum Live-Betrieb.
Jetzt existieren dieselben Anpassungen als echte, einzelne Git-Commits auf diesem Fork, oben auf der echten Upstream-Historie. Ein Update ist damit ein normaler, sichtbarer Git-Vorgang (Merge, ggf. mit Konflikten, die du siehst und lösen musst) statt eines stillen Text-Matchings, das unbemerkt scheitern kann.
Der Update-Zyklus im Überblick
flowchart TD
GH["GitHub upstream<br/>NousResearch/hermes-agent"]
subgraph LOCAL["Lokaler Fork — ~/Documents/2ndbrain/hermes/"]
direction TB
FETCH["1. git fetch upstream"]
MERGE["2. git merge upstream/main<br/>Konflikte mit Patch-Commits von Hand loesen"]
BUILD["3. venv + pip install -e .<br/>Smoke-Test: Imports, hermes --help"]
LIVE["4. Live-Test auf dem Mac<br/>echten Job durch den Gateway laufen lassen"]
end
PUSH["5. git push origin main"]
FORGEJO["Forgejo origin<br/>iris/hermes-agent : main"]
subgraph PROD["Produktion"]
direction TB
MAC["Mac-Iris<br/>~/.hermes/hermes-agent"]
LINUX["Linux-Iris<br/>iris-hermes + iris-hermes-scheduled"]
end
GH -->|fetch| FETCH --> MERGE
MERGE -->|Konflikt| MERGE
MERGE -->|sauber gemergt| BUILD
BUILD -->|Fehler| MERGE
BUILD -->|ok| LIVE
LIVE -->|haengt oder schlaegt fehl| MERGE
LIVE -->|completed| PUSH
PUSH --> FORGEJO
FORGEJO -->|Iris-Server aktualisieren| MAC
FORGEJO -->|Iris-Server aktualisieren| LINUX
Der zentrale Punkt: alles links von "5. push" passiert lokal auf deinem Rechner, unter deiner
Kontrolle, bevor irgendeine Produktionsinstanz etwas davon sieht. Erst ein git push origin main macht einen neuen Stand für "Iris-Server aktualisieren" sichtbar — und das nur, weil du
ihn vorher selbst gebaut und getestet hast, nicht weil ein Cron-Job oder ein Container-Boot
blind git pull gegen GitHub gemacht hat.
Komponenten
| Komponente | Was es ist |
|---|---|
upstream (Remote) |
https://github.com/NousResearch/hermes-agent.git — das echte Original. Nur fetch, nie push. |
origin (Remote) |
http://192.168.178.92:3000/iris/hermes-agent.git — dein Forgejo-Fork. Der einzige Stand, den Produktionsinstanzen sehen. |
| Lokales Arbeitsverzeichnis | ~/Documents/2ndbrain/hermes/ — hier findet Merge, Build und Test statt. Kein Teil des 2ndbrain-Git-Repos (eigenes Repo, siehe CLAUDE.md). |
PORTING-NOTES.md |
Dokumentiert, welche der ursprünglich 18 Laufzeit-Patches wie übernommen wurden — Referenz bei Merge-Konflikten. |
.fork-upstream-base |
Der Commit-Hash des Merge-Base-Punkts zwischen origin/main und upstream/main (git merge-base origin/main upstream/main). Iris' "Hermes-Agent-Version"-Anzeige nutzt ihn, um über GitHubs Compare-API zu ermitteln, wie viele echte Upstream-Commits dem Fork fehlen, ohne dass die Produktivinstallation selbst einen upstream-Remote braucht. Muss nach jedem git merge upstream/main neu berechnet und mitcommittet werden (siehe CLAUDE.md). |
| Mac-Produktivinstanz | ~/.hermes/hermes-agent — der tatsächlich von deinem Companion-Panel genutzte Hermes. |
| Linux-Produktivinstanzen | iris-hermes/iris-hermes-scheduled-Container auf alf@iris-server (und jedem weiteren deployten Linux-Server). |
| "Iris-Server aktualisieren" | Menüpunkt in Iris/IrisClient — löst POST /hermes/agent/update aus (Mac: IrisRemoteServer.swift, Linux: linux-server/iris-server/app/hermes_agent_update.py), die intern git pull gegen den jeweils konfigurierten Remote macht. |
Ein Update durchführen
Alles im lokalen Arbeitsverzeichnis:
cd ~/Documents/2ndbrain/hermes
# 1. Upstream-Stand holen
git fetch upstream
# 2. In main mergen
git merge upstream/main
# Bei Konflikten: git log -p -- <datei> zeigt dir den ursprünglichen Patch-Commit und seine
# Begründung. Löse den Konflikt aus dieser Absicht heraus, nicht durch blindes "unsere/ihre
# Version nehmen". PORTING-NOTES.md hilft bei der Einordnung, welche Änderung wofür da ist.
git add <konfliktdatei>
git commit
Wenn ein Patch beim Mergen komplett verschwindet (Upstream hat die Zeilen, die er ändert,
selbst entfernt/umgebaut), prüfe wie in PORTING-NOTES.mds "moot"-Fällen beschrieben: löst
Upstream das ursprüngliche Problem jetzt selbst? Wenn ja, lass den Patch einfach weg und trage
das in PORTING-NOTES.md nach. Wenn nein, baue die gleiche Absicht gegen die neue Code-Struktur
neu — kein Commit einfach fallenlassen, ohne zu verstehen warum.
Testen
1. Smoke-Test (schnell, immer machen)
python3.12 -m venv /tmp/hermes-fork-test-venv # system-python kann zu neu sein, siehe pyproject.toml
source /tmp/hermes-fork-test-venv/bin/activate
pip install -e .
python3 -c "import gateway" # oder welches Modul dein aktueller Patch berührt hat
hermes --help # CLI-Entry-Point funktioniert
Reicht NICHT aus, um den kritischen "Job hängt für immer"-Fall auszuschließen — dafür braucht es einen echten Lauf gegen einen echten Gateway (nächster Abschnitt).
2. Live-Test auf dem Mac (der eigentlich aussagekräftige Test)
Testet den Fork im echten Zusammenspiel mit deinem laufenden Companion-Panel-Hermes, ohne etwas dauerhaft zu verändern — alles über Git-Branches, jederzeit reversibel.
cd ~/.hermes/hermes-agent
# Einmalig (überspringen, falls der Remote schon existiert):
git remote add fork-test /Users/alflewerken/Documents/2ndbrain/hermes
# Aktuellen Fork-Stand holen
git fetch fork-test
# Lokale Mac-spezifische Änderungen wegsichern (Shebang-Fix, ggf. von Hermes selbst
# generierte Skill-Notizen) — siehe unten "Rückbau" zum Wiederherstellen
git stash push -m "pre-fork-test"
# Auf den Fork-Stand wechseln (neuer Branch, falls noch nicht vorhanden)
git checkout -b fork-test-main fork-test/main
# ...oder falls der Branch schon existiert:
# git checkout fork-test-main && git merge fork-test/main
# Mac-lokalen Shebang wieder auf die eigene venv setzen (kommt nie aus dem Fork,
# siehe PORTING-NOTES.md "Nicht portierbar" — `hermes_hermes_cli_shebang`)
Öffne hermes (die Datei im Repo-Root) und setze die erste Zeile auf:
#!/Users/alflewerken/.hermes/hermes-agent/venv/bin/python3
# Gateway neu starten, damit er den neuen Code lädt
source venv/bin/activate
python -m hermes_cli.main gateway restart
# Bearer-Token für die lokale Gateway-API holen
grep API_SERVER_KEY ~/.hermes/.env
# Echten Testjob starten
TOKEN="<der Wert von oben>"
curl -s -X POST http://127.0.0.1:8642/v1/runs \
-H "Authorization: Bearer $TOKEN" -H "Content-Type: application/json" \
-d '{"input":[{"role":"user","content":"Antworte nur mit dem Wort OK."}]}'
# → liefert {"run_id": "run_...", "status": "started", ...}
# Status pollen, bis "completed" ODER "failed" (NIE dauerhaft "running")
curl -s http://127.0.0.1:8642/v1/runs/<run_id> -H "Authorization: Bearer $TOKEN"
Wichtige Stolperfalle: ~/.hermes/config.yamls model:-Block (das global konfigurierte
Standard-Backend, das der Gateway für einen Lauf ohne explizite Modellangabe nutzt) kann vom
Backend abweichen, das gerade in Iris' Einstellungen ("Agent LLM") ausgewählt ist — beide werden
nicht immer synchron gehalten. Prüfe vor dem Test, welches Backend in Iris tatsächlich aktiv
läuft ("Server läuft"-Anzeige in den Einstellungen), und stelle sicher, dass model.base_url in
config.yaml dorthin zeigt — sonst schlägt der Testjob mit "Connection error" fehl, was nichts
mit dem Fork zu tun hat, sondern nur mit einem falsch konfigurierten Backend. Bei mlx-vlm/LM
Studio: der default-Modellname muss exakt der id aus GET <base_url>/models entsprechen
(oft ein voller Dateipfad, kein Kurzname).
Ergebnis lesen: "status": "completed" mit einem "output"-Feld = Erfolg, der Job ist
NICHT hängengeblieben. "status": "failed" mit einer klaren "error"-Meldung ist ebenfalls ein
akzeptables Testergebnis (der Run-Lifecycle selbst funktioniert, das eigentliche Problem liegt
woanders, z. B. Backend nicht erreichbar). Bleibt der Status über mehrere Minuten bei
"running" hängen, obwohl das Backend nachweislich erreichbar ist — das ist der Fehlerfall,
den dieser ganze Fork verhindern soll. Dann: NICHT pushen, den Merge-Commit nochmal prüfen,
insbesondere ob gateway/platforms/api_server_runs.py (der SSE-Broadcast-Fix) den Merge
überstanden hat.
Nach Forgejo pushen
Erst wenn Smoke-Test UND Live-Test beide grün sind:
cd ~/Documents/2ndbrain/hermes
git push origin main
Damit "Iris-Server aktualisieren" den Fork tatsächlich nutzt
✅ Vollständig umgestellt, verifiziert 2026-09-07. Die beiden /hermes/agent/update-Routen
(Mac + Linux) machen nur noch einen reinen git pull origin main — kein patch_hermes.py-
Reapply-Schritt mehr, die Datei selbst ist gelöscht.
- Mac:
Iris/Resources/install_hermes.shrepointet~/.hermes/hermes-agentsoriginauf den Forgejo-Fork und setzt hart auf dessenmainzurück — sowohl VOR einem erneuten Lauf (damit der Installer-eigene internegit pullschon den Fork trifft) als auch DANACH (deckt eine frische Neuinstallation ab, die zwangsläufig erst von GitHub klont). - Linux:
linux-server/iris-server/hermes/Dockerfilemacht denselben Repoint+Hard-Reset nach dem offiziellen NousResearch-Installer — jedes gebaute Image landet damit direkt auf dem gepatchten Fork-Stand. - Beide bereits laufenden Produktivinstanzen (Mac-Lokalinstallation,
alf@iris-serversiris-hermes/iris-hermes-scheduled) wurden am selben Tag manuell nachsynchronisiert (nicht nur künftige Neuinstallationen) —originzeigt überall nachweislich auf den Fork, ein echter Regressionsjob läuft durch statt für immer auf "running" zu hängen. - Ein erster Deploy-Versuch traf dabei kurzzeitig den ungepatchten Fork-Baseline-Stand
(
d8a07768c5), weil die 13 portierten Patch-Commits lokal committet, aber noch nicht nach Forgejo gepusht waren — gefixt durchgit push origin main, danach alle Instanzen erneut synchronisiert. Lehre: ein lokaler Commit in diesem Arbeitsverzeichnis ist erst wirksam, sobald er tatsächlichgit push origin maindurchlaufen hat, nicht schon beim Committen.
Rückbau / Notausstieg (Mac-Live-Test)
Falls der Live-Test schiefgeht oder du zurück auf den bekannten guten Stand willst:
cd ~/.hermes/hermes-agent
git checkout main # zurück auf den ursprünglichen, unveränderten Stand
git stash pop # lokale Mac-Änderungen (Shebang etc.) wiederherstellen
source venv/bin/activate
python -m hermes_cli.main gateway restart
git remote remove fork-test und git branch -D fork-test-main räumen den Test-Remote/-Branch
komplett weg, falls gewünscht — nicht nötig, beide sind harmlos, wenn sie einfach liegen bleiben.
Offene Punkte
- Der Fork liegt aktuell (Stand 2026-09-07) 189 echte Commits hinter
NousResearch/hermes-agentzurück. Seit dem ursprünglichen Einmal-Port (13 Patches als Commits übernommen, Baseline gegen den damaligen Upstream-Stand geklont) wurde nie eingit merge upstream/maindurchgeführt — der Fork bekommt nur seine eigenen Patch-Commits, nicht Upstreams eigene Weiterentwicklung. Dieser Rückstand ist jetzt direkt in Iris sichtbar ("Iris-Server aktualisieren" zeigt "N Commits hinter dem echten Upstream",.fork-upstream-base+ GitHubs Compare-API machen das ohne einen vollengit fetch upstreammöglich). Ein echter Re-Sync (Schritte 1-5 oben, diesmal gegen 189 Commits statt eines kleinen Deltas) ist bewusst noch nicht angegangen — kein akuter Bedarf, aber je länger gewartet wird, desto größer das Konfliktrisiko beim nächsten Merge. - Nach jedem künftigen
git merge upstream/mainnicht vergessen,.fork-upstream-baseneu zu berechnen und mitzucommitten (siehe dessen Eintrag oben) — sonst zeigt die Commits-Behind-Zahl in der GUI einen veralteten, zu hohen Wert weiter an.