threepp
C++20 기반 크로스플랫폼 3D 라이브러리, 파이썬 바인딩 및 three.js 수준 API 제공
서비스가 중단되면 서버가 증거를 수집하고, LLM이 진단해 원인과 해결책을 한 메시지로 알려줍니다
When a service goes down, the server collects evidence, an LLM diagnoses it, and I get one message with the cause and the fix.
개발 도구Python · ShellGitHub @moutaz121493온라인운영자 미확인
써 보셨어요? 한 번만 눌러 주세요. 로그인은 필요 없어요.
아직 감지된 업데이트가 없습니다. GitHub 릴리스가 나오면 여기에 보입니다.
개인 계정의 공개 저장소 소유자는 GitHub로 로그인해 운영자를 확인하고 소개를 직접 관리할 수 있습니다. 관리자 승인은 필요하지 않습니다.
로그인한 뒤 확인 파일을 만들어 이 저장소의 기본 브랜치에 30분 안에 커밋해 주세요. 다른 브랜치나 포크의 파일은 인정하지 않습니다. 파일을 올린 뒤 아래에서 확인하면 관리자 승인 없이 관리할 수 있습니다. 자격을 유지하려면 파일을 남겨 두세요.
로그인이 필요하면 로그인 화면으로 이동합니다. 로그인 후 이곳으로 돌아와 원하는 확인 버튼을 다시 눌러 주세요.
프로젝트 폴더에서 /nomorevibe verify를 실행하면 소유권을 확인하고 소개를 직접 관리할 수 있습니다.
1분 만에 확인하기A home server that diagnoses its own outages: Uptime Kuma alert → read-only evidence → redaction → LLM diagnosis (no tools) → incident page + one notification. Never executes fixes.
저장소 README에서 가져옴
README 전체를 불러오는 중입니다.
README 전문 보기 ↗When a service on my Raspberry Pi 5 home server goes down, this agent collects evidence, has an AI explain what happened, writes an incident page and sends one phone notification with the likely cause and the commands to fix it. It never runs anything itself: it only diagnoses, and a human decides.
It has run on the Pi since October 2026, watching about 30 services (Docker containers, systemd services, DNS, backups, disks, a Cloudflare tunnel).
http, dig, cert, backup_status) and lists
container/unit names, which are checked against a strict pattern. A config file can never add a command.rm -r, prune, fsck, mkfs, dd, umount, reading .env files, ...) are dropped
before anyone sees them.key=value secrets, notification topic
URLs, URL query strings, e-mail addresses, long hex strings and base64-like blobs.--max-budget-usd) and optionally per
month through a shared budget module. Plus: one diagnosis per monitor per 30 minutes, 10 per day.ProtectSystem=strict, so the whole filesystem is read-only for the
agent except its state and the incident pages.Real false alarms that changed the code:
ProtectSystem=strict sandbox every path
looks read-only. The collector now reads the host's mount table (findmnt --task 1, marked
"host view"), and the prompt only allows calling a disk read-only if those options start with ro,.known-issues.txt gives the model the server's history (e.g. "the HDD used to drop on the old power
supply", "get_throttled=0x80000 is a past soft temperature limit, not a power problem"), which made the
diagnoses noticeably more specific.jobwatch/ closes a gap Uptime Kuma has: is every scheduled job still running?
jobrun NAME MAXAGE command... wraps each cron job and records its last success in ~/.jobs/.jobwatch.py (cron, every 5 min) pushes up/down to a Kuma push monitor "Scheduled jobs", naming every
job whose last success is older than its MAXAGE and every watched systemd timer whose last run failed for
20+ minutes. If jobwatch itself stops, the push monitor goes down on its own.*/30 * * * * jobrun my-sync 7200 /usr/bin/python3 /opt/my-sync/sync.py
*/5 * * * * /usr/bin/python3 /usr/local/bin/jobwatch.py
When you remove a cron job, also delete its ~/.jobs/<name>.ok file, or jobwatch keeps reporting it as late.
Requirements: Python 3.11+ (standard library only), systemd, Docker (for container checks), Uptime Kuma with a status page that lists the monitors (the agent reads its public JSON API), and at least one of:
gemini-ask: any command that takes the system prompt as its last argument and the input on stdin,
accepts --tag, --timeout, --effort and --schema, and prints the JSON answer (mine runs the
Gemini CLI as a locked-down user), orclaude -p works for that user).sudo install -m 755 diag-agent.py /usr/local/bin/diag-agent.py
sudo mkdir -p /etc/diag /var/lib/diag /var/www/incidents
sudo cp examples/monitors.json examples/known-issues.txt /etc/diag/ # then edit both
sudo cp systemd/diag-watch.* /etc/systemd/system/
sudo systemctl daemon-reload && sudo systemctl enable --now diag-watch.timer
sudo diag-agent.py list # monitors from the config
sudo diag-agent.py collect "Paperless" # print the redacted evidence, no AI
sudo diag-agent.py test "Paperless" # evidence + AI diagnosis, printed, no notification
python -m unittest discover -s tests -v # standard library only; runs in CI on Python 3.11 – 3.13
They cover the parts that keep the agent safe: redaction of secrets, the JSON-schema validation and the command blocklist, config values that try to inject commands, HTML escaping and pruning of incident pages, and jobwatch.
Monitor names in monitors.json must match the monitor names in Kuma. A monitor that is not in the config
still gets the generic evidence.
| Variable | Default | |
|---|---|---|
KUMA_URL | http://127.0.0.1:3001 | Uptime Kuma |
KUMA_STATUS_PAGE | home | slug of the status page with the monitors |
DIAG_CONFIG / DIAG_KNOWN | /etc/diag/monitors.json / known-issues.txt | |
DIAG_SITE | /var/www/incidents | where incident pages are written (kept 90 days) |
DIAG_PUBLIC_URL | http://localhost/incidents | link in the notification |
DIAG_NOTIFY | /usr/local/bin/notify | notify <channel> <prio> <title> <msg> <tags> <url>, e.g. an ntfy wrapper |
DIAG_ENGINE / DIAG_FALLBACK | gemini / claude | claude / none |
DIAG_GEMINI_ASK | /usr/local/bin/gemini-ask | |
DIAG_CLAUDE_USER / DIAG_CLAUDE_BIN | claude-runner / ~/.local/bin/claude | |
DIAG_MODEL | sonnet | Claude model for the fallback |
DIAG_MONTHLY_USD | 3 | monthly cap if ai_budget.py is present in /usr/local/lib |
DIAG_BACKUP_STATUS | /var/backups/STATUS | file read by the backup_status check |
MIT