Regelwerk, Agenten, Skills und Werkzeuge veröffentlichen

Erster Stand des öffentlichen Ausschnitts aus dem Vault. Die .gitignore
arbeitet als Positivliste: ausgeschlossen ist alles, eingeschlossen nur,
was ausdrücklich wieder aufgenommen wird. Notizen, Projekte, Finanzen,
das Sitzungsgedächtnis und settings.local.json bleiben damit außen vor.

Der Kundenname in AI/Regelwerk/seo.md ist durch eine neutrale
Bezeichnung ersetzt; die Regeln selbst sind unverändert.

Co-Authored-By: Claude Opus 5 <[email protected]>
This commit is contained in:
Pascal MichelandClaude Opus 5 committed 2026-09-17 22:38:15 +02:00
commit 2c9a4475fc
97 files changed
+14627

No files matched your search

@@ -0,0 +1,110 @@
# Frontmatter-Schema
Obsidian nennt Frontmatter „Properties". Es ist YAML zwischen zwei `---`-Zeilen
am Dateianfang. Der Index liest genau diese Felder — was hier fehlt, muss der
Agent sich durch Öffnen der Datei erarbeiten, und genau das kostet Kontext.
## Pflichtfelder (alle Notiztypen)
| Feld | Typ | Bedeutung |
|---|---|---|
| `uid` | String | Stabile ID, Format `YYYYMMDD-slug`. Überlebt Umbenennen und Verschieben; Verweise in Skripten hängen daran. |
| `type` | Enum | Steuert Gruppierung, Templates und Abfragen. Gewinnt gegen die Ableitung aus dem Ordner. |
| `title` | String | Anzeigename. Fehlt er, nimmt der Index die erste `#`-Überschrift, sonst den Dateinamen. |
| `status` | Enum | Lebenszyklus, siehe unten. |
| `summary` | String | **Ein Satz, max. 160 Zeichen.** Worum geht es und wofür macht man die Notiz auf. |
| `tags` | Liste | Kleingeschrieben, ohne `#`, Technologie/Thema. 3–6 Stück, nicht 20. |
| `created` | Datum | `YYYY-MM-DD` |
| `updated` | Datum | `YYYY-MM-DD`, bei inhaltlichen Änderungen mitziehen. |
### Erlaubte `type`-Werte
`project-code`, `template-project`, `note-template`, `research`, `area`,
`resource`, `moc`, `decision`, `inbox`, `archive`
Neue Typen nur bewusst einführen und dann in `scripts/vaultlib.py` unter
`KNOWN_TYPES` eintragen, sonst meldet der Doctor sie als unbekannt.
### Erlaubte `status`-Werte
| Wert | Bedeutung |
|---|---|
| `idea` | notiert, noch nicht begonnen |
| `active` | wird gerade bearbeitet |
| `paused` | bewusst liegengelassen, kommt zurück |
| `done` | abgeschlossen, noch am Platz |
| `archived` | abgeschlossen und nach `90_Archive/` verschoben |
| `reference` | Dauerhaftes ohne Fortschritt (Areas, Ressourcen, Templates) |
## Zusätzliche Felder je Typ
### `project-code`
| Feld | Beispiel | Zweck |
|---|---|---|
| `repo` | `[email protected]:me/auth-service.git` | Sprung ins Repo ohne Suche |
| `lang` | `go` | Hauptsprache |
| `stack` | `[postgres, keycloak, docker]` | Umgebung auf einen Blick |
| `template_of` | `go-service-starter` | aus welchem Template-Projekt entstanden |
| `area` | `infrastruktur` | zugehöriger Dauerbereich |
### `research`
| Feld | Beispiel | Zweck |
|---|---|---|
| `question` | `Welche Rate-Limiting-Strategie passt zu Gateway X?` | die eine Frage |
| `sources` | `[https://…, "Buch, S. 40"]` | Belege |
| `confidence` | `low` / `medium` / `high` | wie belastbar die Antwort ist |
| `project` | `auth-service` | auslösendes Projekt |
### `template-project`
| Feld | Beispiel | Zweck |
|---|---|---|
| `use_when` | `Neuer Go-Service mit HTTP-API und Postgres` | Auswahl ohne Öffnen |
| `stack` | `[go, postgres, docker]` | |
| `template_of` | — | bleibt leer; wird in den abgeleiteten Projekten gesetzt |
### `decision` (ADR)
| Feld | Beispiel |
|---|---|
| `project` | `auth-service` |
| `decided` | `2026-08-03` |
| `supersedes` | `20260101-mongo-als-store` |
### `area`, `resource`, `moc`, `note-template`
Nur die Pflichtfelder. Bei `moc` ist `summary` besonders wichtig, weil MOCs
Einstiegspunkte sind.
## Beispiel
```yaml
---
uid: 20260803-auth-service
type: project-code
title: Auth Service
status: active
summary: OIDC-Auth-Service für die interne Toolchain, Go + Keycloak, löst die verteilten Basic-Auth-Setups ab.
tags: [go, oidc, keycloak, infrastruktur]
repo: [email protected]:me/auth-service.git
lang: go
stack: [postgres, keycloak, docker]
template_of: go-service-starter
area: infrastruktur
created: 2026-08-03
updated: 2026-08-03
---
```
## Was nicht ins Frontmatter gehört
- Fließtext oder mehrzeilige Beschreibungen — dafür ist der Body da.
- Werte, die sich täglich ändern (Fortschritt in Prozent, laufende Zahlen).
- Secrets, Tokens, Passwörter, Zugangsdaten. Nie, auch nicht „nur kurz".
- Duplikate von Wikilinks — Links stehen im Body unter `## Referenzen`.
## Massenpflege
`vault_doctor.py --fix-missing` ergänzt fehlende Felder konservativ: `type` aus
dem Ordner, `title` aus der ersten Überschrift, `summary` aus dem ersten Absatz,
`uid` aus Datum + Slug. Es überschreibt nie vorhandene Werte und rührt den Body
nicht an. Standard ist ein Trockenlauf; erst `--apply` schreibt. Danach die
generierten `summary`-Werte durchsehen — automatisch abgeleitete Sätze sind
brauchbar, aber selten so gut wie ein bewusst geschriebener.
@@ -0,0 +1,128 @@
# Die Referenzschicht
## Warum überhaupt ein Index
Ein Agent, der eine Frage an einen Vault mit 500 Notizen stellt, hat drei
Möglichkeiten: alles lesen (sprengt den Kontext), grep (findet Wortformen, aber
nicht Bedeutung, und liefert Treffer ohne Einordnung), oder eine
Zwischenschicht, die pro Notiz genau so viel weiß, dass sich entscheiden lässt,
ob man sie aufmacht. Die dritte Variante ist der Index.
Größenordnung: 500 Notizen à 800 Wörter sind rund 500.000 Token. Der Index
derselben 500 Notizen liegt bei etwa 25.000 Token — und eine typische Abfrage
gibt davon 10–40 Zeilen aus, also ein paar hundert Token. Deshalb: nie den Index
komplett lesen, immer `vault_query.py` fragen.
## Erzeugte Dateien
### `_index/vault-index.json`
Kompaktes JSON ohne Einrückung, Kurzschlüssel zur Platzersparnis:
| Schlüssel | Bedeutung |
|---|---|
| `p` | Pfad relativ zum Vault |
| `u` | uid |
| `t` | type |
| `s` | status |
| `n` | Titel |
| `m` | summary |
| `g` | tags |
| `r` | Projekt-Slug |
| `c` / `d` | created / updated |
| `h` | Überschriften (max. 12) |
| `l` | ausgehende Links |
| `w` | Wortzahl (bei Assets: Dateigröße) |
Leere Felder fehlen ganz. Der `meta`-Block enthält Zählungen, Typverteilung,
Statusverteilung, Top-Tags und die Zahl toter Links.
Das Feld `h` ist der zweite Hebel nach `m`: Bei einer langen Notiz zeigen die
Überschriften, welcher Abschnitt gebraucht wird — statt 3.000 Wörter zu lesen,
liest man 300.
### `_index/INDEX.md`
Menschenlesbare Übersicht, nach Typ gruppiert, jede Zeile ein Wikilink plus
Zusammenfassung. In Obsidian direkt navigierbar. Bei über 200 Notizen enthält
die Datei selbst den Hinweis, sie nicht komplett zu lesen.
### `_index/backlinks.json`
`{ "pfad/zur/notiz.md": ["pfad/quelle1.md", …] }`. Basis für `--links-to` und
die Waisen-Erkennung.
## Wann neu bauen
- nach dem Anlegen, Verschieben, Umbenennen oder Löschen von Notizen
- nach Frontmatter-Änderungen
- vor einer Arbeitssitzung, wenn zwischendurch in Obsidian gearbeitet wurde
`vault_query.py` vergleicht die Änderungszeiten und warnt auf stderr, wenn
Notizen neuer sind als der Index. Der Lauf über einige tausend Dateien dauert
Sekunden, also im Zweifel neu bauen.
Automatisieren geht per Git-Hook (`.git/hooks/pre-commit`) oder Cron:
```bash
python3 .claude/skills/obsidian-vault-navigator/scripts/build_index.py --vault . --quiet
```
## Abfrage-Rezepte
```bash
Q=".claude/skills/obsidian-vault-navigator/scripts/vault_query.py"
# Womit habe ich mich zu Thema X beschäftigt?
python3 $Q --text x
# Laufende Code-Projekte, als fertige Wikilink-Liste für eine Antwort
python3 $Q --type project-code --status active --format md
# Alles zu einem Projekt, inklusive Unternotizen und Anhängen
python3 $Q --project auth-service
# Passendes Template-Projekt finden, ohne eines zu öffnen
python3 $Q --type template-project
# Was hat sich diese Woche getan?
python3 $Q --since 7 --sort updated
# Kandidaten fürs Archiv
python3 $Q --status active --stale 180
# Wer verweist auf diese Notiz?
python3 $Q --links-to 30_Research/rate-limiting.md
# Pflegeliste: Notizen ohne summary
python3 $Q --no-summary --limit 100 --format paths
# Struktur einer langen Notiz sehen, bevor man sie liest
python3 $Q --text "kubernetes netzwerk" --format headings
```
Mehrere `--text` werden UND-verknüpft, mehrere `--type`/`--tag`/`--status`
ODER-verknüpft (bei `--tag` müssen alle angegebenen Tags vorhanden sein).
## Wenn der Index nichts findet
1. Filter lockern — oft ist `--type` zu eng gesetzt.
2. Anderes Wort probieren; der Index kennt nur Titel, Summary, Tags,
Überschriften und Pfad, keinen Fließtext.
3. Erst dann Volltext: `grep -ril "begriff" --include="*.md" .`
4. Findet grep etwas, das der Index nicht hatte, ist das ein Befund: Der Notiz
fehlt ein Tag oder eine bessere `summary`. Gleich nachziehen — der Index wird
dadurch mit jedem Miss besser.
## Grenzen
Der Index ist Metadaten, keine Semantik. Er findet nichts, was nirgends benannt
ist, und er versteht keine Synonyme. Für semantische Suche im großen Vault gibt
es lokale Werkzeuge (z. B. Obsidians eigene Suche mit Operatoren oder externe
Embedding-Indizes) — die ersetzen diese Schicht nicht, sondern ergänzen sie: Der
Index bleibt die billige erste Stufe.
## Verhältnis zu Obsidian Bases
Obsidian Bases (`.base`-Dateien) erzeugen Tabellen- und Kartenansichten aus
Properties — dieselben Felder, die auch der Index nutzt. Wer im Obsidian-UI
dieselben Übersichten will, legt Bases an; für den Agenten bleibt der
JSON-Index der billigere Weg. Für die korrekte `.base`-Syntax den offiziellen
Skill `obsidian-bases` verwenden.
@@ -0,0 +1,96 @@
# Vault-Struktur
## Ordner im Detail
### `00_Inbox/`
Alles, was schnell reinmuss: Fundstücke, Ideen, Gesprächsnotizen. Frontmatter
darf hier minimal sein (`type: inbox`, `title`, `created`). Der Ordner ist ein
Durchlauferhitzer, kein Lager — was länger als zwei Wochen liegt, meldet
`vault_doctor.py`.
### `10_Projects/<slug>/`
Ein Vorhaben mit Ziel und absehbarem Ende. Jedes Projekt ist ein **Ordner**,
kein einzelnes File, weil Projekte fast immer mehrere Notizen und Anhänge
sammeln:
```
10_Projects/auth-service/
├── index.md Projektnotiz — der Einstieg, type: project-code
├── decisions/ ADRs, type: decision
├── notes/ Arbeitsnotizen, Meetings, Logs
└── assets/ Diagramme, Exporte, PDFs
```
`index.md` ist Pflicht und trägt die Projekt-Zusammenfassung. Alle Unternotizen
tragen `project: <slug>` im Frontmatter — daran hängt `vault_query.py --project`.
Slug-Regel: kleingeschrieben, Bindestriche, keine Umlaute, so kurz wie
eindeutig (`auth-service`, nicht `Auth Service (neu, 2026)`).
### `20_Areas/`
Verantwortungsbereiche ohne Enddatum: Infrastruktur, Security, Homelab,
Weiterbildung, Kunde XY. Eine Area-Notiz ist gleichzeitig Landkarte für ihren
Bereich. Projekte verlinken auf ihre Area, nicht umgekehrt hart verdrahtet —
die Projektliste einer Area entsteht per Abfrage.
### `30_Research/`
Recherche, die über ein einzelnes Projekt hinaus Bestand hat. Eine Notiz = eine
Frage. Ist die Recherche nur für ein Projekt relevant und danach erledigt,
gehört sie in `10_Projects/<slug>/notes/`. Faustregel: Würde man das in einem
Jahr auch ohne dieses Projekt nochmal aufmachen? Dann `30_Research/`.
### `40_Templates/`
- `note-templates/` — Vorlagen für einzelne Notizen. Auch in Obsidian selbst
als Template-Ordner einstellbar (Einstellungen → Templates).
- `project-templates/` — **Template-Projekte**: vollständige Boilerplates, aus
denen neue Projekte entstehen (Starter-Repo-Struktur, Standard-Setups,
wiederkehrende Auftragsformate). Jedes Template-Projekt hat `index.md` mit
`use_when` im Frontmatter, damit die Auswahl später ohne Öffnen funktioniert.
Templates werden vom Doctor nicht als verwaist gemeldet und tauchen im Index
als eigene Gruppe auf.
### `50_Resources/`
Wissen ohne Projektbezug: Snippets, Runbooks, Cheatsheets, Konfigurations-
Notizen, Tool-Vergleiche. Der Unterschied zu `30_Research/`: Ressourcen sind
Nachschlagewerk, Research beantwortet eine Frage.
### `90_Archive/`
Abgeschlossenes bleibt lesbar und indexiert, ist aber aus dem Blick. Beim
Archivieren `status: archived` setzen und den kompletten Projektordner
verschieben, damit relative Verweise erhalten bleiben.
### `_index/`
Generiert von `build_index.py`. Enthält `vault-index.json` (Maschine),
`INDEX.md` (Mensch), `backlinks.json`. Nie von Hand editieren. Wer den Ordner
in Obsidian nicht sehen will: Einstellungen → Dateien und Links → „Ausgeschlossene
Dateien" auf `_index` setzen (er bleibt auf der Platte und für die Skripte
nutzbar).
## Wohin gehört diese Notiz?
1. Gehört sie zu einem konkreten Vorhaben mit Ende? → `10_Projects/<slug>/`
2. Beantwortet sie eine Frage, die auch ohne das Vorhaben interessant bleibt?
→ `30_Research/`
3. Ist es eine Vorlage oder ein Boilerplate? → `40_Templates/…`
4. Ist es Nachschlagewissen ohne Frage und ohne Vorhaben? → `50_Resources/`
5. Ist es ein Dauerbereich, unter dem mehrere Projekte hängen? → `20_Areas/`
6. Weiß man es nicht? → `00_Inbox/` und beim nächsten Aufräumen entscheiden.
Das ist kein Versagen, sondern der vorgesehene Weg.
## Dateinamen
- Dateiname = sprechender Titel, keine Datumspräfixe (Datum steht im
Frontmatter und ist dort auch sortierbar).
- Ausnahme: Daily-/Log-Notizen, dort `YYYY-MM-DD.md`.
- Projekt- und Template-Ordner tragen Slugs, einzelne Notizen dürfen Leerzeichen
und Großschreibung haben — Obsidian-Wikilinks kommen damit klar.
- Keine Umlaute in Ordnernamen; in Dateinamen sind sie unkritisch, aber Slugs
bleiben ASCII.
## Anpassung der Struktur
Die Ordnernamen sind nicht heilig, die Zuordnung Pfad → Typ schon: Sie steht in
`scripts/vaultlib.py` unter `FOLDER_TYPES`. Wer umbenennt, passt dort an —
sonst raten die Skripte falsch, und `type` im Frontmatter muss überall explizit
gesetzt sein. Frontmatter gewinnt immer gegen die Ordner-Ableitung.
@@ -0,0 +1,128 @@
# Workflows
Alle Pfade unten gehen davon aus, dass der Skill unter
`.claude/skills/obsidian-vault-navigator/` im Vault liegt.
## Frage beantworten („was habe ich zu X?")
1. `vault_query.py --text x` — bei vielen Treffern mit `--type` oder `--path`
nachschärfen.
2. Trefferliste dem Nutzer als Wikilink-Liste zeigen (`--format md`), damit er
in Obsidian direkt springen kann.
3. Reicht die Zusammenfassung für die Antwort, ist hier Schluss.
4. Sonst die 1–3 relevantesten Notizen öffnen. Bei langen Notizen vorher
`--format headings` und nur den passenden Abschnitt lesen.
5. Kommt bei der Antwort etwas Neues heraus, das später wieder gebraucht wird:
als Notiz ablegen oder an die bestehende anhängen.
## Neues Code-Projekt
1. Prüfen, ob es das schon gibt: `vault_query.py --text "<name>"`.
2. Passendes Template-Projekt suchen: `vault_query.py --type template-project`.
Die `use_when`-Zeilen reichen zur Auswahl.
3. Anlegen:
`new_note.py --type project-code --title "Auth Service" --tags go,oidc --summary "…"`
4. Wenn ein Template genutzt wird: dessen Ordner nach
`10_Projects/<slug>/` kopieren, dann `template_of: <template-slug>` ins
Frontmatter des neuen Projekts, und im Template-Projekt unter „Abgeleitete
Projekte" den Rückverweis eintragen.
5. Area verlinken, `repo`/`lang`/`stack` füllen.
6. `build_index.py`.
## Neue Recherche
1. Frage formulieren — eine Frage, eine Notiz. Passt die Frage nicht in einen
Satz, sind es zwei Notizen.
2. `new_note.py --type research --title "…" --project <slug>`
3. `question` ins Frontmatter, Antwort zuerst schreiben, Belege darunter.
4. `confidence` ehrlich setzen; `low` ist ein nützlicher Wert, kein Makel.
5. Vom auslösenden Projekt aus verlinken, damit die Recherche nicht verwaist.
6. `build_index.py`.
## Template-Projekt anlegen
Ein Template-Projekt entsteht meist rückwärts: Ein Projekt lief gut, die
Struktur soll wiederverwendet werden.
1. Projektordner nach `40_Templates/project-templates/<slug>/` kopieren.
2. Projektspezifisches entfernen: Namen, Secrets, Kundendaten, Logs,
Zwischenstände.
3. Platzhalter einführen und im Template `index.md` unter „Anwendung"
dokumentieren, welche ersetzt werden müssen.
4. `type: template-project`, `use_when` und `stack` setzen.
5. `build_index.py`.
## Inbox aufräumen
1. `vault_query.py --path 00_Inbox --sort updated`
2. Pro Notiz einen Zielort vorschlagen — mit der Regel aus
`references/vault-structure.md` als Begründung.
3. Die gesamte Liste als Vorschlag zeigen und **auf Freigabe warten**. Erst dann
verschieben, in Gruppen, nicht alles auf einmal.
4. Beim Verschieben Frontmatter vervollständigen (`type`, `summary`, `tags`).
5. `build_index.py`, danach `vault_doctor.py`, um tote Links zu finden, die
durchs Verschieben entstanden sind.
## Projekt abschließen
1. `status: done`, `updated` aktualisieren.
2. Im `index.md` einen Abschnitt „Ergebnis" ergänzen: was rauskam, was man
beim nächsten Mal anders machen würde. Das ist der Teil, der später gelesen
wird.
3. Lohnt sich ein Template-Projekt daraus? Siehe oben.
4. Kompletten Ordner nach `90_Archive/<slug>/` verschieben, `status: archived`.
5. `build_index.py`, dann `vault_doctor.py` gegen tote Links.
## Wöchentliche Pflege
```bash
python3 .claude/skills/obsidian-vault-navigator/scripts/build_index.py --vault .
python3 .claude/skills/obsidian-vault-navigator/scripts/vault_doctor.py --vault .
python3 .claude/skills/obsidian-vault-navigator/scripts/vault_query.py --since 7 --sort updated
python3 .claude/skills/obsidian-vault-navigator/scripts/vault_query.py --status active --stale 90
```
Daraus wird eine kurze Lage: was ist neu, was liegt fest, was fehlt an
Metadaten, was sollte ins Archiv. Änderungsvorschläge sammeln und gebündelt
vorlegen, nicht einzeln durchführen.
## Migration eines bestehenden Vaults
Der heikelste Fall — hier geht es um Dateien, an denen jahrelang gearbeitet
wurde. Nie im Bulk, nie ohne Freigabe, und immer mit einer Rückfahrkarte.
1. **Sicherung**: Vault in Git nehmen (`git init && git add -A && git commit`)
oder eine Kopie anlegen. Ohne das nicht anfangen — und den Nutzer das
bestätigen lassen.
2. **Bestandsaufnahme**: `build_index.py` auf dem Vault, so wie er ist. Der
Index läuft auch ohne Frontmatter; Typen werden dann aus Pfaden geraten oder
auf `note` gesetzt. Danach `vault_doctor.py` für den Ist-Zustand.
3. **Lage zeigen**: Anzahl Notizen, Typverteilung, wie viele ohne Frontmatter,
wie viele Waisen, größte Ordner. Erst danach über Struktur reden.
4. **Struktur anlegen**, ohne Bestehendes anzufassen: die Zielordner erzeugen,
`CLAUDE.md` in die Wurzel, Templates einsortieren.
5. **Frontmatter zuerst, Verschieben später.** `vault_doctor.py --fix-missing`
erst im Trockenlauf zeigen, dann auf einem Teilbereich mit `--apply`
ausprobieren, Ergebnis gemeinsam ansehen, dann den Rest.
6. **In Wellen verschieben**, thematisch sortiert: erst die eindeutigen Fälle
(klar erkennbare Projekte), dann Research, zuletzt der Rest. Nach jeder Welle
`build_index.py` + `vault_doctor.py`, tote Links reparieren, Nutzer draufschauen
lassen.
7. **Restposten** landen in `00_Inbox/` und werden nach und nach entschieden.
Ein Vault muss nicht an einem Tag fertig sortiert sein.
8. **Zusammenfassungen nachziehen**: `vault_query.py --no-summary` liefert die
Pflegeliste. Automatisch abgeleitete Summaries sind ein Start, kein Ergebnis
— die 30 wichtigsten Notizen von Hand nachschärfen bringt mehr als 300
maschinell erzeugte Sätze.
## Wenn der Nutzer in Claude Code arbeitet
Der Vault als Arbeitsverzeichnis öffnen, damit `CLAUDE.md` greift und die
Skript-Pfade stimmen. Ist das Code-Repo eines Projekts das Arbeitsverzeichnis
und der Vault liegt woanders, immer `--vault <pfad>` mitgeben — die Skripte
brauchen kein Arbeitsverzeichnis im Vault.
Ein Muster, das sich lohnt: Am Ende einer Coding-Session die Projektnotiz
aktualisieren (Stand, offene Punkte, getroffene Entscheidungen) und
`build_index.py` laufen lassen. Die nächste Session beginnt dann mit einer
Abfrage statt mit dem Wiederlesen des Repos.