From 228b6180305e044e32e83ff5dee2bde724772ba7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Tr=C3=B6ger?= Date: Sat, 13 Jun 2026 08:21:37 +0200 Subject: [PATCH 01/11] =?UTF-8?q?feat:=20/project-review=20Skill=20f=C3=BC?= =?UTF-8?q?r=20dom=C3=A4nenunabh=C3=A4ngige=20Dokument-Reviews?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Neuer Skill der Nicht-Software-Dokumente (Bauanleitungen, Hardware-Pläne, Analysen) reviewt. Erkennt die Domäne automatisch, leitet Prüfkategorien ab und lässt den User per MultiSelect wählen. Co-Authored-By: Claude Opus 4.6 --- CLAUDE.md | 1 + skills/project-review/SKILL.md | 104 +++++++++++++++++++++++++++++++++ 2 files changed, 105 insertions(+) create mode 100644 skills/project-review/SKILL.md diff --git a/CLAUDE.md b/CLAUDE.md index d1b47c1..62fb688 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -103,6 +103,7 @@ Kurzbefehl für den gesamten Ablauf: `/story` | `/story` | `skills/story/SKILL.md` | Voller Lifecycle von Research bis PR | | `/workflow-review` | `skills/workflow-review/SKILL.md` | Opus reviewt alle Skills/Konfig → Umsetzungsplan für Sonnet | | `/implement` | `skills/implement/SKILL.md` | Implementierung direkt aus bestehendem Plan (überspringt Research/Planung) | +| `/project-review` | `skills/project-review/SKILL.md` | Domänenunabhängiges Review für Nicht-Software-Dokumente (Bau, Hardware, Analysen) | ## Agenten diff --git a/skills/project-review/SKILL.md b/skills/project-review/SKILL.md new file mode 100644 index 0000000..4ef0c6b --- /dev/null +++ b/skills/project-review/SKILL.md @@ -0,0 +1,104 @@ +--- +description: Domänenunabhängiges Review für beliebige Projektdokumente — Bauanleitungen, Analysen, Hardware-Pläne, Konzepte. Erkennt die Domäne automatisch, leitet passende Prüfkategorien ab und lässt den User wählen. Aktivieren wenn ein nicht-Software-Dokument auf Vollständigkeit, Korrektheit und Risiken geprüft werden soll. Nicht verwenden für Software-Pläne (dafür /plan-review) oder Code-Reviews (dafür /code-review). +model: claude-opus-4-6 +--- + +# /project-review — Domänenunabhängiges Dokument-Review + +Argument: Pfad zu einer Datei oder einem Verzeichnis. Ohne Argument: User fragen. + +## Phase 1 — Dokument einlesen und Domäne erkennen + +1. Lies das Zieldokument (bei Verzeichnis: alle `.md`-Dateien darin). +2. Lies eine vorhandene `CLAUDE.md` im selben Verzeichnis oder Elternverzeichnis (falls vorhanden). +3. Bestimme die **Domäne** anhand des Inhalts. Beispiele: + +| Signal im Dokument | Domäne | +|---|---| +| Schaltpläne, Verdrahtung, Sensoren, 230V, Relais | Elektrotechnik / Hardware | +| Heizlast, COP, Wärmepumpe, Pufferspeicher, Hydraulik | Haustechnik / Thermodynamik | +| Statik, Fundament, Beton, Bewehrung | Bau / Konstruktion | +| Rezepte, Zutaten, Garzeiten | Kochen | +| Workflow, Prozess, Organisation | Projektmanagement | + +Nenne die erkannte Domäne dem User in einem Satz. + +## Phase 2 — Prüfkategorien ableiten und zur Auswahl stellen + +Leite **4–8 Prüfkategorien** aus Domäne und Dokumentinhalt ab. Jede Kategorie besteht aus: +- **Name** (kurz, z.B. "Elektrosicherheit") +- **Beschreibung** (ein Satz, was geprüft wird) +- **Typische Prüfpunkte** (2–4 konkrete Fragen) + +Die Kategorien sollen das Dokument vollständig abdecken. Typische Muster: + +**Immer dabei (domänenübergreifend):** +- Vollständigkeit — fehlen Abschnitte, Schritte, Angaben? +- Korrektheit — sind Fakten, Berechnungen, Angaben nachvollziehbar und widerspruchsfrei? +- Risiken — was kann schiefgehen, was fehlt als Fallback? + +**Domänenspezifisch ableiten**, z.B.: +- Elektrotechnik: Sicherheit (Absicherung, Schutzleiter, Spannungsfreiheit), Komponentenwahl, Diagnose +- Haustechnik: Dimensionierung, Regelstrategie, Normen/Förderung +- Bau: Statik, Materialwahl, Bauvorschriften + +Stelle die Kategorien dem User mit `AskUserQuestion` zur Auswahl (multiSelect). Vorauswahl: alle. + +## Phase 3 — Review durchführen + +Prüfe das Dokument anhand der gewählten Kategorien. Für jede Kategorie: + +1. Lies die relevanten Abschnitte nochmals gezielt +2. Prüfe jeden der typischen Prüfpunkte +3. Bewerte: OK / Risiko / Blocker + +**Bewertungsmaßstab:** +- **OK**: Korrekt und vollständig dokumentiert +- **Risiko**: Funktioniert vermutlich, aber Lücke oder Ungenauigkeit — bewusst abwägen +- **Blocker**: Fehler, fehlende sicherheitskritische Information, oder Widerspruch — vor Umsetzung klären + +## Ausgabe-Format + +``` +## Project-Review: [Dokumenttitel] + +**Domäne:** [erkannte Domäne] +**Dokument:** [Dateipfad(e)] +**Geprüfte Kategorien:** [Liste] + +--- + +### [Kategorie 1] + +#### ✅ OK +- [Befund mit Verweis auf Abschnitt/Zeile] + +#### ⚠️ Risiko +- [Problem] — **Empfehlung:** [konkreter Vorschlag] + +#### ❌ Blocker +- [Problem] — **Muss geklärt werden:** [was fehlt] + +--- + +### [Kategorie 2] +[...] + +--- + +## Gesamtbewertung + +| Kategorie | Ergebnis | +|---|---| +| [Name] | ✅ / ⚠️ / ❌ | + +**Empfehlung:** [Umsetzung freigeben / Dokument zuerst anpassen — mit konkreten Punkten] +``` + +## Regeln + +- Nur echte Probleme als Blocker — keine "könnte man noch ergänzen"-Punkte +- Konkrete Empfehlungen statt vager Hinweise +- Bei Berechnungen: Nachrechnen und Ergebnis angeben +- Bei Normen/Vorschriften: nur nennen wenn du dir sicher bist, sonst als "prüfenswert" markieren +- Keine Lobhudelei — kurz bestätigen was stimmt, Fokus auf Findings From a93cfef13b4383c28ec0ff76da378c4f30e0620d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Tr=C3=B6ger?= Date: Tue, 16 Jun 2026 07:53:58 +0200 Subject: [PATCH 02/11] =?UTF-8?q?feat:=20/docker-compose=20Skill=20f=C3=BC?= =?UTF-8?q?r=20Compose-Stacks=20nach=20Hausregeln?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Skill fragt vier Zielhosts ab (automation, controller, webserver, localhost), prüft Port-Belegung gegen bestehende Compose-Files und aktive Listener und generiert eine docker-compose.yaml plus .env nach den Hausregeln (5 MB Logging, TZ Berlin, relative Bind-Mounts, Secrets in .env). Auf webserver werden interne Ports an die VPN-IP 10.7.0.1 gebunden. Co-Authored-By: Claude Opus 4.7 --- CLAUDE.md | 1 + skills/docker-compose/SKILL.md | 260 +++++++++++++++++++++++++++++++++ 2 files changed, 261 insertions(+) create mode 100644 skills/docker-compose/SKILL.md diff --git a/CLAUDE.md b/CLAUDE.md index 62fb688..4a31119 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -104,6 +104,7 @@ Kurzbefehl für den gesamten Ablauf: `/story` | `/workflow-review` | `skills/workflow-review/SKILL.md` | Opus reviewt alle Skills/Konfig → Umsetzungsplan für Sonnet | | `/implement` | `skills/implement/SKILL.md` | Implementierung direkt aus bestehendem Plan (überspringt Research/Planung) | | `/project-review` | `skills/project-review/SKILL.md` | Domänenunabhängiges Review für Nicht-Software-Dokumente (Bau, Hardware, Analysen) | +| `/docker-compose` | `skills/docker-compose/SKILL.md` | Erstellt/aktualisiert eine docker-compose.yaml nach Hausregeln (4 Zielhosts: automation/controller/webserver/localhost, Port-Belegungs-Check, 5 MB Logging, TZ Berlin, Bind-Mounts, .env-Secrets, VPN-Binding für Webserver) | ## Agenten diff --git a/skills/docker-compose/SKILL.md b/skills/docker-compose/SKILL.md new file mode 100644 index 0000000..fe9a275 --- /dev/null +++ b/skills/docker-compose/SKILL.md @@ -0,0 +1,260 @@ +--- +description: Erstellt oder aktualisiert eine docker-compose.yaml nach den Best Practices dieses Workflows — aktuelle Compose-Syntax, explizite Konfiguration, Secrets in .env, optionales VPN-Binding für den Webserver. Aktivieren wenn ein neuer Container-Stack aufgesetzt oder ein bestehender überarbeitet werden soll. Nicht verwenden für reine Image-Updates, einzelne docker-Befehle oder Dockerfile-Änderungen. +model: claude-opus-4-6 +--- + +# /docker-compose — Compose-Stack nach Hausregeln + +Zielort: ein Verzeichnis unter `/docker//` auf einem der Hosts oder lokal. Der Skill liefert eine `docker-compose.yaml` plus passende `.env`-Vorlage. + +## Phase 0: Aufgabenklärung + +Stelle dem User folgende Fragen, sofern nicht schon im Request beantwortet: + +1. **Name des Stacks** (Verzeichnisname unter `/docker/`) +2. **Welche Services** sind enthalten (Image + Zweck)? +3. **Zielhost** — eine der folgenden vier Optionen, per `AskUserQuestion`: + + | Ziel | SSH-Pfad | Netzwerk-Kontext | + |---|---|---| + | `automation` | `ssh automation:/docker//` | internes LAN, kein VPN-Binding | + | `controller` | `ssh controller:/docker//` | internes LAN, kein VPN-Binding | + | `webserver` | `ssh waldperle:/docker//` | öffentlich, interne Ports an VPN `10.7.0.1` binden | + | `localhost` | aktuelles Arbeitsverzeichnis | kein Bind-Prefix | + +4. **Reverse-Proxy** — soll der Stack über `nginx-proxy-manager` ans Web? Dann `reverse-proxy`-Netz nötig. +5. **Persistente Daten** — welche Verzeichnisse müssen über Restarts/Recreates überleben (Datenbankdaten, Configs, Uploads, Logs)? +6. **Gewünschte Host-Ports** — welche Ports sollen extern erreichbar sein? (werden in Phase 1.5 gegen Belegung geprüft) + +Bei `webserver` zusätzlich: + +> "Sollen die Ports nur über das VPN (`10.7.0.1`) erreichbar sein oder auch öffentlich (z.B. `80`, `443`)?" + +Standardregel: **alle Ports an `10.7.0.1` binden**, nur explizit öffentliche (HTTP/HTTPS für reverse-proxy) bleiben ohne Bind-IP. + +## Phase 1.5: Port-Belegungs-Analyse (Pflicht vor Generierung) + +Bevor irgendein Port in die `docker-compose.yaml` geschrieben wird, **beide** Prüfungen auf dem Zielhost ausführen: + +### Prüfung 1: Alle bestehenden Compose-Files + +```bash +# Bei automation/controller/webserver via SSH: +ssh "grep -rhE '^\s*-\s*\"?([0-9]+\.[0-9]+\.[0-9]+\.[0-9]+:)?[0-9]+:[0-9]+' /docker/ 2>/dev/null \ + | sed -E 's/.*\"?([0-9.]+:)?([0-9]+):.*/\2/' | sort -u" + +# Bei localhost: lokal ausführen (Pfad ggf. anpassen) +grep -rhE '^\s*-\s*\"?([0-9]+\.[0-9]+\.[0-9]+\.[0-9]+:)?[0-9]+:[0-9]+' . 2>/dev/null \ + | sed -E 's/.*\"?([0-9.]+:)?([0-9]+):.*/\2/' | sort -u +``` + +### Prüfung 2: Aktive Listener auf dem Host + +```bash +ssh "ss -tlnp 2>/dev/null | awk 'NR>1 {split(\$4, a, \":\"); print a[length(a)]}' | sort -u" +# Bei localhost: +ss -tlnp 2>/dev/null | awk 'NR>1 {split($4, a, ":"); print a[length(a)]}' | sort -u +``` + +### Konfliktauflösung + +Vergleiche die in Phase 0 gewünschten Host-Ports mit beiden Listen: + +- **Frei in beiden:** Port übernehmen. +- **Belegt in Prüfung 1 (Compose):** zeigen, welcher Stack/Service belegt — User fragen, ob Konflikt akzeptiert ist (selten korrekt) oder ein anderer Port gewählt werden soll. +- **Belegt in Prüfung 2 (Listener):** zeigen welcher Prozess — alternativen Port vorschlagen. +- **Vorschlag bei Konflikt:** nächste freie Port-Nummer aus passendem Bereich (Web-UIs `8000–8999`, DBs `5400+`, Custom `3000–3999`). + +Erst wenn alle gewünschten Ports konfliktfrei sind, weiter zu Phase 3. + +**Hinweis für `webserver`:** das VPN-IP-Prefix `10.7.0.1` ändert nichts an der Belegungsprüfung — ein bereits gebundener Port ist gebunden, egal an welche IP. + +## Phase 1: Pflichtregeln (nicht verhandelbar) + +Diese Regeln gelten für jeden generierten Stack: + +### Compose-Syntax + +- **Kein `version:`-Key.** Compose v2 ignoriert ihn — nicht aufnehmen. +- **`name: `** als oberstes Feld (Project-Name explizit setzen). +- **YAML-Mapping-Stil konsistent** pro Datei (entweder Listen-Stil `- KEY=VAL` oder Map-Stil `KEY: VAL` — nicht mischen innerhalb eines Services). + +### Pro Service + +- **`container_name: `** — explizit, stabile Namen für Logs/Scripts. +- **`hostname: `** — für interne Service-Adressierung in geteilten Netzwerken. +- **`restart: unless-stopped`** als Default. `always` nur wenn der Container nach einem manuellen `docker stop` von alleine wieder hochkommen soll. +- **`environment:`** + - `TZ=Europe/Berlin` ist Pflicht. + - Alle relevanten Env-Variablen explizit auflisten (keine impliziten Defaults aus dem Image — der Image-Default kann sich ändern). + - Sensible Werte (Passwörter, Tokens, Secrets, API-Keys) ausschließlich als `${VARIABLE}` referenzieren — Werte in `.env`. + - Keine Inline-Defaults vom Typ `${VAR:-default}` für Secrets. Für nicht-sensible Werte erlaubt, aber sparsam. +- **`logging:`** + ```yaml + logging: + driver: "json-file" + options: + max-size: "5M" + max-file: "3" + ``` + 5 MB pro Datei × 3 Dateien = max. 15 MB pro Container. +- **`labels:`** + ```yaml + labels: + - "com.centurylinklabs.watchtower.enable=false" + ``` + Default `false` (entspricht globaler CLAUDE.md). Auf `true` setzen, wenn der Container über `:latest` läuft und automatische Updates erwünscht sind. +- **`user: "1000:1000"`** als Default. Ausnahmen nur, wenn das Image Root erfordert (z.B. NPM Port 80/443) — dann mit Kommentar warum. +- **Volumes als relative Bind-Mounts** (`./data:/data`). Niemals absolute Pfade ausserhalb von `./`, niemals named volumes für Datenpersistenz (Backup-Strategie hängt am Bind-Mount). +- **Read-only mounten** wo möglich (`./config:/etc/app/config:ro`). + +### Ports + +- **Immer als gequoteter String:** `"8080:80"`. Unquoted YAML kann `5060:5060` als Sexagesimalzahl interpretieren. +- **Pro Zielhost:** + - `automation`, `controller`, `localhost`: kein IP-Prefix (LAN-intern erreichbar). + - `webserver` (waldperle): alle internen Ports an `10.7.0.1` binden — `"10.7.0.1:8080:80"`. Nur explizit öffentliche Ports (NPM 80/443) ohne IP-Prefix. +- **Belegung muss in Phase 1.5 geprüft sein** — kein Port ohne vorherige Konfliktprüfung. + +### Netzwerke + +- **Externe Standard-Netze:** + - `reverse-proxy` — für alle Container, die über NPM ans Web sollen + - `public` — für Container mit direktem Public-Exposure + - `openhab` — Smart-Home-Stack (nur `automation`) +- Externe Netze in der `networks:`-Sektion immer mit `external: true` markieren. +- Stack-interne Netze ohne `external` deklarieren (oder weglassen — Compose erzeugt dann `_default`). + +### Multi-Service-Stacks + +- **Healthchecks für DB/Cache:** + ```yaml + healthcheck: + test: ["CMD-SHELL", "pg_isready -U ${POSTGRES_USER}"] + interval: 10s + timeout: 5s + retries: 5 + ``` +- **`depends_on` mit `condition: service_healthy`** wo Healthchecks existieren — verhindert Race-Conditions beim Start. + +### Image-Versionen + +- **`:latest`** ist der Default (User-Wunsch: immer neueste Version). +- Bei `:latest` + Watchtower-Enable=`true` → automatische Updates. +- Bei kritischen Stacks (Datenbanken, Auth) kann ein gepinnter Tag sinnvoll sein — explizit beim User nachfragen. + +### Security-Hardening (für exposed Services empfohlen) + +```yaml +cap_drop: + - ALL +security_opt: + - no-new-privileges=true +``` + +Aufnehmen für: Web-UIs, REST-APIs, alles was Ports öffnet. Nicht für DBs/Caches im internen Netz (würde dort oft brechen). + +### `.env`-Datei + +- Liegt im selben Verzeichnis wie die `docker-compose.yaml`. +- Wird per `.gitignore` ausgeschlossen. +- Eine `.env.example` ohne Werte mitliefern — als Vorlage. +- Format: + ``` + # Pflicht + DB_USER= + DB_PASSWORD= + # ... + ``` + +## Phase 2: VPN-Binding für Webserver-Stacks + +Wenn der User in Phase 0 als Zielhost `webserver` (waldperle) gewählt hat: + +1. **Bind-Adresse abfragen** falls nicht bekannt: + + > "Welche VPN-Interface-IP soll gebunden werden? (Standard `waldperle`: `10.7.0.1`)" + +2. **Pro Service-Port entscheiden:** + - Public (im Internet erreichbar, typisch Reverse-Proxy 80/443): ohne IP-Prefix. + - Alle anderen Ports (Web-UIs, DBs, Admin-Interfaces, Metrics): an die VPN-IP binden. + +3. **Begründung im Kopf des Compose-Files als Kommentar dokumentieren:** + + ```yaml + # Webserver-Stack — interne Ports nur via VPN (10.7.0.1) erreichbar. + # Nur 80/443 (Reverse-Proxy) sind öffentlich exponiert. + ``` + +## Phase 3: Generierung + +### 3a: Verzeichnis-Layout + +``` +/ +├── docker-compose.yaml +├── .env (lokal, nicht in Git) +├── .env.example (Vorlage in Git) +├── .gitignore (mind. .env, dazu Daten-Verzeichnisse) +└── +``` + +### 3b: Datei erzeugen + +Generiere die `docker-compose.yaml` nach den Regeln aus Phase 1 + 2. Vor dem Schreiben prüfen, ob die Datei schon existiert — bei Update nur die nötigen Felder anfassen, vorhandene Kommentare/Strukturen erhalten. + +### 3c: Persistente Verzeichnisse anlegen + +Nur als Hinweis an den User — nicht selbst per `mkdir` ausführen. Beispiel: + +> "Vor dem ersten Start: `mkdir -p ./data ./db && chown -R 1000:1000 ./data ./db`" + +### 3d: `.env.example` erzeugen + +Liste alle in der Compose-Datei referenzierten `${VARIABLE}` mit leerem Wert. Sortierung: erst Pflicht, dann optional. Jede Variable mit Einzeiler-Kommentar, wozu sie dient. + +## Phase 4: Validierung + +```bash +# Auf dem Zielhost (automation/controller/webserver via SSH, oder lokal): +docker compose -f /docker-compose.yaml config +``` + +Erfolgreich heisst: keine Warnings, kein "version is obsolete", alle `${VAR}` auflösbar (mit gefüllter `.env`). + +Bei Fehlern: korrigieren, erneut validieren. + +## Phase 5: Test-Empfehlung + +```bash +# Trockenlauf +docker compose -f /docker-compose.yaml config + +# Start +cd && docker compose up -d + +# Logs prüfen +docker compose logs -f + +# Status +docker compose ps +``` + +Warte auf User-Rückmeldung, ob der Stack erfolgreich gestartet ist. + +## Phase 6: Abschluss via /ship + +Wenn die Compose-Datei in einem Git-Repo liegt: `/ship` aufrufen. + +Liegt sie nur lokal auf dem Host (z.B. direkt unter `/docker//` auf `automation`/`waldperle`, ohne Git): User erinnern, die Konfiguration manuell ins Backup aufzunehmen. + +## Pitfalls — explizite Verbote + +- Kein `version:`-Key (obsolet). +- Keine impliziten Image-Defaults für relevante Konfiguration. +- Keine ungequoteten Port-Mappings. +- Keine absoluten Pfade in Bind-Mounts. +- Keine Secrets im Klartext in der Compose-Datei. +- Keine named Volumes für persistente Daten. +- Auf `webserver` (waldperle): kein ungebundener interner Port — sonst public. +- Keine Port-Angabe ohne vorherige Belegungs-Analyse aus Phase 1.5. From 1c39f1fbb85da465798056e24460feb6802ec0ce Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Tr=C3=B6ger?= Date: Tue, 16 Jun 2026 07:54:07 +0200 Subject: [PATCH 03/11] chore: Default-Modell auf claude-opus-4-7 anheben Co-Authored-By: Claude Opus 4.7 --- dotfiles/settings.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dotfiles/settings.json b/dotfiles/settings.json index 7648abc..fcac943 100644 --- a/dotfiles/settings.json +++ b/dotfiles/settings.json @@ -62,7 +62,7 @@ ], "defaultMode": "default" }, - "model": "claude-opus-4-6", + "model": "claude-opus-4-7", "hooks": { "PreToolUse": [ { From c640c5a575bacf342519d6532dd84430ddd627b0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Tr=C3=B6ger?= Date: Tue, 16 Jun 2026 08:02:57 +0200 Subject: [PATCH 04/11] feat: Container-Recherche-Phase im /docker-compose Skill MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Vor der Generierung wird für jedes Image die aktuelle Doku via Context7, Docker Hub und GitHub-Releases konsultiert: Pflicht-Env-Vars der aktuellen Major-Version, Breaking Changes, deprecated Variablen, Default-Ports und Volume-Pfade. Ergebnis landet als Header-Kommentar in der Compose-Datei. Bei kritischen Stacks (DBs, Auth) wird die Major-Version gepinnt statt :latest, um unkontrollierte Major-Upgrades zu vermeiden. Co-Authored-By: Claude Opus 4.7 --- CLAUDE.md | 2 +- skills/docker-compose/SKILL.md | 67 ++++++++++++++++++++++++++++++++-- 2 files changed, 65 insertions(+), 4 deletions(-) diff --git a/CLAUDE.md b/CLAUDE.md index 4a31119..3d53adc 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -104,7 +104,7 @@ Kurzbefehl für den gesamten Ablauf: `/story` | `/workflow-review` | `skills/workflow-review/SKILL.md` | Opus reviewt alle Skills/Konfig → Umsetzungsplan für Sonnet | | `/implement` | `skills/implement/SKILL.md` | Implementierung direkt aus bestehendem Plan (überspringt Research/Planung) | | `/project-review` | `skills/project-review/SKILL.md` | Domänenunabhängiges Review für Nicht-Software-Dokumente (Bau, Hardware, Analysen) | -| `/docker-compose` | `skills/docker-compose/SKILL.md` | Erstellt/aktualisiert eine docker-compose.yaml nach Hausregeln (4 Zielhosts: automation/controller/webserver/localhost, Port-Belegungs-Check, 5 MB Logging, TZ Berlin, Bind-Mounts, .env-Secrets, VPN-Binding für Webserver) | +| `/docker-compose` | `skills/docker-compose/SKILL.md` | Erstellt/aktualisiert eine docker-compose.yaml nach Hausregeln (4 Zielhosts: automation/controller/webserver/localhost, Container-Doku-Recherche, Port-Belegungs-Check, 5 MB Logging, TZ Berlin, Bind-Mounts, .env-Secrets, VPN-Binding für Webserver) | ## Agenten diff --git a/skills/docker-compose/SKILL.md b/skills/docker-compose/SKILL.md index fe9a275..6e4249c 100644 --- a/skills/docker-compose/SKILL.md +++ b/skills/docker-compose/SKILL.md @@ -32,6 +32,67 @@ Bei `webserver` zusätzlich: Standardregel: **alle Ports an `10.7.0.1` binden**, nur explizit öffentliche (HTTP/HTTPS für reverse-proxy) bleiben ohne Bind-IP. +## Phase 0.5: Container-Recherche (Pflicht vor Generierung) + +Für **jedes** Image im Stack die aktuelle Dokumentation konsultieren, bevor die Compose-Datei geschrieben wird. Ziel: korrekte aktuelle Konfiguration, bekannte Breaking Changes berücksichtigen, deprecated Variablen vermeiden. + +### Quellen (in dieser Reihenfolge) + +1. **Context7** (bevorzugt für offizielle Images): + ``` + mcp__plugin_context7_context7__resolve-library-id → Library-ID finden + mcp__plugin_context7_context7__query-docs → gezielte Frage stellen + ``` +2. **Offizielle Docker-Hub-Seite** via `WebFetch`: + ``` + https://hub.docker.com/_/ # Official Images + https://hub.docker.com/r// # Community Images + ``` +3. **GitHub-Releases / CHANGELOG** via `WebFetch` — für Breaking Changes der aktuellen Major-Version. +4. **WebSearch** als Fallback, wenn die obigen Quellen leer bleiben. + +### Was muss konkret geprüft werden? + +Pro Image diese Punkte abklären: + +- **Aktuelle Major-Version** (`:latest` zeigt auf welche?) +- **Breaking Changes** seit der vorherigen Major-Version (z.B. PostgreSQL-Daten-Migration zwischen Major-Versionen, Keycloak `start-dev` vs `start --optimized`, MySQL→MariaDB-Replacements) +- **Pflicht-Env-Vars** der aktuellen Version (z.B. Auth-Defaults wurden in vielen Images entfernt — `POSTGRES_PASSWORD` ist Pflicht, kein Standard mehr) +- **Deprecated Env-Vars** — alte Namen vermeiden +- **Default-Ports** und ob sie sich geändert haben +- **Volume-Pfade** des Images — wo erwartet das Image persistente Daten? +- **Health-Check-Kommando** — was empfiehlt der Maintainer? +- **User/UID-Verhalten** — läuft das Image als Root, gibt es ein `PUID/PGID`-Pattern, oder `user:`-Override möglich? + +### Output dieser Phase + +Bevor weitergegangen wird, dem User eine **Zusammenfassung pro Image** zeigen: + +``` +postgres:latest → aktuell 17.x + Breaking: pg_dump-Format zwischen Major-Versionen inkompatibel — Major-Upgrade + erfordert pg_dumpall/restore (siehe Release-Notes) + Pflicht: POSTGRES_PASSWORD + Empfohlen: POSTGRES_DB, POSTGRES_USER, Healthcheck pg_isready + Volume: /var/lib/postgresql/data +``` + +Bei Major-Sprung gegenüber einem bestehenden Stack: User explizit warnen und Migrationsschritt vorschlagen, bevor `:latest` gepinnt bleibt. + +### Im Compose-Header dokumentieren + +Header-Kommentar in der `docker-compose.yaml`: + +```yaml +# Stack: +# Recherchiert: +# Images: +# postgres:latest → 17.x (Breaking: Major-Upgrade braucht pg_dumpall) +# :latest → x.y (Hinweise/Breaking) +``` + +So bleibt nachvollziehbar, gegen welchen Wissensstand der Stack designed wurde. + ## Phase 1.5: Port-Belegungs-Analyse (Pflicht vor Generierung) Bevor irgendein Port in die `docker-compose.yaml` geschrieben wird, **beide** Prüfungen auf dem Zielhost ausführen: @@ -139,9 +200,9 @@ Diese Regeln gelten für jeden generierten Stack: ### Image-Versionen -- **`:latest`** ist der Default (User-Wunsch: immer neueste Version). -- Bei `:latest` + Watchtower-Enable=`true` → automatische Updates. -- Bei kritischen Stacks (Datenbanken, Auth) kann ein gepinnter Tag sinnvoll sein — explizit beim User nachfragen. +- **`:latest`** ist der Default (User-Wunsch: immer neueste Version) — aber nur, wenn die in Phase 0.5 dokumentierte Major-Version mit der Stack-Konfiguration kompatibel ist. +- Bei `:latest` + Watchtower-Enable=`true` → automatische Updates. Bei Datenbanken nur, wenn das Image rolling-kompatibel ist (oft nicht — siehe PostgreSQL-Hinweis aus Phase 0.5). +- Bei kritischen Stacks (Datenbanken, Auth) Major-Version pinnen (z.B. `postgres:17`) und Major-Upgrades bewusst durchführen. ### Security-Hardening (für exposed Services empfohlen) From 2eb4277aaaaf7283c05ef37fa51bce50ea20ea72 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Tr=C3=B6ger?= Date: Tue, 16 Jun 2026 08:04:29 +0200 Subject: [PATCH 05/11] feat: INSTALL.md pro Stack im /docker-compose Skill MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Phase 3 erweitert um einen Pflichtschritt 3e: INSTALL.md wird neben der docker-compose.yaml im Stack-Verzeichnis erzeugt. Sie enthält Voraussetzungen, Verzeichnis-Setup, .env-Befüllung, Start, Erst-Konfiguration, Backup, Update inkl. Breaking-Change-Hinweisen aus Phase 0.5 sowie Troubleshooting. Bei Updates wird die existierende INSTALL.md ergänzt, nicht überschrieben. Co-Authored-By: Claude Opus 4.7 --- skills/docker-compose/SKILL.md | 91 ++++++++++++++++++++++++++++++++-- 1 file changed, 88 insertions(+), 3 deletions(-) diff --git a/skills/docker-compose/SKILL.md b/skills/docker-compose/SKILL.md index 6e4249c..55f04d9 100644 --- a/skills/docker-compose/SKILL.md +++ b/skills/docker-compose/SKILL.md @@ -254,6 +254,7 @@ Wenn der User in Phase 0 als Zielhost `webserver` (waldperle) gewählt hat: ``` / ├── docker-compose.yaml +├── INSTALL.md (Schritt-für-Schritt-Anleitung) ├── .env (lokal, nicht in Git) ├── .env.example (Vorlage in Git) ├── .gitignore (mind. .env, dazu Daten-Verzeichnisse) @@ -266,14 +267,98 @@ Generiere die `docker-compose.yaml` nach den Regeln aus Phase 1 + 2. Vor dem Sch ### 3c: Persistente Verzeichnisse anlegen -Nur als Hinweis an den User — nicht selbst per `mkdir` ausführen. Beispiel: - -> "Vor dem ersten Start: `mkdir -p ./data ./db && chown -R 1000:1000 ./data ./db`" +Nur als Hinweis an den User — nicht selbst per `mkdir` ausführen. Die konkreten Befehle landen in der `INSTALL.md` (3e). ### 3d: `.env.example` erzeugen Liste alle in der Compose-Datei referenzierten `${VARIABLE}` mit leerem Wert. Sortierung: erst Pflicht, dann optional. Jede Variable mit Einzeiler-Kommentar, wozu sie dient. +### 3e: `INSTALL.md` erzeugen (Pflicht) + +Schritt-für-Schritt-Anleitung im Stack-Verzeichnis. Alle Installationshinweise des Skills landen hier — nicht als Chat-Output, sondern als Datei. Vorlage: + +````markdown +# — Installation + +Recherchiert: +Zielhost: + +## 1. Voraussetzungen + +- Docker + Docker Compose v2 installiert +- Externe Netzwerke vorhanden (falls in Compose referenziert): + ```bash + docker network ls | grep -E 'reverse-proxy|public|' + # Falls fehlend: + docker network create reverse-proxy + ``` + +## 2. Verzeichnis vorbereiten + +```bash +cd /docker/ +mkdir -p ./data ./db # alle persistenten Bind-Mounts aus dem Compose-File +chown -R 1000:1000 ./data ./db +``` + +## 3. .env befüllen + +```bash +cp .env.example .env +chmod 600 .env +$EDITOR .env +``` + +Pflicht-Variablen: +- `` — +- `` — ... + +## 4. Stack starten + +```bash +docker compose config # Trockenlauf — keine Fehler erwartet +docker compose up -d +docker compose ps # alle Services healthy? +docker compose logs -f # auf Initial-Output prüfen +``` + +## 5. Erst-Konfiguration + +- Web-UI: `http://:` (bei webserver via VPN: `http://10.7.0.1:`) +- Initial-Login: +- Reverse-Proxy-Eintrag in NPM anlegen (falls reverse-proxy-Netz genutzt) + +## 6. Backup + +Persistente Verzeichnisse: `./data`, `./db`, `` +Backup-Strategie: + +## 7. Update + +```bash +docker compose pull +docker compose up -d +``` + +**Breaking Changes / Major-Upgrade-Hinweise:** + + +## 8. Troubleshooting + +- Logs: `docker compose logs ` +- Shell: `docker compose exec sh` +- Vollständiger Reset (Achtung — Daten weg!): `docker compose down -v && rm -rf ./data ./db` +```` + +Befülle die Platzhalter aus den Phasen 0, 0.5, 1.5 und 2: +- Stack-Name, Zielhost, Recherche-Datum: aus Phase 0/0.5 +- Pflicht-Variablen und ihre Bedeutung: aus der `.env.example` (3d) +- Breaking-Change-Hinweise: aus der Container-Recherche (Phase 0.5) +- Ports + Bind-IP-Beispiele: aus Phase 1.5 + 2 (bei webserver inkl. `10.7.0.1`) +- Persistente Verzeichnisse: aus den Bind-Mounts der Compose-Datei + +Bei Update eines bestehenden Stacks: existierende `INSTALL.md` lesen, gezielt ergänzen — nicht überschreiben. + ## Phase 4: Validierung ```bash From 58d6ed0b1c03e0b8845b7006973e4f50b79f18ba Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Tr=C3=B6ger?= Date: Tue, 16 Jun 2026 08:06:32 +0200 Subject: [PATCH 06/11] refactor: INSTALL.md nur mit stack-spezifischen Inhalten MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Die starre 8-Sektionen-Vorlage entfernt — sie enthielt viel Boilerplate (Docker-Basics, generische compose-Befehle), der jeder Leser ohnehin kennt. Neuer Ansatz: INSTALL.md listet nur das, was der Leser aus allgemeiner Docker-Kenntnis nicht ableiten kann — konkrete Netze, Pfade, UIDs, Pflicht-Env-Vars, Initial-Zugang, Reverse-Proxy-Setup, Major-Upgrade-Schritte, stack-spezifisches Troubleshooting. Co-Authored-By: Claude Opus 4.7 --- skills/docker-compose/SKILL.md | 99 ++++++++-------------------------- 1 file changed, 23 insertions(+), 76 deletions(-) diff --git a/skills/docker-compose/SKILL.md b/skills/docker-compose/SKILL.md index 55f04d9..ac58afd 100644 --- a/skills/docker-compose/SKILL.md +++ b/skills/docker-compose/SKILL.md @@ -275,89 +275,36 @@ Liste alle in der Compose-Datei referenzierten `${VARIABLE}` mit leerem Wert. So ### 3e: `INSTALL.md` erzeugen (Pflicht) -Schritt-für-Schritt-Anleitung im Stack-Verzeichnis. Alle Installationshinweise des Skills landen hier — nicht als Chat-Output, sondern als Datei. Vorlage: +Die `INSTALL.md` enthält **nur stack-spezifische Inhalte** — alles, was der Leser nicht aus der allgemeinen Docker-Compose-Kenntnis weiss. Allgemeines (was Docker ist, dass `docker compose up -d` startet, dass `.env` aus `.env.example` kopiert wird) **nicht aufnehmen**. -````markdown -# — Installation +#### Was rein muss (sofern für den Stack zutreffend) -Recherchiert: -Zielhost: +- **Header:** Stack-Name, Zielhost, Recherche-Datum (aus Phase 0/0.5) +- **Externe Netzwerke** dieses Stacks: konkrete Namen, die existieren müssen (`reverse-proxy`, `public`, `openhab`, …) +- **Persistente Verzeichnisse** dieses Stacks: exakte Pfade, erforderliche UID/GID, Sonderfälle (z.B. PostgreSQL braucht UID des Postgres-Users) +- **Pflicht-Env-Vars** dieses Stacks: was der Wert bedeutet, Format-Constraints, Generierungs-Hinweis (z.B. "32-Byte-Hex", "openssl rand -hex 32") +- **Initial-Zugang**: Default-Admin-Login, Setup-Wizard-URL, erstes Token aus den Logs ziehen — was dieses Image konkret macht +- **Reverse-Proxy-Einstellungen** für DIESEN Service: Ziel-Container + Port, Pfad-Besonderheiten, WebSocket-Pflicht, Trust-Proxy-Hops, spezielle Header +- **Ports und Erreichbarkeit** dieses Stacks: konkrete URLs, bei `webserver` mit `10.7.0.1` und Public-Variante +- **Backup-relevante Pfade** und stack-spezifische Pre-Backup-Schritte (z.B. `pg_dumpall` vor dem Volume-Backup) +- **Update-Besonderheiten** dieses Images (aus Phase 0.5): Major-Migrations-Skripte, deprecated Env-Vars die ersetzt werden müssen, Reihenfolge bei Multi-Service-Updates +- **Stack-spezifische Healthcheck-/Troubleshooting-Hinweise**: bekannte Fehler des Images, übliche Logmeldungen die Warnung sind aber keine Probleme, container-spezifische Reset-Schritte -## 1. Voraussetzungen +#### Was raus bleibt -- Docker + Docker Compose v2 installiert -- Externe Netzwerke vorhanden (falls in Compose referenziert): - ```bash - docker network ls | grep -E 'reverse-proxy|public|' - # Falls fehlend: - docker network create reverse-proxy - ``` +- Wie man Docker installiert +- Generische `docker compose`-Befehle ohne stack-spezifischen Kontext +- "cp .env.example .env" und ähnliche Standardschritte +- Allgemeine Compose-Theorie -## 2. Verzeichnis vorbereiten +#### Quellen für den Inhalt -```bash -cd /docker/ -mkdir -p ./data ./db # alle persistenten Bind-Mounts aus dem Compose-File -chown -R 1000:1000 ./data ./db -``` +- Phase 0.5 (Container-Recherche) — Breaking Changes, Pflicht-Env-Vars, Volume-Pfade +- Phase 1.5 / 2 — Ports, VPN-Binding +- Compose-Datei selbst — Bind-Mounts, Netzwerke, depends_on-Reihenfolge +- Bei Lücken: erneut Doku des Images via Context7/WebFetch konsultieren, nicht raten -## 3. .env befüllen - -```bash -cp .env.example .env -chmod 600 .env -$EDITOR .env -``` - -Pflicht-Variablen: -- `` — -- `` — ... - -## 4. Stack starten - -```bash -docker compose config # Trockenlauf — keine Fehler erwartet -docker compose up -d -docker compose ps # alle Services healthy? -docker compose logs -f # auf Initial-Output prüfen -``` - -## 5. Erst-Konfiguration - -- Web-UI: `http://:` (bei webserver via VPN: `http://10.7.0.1:`) -- Initial-Login: -- Reverse-Proxy-Eintrag in NPM anlegen (falls reverse-proxy-Netz genutzt) - -## 6. Backup - -Persistente Verzeichnisse: `./data`, `./db`, `` -Backup-Strategie: - -## 7. Update - -```bash -docker compose pull -docker compose up -d -``` - -**Breaking Changes / Major-Upgrade-Hinweise:** - - -## 8. Troubleshooting - -- Logs: `docker compose logs ` -- Shell: `docker compose exec sh` -- Vollständiger Reset (Achtung — Daten weg!): `docker compose down -v && rm -rf ./data ./db` -```` - -Befülle die Platzhalter aus den Phasen 0, 0.5, 1.5 und 2: -- Stack-Name, Zielhost, Recherche-Datum: aus Phase 0/0.5 -- Pflicht-Variablen und ihre Bedeutung: aus der `.env.example` (3d) -- Breaking-Change-Hinweise: aus der Container-Recherche (Phase 0.5) -- Ports + Bind-IP-Beispiele: aus Phase 1.5 + 2 (bei webserver inkl. `10.7.0.1`) -- Persistente Verzeichnisse: aus den Bind-Mounts der Compose-Datei - -Bei Update eines bestehenden Stacks: existierende `INSTALL.md` lesen, gezielt ergänzen — nicht überschreiben. +Bei Update eines bestehenden Stacks: existierende `INSTALL.md` lesen, gezielt ergänzen — nicht überschreiben, keine Sektionen ohne neuen Inhalt einfügen. ## Phase 4: Validierung From dbd833ae5bcbdb7ab02572d51a93ee3c8b096bfe Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Tr=C3=B6ger?= Date: Thu, 18 Jun 2026 21:09:31 +0200 Subject: [PATCH 07/11] Add explanation rules --- dotfiles/CLAUDE.md | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/dotfiles/CLAUDE.md b/dotfiles/CLAUDE.md index 46a7a68..d9204bf 100644 --- a/dotfiles/CLAUDE.md +++ b/dotfiles/CLAUDE.md @@ -92,6 +92,16 @@ Bei User-Korrekturen oder neuen Erkenntnissen zuerst klassifizieren, dann am ric **Niemals Arbeitsregeln im Memory-System ablegen.** Memory ist für Kontext, nicht für Regeln. Wenn eine User-Korrektur eine wiederkehrende Arbeitsregel beschreibt → CLAUDE.md. Immer. +## Erläuterungs-Stil + +Wenn der User um eine Erklärung auf **architektonischer, logischer, konzeptioneller, abstrakter oder prinzipieller Ebene** bittet (oder Varianten wie "vom Konzept her", "rein architektonisch"): + +- Den **Mechanismus der zugrundeliegenden Technik in Fachsprache** erklären (Framework-Konzepte, Lifecycle, Semantik) — keine Alltagsmetaphern (Bibliothekar, Postbote, Restaurant). +- Das **Prinzip generisch** darlegen, **nicht am konkreten Code festmachen**. Am Ende kurz auf die Anwendung im Projekt zurückbeziehen. +- Technische Begriffe (z.B. "detached entity", "managed", "flush", "snapshot", "dirty check") frei verwenden, kurz einführen falls neu im Kontext, aber nicht durch Umschreibungen ersetzen. + +Im Zweifel lieber technischer als metaphorischer. Der User hat solides Fachwissen über die Domäne (z.B. relationale Datenbanken, HTTP, Linux) und möchte framework-/tool-spezifische Konzepte tatsächlich verstehen, nicht durch Metaphern davor abgeschirmt werden. + ## MCP Bei Frameworks/Bibliotheken immer Context-7-Dokumentation abrufen (resolve-library-id / query-docs). From bb91f1ed9fe17638afeddcf9e079ee4d9978bb60 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Tr=C3=B6ger?= Date: Fri, 19 Jun 2026 08:22:03 +0200 Subject: [PATCH 08/11] =?UTF-8?q?fix:=20Statusline=20gegen=20Format-String?= =?UTF-8?q?-Bug=20und=20Zeilenumbruch=20h=C3=A4rten?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Variablen wurden bisher in den printf-Format-String interpoliert. Pfade mit % konnten dadurch als Format-Direktive interpretiert werden und den TUI-Renderer von claude-code aus dem Tritt bringen. Zusätzlich werden Pfade über 25 Zeichen gekürzt, damit die Statusline auf schmalen Terminals nicht umbricht — die zusätzliche Zeile war der wahrscheinliche Auslöser des Render-Drifts ("Ausgabe scrollt nach oben aus dem sichtbaren Bereich"). Co-Authored-By: Claude Opus 4.7 --- dotfiles/statusline-command.sh | 26 ++++++++++++++++---------- 1 file changed, 16 insertions(+), 10 deletions(-) diff --git a/dotfiles/statusline-command.sh b/dotfiles/statusline-command.sh index 74112b1..8c81de5 100644 --- a/dotfiles/statusline-command.sh +++ b/dotfiles/statusline-command.sh @@ -18,19 +18,26 @@ IFS=$'\t' read -r current_dir model total_input total_output context_size used_p total_tokens=$(( (total_input + total_output) / 1000 )) context_limit_k=$(( context_size / 1000 )) -cost_formatted=$(LC_NUMERIC=C awk "BEGIN { - cents = int($cost_usd * 100 + 0.5) - if (cents < 100) printf \"%d¢\", cents - else printf \"\$%.2f\", $cost_usd -}") +cost_formatted=$(LC_NUMERIC=C awk -v cost="$cost_usd" 'BEGIN { + cents = int(cost * 100 + 0.5) + if (cents < 100) printf "%d¢", cents + else printf "$%.2f", cost +}') user=$(whoami) host=$(hostname -s) +# Lange Pfade kürzen, damit die Statusline nie umbricht (sonst gerät der +# claude-code-Renderer aus dem Tritt, weil er 1 Zeile am unteren Rand erwartet). +display_dir=$current_dir +if [ ${#display_dir} -gt 25 ]; then + display_dir=".../$(basename "$(dirname "$current_dir")")/$(basename "$current_dir")" +fi + git_branch="" if [ -n "$current_dir" ] && git -C "$current_dir" rev-parse --git-dir > /dev/null 2>&1; then branch=$(git -C "$current_dir" branch --show-current 2>/dev/null) - [ -n "$branch" ] && git_branch=" \033[33m($branch)\033[00m" + [ -n "$branch" ] && printf -v git_branch ' \033[33m(%s)\033[00m' "$branch" fi chroot_prefix="" @@ -38,7 +45,6 @@ if [ -r /etc/debian_chroot ]; then chroot_prefix="($(cat /etc/debian_chroot))" fi -printf "${chroot_prefix}\033[32m${user}@${host}\033[00m:\033[34m${current_dir}\033[00m${git_branch}" -printf " \033[90m|\033[00m \033[36m${model}\033[00m" -printf " \033[90m|\033[00m \033[35m${total_tokens}K/${context_limit_k}K (${used_percent}%%)\033[00m" -printf " \033[90m|\033[00m \033[33m${cost_formatted}\033[00m" +printf '%s\033[32m%s@%s\033[00m:\033[34m%s\033[00m%s \033[90m|\033[00m \033[36m%s\033[00m \033[90m|\033[00m \033[35m%dK/%dK (%d%%)\033[00m \033[90m|\033[00m \033[33m%s\033[00m' \ + "$chroot_prefix" "$user" "$host" "$display_dir" "$git_branch" \ + "$model" "$total_tokens" "$context_limit_k" "$used_percent" "$cost_formatted" From 9926c50d2a609a251dd6c348dfe33515fc9e0320 Mon Sep 17 00:00:00 2001 From: Martin Troeger Date: Sat, 4 Jul 2026 11:42:12 +0200 Subject: [PATCH 09/11] CLAUDE.md angepasst --- dotfiles/CLAUDE.md | 9 +++++++++ dotfiles/settings.json | 5 +++-- 2 files changed, 12 insertions(+), 2 deletions(-) diff --git a/dotfiles/CLAUDE.md b/dotfiles/CLAUDE.md index d9204bf..e82888f 100644 --- a/dotfiles/CLAUDE.md +++ b/dotfiles/CLAUDE.md @@ -102,6 +102,15 @@ Wenn der User um eine Erklärung auf **architektonischer, logischer, konzeptione Im Zweifel lieber technischer als metaphorischer. Der User hat solides Fachwissen über die Domäne (z.B. relationale Datenbanken, HTTP, Linux) und möchte framework-/tool-spezifische Konzepte tatsächlich verstehen, nicht durch Metaphern davor abgeschirmt werden. +## Antwort-Stil (Prägnanz) + +Der User ist Informatiker/Techniker und will präzise Kommunikation mit den wesentlichen Fakten — nichts Ungefragtes. + +- **Antwort zuerst, keine Herleitung.** Ergebnis in 1–3 Sätzen; den Weg dahin nur auf Nachfrage. +- **Nur das Gefragte.** Keine ungefragten Optionen, Empfehlungen, Mockups, „wo es hakt"-Exkurse. Höchstens *eine* knappe Schlusszeile als Angebot. +- **Umfang an die konkrete Frage koppeln.** „Kann man X?" → ja/nein + Grund. Ein Artefakt (Diagramm, Tabelle, Umbau) nur liefern, wenn es explizit verlangt wurde — dann aber vollständig und **nicht** um ungefragte Zusätze erweitert. +- **Belege statt Ausbreitung.** `datei:zeile` statt den Code nachzuerzählen. + ## MCP Bei Frameworks/Bibliotheken immer Context-7-Dokumentation abrufen (resolve-library-id / query-docs). diff --git a/dotfiles/settings.json b/dotfiles/settings.json index fcac943..804035c 100644 --- a/dotfiles/settings.json +++ b/dotfiles/settings.json @@ -62,7 +62,7 @@ ], "defaultMode": "default" }, - "model": "claude-opus-4-7", + "model": "opus", "hooks": { "PreToolUse": [ { @@ -112,5 +112,6 @@ }, "language": "German", "editorMode": "vim", - "terminalProgressBarEnabled": false + "terminalProgressBarEnabled": false, + "tui": "fullscreen" } From 77eeb2aac719d6e116ac1c49cbce922c33b2aa7c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Tr=C3=B6ger?= Date: Sat, 4 Jul 2026 11:51:52 +0200 Subject: [PATCH 10/11] docs: Regel zu fehlenden Tools als striktes Stopp-Signal schaerfen --- dotfiles/CLAUDE.md | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/dotfiles/CLAUDE.md b/dotfiles/CLAUDE.md index e82888f..7fd6c07 100644 --- a/dotfiles/CLAUDE.md +++ b/dotfiles/CLAUDE.md @@ -64,7 +64,16 @@ Niemals direkt auf `main` committen. Alle Aenderungen ueber Feature-Branches und ## Fehlende Tools -Wenn ein benötigtes CLI-Tool fehlt: **nicht** mit Workarounds (curl, rohe API-Calls) umgehen. Stattdessen: +**Sobald die saubere Lösung ein Standard-CLI-Tool braucht, das fehlt: STOPP.** +Zuerst die Installation vorschlagen und auf den User warten — **bevor** irgendeine +Alternative gebaut wird. Eine fehlende Abhängigkeit ist ein Stopp-Signal, keine +Designfrage. Der User installiert lieber ein Tool, als dass komplizierte +Eigenlösungen entstehen. + +Kein Ausweichen auf curl/rohe API-Calls, nachgebaute Login-Flows, HTML-/Token- +Parsing oder mehrstufige Eigenkonstruktionen — auch nicht „nur kurz zum Testen". +Solche Konstrukte gar nicht erst anfangen; das fehlende Tool ist immer der erste +Lösungsweg. 1. User informieren welches Tool fehlt und den Installations-Befehl nennen 2. User führt den Befehl in einer separaten Konsole aus (sudo funktioniert dort) From 39ddcc86ab80ee6a4148242065b40bf15457ce80 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Tr=C3=B6ger?= Date: Sun, 5 Jul 2026 10:35:30 +0200 Subject: [PATCH 11/11] docs: AsciiDoc als Standard-Dokumentenformat festlegen Alle Dokumente kuenftig als .adoc statt Markdown. Von Tools erzwungene Dateien (CLAUDE.md, MEMORY.md, README.md) bleiben Markdown. Co-Authored-By: Claude Opus 4.8 --- dotfiles/CLAUDE.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/dotfiles/CLAUDE.md b/dotfiles/CLAUDE.md index 7fd6c07..ff258cb 100644 --- a/dotfiles/CLAUDE.md +++ b/dotfiles/CLAUDE.md @@ -4,6 +4,10 @@ Alle Texte, Kommentare und Kommunikation auf Deutsch. Technische Begriffe und Code-Bezeichner bleiben im Original. +## Dokumentenformat + +**Immer AsciiDoc (`.adoc`) statt Markdown** für alle Dokumente (Analysen, Pläne, Berichte, Anfragen usw.). Neue Dokumente als `.adoc` anlegen. Bestehende `.md`-Dateien nur auf ausdrücklichen Wunsch konvertieren. Ausnahmen: von Tools erzwungene Dateien (`CLAUDE.md`, `MEMORY.md`, `README.md` wo vom Workflow verlangt) bleiben Markdown. + ## Entwicklungsprinzipien - **Single Responsibility:** Jede Datei, jede Funktion hat genau eine Aufgabe