Files
semprini-maintainer/CLAUDE.md
T
paulandClaude Opus 4.8 e91b129841 Initial commit: autonomous maintenance agent for semprini stack
systemd-deployed daemon that drives the semprini-core stack-support agent
headless via Claude Code, monitors health via Uptime Kuma, applies safe
upgrades, and escalates to the operator over Matrix.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-21 17:20:06 +12:00

3.1 KiB

semprini-maintainer — Claude Instructions

What this is

A standalone, always-on autonomous maintenance agent for the semprini.me container stack, deployed as a systemd service (semprini-maintainer). It keeps the stack healthy and current and talks to the operator over Matrix (chat.semprini.me).

It is the unattended driver for the canonical stack-support agent, which lives in the separate semprini-core repo. This project does not reimplement that logic — it gathers state and invokes the stack-support agent headless via Claude Code, then relays/acts on the agent's JSON result.

Relationship to other projects

  • semprini-core (../semprini-core) — the Enterprise Landing Zone this agent maintains. At runtime the daemon reads, from the path in config.json repo_dir:
    • agents/stack-support.agent.md (injected as system prompt)
    • docs/stack-support-runbook.md
    • core_stack/compose*.yml Keep the stack-support agent definition canonical in semprini-core — do not fork a copy here.
  • Other projects (e.g. ../semprini-blog) that register Uptime Kuma monitors are also maintained; their repos are exposed to the agent via extra_dirs.

How it works (one screen)

  • Scope = whatever Uptime Kuma tracks at check time, re-read every cycle (never hard-coded). Kuma's heartbeat is the health signal — the daemon does not re-probe. Kuma's root-owned kuma.db is read via a throwaway keinos/sqlite3 container mounting the uptime-kuma-data volume read-only.
  • Health loop (5 min): down services confirmed over down_confirmations cycles → invoke stack-support agent to remediate → report to Matrix.
  • Upgrade loop (7 days): resolve containers behind tracked services → agent researches + applies safe upgrades (test, pin, rollback); escalates major/breaking ones to Matrix.
  • Matrix: bot @maintainer:semprini.me DMs @paul:semprini.me. Escalations are numbered questions; the reply is fed back to the agent to carry out.
  • Autonomy (config.jsonautonomy): full (default) | fix-only | notify.

Conventions / guardrails

  • Runs as host user paul (in docker group), not root — Claude Code refuses --permission-mode bypassPermissions under root.
  • maintainer.py is stdlib-only — keep it dependency-free so it deploys without a venv.
  • Secrets live in config.json and .bot-secretsnever commit (gitignored).
  • Prefer editing existing files over adding new ones.

Files

File Purpose
maintainer.py The daemon (stdlib only).
config.example.json Template — copy to config.json.
register-matrix-bot.sh Creates @maintainer account + DM room; writes token to config.
install.sh Syntax-check, install unit, enable + start.
semprini-maintainer.service systemd unit (runs as paul).
docs/architecture.md Architecture decision record.

Test without the service

python3 maintainer.py --config config.json --once health
python3 maintainer.py --config config.json --once upgrade
python3 maintainer.py --config config.json --once replies