Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
19 KiB
Umbau: OpenChamber als Coding-Bahn, Lucy bleibt SysAdmin
Entschieden 21.08.2026. Rückbau der Hermes-Coding-Bahn ist erledigt, der Aufbau von OpenChamber steht aus. Diese Datei ist die Übergabe an die nächste Sitzung.
Die Entscheidung
Zwei getrennte Bahnen — der Weg, der bei diesem Stack schon einmal funktioniert hat:
| Bahn | Werkzeug | Zweck |
|---|---|---|
| Betrieb | Hermes-Runtime (Lucy) | SysAdmin, Telegram, Crons, Gedächtnis, Skills, Stimme, PC-Steuerung |
| Coding | OpenChamber über OpenCode | Nur programmieren. Getrennt von Lucy. |
| Motor | llama-swap :8080 / MC2-Gateway :9010 |
beide Bahnen teilen sich die Modelle |
| Steuerpult | MC2 :9001 |
unverändert |
Warum getrennt: Der Versuch, beides in Hermes Desktop zu vereinen, ist an zwei Dingen gescheitert — die Gateway-Registry akzeptiert kein Benutzer/Passwort (nur Session-Token oder OAuth, beides für eine selbstgehostete Box ungeeignet), und der Sessions-Reiter fiel dadurch immer auf „This device" zurück. Details in der Gedächtnisnotiz vom 20./21.08.
Was bereits erledigt ist (21.08.)
PC:
- Hermes Desktop + CLI deinstalliert (
hermes uninstall --full), Reste von Hand entfernt AppData\Local\hermes,AppData\Roaming\Hermes,~\.hermes— alle weg- Startmenü- und Desktop-Verknüpfungen entfernt
- Env-Variablen bereinigt;
HERMES_PC_TOKENbleibt bewusst (Lucys PC-Executor auf:7777) - Node v24.19.0 in
Program Filesist unabhängig → bleibt, erfüllt OpenChambers Anforderung (≥22)
Box:
- Bot-Profile
coder+debuggerentfernt (gesichert in~/archiv-aufraeumen-20260820/) ~/.hermes/desktop-ssh/entfernt,desktop-auth.enventfernt- ufw: Port 9119 wieder zu — nur noch
22 · 9001 · 8080 · 7681 - Dashboard bleibt auf
0.0.0.0:9119gebunden mit Anmeldung, damit MC2s/hermes-ui-Proxy nicht mehr passwortlos aus dem LAN erreichbar ist (das war ein offenes Scheunentor). Zugang:~/.hermes/dashboard-login.txt(0600), Benutzercommander. ‼️ Zugangsdaten stehen nur inconfig.yaml— die frühereEnvironmentFilehat sie still überstimmt und kostete eine Fehlersuche. Eine Quelle, eine Wahrheit.
Verifiziert nach dem Rückbau: 5 Dienste aktiv · 4 MCP-Server · 4 Crons · Telegram connected
· PC-Executor HTTP 200. Lucy ist vollständig funktionsfähig.
Was aufzubauen ist
1. OpenCode auf der Box
Wurde beim Juli-Rückbau entfernt (command -v opencode → leer). Muss neu.
# Installation (Box)
curl -fsSL https://opencode.ai/install | bash
# Provider auf den lokalen Motor zeigen lassen: ~/.config/opencode/opencode.json
# base_url http://127.0.0.1:9010/v1 (MC2-Gateway, kann model:auto)
# oder http://127.0.0.1:8080/v1 (llama-swap direkt)
# api_key local
Als systemd-User-Dienst (wie alle anderen — reboot-fest, sudo-frei):
opencode serve --hostname 0.0.0.0 --port 4096
Danach ufw allow from 192.168.178.0/24 to any port 4096 proto tcp.
2. OpenChamber auf dem PC
Desktop-Version von den GitHub-Releases (openchamber/openchamber, MIT, ~9,1k ★).
Wichtig: Die Desktop-Variante bringt eine eigene OpenCode-CLI mit — für den Remote-Betrieb
muss sie ausgeschaltet werden:
OPENCODE_HOST = http://192.168.178.151:4096 ← volle Adresse MIT Port, OHNE Pfad
OPENCODE_SKIP_START = true
Fehlt der Port oder hängt ein Pfad dran, ignoriert OpenChamber die Variable und startet stillschweigend seinen eigenen Server. Genau diese Klasse Fehler hat uns bei Hermes einen halben Tag gekostet.
Modelle, Provider und Schlüssel liegen in OpenCode, nicht in OpenChamber.
3. Modellwahl — nicht wieder den dichten Coder
★★ fast (Qwen3.6-35B-A3B) nehmen, nicht coder (Qwen3.8-27B). Gemessen:
| Ausgabe | Eingabe | SWE-bench Verified | |
|---|---|---|---|
fast Qwen3.6-35B-A3B (MoE) |
95,7 t/s | 221 t/s | 73,4 |
coder Qwen3.8-27B (dicht) |
12,6 t/s | 144 t/s | keine agentische Messung |
Das dichte Modell ist bandbreitenlimitiert (17 GB ÷ 215 GB/s ≈ 12,6 t/s = Hardware-Limit). Der MoE ist schneller und besser.
4. Die Arbeitsanweisung mitnehmen — der wichtigste Fund überhaupt
Der Agent las in Lauf A eine ganze Nacht lang und schrieb null Dateien. Mit dieser Zeile im Auftrag schrieb er in 24 Minuten fünf:
„Arbeite Datei für Datei. Lies HÖCHSTENS zwei Dateien, bevor du die erste änderst. Kein Gesamtplan, keine Vollinventur. Eine halbfertige Änderung ist wertvoller als eine vollständige Analyse ohne Änderung."
Gehört in OpenChambers System-Prompt bzw. AGENTS.md der Projekte.
Bekannte Fallen (aus dem Juli-Audit + heute)
- Bus-Faktor 1 bei OpenChamber: ~70–80 % der Commits von einer Person. Version pinnen, nicht blind auto-updaten.
- Windows-Installer unsigniert → SmartScreen-Warnung ist erwartbar, kein Alarm.
- Nie ohne
--ui-passwordüber localhost hinaus binden. opencode web(nicht OpenChamber!) hat einen kaputten Projekt-Finder für$HOME— falls irgendwo ein leerer Projektbaum auftaucht, ist das der Grund.- Git-Push zum Gitea geht vom PC nur über PowerShell/GCM, nicht aus der Git-Bash.
Erster Test nach dem Aufbau
Die Referenzaufgabe liegt bereit und ist halb erledigt — ideal zum Vergleich:
Worktree: ~/projekte/mc2-referenz (Zweig referenz/mem0-ausbau)
Aufgabe: docs/aufgaben/referenzaufgabe-mem0-ausbau.md
Prüfung: bash docs/aufgaben/referenz-check.sh
Stand: 5 von 17 Dateien erledigt (Hermes-Lauf A2, abgebrochen durch SSH-Fehler)
Damit lässt sich direkt vergleichen: Wie lange braucht OpenChamber + fast für dieselben
17 Dateien? Hermes + dichter Coder brauchte hochgerechnet ~80 Minuten; die Rechnung für
fast sagt ~30.
Stand nach dem Aufbau (21.08.2026)
Beide Bahnen stehen. Der Aufbau ist erledigt, der Referenzlauf steht aus.
Box (192.168.178.151)
| Sache | Wert |
|---|---|
| OpenCode | 1.18.20, ~/.opencode/bin/opencode (eigenständiges Binary, kein Node nötig) |
| Dienst | opencode-server.service (systemd user, enabled, Linger=yes → reboot-fest) |
| Lauscht | 0.0.0.0:4096, Arbeitsverzeichnis ~/projekte |
| ufw | Regel 5: 4096/tcp ALLOW IN 192.168.178.0/24 |
| Provider | box → http://127.0.0.1:9010/v1 (MC2-Gateway), apiKey: local |
| Modelle | box/fast (Standard) · box/heavy · box/hermes (small_model) · box/coder (nur Vergleich) |
| Autoupdate | false in opencode.json |
Konfiguration: ~/.config/opencode/opencode.json.
Nur Rollen-Aliase, keine Modell-Eigennamen — die Konsolidierung wirft Eigennamen sonst raus (Regel vom 20.08.).
Arbeitsanweisung — global verdrahtet
Liegt als ~/.config/opencode/ARBEITSANWEISUNG.md und ist über instructions in
opencode.json in jeder Sitzung aktiv, nicht nur in Projekten mit AGENTS.md.
Gegengeprüft: „Wie viele Dateien höchstens?" → 2. ~ wird von OpenCode expandiert.
PC
| Sache | Wert |
|---|---|
| OpenChamber | v1.19.0 (18.08.), %LOCALAPPDATA%\Programs\@openchamberelectron |
| Signatur | NotSigned — erwartet, kein Alarm |
OPENCODE_HOST |
http://192.168.178.151:4096 (User-Env, mit Port, ohne Pfad) |
OPENCODE_SKIP_START |
true (User-Env) |
Verifiziert: OpenChamber hält 8 offene TCP-Verbindungen zur Box auf :4096,
startet keinen eigenen OpenCode (kein lokaler Prozess, kein lokaler Port).
Damit ist genau der Punkt genommen, an dem Hermes Desktop gescheitert ist.
Auto-Update: kein Riegel nötig. Im Bundle steht autoUpdater.autoDownload = false und
autoInstallOnAppQuit = false — OpenChamber lädt nie von selbst, es meldet nur und wartet
auf einen Klick. Die Version ist damit faktisch gepinnt.
‼️ Offene Sicherheitsentscheidung — bewusst so gewählt
Der Server läuft ohne Anmeldung im LAN. Beim Start meldet er selbst:
Warning: OPENCODE_SERVER_PASSWORD is not set; server is unsecured.
Praktisch heißt das: jedes Gerät im 192.168.178.0/24 kann über die API beliebige
Befehle als hitonabi auf der Box ausführen — dieselbe Klasse Loch wie das passwortlose
Dashboard auf :9119, das am 20.08. zugemacht wurde.
★★ Ein Riegel wäre da und kostet nichts: OpenChamber schickt HTTP-Basic-Auth mit, wenn
OPENCODE_SERVER_PASSWORD gesetzt ist (Benutzer aus OPENCODE_SERVER_USERNAME,
Standard opencode). Server-Variable in der systemd-Unit, gleiche Variable als User-Env
auf dem PC — kein Tunnel, keine Umstellung, der Port bleibt offen im LAN.
Der User hat am 21.08. bewusst dagegen entschieden („so lassen"). Nicht neu aufrollen, aber hier notiert, damit es kein stiller Defekt bleibt.
Nächster Schritt: der Referenzlauf
Alles steht bereit, nichts wurde am Prüfstand angefasst:
Worktree: ~/projekte/mc2-referenz (Zweig referenz/mem0-ausbau)
Stand: 5 von 17 Dateien erledigt, referenz-check.sh sagt ROT
Prüfung: bash docs/aufgaben/referenz-check.sh
Die Arbeitsanweisung wirkt dort über die globale Instruktion — AGENTS.md im Worktree
wurde absichtlich nicht angefasst, damit der Vergleich zu Lauf A/A2 sauber bleibt.
Zu messen: Wie lange braucht OpenChamber + fast für dieselben 17 Dateien?
Hermes + dichter coder brauchte hochgerechnet ~80 Minuten; die Rechnung für fast sagt ~30.
‼️ Falle: der Ordner-Knopf reicht Windows-Pfade an die Box durch
Beim ersten Lauf sofort hineingetappt (21.08., ~1 h verloren). Die Sitzung stand auf:
/home/hitonabi/projekte/F:\Coding Stuff\mission-control-2
OpenChamber hatte den Windows-Pfad des PCs an den Box-Server durchgereicht, der ihn hinten
an sein WorkingDirectory klebte. Das Verzeichnis existiert auf der Box nicht → der Agent hat
kein Arbeitsverzeichnis, es geht keine einzige Anfrage an den Motor raus. In der Oberfläche
sieht das aus wie „hängt": Nachricht steht da, eine Zusammenfassung erscheint, danach nichts.
tokens: 0/0.
Ursache, im Bundle nachgesehen: OpenChamber öffnet Ordner über Electrons natives
showOpenDialog — den lokalen Windows-Dateibrowser. Einen Fern-Auswähler gibt es nicht.
Im Fernbetrieb liefert dieser Knopf also immer einen unbrauchbaren Pfad.
Der richtige Weg: Seitenleiste → „Projekt hinzufügen". Das ist ein eigener Dialog
(directoryExplorerDialog) mit Baum und Eingabefeld („Enter path or select from tree…"),
und der geht über den Server — also über die Box.
Diagnose in einem Befehl — wenn wieder „nichts passiert", zeigt das den Grund sofort:
ssh hitonabi@192.168.178.151 "curl -s http://127.0.0.1:4096/session | python3 -c \"import json,sys; s=json.load(sys.stdin); s.sort(key=lambda x: x['time']['updated'], reverse=True); x=s[0]; print(x['directory'], x.get('model'), x.get('tokens'))\""
Steht dort ein Pfad mit F:\ oder tokens 0/0, ist es diese Falle.
Merke: Ein Projekt taucht in der Server-Liste erst auf, wenn dort einmal eine Sitzung lief.
mc2-referenz wurde am 21.08. mit einem harmlosen Lauf angemeldet (box/hermes, „Antworte nur
mit OK") — Worktree danach nachgemessen unverändert: 5 geänderte Dateien, HEAD e04ace2.
▶▶ Kurswechsel 21.08. (nachmittags): Quelle ist der PC, nicht die Box
Der Fernbetrieb oben war falsch herum gedacht. Der User arbeitet so — und so ist es jetzt gebaut:
F:\Coding Stuff\… ← Quelle der Wahrheit, liegt IMMER lokal
│ OpenChamber startet seine EIGENE OpenCode-CLI und arbeitet an lokalen Dateien
│ git push (PowerShell/GCM)
▼
Gitea 192.168.178.153:3000
│ projekte-sync (stuendlich, --ff-only) — oder sofort per Skript
▼
AI-Box ~/projekte/… ← Spiegel fuer Deploy / CI / Lucy
▲
└─ von der Box kommt NUR noch das Modell (Inferenz ueber HTTP)
Damit faellt die Windows-Pfad-Falle ersatzlos weg — es gibt keine Fernpfade mehr.
★★ Kein Box-Umbau noetig: MC2 :9001/v1 ist der Modellweg
Erst war geplant, den Gateway :9010 ins LAN zu binden. Ueberfluessig — die Gateway-Unit
sagt es selbst: „LAN-Clients kommen weiter ueber MC2 :9001/v1, das roh hierher
durchreicht." Der Port ist seit jeher offen.
Vom PC aus gemessen: :9001/v1/models liefert die Rollen-Aliase (fast, heavy,
hermes, coder), fast antwortet in 0,7 s. Kein neuer Port, keine Neubindung,
keine ufw-Regel — und keine Modell-Eigennamen in der PC-Konfiguration (die Regel vom
20.08. bleibt gewahrt). llama-swap :8080 waere die Alternative gewesen, liefert aber nur
Eigennamen (Qwen3.6-35B-A3B) → genau der stille 404 vom 19.08.
Was auf dem PC steht
C:\Users\TobisPC\.config\opencode\opencode.json — Provider aibox →
http://192.168.178.151:9001/v1, Standard aibox/fast, small_model aibox/hermes.
Die Juli-Struktur ist erhalten: Agenten plan(heavy) · build(fast) · explore(hermes) ·
review(heavy), inklusive IDE-Zaun (ssh/scp/sftp deny, gezielte Arcane-Ausnahme;
Catch-all *: allow steht ZUERST, weil OpenCode findLast auswertet).
Arbeitsanweisung als ARBEITSANWEISUNG.md daneben, ueber instructions global geladen.
Das Plugin plugin/mc2-governor.ts wird automatisch mitgeladen: Werkzeug-Zaun,
Pruef-Tor-Schleife, Savepoint statt Zusammenfassen, Meldungen an Lucys Stimme.
‼️ Es blockt git push absichtlich — „Veroeffentlichen ist Sache des Menschen."
Der Agent codet, gepusht wird von Hand (siehe Skript unten).
Gebuendelte CLI: OpenCode 1.18.18 in OpenChambers resources\opencode-cli.
Im lokalen Betrieb vergibt OpenChamber dem Server automatisch ein Passwort
(OPENCODE_SERVER_PASSWORD, lifecycle-owned) — /config antwortet von aussen mit 401.
Der Schutz, den der Box-Server nicht hatte, ist hier also gratis dabei.
Env-Variablen OPENCODE_HOST und OPENCODE_SKIP_START sind wieder ENTFERNT.
Sie erzwingen den Fernbetrieb; mit ihnen startet OpenChamber keine eigene CLI.
Box zurueckgebaut
opencode-server.service ist gestoppt, deaktiviert und geloescht, die ufw-Regel fuer
4096 wieder entfernt. Damit erledigt sich die offene Sicherheitsfrage von heute Mittag
von selbst: der ungeschuetzte Dienst existiert nicht mehr. ufw steht wieder auf
22 · 9001 · 8080 · 7681.
deploy/push-und-sync.ps1 — der Handschlag
.\deploy\push-und-sync.ps1 # committen -> pushen -> Box zieht sofort nach
.\deploy\push-und-sync.ps1 -NurSync # nur nachziehen
.\deploy\push-und-sync.ps1 -Pfad "F:\Coding Stuff\rippy"
Stoesst projekte-sync sofort an, statt bis zu 60 Minuten auf den Timer zu warten —
kein zweiter Mechanismus, nur ein Ausloeser. Meldet danach, auf welchem Commit die Box steht.
‼️ Falle beim Bauen gefunden: Der Repo-Name darf nicht aus dem Ordnernamen kommen —
lokal heisst es mission-control-2, in Gitea mission-control-v2. Das Skript liest ihn
aus der Remote-URL. Getestet gegen beide Faelle: MC2 (Live-Deployment, liegt als
Verknuepfung unter ~/projekte) und rippy (normales Projekt, a14449e).
Offener Punkt: PC-Remote haengt an der DDNS-Domain
Der PC pusht nach https://git.tobisniceshomelab.ddnsfree.com/…, die Box nutzt intern
http://192.168.178.153:3000. Die Domain ist nachts durch die Zwangstrennung zeitweise
tot (Lehre vom 24.07.). Umstellen mit:
git remote set-url origin http://192.168.178.153:3000/Hitonabi/mission-control-v2.git
Noch nicht gemacht — aendert Git-Konfiguration in den Repos des Users.
Abschluss der Coding Lane (21.08.2026, abends)
Der Zugang: ein SSH-Schluessel, kein Token mehr
Der Ausloeser: Mitten in der Sitzung scheiterte ein Push, der eine Stunde
vorher noch ging — remote: Failed to authenticate user. Der Git Credential
Manager haelt fuer Gitea ein OAuth-Token mit einer Stunde Laufzeit. Damit ist
HTTP fuer einen Agenten, der selbst pushen soll, strukturell ungeeignet.
Was dabei herauskam: Giteas SSH war nie funktionsfaehig. In der app.ini
stand zwar DISABLE_SSH = false und SSH_PORT = 22, aber im Container gibt es
keinen git-Benutzer und keine authorized_keys — Port 22 gehoert dem
System-sshd. Es sah nur so aus, als koennte man ueber SSH klonen.
Loesung: Giteas eingebauten SSH-Server eingeschaltet (Port 22 ist belegt,
deshalb 2222). Der verwaltet die Schluessel selbst, direkt aus der Datenbank —
kein git-Benutzer, keine authorized_keys.
# /etc/gitea/app.ini, [server] (Sicherung: app.ini.bak-20260821)
SSH_PORT = 2222
SSH_LISTEN_PORT = 2222
START_SSH_SERVER = true
SSH_LISTEN_HOST = 0.0.0.0
‼️‼️ Der SSH-Benutzer heisst gitea, NICHT git. Gitea laeuft unter diesem
Namen und weist alles andere ab. Die Fehlermeldung steht nur im Gitea-Log, nicht
beim Client — ssh sagt bloss Permission denied (publickey):
Invalid SSH username git - must use gitea for all git operations via ssh
Auf dem PC (~/.ssh/config) — noetig, weil hier acht Schluessel liegen
und ssh sonst der Reihe nach durchprobiert, bis Gitea abbricht:
Host 192.168.178.153 gitea gitea.heimnetz
HostName 192.168.178.153
Port 2222
User gitea
IdentityFile ~/.ssh/id_general
IdentitiesOnly yes
Der Schluessel id_general ist in Gitea hinterlegt (Nr. 3) — derselbe, mit dem
du auf Box, pve und Arcane kommst. Von acht Zugangsdaten auf einen.
Alle sieben PC-Repos stehen jetzt auf
ssh://gitea@192.168.178.153:2222/Hitonabi/<repo>.git.
Das TTT2-Projekt bleibt unberuehrt — es haengt an einer anderen Domain und ist
als „Finished" markiert.
Gemessen, nicht angenommen
| Test | Ergebnis |
|---|---|
ssh -T gitea |
„Hi there, Hitonabi! You've successfully authenticated with the key named id_general" |
| Push aus PowerShell | 8 Commits, 7c23ebf..25dbfb2 |
| Push aus dem Agenten | durchgelaufen, keine Passwortabfrage |
| Erzwungener Push aus dem Agenten | vom Werkzeug-Zaun abgewiesen |
push-und-sync.ps1 komplett |
Commit → Push → Box zieht nach |
Der Sonderfall MC2
projekte-sync zieht mission-control-v2 absichtlich nicht — die Box
bedient daraus den laufenden Dienst auf :9001. Nach einem Push steht dort
weiter der alte Commit, und das ist richtig so. Das Live-Deployment braucht
seinen eigenen, bewussten Schritt. Alle anderen Projekte werden normal gezogen.
Fallen fuer das naechste Mal
sedmit$und\nueber PowerShell zerlegt sich. Der erste Anlauf, dieapp.inizu aendern, lief ins Leere und die Datei blieb unveraendert — ohne Fehlermeldung. In einzelne Ersetzungen zerlegen und danach nachsehen.- Ein Dienst-Neustart nach einer Konfig-Aenderung ist noch keine Bestaetigung: Gitea startete brav neu — mit der alten Datei.
- Acht SSH-Schluessel auf dem PC sind selbst ein Befund.
IdentitiesOnly yesist Pflicht, sonst bricht die Gegenseite vorher ab.