system-droid: ein Wachhund, der meine Systeme selbst prüft und selbst repariert
Meine lokalen Dienste starben immer lautlos — der Morgenbericht kam einfach nicht, Tokens liefen ab, Backups froren ein. Also baute ich einen launchd-Droiden, der alle zwei Stunden alles prüft, per Claude-Agent repariert, was gefahrlos geht, und mir nur schreibt, wenn wirklich ein Mensch gebraucht wird.
TL;DR
system-droid ist ein kleines Go-Programm, das launchd alle zwei Stunden und nach jedem Aufwachen des Macs startet. Es geht eine Prüfliste über alle meine lokalen Dienste durch, bleibt still, solange alles läuft, und meldet sich nur dann per Telegram, wenn wirklich etwas kaputt ist. Einmal täglich schickt es eine kurze Alles-läuft-Zusammenfassung, damit Stille nie "unbekannt" bedeutet. Und wenn doch etwas ausfällt, versucht es zuerst, das selbst zu beheben: Ein eigener Claude-Agent (Opus) spürt die Ursache auf und repariert sie — und ruft mich nur, wenn er scheitert.
◆ Усі системи в нормі · 10/10 · 2026-08-17 09:00
— OpenClaw / Resonance
◆ styletts2-ua (tts) — локальний український TTS :8123
◆ openclaw gateway (:18789) — ядро агента Resonance (launchd + порт)
◆ openclaw hooks — hooks-ендпоінт увімкнено
— Інфраструктура
◆ cli-proxy Claude auth — робочий Claude-токен (валідність, авто-оновлення)
◆ system-droid — сам вартовий (надсилає ці звіти)
◆ otel-block — корпоративна телеметрія заблокована у firewall
◆ vault git backup — git-копія Obsidian-сховища на GitHubWarum es das gibt
In den letzten Monaten hatte sich bei mir unbemerkt ein ganzer Fuhrpark lokaler Automatisierung angesammelt: ein OpenClaw-Agent ("Resonance"), ein ukrainischer StyleTTS2-Sprachserver, ein LLM-Proxy vor Claude, tägliche Notiz-Generatoren für Obsidian, eine Git-Kopie meines Vaults, eine Firewall-Regel gegen Firmen-Telemetrie. Jedes dieser Dinge ist genau so lange nützlich, wie es läuft. Und kaputtgegangen sind sie immer auf dieselbe Art — lautlos.
Der Morgenbericht kam einfach nicht an, und ich bemerkte es erst am Abend. Der Scheduler schoss einen Prozess ab, doch der letzte Lauf sah trotzdem "erfolgreich" aus. Ein Auth-Token lief ab, und die Generierung konnte wochenlang von einer Notlösung leben. Keiner dieser Ausfälle meldet sich selbst: Ein Dienst beschwert sich nicht — er verschwindet einfach. Ich brauchte jemanden, der das für mich bemerkt.
Wie es funktioniert
Das ganze System ist eine Binärdatei plus eine config.json mit zwei Arten von Prüfungen: HTTP (der Dienst antwortet auf /health) und Kommando (ein Skript endet mit 0). launchd startet den Droiden nach Zeitplan; er führt die Prüfungen parallel aus und entscheidet, ob ich überhaupt gestört werden muss. Ein neues System unter Beobachtung zu stellen ist eine Zeile in der Konfiguration — ohne Neukompilieren.
Das Kernprinzip ist sparsamer Umgang mit Aufmerksamkeit. Keine Dashboards, die man öffnen muss, kein "alles gut"-Spam alle zwei Stunden. Es gibt genau drei Arten von Nachrichten: die tägliche Alles-läuft-Zusammenfassung; "kaputt — habe ich repariert"; und "kaputt — ich brauche dich". Alles andere ist Stille.
Selbstheilung
Wenn eine Prüfung fehlschlägt, läuft der Droide nicht sofort zu mir. Zuerst startet er einen Claude-Agenten mit eingeschränktem Werkzeugsatz und Schreibrechten nur für bestimmte Verzeichnisse. Vor jedem Versuch wird ein Git-Snapshot aller Arbeitsverzeichnisse angelegt, sodass sich jede Änderung des Agenten mit einem Befehl zurückrollen lässt — die Snapshot-Hashes stehen direkt in der Nachricht:
🔧 system droid — полагоджено автоматично, 1 спроба (2026-08-02 07:41)
Було зламано:
• news digest freshness — застарілий дайджест: 2026-07-31 (2 дні тому)
✅ Зараз усі перевірки зелені.
↩️ Відкат змін агента (git reset --hard на знімок):
• ~/Developer/system-droid @ f037cfb
• ~/Developer/obsidian-cron @ e98746cUnd das ist kein Spielzeug: Der Agent hat nach einem nächtlichen Netzausfall tatsächlich einen veralteten Digest neu erzeugt, eine hängende launchd-Aufgabe selbst neu geladen und selbst diagnostiziert, dass sich ein Token-Problem ohne mich nicht lösen lässt. In der Nachricht sehe ich, was kaputt war, was der Agent getan hat und wie es ausging.
Was er schon erwischt hat
In sieben Wochen hat der Droide mehrere lautlose Ausfälle — jeder hätte tagelang leben können — in Nachrichten verwandelt, die ich sofort sah:
- Ein abgeschossener Berichtsgenerator. Der macOS-Kernel schoss den Prozess direkt nach einem Neubau der Binärdatei ab — der Morgenbericht wäre schlicht nie erschienen, und niemand hätte es gemerkt.
- Ein abgelaufener Refresh-Token. Der Proxy erneuerte seinen Access-Token nicht mehr, jeder LLM-Aufruf kam mit 401 zurück. Der Droide sagte es klar: Hier hilft nur ein neues Login — ein Befehl, zwei Minuten.
- Ein Platzhalter statt Analyse. Die Generierung endete "erfolgreich", aber in der Notiz stand Ersatztext statt KI-Analyse. Die Prüfung des Inhalts — nicht des Exit-Codes — fing das am ersten Tag.
- Ein festhängendes Vault-Backup. Das Git-Plugin committete lokal weiter, während der Push zu GitHub still gestorben war — das Backup wäre eingefroren, entdeckt im denkbar schlechtesten Moment.
Was er bewusst nicht repariert
Die wichtigste Entscheidung in diesem System ist nicht, was man automatisiert, sondern was nicht. Einige Prüfungen sind als Nur-Melden markiert: alles rund um Authentifizierung, fremde Systeme und die Sitzungen meines eigenen Agenten. Ein abgelaufenes OAuth lässt sich nicht per Skript "reparieren" — ein Mensch muss es im Browser neu ausstellen. Dem Agenten ist ausdrücklich verboten, Tokens anzufassen, meine laufenden Dienste neu zu starten oder eine Prüfung so lange zurechtzubiegen, bis sie grün wird.
Es gibt auch eine physische Grenze: Der Reparatur-Agent ist selbst ein Claude-CLI, und wenn Netz oder Auth ausfallen, fällt er mit allem anderen aus. Was das System zerbricht, zerbricht auch die Hände, die es reparieren. Ehrliches Verhalten heißt dort nicht heldenhafte Versuche, sondern ein klares "ich brauche dich" — mit Anleitung, was genau zu tun ist.
Die Kleinigkeiten, auf denen alles ruhte
Die meiste Zeit kosteten nicht die Prüfungen, sondern die Zuverlässigkeit des Wächters selbst. Erstens: Eine Go-Binärdatei an Ort und Stelle neu zu bauen ändert ihre Signatur, und launchd cacht Signatur-Anforderungen — den nächsten geplanten Lauf tötet das System schlicht. Ein Build endet jetzt immer mit einem Neuladen der Aufgabe:
# Перезбирання бінарника на місці змінює його cdhash, а launchd кешує
# вимоги до підпису (LWCR) на момент bootstrap. Після збирання кеш
# застаріває — і наступний плановий запуск ядро вбиває (exit 9) або
# launchd відмовляється його запускати (exit 78 / EX_CONFIG).
# Тому збирання ЗАВЖДИ закінчується перезавантаженням задачі:
go build -o system-droid .
codesign --verify --strict system-droid
launchctl bootout "gui/$(id -u)/com.oleksii.system-droid" 2>/dev/null || true
launchctl bootstrap "gui/$(id -u)" ~/Library/LaunchAgents/com.oleksii.system-droid.plist
./check-self.sh # свіжий запуск має бути зеленимZweitens: Bei KeepAlive-Diensten ist der Exit-Code des letzten Laufs eine irreführende Metrik. Nach jedem Neustart steht dort SIGTERM, und ein völlig lebendiger Dienst wirkt kaputt. Die richtige Frage ist nicht "wie hat er sich beendet", sondern "läuft er gerade":
# У KeepAlive-демона LastExitStatus після КОЖНОГО перезапуску
# ненульовий (15/SIGTERM) — тож перевірка "останній запуск успішний"
# хибно валить цілком живий сервіс. Правильне питання інше:
# чи працює він ПРЯМО ЗАРАЗ?
info=$(launchctl list "$1" 2>/dev/null) || { echo "not loaded"; exit 1; }
pid=$(printf '%s\n' "$info" | awk -F'= ' '/"PID"/{gsub(/[ ;]/,"",$2);print $2}')
[ -n "$pid" ] && [ "$pid" != "0" ] && { echo "running (pid $pid)"; exit 0; }
echo "loaded but not running"; exit 1Drittens: Prüfe genau das Objekt, von dem das System abhängt. Meine erste Token-Prüfung rechnete "Ausstellungsdatum plus ein Jahr" — und leuchtete grün, während der echte Token seit einem Tag 401 zurückgab:
# Календарна перевірка сяяла зеленим — річному токену ще жити й жити:
claude oauth token — OK: valid, 365d left
# А справжній робочий токен тим часом помер, і логи проксі це знали:
token refresh failed: {"error":"invalid_grant","error_description":"Refresh token expired"}
POST /v1/chat/completions → 401 "OAuth access token has expired. Re-authenticate."Und viertens: Ein einzelner Netzaussetzer um drei Uhr nachts ist kein Grund, einen Menschen zu wecken. Der Alarm "Eingriff nötig" feuert jetzt nur, wenn das Problem zwei aufeinanderfolgende Läufe überlebt. Einmalige Störungen lösen sich von selbst auf; echte kommen trotzdem durch — nur zwei Stunden später:
// Тривога "потрібне втручання" — лише якщо перевірка провалилася
// два запуски поспіль. Нічний обрив мережі, демон посеред перезапуску,
// пробудження зі сну — все це минає само до наступного циклу,
// і будити людину через таке не можна. Успішне лікування,
// навпаки, повідомляється одразу — це добра новина, а не шум.
counts := loadHealCounts() // ~/.system-droid-heal-state.json
for _, r := range stillFailing {
counts[r.Name]++
}
var persistent []Result
for _, r := range stillFailing {
if counts[r.Name] >= 2 { // поріг ескалації
persistent = append(persistent, r)
}
}
// сповіщення — лише якщо len(persistent) > 0Augen für einen anderen Agenten
Neben Telegram läuft der Droide auch als MCP-Server. Das heißt, mein lokaler Agent kann ihn direkt nach dem Systemzustand fragen: Statt Berichte zu lesen, sage ich "prüf, ob alles läuft" — der Agent ruft get_health auf, führt jede Prüfung live aus und antwortet. Monitoring hörte auf, eine Seite zum Anschauen zu sein, und wurde ein Dienst, den man befragt.
# Дроїд працює і як MCP-сервер — локальний агент питає його сам:
Resonance › виклич get_health у system-droid і скажи, чи все зелене
get_health →
overall: 🟢 OK — 10/10 green (2026-08-17 09:00)
🟢 openclaw gateway (:18789) — ядро агента Resonance (launchd + порт)
🟢 cli-proxy Claude auth — робочий Claude-токен (валідність, авто-оновлення)
...Fazit
Technisch ist hier nichts kompliziert: Go, launchd, ein paar Shell-Skripte und ein Telegram-Bot. Aber genau dieses simple Bündel hat das Gefühl für den ganzen Automatisierungs-Fuhrpark verändert: Ich führe keine mentale Liste mehr von Dingen, die ich "nicht vergessen darf zu prüfen". Das ist jetzt der Job des Droiden.
Sieben Wochen lang war er meist still. Jede Nachricht, die er doch schickte, war entweder eine gute Neuigkeit über bereits Repariertes oder ein präziser Hinweis, wo meine zwei Minuten gebraucht wurden. Genau das bedeutet Komfort: ein System, das andere Systeme bewacht — und deine Stille respektiert.
Einen Fehler entdeckt?
Ein falscher Fakt, eine schiefe Übersetzung, etwas, das in diesem Artikel falsch klingt? Schreib mir — in deiner eigenen Sprache.