No description
  • Python 94.4%
  • HTML 3.4%
  • Shell 0.9%
  • CSS 0.7%
  • Dockerfile 0.6%
Find a file
Repository files (latest commit first)
Filename Latest commit message Latest commit date
renovate 0ceb7a0470
All checks were successful
CI / audit (push) Successful in 43s
CI / test (push) Successful in 1m34s
Merge pull request 'chore(deps): update python docker tag to v3.15' (#4) from renovate/python-3.x into main
2026-11-04 02:08:53 +00:00
.forgejo/workflows chore(deps): update dependency python to 3.15 2026-11-02 02:08:37 +00:00
autopilot fix: CI repair sessions see the user's comments and fix causes inside the repo 2026-10-29 12:29:49 +01:00
docker feat: isolate agent sessions, release by tag, hand Renovate repairs over for review 2026-10-27 21:05:36 +01:00
docs docs: per-job networks and capacity 6 on the CI runner 2026-10-29 12:58:17 +01:00
reference docs: initial ideas, spec and implementation plan 2026-10-24 00:05:16 +02:00
scripts chore: script for one Docker network per CI job on services-collab 2026-10-27 23:51:22 +01:00
tests fix: CI repair sessions see the user's comments and fix causes inside the repo 2026-10-29 12:29:49 +01:00
.env.example feat: isolate agent sessions, release by tag, hand Renovate repairs over for review 2026-10-27 21:05:36 +01:00
.gitignore feat: scaffold (config, Dockerfile, compose, main loop) 2026-10-24 00:05:46 +02:00
CHANGELOG.md fix: CI repair sessions see the user's comments and fix causes inside the repo 2026-10-29 12:29:49 +01:00
compose.yaml feat: isolate agent sessions, release by tag, hand Renovate repairs over for review 2026-10-27 21:05:36 +01:00
config.example.yaml feat: isolate agent sessions, release by tag, hand Renovate repairs over for review 2026-10-27 21:05:36 +01:00
Dockerfile chore(deps): update python docker tag to v3.15 2026-11-03 07:50:11 +00:00
pyproject.toml fix: CI repair sessions see the user's comments and fix causes inside the repo 2026-10-29 12:29:49 +01:00
README.md feat: merge issue PRs only after green CI and repair red CI with the logs 2026-10-27 23:48:42 +01:00
renovate.json Add renovate.json 2026-10-27 11:32:43 +00:00

agent-autopilot (Arbeitstitel)

Forgejo-Issues werden von Claude Code, Codex oder Kimi Code bearbeitet. Ein Dashboard verwaltet Projekte, Modelle, Agentenkonten, Releases und SSH-Deployments. App und Deployer laufen als zwei Container mit demselben Image; die SQLite-Daten liegen persistent unter data/.

Betrieb

Einrichten

  1. Forgejo-Token: Unter Einstellungen → Anwendungen einen Token mit repository (Lesen/Schreiben), issue (Lesen/Schreiben) und user (Lesen; ohne ihn scheitert die Repo-Erkennung über /user/repos mit 403) anlegen und in .env als FORGEJO_TOKEN=... eintragen. config.example.yaml nach data/config.yaml kopieren und Forgejo-URL, OAuth und Agentenkonten anpassen.

  2. OAuth-Dashboard: In Forgejo eine öffentliche OAuth-App mit Authorization Code und PKCE anlegen. Redirect-URL ist <dashboard.external_url>/oauth/callback. Die Client-ID kommt in dashboard.client_id, nur Benutzer aus dashboard.allowed_users dürfen sich anmelden. Für einen Zugriff über einen Reverse Proxy external_url auf die HTTPS-URL setzen. Der Port wird standardmäßig nur an 127.0.0.1:8080 veröffentlicht (AUTOPILOT_HOST/AUTOPILOT_PORT).

  3. Projekte: Vorhandene YAML-Projekte werden nur beim ersten Start nach SQLite importiert. Danach ist die Datenbank führend und alle Projektänderungen erfolgen im Dashboard. Repos, auf die der technische Forgejo-Nutzer neu Zugriff erhält, erscheinen automatisch beim nächsten Poll. Agentenläufe und Deployments bleiben bis zur manuellen Freigabe deaktiviert.

  4. Agenten anmelden: Das erste Claude-Konto claude-default nutzt data/claude:

    docker compose run --rm autopilot claude
    

    Weitere Konten aus agents.accounts verwenden getrennte Homes. Beispiele:

    docker compose run --rm -e CLAUDE_CONFIG_DIR=/data/accounts/claude-2 autopilot claude
    docker compose run --rm -e CODEX_HOME=/data/accounts/codex-1 autopilot codex login
    docker compose run --rm -e KIMI_CODE_HOME=/data/accounts/kimi-1 autopilot kimi
    

    Bei Kimi im interaktiven Programm anmelden. Zugangsdaten werden nicht ins Dashboard kopiert. Der Fallback erfolgt nach Priorität nur zwischen Konten desselben Agenten. Sessions und Kontopausen sind pro Konto getrennt; ein erschöpftes Claude-Konto blockiert Codex/Kimi nicht.

  5. Starten: AUTOPILOT_VERSION in .env setzen (Tags unter Packages in Forgejo), dann:

    docker compose pull && docker compose up -d
    docker compose logs -f autopilot deployer
    

    Das Image entsteht in der Release-Pipeline, nicht auf der VM. max_parallel begrenzt die gleichzeitigen Agentensitzungen. Agent, Modell und globale Defaults sind im Dashboard einstellbar; leere Projektangaben erben den globalen Default.

Releases und SSH-Deployments

Pro Projekt erstellt release: true nach fertigen Änderungen ein Release. Der Versions-Bump (patch, minor, major), eigene Release-Regeln und Prüfbedarf sind projektbezogen einstellbar. Bei release_after_ci: true wird das Forgejo-Release erst nach grüner CI des Release-Commits auf dem Basis-Branch angelegt. Tag und Release zeigen immer genau auf den geprüften Commit.

Hat das Projekt eine eigene Release-Pipeline auf Tags (Horae, Vigilia, autopilot), gehört es auf release_mode: tag: autopilot setzt dann nur den Tag, die Pipeline baut das Image und legt das Release an. autopilot verfolgt den Lauf und meldet das Ergebnis im Issue bzw. PR. So sieht der Deployer ein Release erst, wenn das Image existiert; Entwürfe ignoriert er. Offene Rückfragen und Nacharbeiten nutzen die gespeicherte Sitzung des jeweiligen Agentenkontos. delivery: direct pusht ohne PR auf den Basis-Branch.

Für Deployments pro Projekt im Dashboard SSH-Host, Port, Benutzer, Schlüsseldatei, Known-Hosts-Datei und Remote-Befehl mit {tag} eintragen. Beispiel: /opt/demo/deploy.sh {tag}. Die Dateien liegen auf dem Host in deploy-keys/ und werden nur dem Deployer read-only unter /run/deploy-keys eingebunden:

mkdir -p deploy-keys
ssh-keygen -t ed25519 -f deploy-keys/demo-ed25519
ssh-keyscan -H vm.example.net > deploy-keys/known_hosts
chmod 600 deploy-keys/demo-ed25519

Den Hostschlüssel beim ersten ssh-keyscan anhand des vertrauenswürdigen Fingerabdrucks prüfen und den öffentlichen Schlüssel auf der Ziel-VM für den Deploy-Benutzer hinterlegen. Der Deployer nutzt BatchMode=yes und StrictHostKeyChecking=yes, daher funktionieren keine interaktiven Passwort- oder Hostschlüssel-Abfragen.

Der Deployer beobachtet tatsächlich vorhandene Forgejo-Releases, nicht lediglich vorbereitete Release-Jobs. Beim ersten Aktivieren ist der vorhandene Bestand nur eine Baseline und wird nicht nachgeholt. Jedes danach neu erscheinende Release wird genau einmal automatisch eingeplant; Neustarts erzeugen keine Duplikate. Im Projekt kann jedes erkannte Release zusätzlich manuell deployt oder ein Fehlschlag als neuer Versuch wiederholt werden. Pro Projekt läuft höchstens ein Deployment gleichzeitig.

Isolation

Agent-Sitzungen führen Code aus, den niemand geprüft hat: neue Versionen von Abhängigkeiten, Tests, Build-Skripte. autopilot läuft deshalb ohne Docker-Socket und mit Obergrenzen für Speicher und CPU (AUTOPILOT_MEM_LIMIT, AUTOPILOT_CPUS). Vorerst teilt er sich services-collab mit Forgejo und der Produktion; eine eigene VM ist Stufe 3 in docs/08-isolation-plan.md. Im Container laufen zwei Nutzer:

Nutzer Was Darf
autopilot Dienst, Deployer, Dashboard Forgejo-Token, state.db, config.yaml, Logs, Push
agent jede Agent-Sitzung, docker compose run … claude Konten unter data/claude, data/accounts, eigenes Home

Gemeinsam haben beide nur die Worktrees unter data/work (Gruppe work). Der Container startet als root, setzt die Rechte unter data/ (docker/entrypoint.sh) und wechselt dann den Nutzer. Sitzungen, die eine Datenbank brauchen, erreichen den Wegwerf-Postgres testdb (postgres://test:test@testdb:5432/test); das gehört in prompt_extra des Projekts.

Was eine übernommene Sitzung trotzdem erreicht: das Agentenkonto, die Worktrees und alles, was der Host im Netz anbietet. Aus dem Container käme sie nur über eine Kernel-Lücke.

Benutzen

  • Issue im freigegebenen Projekt anlegen (Autor muss in allowed_users stehen), Label autopilot setzen. Der Dienst legt fehlende Labels selbst an.
  • Ein Issue-PR wird erst nach grüner CI gemergt und released. Ist sie rot, bekommt die Sitzung die fehlgeschlagenen Jobs und repariert auf demselben Branch (zählt gegen max_attempts). Liegt die Ursache nicht in der Änderung (CI-Infrastruktur, flaky), meldet sie das und der Issue wird blockiert. Repos ohne CI gehen nach 15 Minuten ohne Status weiter.
  • in-arbeit kennzeichnet einen Lauf, rückfrage wartet auf einen Kommentar, blockiert nach maximalen Versuchen, zu-prüfen auf menschliche Kontrolle. Zum Wiederholen Issue öffnen und zu-prüfen/blockiert entfernen.
  • Rote Renovate-PRs können projektbezogen übernommen werden (renovate); auch dabei gelten Agenten- und Kontoeinstellungen. Übersprungen werden der Onboarding-PR und PRs, solange der Basis-Branch selbst rot ist. Ist die CI nach der Reparatur grün, bekommt der PR zu-prüfen: Mergen oder das Label entfernen löst Merge und Release aus (renovate_automerge mergt ohne Prüfung). Ändert eine Reparatur CI-Workflows, wird nichts gepusht und der PR blockiert. Gemergte Sicherheitsupdates (Label security) lösen ein Release aus (renovate_security_release, Standard an); grüne Updates mergt Renovate selbst. Die Release-Beobachtung behandelt manuelle, Issue- und Renovate-Releases gleich.
  • Zustand: data/state.db (Projekte, Jobs, Runs, Konten, Releases, Deployments), Agentenlogs in data/logs/, Arbeitsverzeichnisse in data/work/.

Entwickeln

uv venv .venv && uv pip install --python .venv/bin/python -e '.[dev]'
AUTOPILOT_DATA=/tmp .venv/bin/python -m pytest

Releases dieses Repos

Nicht zu verwechseln mit den Releases, die autopilot für seine Projekte macht (oben): hier geht es um autopilot selbst. Dieselbe Strategie wie bei Horae und Vigilia:

  • CI (.forgejo/workflows/ci.yaml) bei jedem Push auf main und bei Pull Requests: Tests und pip-audit. Baut kein Image.
  • Release nur per Tag vX.Y.Z (.forgejo/workflows/release.yaml): wartet auf die grüne CI desselben Commits (scripts/ci_gate.py), prüft Tag gegen die Version in pyproject.toml und einen Abschnitt in CHANGELOG.md (scripts/release_check.py), baut und pusht git.mila-hofmann.de/mila/autopilot:<version> (dazu :X.Y und :latest) und legt das Forgejo-Release mit dem Changelog-Text an. Braucht das Actions-Secret REGISTRY wie Horae.
  • Ablauf:
    scripts/bump-version.sh 0.2.0     # schreibt die Version in pyproject.toml
    $EDITOR CHANGELOG.md              # [Unreleased] -> ## [0.2.0] - <Datum>, neues leeres [Unreleased]
    git commit -am "chore: release 0.2.0" && git push
    # CI von main abwarten, dann:
    git tag v0.2.0 && git push origin v0.2.0
    
  • Auf der VM (~/docker-compose-files/autopilot) liegen nur compose.yaml, .env, deploy-keys/ und data/. Ein Update ist AUTOPILOT_VERSION in .env plus docker compose pull && docker compose up -d; zurück geht es mit der alten Nummer. Seit 0.2.0 (2026-10-27).

Zielbild

Ein autonomer Agent, der als installierte App läuft und

  • beliebig vielen Projekten auf dem eigenen Forgejo zugewiesen werden kann,
  • diese Projekte periodisch überwacht (Issues, PR-Kommentare, CI-Status und Releases),
  • sobald es etwas zu tun gibt, eine Agent-Sitzung startet, die Arbeit erledigt und im Issue antwortet,
  • dabei Claude Code, Codex und Kimi Code projektbezogen nutzt und bei erschöpftem Kontingent zwischen mehreren Konten desselben Agenten wechselt.

Regel Nr. 1: erst suchen, dann bauen

Bevor wir irgendetwas davon selbst bauen und dauerhaft pflegen, suchen wir nach fertigen Lösungen. Eigenbau nur für die Lücke, die danach übrig bleibt. Siehe docs/03-build-vs-buy.md für Suchbegriffe und Kriterien. Der Eigenbau in Vigilia entstand pragmatisch, nicht nach einer solchen Suche.

Inhalt

Datei Inhalt
docs/01-current-implementation.md Wie der Autopilot in Vigilia heute funktioniert
docs/02-ideas.md Frühe Ideen aus dem Chat
docs/03-build-vs-buy.md Suchauftrag nach fertigen Lösungen, Bewertungskriterien
docs/07-renovate-handover.md Spezifikation der inzwischen integrierten Renovate-Übernahme
docs/08-isolation-plan.md Isolation von Sitzungen und CI: was umgesetzt ist, was als Nächstes kommt
reference/autopilot.py, reference/autopilot_prompt.md Schnappschuss des Vigilia-Stands vom 2026-10-23 (nur Referenz, nicht pflegen)